mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 13:10:02 +01:00
TGUI reset and removal of unticked files and ci suite update (#14677)
* Adds easy to extend custom svg font. (#57717) Just throw in svgs into tgui/packages/tgfont/icons directory and you can use them in tgui with tg- prefix. Co-authored-by: Style Mistake <stylemistake@gmail.com> Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> * Update build.js * Update build.js * Update build.js * ew * more?? * Update validate_dme.py * Update validate_dme.py * Delete explorer_gear.dm Co-authored-by: AnturK <AnturK@users.noreply.github.com> Co-authored-by: Style Mistake <stylemistake@gmail.com> Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
This commit is contained in:
co-authored by
Style Mistake
Mothblocks
AnturK
parent
865ae82d66
commit
de8807eee2
@@ -14,12 +14,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Restore SpacemanDMM cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/SpacemanDMM
|
||||
key: ${{ runner.os }}-spacemandmm-${{ secrets.CACHE_PURGE_KEY }}
|
||||
- name: Restore Yarn cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: tgui/.yarn/cache
|
||||
key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }}
|
||||
@@ -39,6 +39,7 @@ jobs:
|
||||
bash tools/ci/check_changelogs.sh
|
||||
bash tools/ci/check_grep.sh
|
||||
bash tools/ci/check_misc.sh
|
||||
tools/bootstrap/python tools/validate_dme.py <tgstation.dme
|
||||
tools/build/build --ci lint tgui-test
|
||||
tools/bootstrap/python -m dmi.test
|
||||
tools/bootstrap/python -m mapmerge2.dmm_test
|
||||
@@ -56,7 +57,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Restore BYOND cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/BYOND
|
||||
key: ${{ runner.os }}-byond-${{ secrets.CACHE_PURGE_KEY }}
|
||||
@@ -105,7 +106,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Restore BYOND cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/BYOND
|
||||
key: ${{ runner.os }}-byond-${{ secrets.CACHE_PURGE_KEY }}
|
||||
@@ -181,7 +182,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Restore Yarn cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: tgui/.yarn/cache
|
||||
key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }}
|
||||
|
||||
@@ -1,399 +0,0 @@
|
||||
//as of:10/28/2019:
|
||||
//boxstation: ~153 loot items spawned
|
||||
//metastation: ~183 loot items spawned
|
||||
//deltastation: ~165 loot items spawned
|
||||
|
||||
//how to balance maint loot spawns:
|
||||
// 1) Ensure each category has items of approximately the same power level
|
||||
// 2) Tune weight of each category until average power of a maint loot spawn is acceptable
|
||||
// 3) Mapping considerations - Loot value should scale with difficulty of acquisition, or an assistaint will run through collecting free gear with no risk
|
||||
|
||||
//goal of maint loot:
|
||||
// 1) Provide random equipment to people who take effort to crawl maint
|
||||
// 2) Create memorable moments with very rare, crazy items
|
||||
|
||||
//Loot tables
|
||||
|
||||
GLOBAL_LIST_INIT(trash_loot, list(//junk: useless, very easy to get, or ghetto chemistry items
|
||||
list(//trash
|
||||
/obj/item/trash/can = 1,
|
||||
/obj/item/trash/candy = 1,
|
||||
/obj/item/trash/cheesie = 1,
|
||||
/obj/item/trash/chips = 1,
|
||||
/obj/item/trash/pistachios = 1,
|
||||
/obj/item/trash/popcorn = 1,
|
||||
/obj/item/trash/raisins = 1,
|
||||
/obj/item/trash/sosjerky = 1,
|
||||
|
||||
/obj/item/c_tube = 1,
|
||||
/obj/item/disk/data = 1,
|
||||
/obj/item/folder/yellow = 1,
|
||||
/obj/item/hand_labeler = 1,
|
||||
/obj/item/paper = 1,
|
||||
/obj/item/paper/crumpled = 1,
|
||||
/obj/item/pen = 1,
|
||||
/obj/item/photo/old = 1,
|
||||
/obj/item/poster/random_contraband = 1,
|
||||
/obj/item/poster/random_official = 1,
|
||||
/obj/item/stack/sheet/cardboard = 1,
|
||||
/obj/item/storage/box = 1,
|
||||
|
||||
/obj/effect/decal/cleanable/ash = 1,
|
||||
/obj/item/camera = 1,
|
||||
/obj/item/camera_film = 1,
|
||||
/obj/item/cigbutt = 1,
|
||||
/obj/item/coin/silver = 1,
|
||||
/obj/item/food/urinalcake = 1,
|
||||
/obj/item/light/bulb = 1,
|
||||
/obj/item/light/tube = 1,
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass = 1,
|
||||
|
||||
/obj/item/airlock_painter = 1,
|
||||
/obj/item/airlock_painter/decal = 1,
|
||||
/obj/item/airlock_painter/decal/tile = 1,
|
||||
/obj/item/clothing/mask/breath = 1,
|
||||
/obj/item/rack_parts = 1,
|
||||
/obj/item/shard = 1,
|
||||
|
||||
/obj/item/reagent_containers/pill/maintenance/achievement = 1,
|
||||
/obj/item/toy/eightball = 1,
|
||||
) = 8,
|
||||
|
||||
list(//tier 1 stock parts
|
||||
/obj/item/stock_parts/capacitor = 1,
|
||||
/obj/item/stock_parts/manipulator = 1,
|
||||
/obj/item/stock_parts/matter_bin = 1,
|
||||
/obj/item/stock_parts/micro_laser = 1,
|
||||
/obj/item/stock_parts/scanning_module = 1,
|
||||
) = 1,
|
||||
))
|
||||
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(common_loot, list( //common: basic items
|
||||
list(//tools
|
||||
/obj/item/analyzer = 1,
|
||||
/obj/item/crowbar = 1,
|
||||
/obj/item/geiger_counter = 1,
|
||||
/obj/item/mop = 1,
|
||||
/obj/item/pushbroom = 1,
|
||||
/obj/item/reagent_containers/glass/bucket = 1,
|
||||
/obj/item/screwdriver = 1,
|
||||
/obj/item/t_scanner = 1,
|
||||
/obj/item/toy/crayon/spraycan = 1,
|
||||
/obj/item/weldingtool = 1,
|
||||
/obj/item/wirecutters = 1,
|
||||
/obj/item/wrench = 1,
|
||||
) = 1,
|
||||
|
||||
list(//equipment
|
||||
/obj/effect/spawner/random/clothing/gloves = 1,
|
||||
/obj/item/clothing/glasses/meson = 1,
|
||||
/obj/item/clothing/glasses/science = 1,
|
||||
/obj/item/clothing/gloves/color/black = 1,
|
||||
/obj/item/clothing/gloves/color/fyellow = 1,
|
||||
/obj/item/clothing/mask/gas/alt = 1, //SKYRAT EDIT CHANGE - ORIGINAL: /obj/item/clothing/mask/gas = 1,
|
||||
/obj/item/clothing/shoes/sneakers/black = 1,
|
||||
/obj/item/clothing/suit/hazardvest = 1,
|
||||
/obj/item/clothing/suit/toggle/labcoat = 1,
|
||||
/obj/item/clothing/under/color/grey = 1,
|
||||
/obj/item/radio/headset = 1,
|
||||
/obj/item/storage/backpack = 1,
|
||||
/obj/item/storage/belt/fannypack = 1,
|
||||
/obj/item/storage/wallet/random = 1,
|
||||
) = 1,
|
||||
|
||||
list(//construction and crafting
|
||||
/obj/item/sign = 1,
|
||||
/obj/item/stack/cable_coil = 1,
|
||||
/obj/item/stack/rods/twentyfive = 1,
|
||||
/obj/item/stack/sheet/iron/twenty = 1,
|
||||
/obj/item/stack/sheet/mineral/plasma = 1,
|
||||
/obj/item/stock_parts/cell = 1,
|
||||
/obj/item/stock_parts/cell/crank = 1, // SKYRAT EDIT ADD - NEW_CELLS
|
||||
|
||||
//assemblies
|
||||
/obj/item/assembly/health = 1,
|
||||
/obj/item/assembly/igniter = 1,
|
||||
/obj/item/assembly/infra = 1,
|
||||
/obj/item/assembly/mousetrap = 1,
|
||||
/obj/item/assembly/prox_sensor = 1,
|
||||
/obj/item/assembly/signaler = 1,
|
||||
/obj/item/assembly/timer = 1,
|
||||
/obj/item/stack/package_wrap = 1,
|
||||
/obj/item/stack/wrapping_paper = 1,
|
||||
) = 1,
|
||||
|
||||
list(//medical and chemicals
|
||||
/obj/item/grenade/chem_grenade/cleaner = 1,
|
||||
/obj/item/lead_pipe = 1,
|
||||
/obj/item/reagent_containers/glass/beaker = 1,
|
||||
/obj/item/reagent_containers/glass/bottle/random_buffer = 2,
|
||||
/obj/item/reagent_containers/glass/rag = 1,
|
||||
/obj/item/reagent_containers/hypospray/medipen/pumpup = 2,
|
||||
/obj/item/reagent_containers/syringe = 1,
|
||||
/obj/item/stock_parts/cell/lead = 1,
|
||||
/obj/item/storage/box/matches = 1,
|
||||
/obj/item/storage/fancy/cigarettes/dromedaryco = 1,
|
||||
) = 1,
|
||||
|
||||
list(//food
|
||||
/obj/item/reagent_containers/food/drinks/bottle/beer = 1,
|
||||
/obj/item/reagent_containers/food/drinks/coffee = 1,
|
||||
) = 1,
|
||||
|
||||
list(//misc
|
||||
/obj/item/bodybag = 1,
|
||||
/obj/item/extinguisher = 1,
|
||||
/obj/item/grenade/smokebomb = 1,
|
||||
/obj/item/radio/off = 1,
|
||||
/obj/item/stack/spacecash/c10 = 1,
|
||||
/obj/item/stack/sticky_tape = 1,
|
||||
/obj/item/tank/internals/emergency_oxygen = 1,
|
||||
|
||||
//light sources
|
||||
/obj/effect/spawner/random/decoration/glowstick = 1,
|
||||
/obj/item/clothing/head/hardhat/red = 1,
|
||||
/obj/item/flashlight = 1,
|
||||
/obj/item/flashlight/flare = 1,
|
||||
) = 1,
|
||||
))
|
||||
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items
|
||||
list(//tools
|
||||
/obj/item/grenade/iedcasing/spawned = 1,
|
||||
/obj/item/hatchet = 1,
|
||||
/obj/item/melee/baton/security/cattleprod = 1,
|
||||
/obj/item/multitool = 1,
|
||||
/obj/item/pen/fountain = 1,
|
||||
/obj/item/restraints/handcuffs/cable = 1,
|
||||
/obj/item/restraints/legcuffs/bola = 1,
|
||||
/obj/item/roller = 1,
|
||||
/obj/item/spear = 1,
|
||||
/obj/item/weldingtool/largetank = 1,
|
||||
) = 8,
|
||||
|
||||
list(//equipment
|
||||
/obj/item/clothing/ears/earmuffs = 1,
|
||||
/obj/item/clothing/glasses/hud/diagnostic = 1,
|
||||
/obj/item/clothing/glasses/hud/health = 1,
|
||||
/obj/item/clothing/glasses/salesman = 1,
|
||||
/obj/item/clothing/glasses/nightmare_vision = 1,
|
||||
/obj/item/clothing/glasses/welding = 1,
|
||||
/obj/item/clothing/gloves/tackler/offbrand = 1,
|
||||
/obj/item/clothing/head/helmet/old = 1,
|
||||
/obj/item/clothing/head/welding = 1,
|
||||
/obj/item/clothing/mask/muzzle = 1,
|
||||
/obj/item/clothing/suit/armor/vest/old = 1,
|
||||
/obj/item/storage/belt/medical = 1,
|
||||
/obj/item/storage/belt/utility = 1,
|
||||
) = 8,
|
||||
|
||||
list(//strange objects
|
||||
/obj/item/relic = 5,
|
||||
) = 8,
|
||||
|
||||
list(//construction and crafting
|
||||
/obj/item/beacon = 1,
|
||||
/obj/item/paper/fluff/stations/soap = 1, //recipes count as crafting.
|
||||
/obj/item/plaque = 1,
|
||||
/obj/item/seeds/kronkus = 1,
|
||||
/obj/item/seeds/odious_puffball = 1,
|
||||
/obj/item/stack/sheet/mineral/wood/fifty = 1,
|
||||
/obj/item/stock_parts/cell/high = 1,
|
||||
/obj/item/storage/box/clown = 1,
|
||||
/obj/item/weaponcrafting/receiver = 1,
|
||||
) = 8,
|
||||
|
||||
list(//medical and chemicals
|
||||
list(//basic healing items
|
||||
/obj/item/stack/medical/gauze = 1,
|
||||
/obj/item/stack/medical/mesh = 1,
|
||||
/obj/item/stack/medical/suture = 1,
|
||||
) = 1,
|
||||
list(//medical chems
|
||||
/obj/item/reagent_containers/glass/bottle/multiver = 1,
|
||||
/obj/item/reagent_containers/hypospray/medipen = 1,
|
||||
/obj/item/reagent_containers/syringe/convermol = 1,
|
||||
) = 1,
|
||||
list(//drinks
|
||||
/obj/item/reagent_containers/food/drinks/bottle/vodka = 1,
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola = 1,
|
||||
/obj/item/reagent_containers/food/drinks/soda_cans/grey_bull = 1,
|
||||
) = 1,
|
||||
list(//sprayers
|
||||
/obj/item/reagent_containers/spray = 1,
|
||||
/obj/item/watertank = 1,
|
||||
/obj/item/watertank/janitor = 1,
|
||||
) = 1,
|
||||
) = 8,
|
||||
|
||||
list(//food
|
||||
/obj/item/food/canned/peaches/maint = 1,
|
||||
/obj/item/storage/box/donkpockets = 1,
|
||||
/obj/item/storage/box/gum/happiness = 1,
|
||||
list(//Donk Varieties
|
||||
/obj/item/storage/box/donkpockets/donkpocketberry = 1,
|
||||
/obj/item/storage/box/donkpockets/donkpockethonk = 1,
|
||||
/obj/item/storage/box/donkpockets/donkpocketpizza = 1,
|
||||
/obj/item/storage/box/donkpockets/donkpocketspicy = 1,
|
||||
/obj/item/storage/box/donkpockets/donkpocketteriyaki = 1,
|
||||
) = 1,
|
||||
list(//Donk-dinner Varieties
|
||||
/obj/item/food/ready_donk = 1,
|
||||
/obj/item/food/ready_donk/donkhiladas = 1,
|
||||
/obj/item/food/ready_donk/mac_n_cheese = 1,
|
||||
) = 1,
|
||||
/obj/item/food/monkeycube = 1,
|
||||
) = 8,
|
||||
|
||||
list(//modsuits
|
||||
/obj/effect/spawner/random/mod/maint = 3,
|
||||
/obj/item/mod/construction/broken_core = 1,
|
||||
) = 4,
|
||||
|
||||
list(//music
|
||||
/obj/item/instrument/accordion = 5,
|
||||
/obj/item/instrument/banjo = 5,
|
||||
/obj/item/instrument/bikehorn = 2,
|
||||
/obj/item/instrument/eguitar = 5,
|
||||
/obj/item/instrument/glockenspiel = 5,
|
||||
/obj/item/instrument/guitar = 5,
|
||||
/obj/item/instrument/harmonica = 5,
|
||||
/obj/item/instrument/musicalmoth = 1,
|
||||
/obj/item/instrument/recorder = 5,
|
||||
/obj/item/instrument/saxophone = 5,
|
||||
/obj/item/instrument/trombone = 5,
|
||||
/obj/item/instrument/trumpet = 5,
|
||||
/obj/item/instrument/violin = 5,
|
||||
/obj/item/instrument/violin/golden = 2,
|
||||
) = 2,
|
||||
|
||||
list(//fakeout items, keep this list at low relative weight
|
||||
/obj/item/clothing/shoes/jackboots = 1,
|
||||
/obj/item/dice/d20 = 1, //To balance out the stealth die of fates in oddities
|
||||
) = 1,
|
||||
))
|
||||
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(rarity_loot, list(//rare: really good items
|
||||
list(//tools
|
||||
/obj/item/assembly/flash/memorizer = 1,
|
||||
/obj/item/flashlight/flashdark = 1,
|
||||
/obj/item/knife/kitchen = 1,
|
||||
/obj/item/melee/baton/security/cattleprod/teleprod = 1,
|
||||
/obj/item/pen/survival = 1,
|
||||
/obj/item/restraints/handcuffs = 1,
|
||||
/obj/item/shield/riot/buckler = 1,
|
||||
/obj/item/throwing_star = 1,
|
||||
/obj/item/weldingtool/hugetank = 1,
|
||||
/obj/item/fishing_rod/master = 1,
|
||||
) = 1,
|
||||
|
||||
list(//equipment
|
||||
/obj/item/clothing/glasses/hud/security = 1,
|
||||
/obj/item/clothing/glasses/sunglasses = 1,
|
||||
/obj/item/clothing/gloves/color/black = 1,
|
||||
/obj/item/clothing/gloves/color/yellow = 1,
|
||||
/obj/item/clothing/gloves/tackler/combat = 1,
|
||||
/obj/item/clothing/head/helmet/justice = 1,
|
||||
/obj/item/storage/belt/military/assault = 1,
|
||||
/obj/item/storage/belt/security = 1,
|
||||
) = 1,
|
||||
|
||||
list(//paint
|
||||
/obj/item/paint/anycolor = 1,
|
||||
/obj/item/paint/black = 1,
|
||||
/obj/item/paint/blue = 1,
|
||||
/obj/item/paint/green = 1,
|
||||
/obj/item/paint/paint_remover = 1,
|
||||
/obj/item/paint/red = 1,
|
||||
/obj/item/paint/violet = 1,
|
||||
/obj/item/paint/white = 1,
|
||||
/obj/item/paint/yellow = 1,
|
||||
) = 1,
|
||||
|
||||
list(//medical and chemicals
|
||||
list(//medkits
|
||||
/obj/item/storage/box/hug/medical = 1,
|
||||
/obj/item/storage/medkit/emergency = 1,
|
||||
/obj/item/storage/medkit/regular = 1,
|
||||
) = 1,
|
||||
list(//medical chems
|
||||
/obj/item/reagent_containers/hypospray/medipen/oxandrolone = 1,
|
||||
/obj/item/reagent_containers/hypospray/medipen/salacid = 1,
|
||||
/obj/item/reagent_containers/syringe/contraband/methamphetamine = 1,
|
||||
) = 1,
|
||||
) = 1,
|
||||
|
||||
list(//misc
|
||||
/obj/item/book/granter/crafting_recipe/pipegun_prime = 1,
|
||||
/obj/item/book/granter/crafting_recipe/trash_cannon = 1,
|
||||
/obj/item/disk/nuclear/fake = 1,
|
||||
/obj/item/skillchip/brainwashing = 1,
|
||||
/obj/item/tattoo_kit = 1,
|
||||
) = 1,
|
||||
|
||||
))
|
||||
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(oddity_loot, list(//oddity: strange or crazy items
|
||||
/obj/effect/rune/teleport = 1,
|
||||
/obj/item/clothing/head/helmet/abductor = 1,
|
||||
/obj/item/clothing/shoes/jackboots/fast = 1,
|
||||
/obj/item/clothing/suit/armor/reactive/table = 1,
|
||||
/obj/item/dice/d20/fate/stealth/cursed = 1, //Only rolls 1
|
||||
/obj/item/dice/d20/fate/stealth/one_use = 1, //Looks like a d20, keep the d20 in the uncommon pool.
|
||||
/obj/item/shadowcloak = 1,
|
||||
/obj/item/spear/grey_tide = 1,
|
||||
/obj/item/storage/box/donkpockets/donkpocketgondola = 1,
|
||||
list(//music
|
||||
/obj/item/instrument/saxophone/spectral = 1,
|
||||
/obj/item/instrument/trombone/spectral = 1,
|
||||
/obj/item/instrument/trumpet/spectral = 1,
|
||||
) = 1,
|
||||
/obj/item/toy/cards/deck/tarot/haunted = 1,
|
||||
))
|
||||
|
||||
//Maintenance loot spawner pools
|
||||
#define maint_trash_weight 4500
|
||||
#define maint_common_weight 4500
|
||||
#define maint_uncommon_weight 900
|
||||
#define maint_rarity_weight 99
|
||||
#define maint_oddity_weight 1 //1 out of 10,000 would give metastation (180 spawns) a 2 in 111 chance of spawning an oddity per round, similar to xeno egg
|
||||
#define maint_holiday_weight 3500 // When holiday loot is enabled, it'll give every loot item a 25% chance of being a holiday item
|
||||
|
||||
//Loot pool used by default maintenance loot spawners
|
||||
GLOBAL_LIST_INIT(maintenance_loot, list(
|
||||
GLOB.trash_loot = maint_trash_weight,
|
||||
GLOB.common_loot = maint_common_weight,
|
||||
GLOB.uncommon_loot = maint_uncommon_weight,
|
||||
GLOB.rarity_loot = maint_rarity_weight,
|
||||
GLOB.oddity_loot = maint_oddity_weight,
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(ratking_trash, list(//Garbage: used by the regal rat mob when spawning garbage.
|
||||
/obj/item/cigbutt,
|
||||
/obj/item/trash/candy,
|
||||
/obj/item/trash/cheesie,
|
||||
/obj/item/trash/chips,
|
||||
/obj/item/trash/pistachios,
|
||||
/obj/item/trash/popcorn,
|
||||
/obj/item/trash/raisins,
|
||||
/obj/item/trash/sosjerky,
|
||||
/obj/item/trash/syndi_cakes,
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(ratking_coins, list(//Coins: Used by the regal rat mob when spawning coins.
|
||||
/obj/item/coin/iron,
|
||||
/obj/item/coin/plastic,
|
||||
/obj/item/coin/silver,
|
||||
/obj/item/coin/titanium,
|
||||
))
|
||||
|
||||
// List of all maintenance loot spawners, for easy finding at roundstart.
|
||||
GLOBAL_LIST_EMPTY(maintenance_loot_spawners)
|
||||
@@ -1,925 +0,0 @@
|
||||
/datum/action
|
||||
var/name = "Generic Action"
|
||||
var/desc
|
||||
var/datum/target
|
||||
var/check_flags = NONE
|
||||
var/processing = FALSE
|
||||
var/buttontooltipstyle = ""
|
||||
var/transparent_when_unavailable = TRUE
|
||||
/// Where any buttons we create should be by default. Accepts screen_loc and location defines
|
||||
var/default_button_position = SCRN_OBJ_IN_LIST
|
||||
|
||||
var/button_icon = 'icons/mob/actions/backgrounds.dmi' //This is the file for the BACKGROUND icon
|
||||
var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND //And this is the state for the background icon
|
||||
|
||||
var/icon_icon = 'icons/hud/actions.dmi' //This is the file for the ACTION icon
|
||||
var/button_icon_state = "default" //And this is the state for the action icon
|
||||
var/mob/owner
|
||||
///List of all mobs that are viewing our action button -> A unique movable for them to view.
|
||||
var/list/viewers = list()
|
||||
|
||||
/datum/action/New(Target)
|
||||
link_to(Target)
|
||||
|
||||
/datum/action/proc/link_to(Target)
|
||||
target = Target
|
||||
RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/OnUpdatedIcon)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE)
|
||||
|
||||
/datum/action/Destroy()
|
||||
if(owner)
|
||||
Remove(owner)
|
||||
target = null
|
||||
QDEL_LIST_ASSOC_VAL(viewers) // Qdel the buttons in the viewers list **NOT THE HUDS**
|
||||
return ..()
|
||||
|
||||
/datum/action/proc/Grant(mob/M)
|
||||
if(!M)
|
||||
Remove(owner)
|
||||
return
|
||||
if(owner)
|
||||
if(owner == M)
|
||||
return
|
||||
Remove(owner)
|
||||
owner = M
|
||||
RegisterSignal(owner, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE)
|
||||
|
||||
GiveAction(M)
|
||||
|
||||
/datum/action/proc/clear_ref(datum/ref)
|
||||
SIGNAL_HANDLER
|
||||
if(ref == owner)
|
||||
Remove(owner)
|
||||
if(ref == target)
|
||||
qdel(src)
|
||||
|
||||
/datum/action/proc/Remove(mob/M)
|
||||
for(var/datum/hud/hud in viewers)
|
||||
if(!hud.mymob)
|
||||
continue
|
||||
HideFrom(hud.mymob)
|
||||
LAZYREMOVE(M.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared
|
||||
viewers = list()
|
||||
|
||||
if(owner)
|
||||
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
|
||||
if(target == owner)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/clear_ref)
|
||||
owner = null
|
||||
|
||||
/datum/action/proc/Trigger(trigger_flags)
|
||||
if(!IsAvailable())
|
||||
return FALSE
|
||||
if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/action/proc/IsAvailable()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
if((check_flags & AB_CHECK_HANDS_BLOCKED) && HAS_TRAIT(owner, TRAIT_HANDS_BLOCKED))
|
||||
return FALSE
|
||||
if((check_flags & AB_CHECK_IMMOBILE) && HAS_TRAIT(owner, TRAIT_IMMOBILIZED))
|
||||
return FALSE
|
||||
if((check_flags & AB_CHECK_LYING) && isliving(owner))
|
||||
var/mob/living/action_user = owner
|
||||
if(action_user.body_position == LYING_DOWN)
|
||||
return FALSE
|
||||
if((check_flags & AB_CHECK_CONSCIOUS) && owner.stat != CONSCIOUS)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/proc/UpdateButtons(status_only, force)
|
||||
for(var/datum/hud/hud in viewers)
|
||||
var/atom/movable/screen/movable/button = viewers[hud]
|
||||
UpdateButton(button, status_only, force)
|
||||
|
||||
/datum/action/proc/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE)
|
||||
if(!button)
|
||||
return
|
||||
if(!status_only)
|
||||
button.name = name
|
||||
button.desc = desc
|
||||
if(owner?.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND)
|
||||
var/list/settings = owner.hud_used.get_action_buttons_icons()
|
||||
if(button.icon != settings["bg_icon"])
|
||||
button.icon = settings["bg_icon"]
|
||||
if(button.icon_state != settings["bg_state"])
|
||||
button.icon_state = settings["bg_state"]
|
||||
else
|
||||
if(button.icon != button_icon)
|
||||
button.icon = button_icon
|
||||
if(button.icon_state != background_icon_state)
|
||||
button.icon_state = background_icon_state
|
||||
|
||||
ApplyIcon(button, force)
|
||||
|
||||
if(!IsAvailable())
|
||||
button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0)
|
||||
else
|
||||
button.color = rgb(255,255,255,255)
|
||||
return TRUE
|
||||
|
||||
/datum/action/proc/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force = FALSE)
|
||||
if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force))
|
||||
current_button.cut_overlays(TRUE)
|
||||
current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state))
|
||||
current_button.button_icon_state = button_icon_state
|
||||
|
||||
/datum/action/proc/OnUpdatedIcon()
|
||||
SIGNAL_HANDLER
|
||||
UpdateButtons()
|
||||
|
||||
//Give our action button to the player
|
||||
/datum/action/proc/GiveAction(mob/viewer)
|
||||
var/datum/hud/our_hud = viewer.hud_used
|
||||
if(viewers[our_hud]) // Already have a copy of us? go away
|
||||
return
|
||||
|
||||
LAZYOR(viewer.actions, src) // Move this in
|
||||
ShowTo(viewer)
|
||||
|
||||
//Adds our action button to the screen of a player
|
||||
/datum/action/proc/ShowTo(mob/viewer)
|
||||
var/datum/hud/our_hud = viewer.hud_used
|
||||
if(!our_hud || viewers[our_hud]) // There's no point in this if you have no hud in the first place
|
||||
return
|
||||
|
||||
var/atom/movable/screen/movable/action_button/button = CreateButton()
|
||||
SetId(button, viewer)
|
||||
|
||||
button.our_hud = our_hud
|
||||
viewers[our_hud] = button
|
||||
if(viewer.client)
|
||||
viewer.client.screen += button
|
||||
|
||||
button.load_position(viewer)
|
||||
viewer.update_action_buttons()
|
||||
|
||||
//Removes our action button from the screen of a player
|
||||
/datum/action/proc/HideFrom(mob/viewer)
|
||||
var/datum/hud/our_hud = viewer.hud_used
|
||||
var/atom/movable/screen/movable/action_button/button = viewers[our_hud]
|
||||
LAZYREMOVE(viewer.actions, src)
|
||||
if(button)
|
||||
qdel(button)
|
||||
|
||||
/datum/action/proc/CreateButton()
|
||||
var/atom/movable/screen/movable/action_button/button = new()
|
||||
button.linked_action = src
|
||||
button.name = name
|
||||
button.actiontooltipstyle = buttontooltipstyle
|
||||
if(desc)
|
||||
button.desc = desc
|
||||
return button
|
||||
|
||||
/datum/action/proc/SetId(atom/movable/screen/movable/action_button/our_button, mob/owner)
|
||||
//button id generation
|
||||
var/bitfield = 0
|
||||
for(var/datum/action/action in owner.actions)
|
||||
if(action == src) // This could be us, which is dumb
|
||||
continue
|
||||
var/atom/movable/screen/movable/action_button/button = action.viewers[owner.hud_used]
|
||||
if(action.name == name && button.id)
|
||||
bitfield |= button.id
|
||||
|
||||
bitfield = ~bitfield // Flip our possible ids, so we can check if we've found a unique one
|
||||
for(var/i in 0 to 23) // We get 24 possible bitflags in dm
|
||||
var/bitflag = 1 << i // Shift us over one
|
||||
if(bitfield & bitflag)
|
||||
our_button.id = bitflag
|
||||
return
|
||||
|
||||
//Presets for item actions
|
||||
/datum/action/item_action
|
||||
check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS
|
||||
button_icon_state = null
|
||||
// If you want to override the normal icon being the item
|
||||
// then change this to an icon state
|
||||
|
||||
/datum/action/item_action/New(Target)
|
||||
..()
|
||||
var/obj/item/I = target
|
||||
LAZYINITLIST(I.actions)
|
||||
I.actions += src
|
||||
|
||||
/datum/action/item_action/Destroy()
|
||||
var/obj/item/I = target
|
||||
I.actions -= src
|
||||
UNSETEMPTY(I.actions)
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/Trigger(trigger_flags)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(target)
|
||||
var/obj/item/I = target
|
||||
I.ui_action_click(owner, src)
|
||||
return TRUE
|
||||
|
||||
/datum/action/item_action/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force)
|
||||
var/obj/item/item_target = target
|
||||
if(button_icon && button_icon_state)
|
||||
// If set, use the custom icon that we set instead
|
||||
// of the item appearence
|
||||
..()
|
||||
else if((target && current_button.appearance_cache != item_target.appearance) || force) //replace with /ref comparison if this is not valid.
|
||||
var/old_layer = item_target.layer
|
||||
var/old_plane = item_target.plane
|
||||
item_target.layer = FLOAT_LAYER //AAAH
|
||||
item_target.plane = FLOAT_PLANE //^ what that guy said
|
||||
current_button.cut_overlays()
|
||||
current_button.add_overlay(item_target)
|
||||
item_target.layer = old_layer
|
||||
item_target.plane = old_plane
|
||||
current_button.appearance_cache = item_target.appearance
|
||||
|
||||
/datum/action/item_action/toggle_light
|
||||
name = "Toggle Light"
|
||||
|
||||
/datum/action/item_action/toggle_light/Trigger(trigger_flags)
|
||||
if(istype(target, /obj/item/modular_computer))
|
||||
var/obj/item/modular_computer/mc = target
|
||||
mc.toggle_flashlight()
|
||||
return
|
||||
..()
|
||||
|
||||
/datum/action/item_action/toggle_hood
|
||||
name = "Toggle Hood"
|
||||
|
||||
/datum/action/item_action/toggle_firemode
|
||||
icon_icon = 'modular_skyrat/master_files/icons/mob/actions/actions_items.dmi' //SKYRAT EDIT ADDITION
|
||||
button_icon_state = "fireselect_no" //SKYRAT EDIT ADDITION
|
||||
name = "Toggle Firemode"
|
||||
|
||||
/datum/action/item_action/rcl_col
|
||||
name = "Change Cable Color"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "rcl_rainbow"
|
||||
|
||||
/datum/action/item_action/rcl_gui
|
||||
name = "Toggle Fast Wiring Gui"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "rcl_gui"
|
||||
|
||||
/datum/action/item_action/startchainsaw
|
||||
name = "Pull The Starting Cord"
|
||||
|
||||
/datum/action/item_action/toggle_computer_light
|
||||
name = "Toggle Flashlight"
|
||||
|
||||
/datum/action/item_action/toggle_gunlight
|
||||
name = "Toggle Gunlight"
|
||||
|
||||
/datum/action/item_action/toggle_mode
|
||||
name = "Toggle Mode"
|
||||
|
||||
/datum/action/item_action/toggle_barrier_spread
|
||||
name = "Toggle Barrier Spread"
|
||||
|
||||
/datum/action/item_action/equip_unequip_ted_gun
|
||||
name = "Equip/Unequip TED Gun"
|
||||
|
||||
/datum/action/item_action/toggle_paddles
|
||||
name = "Toggle Paddles"
|
||||
|
||||
/datum/action/item_action/set_internals
|
||||
name = "Set Internals"
|
||||
|
||||
/datum/action/item_action/set_internals/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force)
|
||||
if(!..()) // no button available
|
||||
return
|
||||
if(!iscarbon(owner))
|
||||
return
|
||||
var/mob/living/carbon/C = owner
|
||||
if(target == C.internal)
|
||||
button.icon_state = "template_active"
|
||||
|
||||
/datum/action/item_action/pick_color
|
||||
name = "Choose A Color"
|
||||
|
||||
/datum/action/item_action/toggle_mister
|
||||
name = "Toggle Mister"
|
||||
|
||||
/datum/action/item_action/activate_injector
|
||||
name = "Activate Injector"
|
||||
|
||||
/datum/action/item_action/toggle_helmet_light
|
||||
name = "Toggle Helmet Light"
|
||||
|
||||
/datum/action/item_action/toggle_welding_screen
|
||||
name = "Toggle Welding Screen"
|
||||
|
||||
/datum/action/item_action/toggle_welding_screen/Trigger(trigger_flags)
|
||||
var/obj/item/clothing/head/hardhat/weldhat/H = target
|
||||
if(istype(H))
|
||||
H.toggle_welding_screen(owner)
|
||||
|
||||
/datum/action/item_action/toggle_welding_screen/plasmaman
|
||||
name = "Toggle Welding Screen"
|
||||
|
||||
/datum/action/item_action/toggle_welding_screen/plasmaman/Trigger(trigger_flags)
|
||||
var/obj/item/clothing/head/helmet/space/plasmaman/H = target
|
||||
if(istype(H))
|
||||
H.toggle_welding_screen(owner)
|
||||
|
||||
/datum/action/item_action/toggle_spacesuit
|
||||
name = "Toggle Suit Thermal Regulator"
|
||||
icon_icon = 'icons/mob/actions/actions_spacesuit.dmi'
|
||||
button_icon_state = "thermal_off"
|
||||
|
||||
/datum/action/item_action/toggle_spacesuit/New(Target)
|
||||
. = ..()
|
||||
RegisterSignal(target, COMSIG_SUIT_SPACE_TOGGLE, .proc/toggle)
|
||||
|
||||
/datum/action/item_action/toggle_spacesuit/Destroy()
|
||||
UnregisterSignal(target, COMSIG_SUIT_SPACE_TOGGLE)
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/toggle_spacesuit/Trigger(trigger_flags)
|
||||
var/obj/item/clothing/suit/space/suit = target
|
||||
if(!istype(suit))
|
||||
return
|
||||
suit.toggle_spacesuit()
|
||||
|
||||
/// Toggle the action icon for the space suit thermal regulator
|
||||
/datum/action/item_action/toggle_spacesuit/proc/toggle(obj/item/clothing/suit/space/suit)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
button_icon_state = "thermal_[suit.thermal_on ? "on" : "off"]"
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/item_action/vortex_recall
|
||||
name = "Vortex Recall"
|
||||
desc = "Recall yourself, and anyone nearby, to an attuned hierophant beacon at any time.<br>If the beacon is still attached, will detach it."
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "vortex_recall"
|
||||
|
||||
/datum/action/item_action/vortex_recall/IsAvailable()
|
||||
var/area/current_area = get_area(target)
|
||||
if(current_area.area_flags & NOTELEPORT)
|
||||
to_chat(owner, span_notice("[target] fizzles uselessly."))
|
||||
return
|
||||
if(istype(target, /obj/item/hierophant_club))
|
||||
var/obj/item/hierophant_club/H = target
|
||||
if(H.teleporting)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/berserk_mode
|
||||
name = "Berserk"
|
||||
desc = "Increase your movement and melee speed while also increasing your melee armor for a short amount of time."
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "berserk_mode"
|
||||
background_icon_state = "bg_demon"
|
||||
|
||||
/datum/action/item_action/berserk_mode/Trigger(trigger_flags)
|
||||
if(istype(target, /obj/item/clothing/head/hooded/berserker))
|
||||
var/obj/item/clothing/head/hooded/berserker/berzerk = target
|
||||
if(berzerk.berserk_active)
|
||||
to_chat(owner, span_warning("You are already berserk!"))
|
||||
return
|
||||
if(berzerk.berserk_charge < 100)
|
||||
to_chat(owner, span_warning("You don't have a full charge."))
|
||||
return
|
||||
berzerk.berserk_mode(owner)
|
||||
return
|
||||
..()
|
||||
|
||||
/datum/action/item_action/toggle_helmet_flashlight
|
||||
name = "Toggle Helmet Flashlight"
|
||||
|
||||
/datum/action/item_action/toggle_helmet_mode
|
||||
name = "Toggle Helmet Mode"
|
||||
|
||||
/datum/action/item_action/crew_monitor
|
||||
name = "Interface With Crew Monitor"
|
||||
|
||||
/datum/action/item_action/toggle
|
||||
|
||||
/datum/action/item_action/toggle/New(Target)
|
||||
..()
|
||||
var/obj/item/item_target = target
|
||||
name = "Toggle [item_target.name]"
|
||||
|
||||
/datum/action/item_action/halt
|
||||
name = "HALT!"
|
||||
|
||||
/datum/action/item_action/toggle_voice_box
|
||||
name = "Toggle Voice Box"
|
||||
|
||||
/datum/action/item_action/change
|
||||
name = "Change"
|
||||
|
||||
/datum/action/item_action/nano_picket_sign
|
||||
name = "Retext Nano Picket Sign"
|
||||
|
||||
/datum/action/item_action/nano_picket_sign/Trigger(trigger_flags)
|
||||
if(!istype(target, /obj/item/picket_sign))
|
||||
return
|
||||
var/obj/item/picket_sign/sign = target
|
||||
sign.retext(owner)
|
||||
|
||||
/datum/action/item_action/adjust
|
||||
|
||||
/datum/action/item_action/adjust/New(Target)
|
||||
..()
|
||||
var/obj/item/item_target = target
|
||||
name = "Adjust [item_target.name]"
|
||||
|
||||
/datum/action/item_action/switch_hud
|
||||
name = "Switch HUD"
|
||||
|
||||
/datum/action/item_action/toggle_human_head
|
||||
name = "Toggle Human Head"
|
||||
|
||||
/datum/action/item_action/toggle_helmet
|
||||
name = "Toggle Helmet"
|
||||
|
||||
/datum/action/item_action/toggle_seclight
|
||||
name = "Toggle Seclight"
|
||||
|
||||
/datum/action/item_action/toggle_jetpack
|
||||
name = "Toggle Jetpack"
|
||||
|
||||
/datum/action/item_action/jetpack_stabilization
|
||||
name = "Toggle Jetpack Stabilization"
|
||||
|
||||
/datum/action/item_action/jetpack_stabilization/IsAvailable()
|
||||
var/obj/item/tank/jetpack/J = target
|
||||
if(!istype(J) || !J.on)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/hands_free
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
|
||||
/datum/action/item_action/hands_free/activate
|
||||
name = "Activate"
|
||||
|
||||
/datum/action/item_action/hands_free/shift_nerves
|
||||
name = "Shift Nerves"
|
||||
|
||||
/datum/action/item_action/explosive_implant
|
||||
check_flags = NONE
|
||||
name = "Activate Explosive Implant"
|
||||
|
||||
/datum/action/item_action/instrument
|
||||
name = "Use Instrument"
|
||||
desc = "Use the instrument specified"
|
||||
|
||||
/datum/action/item_action/instrument/Trigger(trigger_flags)
|
||||
if(istype(target, /obj/item/instrument))
|
||||
var/obj/item/instrument/I = target
|
||||
I.interact(usr)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/activate_remote_view
|
||||
name = "Activate Remote View"
|
||||
desc = "Activates the Remote View of your spy sunglasses."
|
||||
|
||||
/datum/action/item_action/organ_action
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
|
||||
/datum/action/item_action/organ_action/IsAvailable()
|
||||
var/obj/item/organ/I = target
|
||||
if(!I.owner)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/organ_action/toggle/New(Target)
|
||||
..()
|
||||
var/obj/item/organ/organ_target = target
|
||||
name = "Toggle [organ_target.name]"
|
||||
|
||||
/datum/action/item_action/organ_action/use/New(Target)
|
||||
..()
|
||||
var/obj/item/organ/organ_target = target
|
||||
name = "Use [organ_target.name]"
|
||||
|
||||
/datum/action/item_action/cult_dagger
|
||||
name = "Draw Blood Rune"
|
||||
desc = "Use the ritual dagger to create a powerful blood rune"
|
||||
icon_icon = 'icons/mob/actions/actions_cult.dmi'
|
||||
button_icon_state = "draw"
|
||||
buttontooltipstyle = "cult"
|
||||
background_icon_state = "bg_demon"
|
||||
default_button_position = "6:157,4:-2"
|
||||
|
||||
/datum/action/item_action/cult_dagger/Grant(mob/M)
|
||||
if(!IS_CULTIST(M))
|
||||
Remove(owner)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/cult_dagger/Trigger(trigger_flags)
|
||||
for(var/obj/item/held_item as anything in owner.held_items) // In case we were already holding a dagger
|
||||
if(istype(held_item, /obj/item/melee/cultblade/dagger))
|
||||
held_item.attack_self(owner)
|
||||
return
|
||||
var/obj/item/target_item = target
|
||||
if(owner.can_equip(target_item, ITEM_SLOT_HANDS))
|
||||
owner.temporarilyRemoveItemFromInventory(target_item)
|
||||
owner.put_in_hands(target_item)
|
||||
target_item.attack_self(owner)
|
||||
return
|
||||
|
||||
if(!isliving(owner))
|
||||
to_chat(owner, span_warning("You lack the necessary living force for this action."))
|
||||
return
|
||||
|
||||
var/mob/living/living_owner = owner
|
||||
if (living_owner.usable_hands <= 0)
|
||||
to_chat(living_owner, span_warning("You don't have any usable hands!"))
|
||||
else
|
||||
to_chat(living_owner, span_warning("Your hands are full!"))
|
||||
|
||||
|
||||
///MGS BOX!
|
||||
/datum/action/item_action/agent_box
|
||||
name = "Deploy Box"
|
||||
desc = "Find inner peace, here, in the box."
|
||||
check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS
|
||||
background_icon_state = "bg_agent"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "deploy_box"
|
||||
///The type of closet this action spawns.
|
||||
var/boxtype = /obj/structure/closet/cardboard/agent
|
||||
COOLDOWN_DECLARE(box_cooldown)
|
||||
|
||||
///Handles opening and closing the box.
|
||||
/datum/action/item_action/agent_box/Trigger(trigger_flags)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(istype(owner.loc, /obj/structure/closet/cardboard/agent))
|
||||
var/obj/structure/closet/cardboard/agent/box = owner.loc
|
||||
if(box.open())
|
||||
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
||||
return
|
||||
//Box closing from here on out.
|
||||
if(!isturf(owner.loc)) //Don't let the player use this to escape mechs/welded closets.
|
||||
to_chat(owner, span_warning("You need more space to activate this implant!"))
|
||||
return
|
||||
if(!COOLDOWN_FINISHED(src, box_cooldown))
|
||||
return
|
||||
COOLDOWN_START(src, box_cooldown, 10 SECONDS)
|
||||
var/box = new boxtype(owner.drop_location())
|
||||
owner.forceMove(box)
|
||||
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
||||
|
||||
/datum/action/item_action/agent_box/Grant(mob/M)
|
||||
. = ..()
|
||||
if(owner)
|
||||
RegisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT, .proc/suicide_act)
|
||||
|
||||
/datum/action/item_action/agent_box/Remove(mob/M)
|
||||
if(owner)
|
||||
UnregisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT)
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/agent_box/proc/suicide_act(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!istype(owner.loc, /obj/structure/closet/cardboard/agent))
|
||||
return
|
||||
|
||||
var/obj/structure/closet/cardboard/agent/box = owner.loc
|
||||
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
||||
box.open()
|
||||
owner.visible_message(span_suicide("[owner] falls out of [box]! It looks like [owner.p_they()] committed suicide!"))
|
||||
owner.throw_at(get_turf(owner))
|
||||
return OXYLOSS
|
||||
|
||||
//Preset for spells
|
||||
/datum/action/spell_action
|
||||
check_flags = NONE
|
||||
background_icon_state = "bg_spell"
|
||||
|
||||
/datum/action/spell_action/New(Target)
|
||||
..()
|
||||
var/obj/effect/proc_holder/S = target
|
||||
S.action = src
|
||||
name = S.name
|
||||
desc = S.desc
|
||||
icon_icon = S.action_icon
|
||||
button_icon_state = S.action_icon_state
|
||||
background_icon_state = S.action_background_icon_state
|
||||
|
||||
/datum/action/spell_action/Destroy()
|
||||
var/obj/effect/proc_holder/S = target
|
||||
S.action = null
|
||||
return ..()
|
||||
|
||||
/datum/action/spell_action/Trigger(trigger_flags)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(target)
|
||||
var/obj/effect/proc_holder/S = target
|
||||
S.Click()
|
||||
return TRUE
|
||||
|
||||
/datum/action/spell_action/IsAvailable()
|
||||
if(!target)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/spell_action/spell
|
||||
|
||||
/datum/action/spell_action/spell/IsAvailable()
|
||||
if(!target)
|
||||
return FALSE
|
||||
var/obj/effect/proc_holder/spell/S = target
|
||||
if(owner)
|
||||
return S.can_cast(owner)
|
||||
return FALSE
|
||||
|
||||
/datum/action/spell_action/alien
|
||||
|
||||
/datum/action/spell_action/alien/IsAvailable()
|
||||
if(!target)
|
||||
return FALSE
|
||||
var/obj/effect/proc_holder/alien/ab = target
|
||||
if(owner)
|
||||
return ab.cost_check(ab.check_turf,owner,1)
|
||||
return FALSE
|
||||
|
||||
|
||||
|
||||
//Preset for general and toggled actions
|
||||
/datum/action/innate
|
||||
check_flags = NONE
|
||||
var/active = 0
|
||||
|
||||
/datum/action/innate/Trigger(trigger_flags)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(!active)
|
||||
Activate()
|
||||
else
|
||||
Deactivate()
|
||||
return TRUE
|
||||
|
||||
/datum/action/innate/proc/Activate()
|
||||
return
|
||||
|
||||
/datum/action/innate/proc/Deactivate()
|
||||
return
|
||||
|
||||
//Preset for an action with a cooldown
|
||||
|
||||
/datum/action/cooldown
|
||||
check_flags = NONE
|
||||
transparent_when_unavailable = FALSE
|
||||
// The default cooldown applied when StartCooldown() is called
|
||||
var/cooldown_time = 0
|
||||
// The actual next time this ability can be used
|
||||
var/next_use_time = 0
|
||||
// Whether or not you want the cooldown for the ability to display in text form
|
||||
var/text_cooldown = TRUE
|
||||
// Setting for intercepting clicks before activating the ability
|
||||
var/click_to_activate = FALSE
|
||||
// Shares cooldowns with other cooldown abilities of the same value, not active if null
|
||||
var/shared_cooldown
|
||||
|
||||
/datum/action/cooldown/CreateButton()
|
||||
var/atom/movable/screen/movable/action_button/button = ..()
|
||||
button.maptext = ""
|
||||
button.maptext_x = 8
|
||||
button.maptext_y = 0
|
||||
button.maptext_width = 24
|
||||
button.maptext_height = 12
|
||||
return button
|
||||
|
||||
/datum/action/cooldown/IsAvailable()
|
||||
return ..() && (next_use_time <= world.time)
|
||||
|
||||
/// Starts a cooldown time to be shared with similar abilities, will use default cooldown time if an override is not specified
|
||||
/datum/action/cooldown/proc/StartCooldown(override_cooldown_time)
|
||||
if(shared_cooldown)
|
||||
for(var/datum/action/cooldown/shared_ability in owner.actions - src)
|
||||
if(shared_cooldown == shared_ability.shared_cooldown)
|
||||
if(isnum(override_cooldown_time))
|
||||
shared_ability.StartCooldownSelf(override_cooldown_time)
|
||||
else
|
||||
shared_ability.StartCooldownSelf(cooldown_time)
|
||||
StartCooldownSelf(override_cooldown_time)
|
||||
|
||||
/// Starts a cooldown time for this ability only, will use default cooldown time if an override is not specified
|
||||
/datum/action/cooldown/proc/StartCooldownSelf(override_cooldown_time)
|
||||
if(isnum(override_cooldown_time))
|
||||
next_use_time = world.time + override_cooldown_time
|
||||
else
|
||||
next_use_time = world.time + cooldown_time
|
||||
UpdateButtons()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/datum/action/cooldown/Trigger(trigger_flags, atom/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!owner)
|
||||
return FALSE
|
||||
if(click_to_activate)
|
||||
if(target)
|
||||
// For automatic / mob handling
|
||||
return InterceptClickOn(owner, null, target)
|
||||
if(owner.click_intercept == src)
|
||||
owner.click_intercept = null
|
||||
else
|
||||
owner.click_intercept = src
|
||||
for(var/datum/action/cooldown/ability in owner.actions)
|
||||
ability.UpdateButtons()
|
||||
return TRUE
|
||||
return PreActivate(owner)
|
||||
|
||||
/// Intercepts client owner clicks to activate the ability
|
||||
/datum/action/cooldown/proc/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(!IsAvailable())
|
||||
return FALSE
|
||||
if(!target)
|
||||
return FALSE
|
||||
PreActivate(target)
|
||||
caller.click_intercept = null
|
||||
return TRUE
|
||||
|
||||
/// For signal calling
|
||||
/datum/action/cooldown/proc/PreActivate(atom/target)
|
||||
if(SEND_SIGNAL(owner, COMSIG_ABILITY_STARTED, src) & COMPONENT_BLOCK_ABILITY_START)
|
||||
return
|
||||
. = Activate(target)
|
||||
SEND_SIGNAL(owner, COMSIG_ABILITY_FINISHED, src)
|
||||
|
||||
/// To be implemented by subtypes
|
||||
/datum/action/cooldown/proc/Activate(atom/target)
|
||||
return
|
||||
|
||||
/datum/action/cooldown/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE)
|
||||
. = ..()
|
||||
if(!button)
|
||||
return
|
||||
var/time_left = max(next_use_time - world.time, 0)
|
||||
if(text_cooldown)
|
||||
button.maptext = MAPTEXT("<b>[round(time_left/10, 0.1)]</b>")
|
||||
if(!owner || time_left == 0)
|
||||
button.maptext = ""
|
||||
if(IsAvailable() && owner.click_intercept == src)
|
||||
button.color = COLOR_GREEN
|
||||
|
||||
/datum/action/cooldown/process()
|
||||
var/time_left = max(next_use_time - world.time, 0)
|
||||
if(!owner || time_left == 0)
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/cooldown/Grant(mob/M)
|
||||
..()
|
||||
if(!owner)
|
||||
return
|
||||
UpdateButtons()
|
||||
if(next_use_time > world.time)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
///Like a cooldown action, but with an associated proc holder.
|
||||
/datum/action/cooldown/spell_like
|
||||
|
||||
/datum/action/cooldown/spell_like/New(Target)
|
||||
..()
|
||||
var/obj/effect/proc_holder/our_proc_holder = Target
|
||||
our_proc_holder.action = src
|
||||
name = our_proc_holder.name
|
||||
desc = our_proc_holder.desc
|
||||
icon_icon = our_proc_holder.action_icon
|
||||
button_icon_state = our_proc_holder.action_icon_state
|
||||
background_icon_state = our_proc_holder.action_background_icon_state
|
||||
|
||||
/datum/action/cooldown/spell_like/Activate(atom/activate_target)
|
||||
if(!target)
|
||||
return FALSE
|
||||
|
||||
StartCooldown(10 SECONDS)
|
||||
var/obj/effect/proc_holder/our_proc_holder = target
|
||||
our_proc_holder.Click()
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
//Stickmemes
|
||||
/datum/action/item_action/stickmen
|
||||
name = "Summon Stick Minions"
|
||||
desc = "Allows you to summon faithful stickmen allies to aide you in battle."
|
||||
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
|
||||
button_icon_state = "art_summon"
|
||||
|
||||
//surf_ss13
|
||||
/datum/action/item_action/bhop
|
||||
name = "Activate Jump Boots"
|
||||
desc = "Activates the jump boot's internal propulsion system, allowing the user to dash over 4-wide gaps."
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "jetboot"
|
||||
|
||||
/datum/action/item_action/bhop/brocket
|
||||
name = "Activate Rocket Boots"
|
||||
desc = "Activates the boot's rocket propulsion system, allowing the user to hurl themselves great distances."
|
||||
|
||||
/datum/action/language_menu
|
||||
name = "Language Menu"
|
||||
desc = "Open the language menu to review your languages, their keys, and select your default language."
|
||||
button_icon_state = "language_menu"
|
||||
check_flags = NONE
|
||||
|
||||
/datum/action/language_menu/Trigger(trigger_flags)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(ismob(owner))
|
||||
var/mob/M = owner
|
||||
var/datum/language_holder/H = M.get_language_holder()
|
||||
H.open_language_menu(usr)
|
||||
|
||||
/datum/action/item_action/wheelys
|
||||
name = "Toggle Wheels"
|
||||
desc = "Pops out or in your shoes' wheels."
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "wheelys"
|
||||
|
||||
/datum/action/item_action/kindle_kicks
|
||||
name = "Activate Kindle Kicks"
|
||||
desc = "Kick you feet together, activating the lights in your Kindle Kicks."
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "kindleKicks"
|
||||
|
||||
//Small sprites
|
||||
/datum/action/small_sprite
|
||||
name = "Toggle Giant Sprite"
|
||||
desc = "Others will always see you as giant."
|
||||
icon_icon = 'icons/mob/actions/actions_xeno.dmi'
|
||||
button_icon_state = "smallqueen"
|
||||
background_icon_state = "bg_alien"
|
||||
var/small = FALSE
|
||||
var/small_icon
|
||||
var/small_icon_state
|
||||
|
||||
/datum/action/small_sprite/queen
|
||||
small_icon = 'icons/mob/alien.dmi'
|
||||
small_icon_state = "alienq"
|
||||
|
||||
/datum/action/small_sprite/megafauna
|
||||
icon_icon = 'icons/mob/actions/actions_xeno.dmi'
|
||||
small_icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
|
||||
/datum/action/small_sprite/megafauna/drake
|
||||
small_icon_state = "ash_whelp"
|
||||
|
||||
/datum/action/small_sprite/megafauna/colossus
|
||||
small_icon_state = "Basilisk"
|
||||
|
||||
/datum/action/small_sprite/megafauna/bubblegum
|
||||
small_icon_state = "goliath2"
|
||||
|
||||
/datum/action/small_sprite/megafauna/legion
|
||||
small_icon_state = "mega_legion"
|
||||
|
||||
/datum/action/small_sprite/mega_arachnid
|
||||
small_icon = 'icons/mob/jungle/arachnid.dmi'
|
||||
small_icon_state = "arachnid_mini"
|
||||
background_icon_state = "bg_demon"
|
||||
|
||||
/datum/action/small_sprite/space_dragon
|
||||
small_icon = 'icons/mob/carp.dmi'
|
||||
small_icon_state = "carp"
|
||||
icon_icon = 'icons/mob/carp.dmi'
|
||||
button_icon_state = "carp"
|
||||
|
||||
/datum/action/small_sprite/Trigger(trigger_flags)
|
||||
..()
|
||||
if(!small)
|
||||
var/image/I = image(icon = small_icon, icon_state = small_icon_state, loc = owner)
|
||||
I.override = TRUE
|
||||
I.pixel_x -= owner.pixel_x
|
||||
I.pixel_y -= owner.pixel_y
|
||||
owner.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic, "smallsprite", I, AA_TARGET_SEE_APPEARANCE | AA_MATCH_TARGET_OVERLAYS)
|
||||
small = TRUE
|
||||
else
|
||||
owner.remove_alt_appearance("smallsprite")
|
||||
small = FALSE
|
||||
|
||||
/datum/action/item_action/storage_gather_mode
|
||||
name = "Switch gathering mode"
|
||||
desc = "Switches the gathering mode of a storage object."
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "storage_gather_switch"
|
||||
|
||||
/datum/action/item_action/storage_gather_mode/ApplyIcon(atom/movable/screen/movable/action_button/current_button)
|
||||
. = ..()
|
||||
var/obj/item/item_target = target
|
||||
var/old_layer = item_target.layer
|
||||
var/old_plane = item_target.plane
|
||||
item_target.layer = FLOAT_LAYER //AAAH
|
||||
item_target.plane = FLOAT_PLANE //^ what that guy said
|
||||
current_button.cut_overlays()
|
||||
current_button.add_overlay(target)
|
||||
item_target.layer = old_layer
|
||||
item_target.plane = old_plane
|
||||
current_button.appearance_cache = item_target.appearance
|
||||
@@ -15,6 +15,8 @@
|
||||
name = "Toggle Hood"
|
||||
|
||||
/datum/action/item_action/toggle_firemode
|
||||
icon_icon = 'modular_skyrat/master_files/icons/mob/actions/actions_items.dmi' //SKYRAT EDIT ADDITION
|
||||
button_icon_state = "fireselect_no" //SKYRAT EDIT ADDITION
|
||||
name = "Toggle Firemode"
|
||||
|
||||
/datum/action/item_action/toggle_gunlight
|
||||
|
||||
@@ -1,499 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
// AIR SENSOR (found in gas tanks)
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/air_sensor
|
||||
name = "gas sensor"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "gsensor1"
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
var/on = TRUE
|
||||
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/machinery/air_sensor/atmos/plasma_tank
|
||||
name = "plasma tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_PLAS
|
||||
/obj/machinery/air_sensor/atmos/ordnance_mixing_tank
|
||||
name = "ordnance mixing gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_ORDNANCE_LAB
|
||||
/obj/machinery/air_sensor/atmos/oxygen_tank
|
||||
name = "oxygen tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_O2
|
||||
/obj/machinery/air_sensor/atmos/nitrogen_tank
|
||||
name = "nitrogen tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_N2
|
||||
/obj/machinery/air_sensor/atmos/mix_tank
|
||||
name = "mix tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_MIX
|
||||
/obj/machinery/air_sensor/atmos/nitrous_tank
|
||||
name = "nitrous oxide tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_N2O
|
||||
/obj/machinery/air_sensor/atmos/air_tank
|
||||
name = "air mix tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_AIR
|
||||
/obj/machinery/air_sensor/atmos/carbon_tank
|
||||
name = "carbon dioxide tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_CO2
|
||||
/obj/machinery/air_sensor/atmos/bz_tank
|
||||
name = "bz tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_BZ
|
||||
/obj/machinery/air_sensor/atmos/freon_tank
|
||||
name = "freon tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_FREON
|
||||
/obj/machinery/air_sensor/atmos/halon_tank
|
||||
name = "halon tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_HALON
|
||||
/obj/machinery/air_sensor/atmos/healium_tank
|
||||
name = "healium tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_HEALIUM
|
||||
/obj/machinery/air_sensor/atmos/hydrogen_tank
|
||||
name = "hydrogen tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_H2
|
||||
/obj/machinery/air_sensor/atmos/hypernoblium_tank
|
||||
name = "hypernoblium tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM
|
||||
/obj/machinery/air_sensor/atmos/miasma_tank
|
||||
name = "miasma tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_MIASMA
|
||||
/obj/machinery/air_sensor/atmos/nitrium_tank
|
||||
name = "nitrium tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_NITRIUM
|
||||
/obj/machinery/air_sensor/atmos/pluoxium_tank
|
||||
name = "pluoxium tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM
|
||||
/obj/machinery/air_sensor/atmos/proto_nitrate_tank
|
||||
name = "proto-nitrate tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE
|
||||
/obj/machinery/air_sensor/atmos/tritium_tank
|
||||
name = "tritium tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_TRITIUM
|
||||
/obj/machinery/air_sensor/atmos/water_vapor_tank
|
||||
name = "water vapor tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_H2O
|
||||
/obj/machinery/air_sensor/atmos/zauker_tank
|
||||
name = "zauker tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_ZAUKER
|
||||
/obj/machinery/air_sensor/atmos/helium_tank
|
||||
name = "helium tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_HELIUM
|
||||
/obj/machinery/air_sensor/atmos/antinoblium_tank
|
||||
name = "antinoblium tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_ANTINOBLIUM
|
||||
/obj/machinery/air_sensor/atmos/incinerator_tank
|
||||
name = "incinerator chamber gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR
|
||||
|
||||
/obj/machinery/air_sensor/update_icon_state()
|
||||
icon_state = "gsensor[on]"
|
||||
return ..()
|
||||
|
||||
/obj/machinery/air_sensor/process_atmos()
|
||||
if(on)
|
||||
var/datum/gas_mixture/air_sample = return_air()
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"sigtype" = "status",
|
||||
"id_tag" = id_tag,
|
||||
"timestamp" = world.time,
|
||||
"pressure" = air_sample.return_pressure(),
|
||||
"temperature" = air_sample.temperature,
|
||||
"gases" = list()
|
||||
))
|
||||
var/total_moles = air_sample.total_moles()
|
||||
if(total_moles)
|
||||
for(var/gas_id in air_sample.gases)
|
||||
var/gas_name = air_sample.gases[gas_id][GAS_META][META_GAS_NAME]
|
||||
signal.data["gases"][gas_name] = air_sample.gases[gas_id][MOLES] / total_moles * 100
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
|
||||
/obj/machinery/air_sensor/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/air_sensor/Initialize(mapload)
|
||||
. = ..()
|
||||
SSair.start_processing_machine(src)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/air_sensor/Destroy()
|
||||
SSair.stop_processing_machine(src)
|
||||
SSradio.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// GENERAL AIR CONTROL (a.k.a atmos computer)
|
||||
/////////////////////////////////////////////////////////////
|
||||
GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
|
||||
/obj/machinery/computer/atmos_control
|
||||
name = "atmospherics monitoring"
|
||||
desc = "Used to monitor the station's atmospherics sensors."
|
||||
icon_screen = "tank"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/list/sensors = list(
|
||||
ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_PLAS = "Plasma Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_BZ = "BZ Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_FREON = "Freon Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_HALON = "Halon Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_HEALIUM = "Healium Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_H2 = "Hydrogen Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM = "Hypernoblium Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_MIASMA = "Miasma Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_NITRIUM = "Nitrium Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM = "Pluoxium Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE = "Proto-Nitrate Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_TRITIUM = "Tritium Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_H2O = "Water Vapor Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_ZAUKER = "Zauker Tank",
|
||||
ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop",
|
||||
ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop",
|
||||
ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber",
|
||||
ATMOS_GAS_MONITOR_SENSOR_ORDNANCE_LAB = "Ordnance Mixing Chamber"
|
||||
)
|
||||
var/list/sensor_information = list()
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
|
||||
/obj/machinery/computer/atmos_control/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.atmos_air_controllers += src
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/computer/atmos_control/Destroy()
|
||||
GLOB.atmos_air_controllers -= src
|
||||
SSradio.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/atmos_control/ui_interact(mob/user, datum/tgui/ui)
|
||||
//SKYRAT EDIT ADDITON BEGIN - AESTHETICS
|
||||
if(clicksound && world.time > next_clicksound && isliving(user))
|
||||
next_clicksound = world.time + rand(50, 100)
|
||||
playsound(src, get_sfx_skyrat(clicksound), clickvol)
|
||||
//SKYRAT EDIT END
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "AtmosControlConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_control/ui_data(mob/user)
|
||||
var/data = list()
|
||||
|
||||
data["sensors"] = list()
|
||||
for(var/id_tag in sensors)
|
||||
var/long_name = sensors[id_tag]
|
||||
var/list/info = sensor_information[id_tag]
|
||||
if(!info)
|
||||
continue
|
||||
data["sensors"] += list(list(
|
||||
"id_tag" = id_tag,
|
||||
"long_name" = sanitize(long_name),
|
||||
"pressure" = info["pressure"],
|
||||
"temperature" = info["temperature"],
|
||||
"gases" = info["gases"]
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_control/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/id_tag = signal.data["id_tag"]
|
||||
if(!id_tag || !sensors.Find(id_tag))
|
||||
return
|
||||
|
||||
sensor_information[id_tag] = signal.data
|
||||
|
||||
/obj/machinery/computer/atmos_control/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
//Incinerator sensor only
|
||||
/obj/machinery/computer/atmos_control/incinerator
|
||||
name = "Incinerator Air Control"
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/incinerator
|
||||
|
||||
//Ordnance mix sensor only
|
||||
/obj/machinery/computer/atmos_control/ordnancemix
|
||||
name = "Ordnance Mixing Air Control"
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_ORDNANCE_LAB = "Ordnance Mixing Chamber")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/ordnancemix
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// LARGE TANK CONTROL
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank
|
||||
var/input_tag
|
||||
var/output_tag
|
||||
frequency = FREQ_ATMOS_STORAGE
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank
|
||||
var/list/input_info
|
||||
var/list/output_info
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/oxygen_tank
|
||||
name = "Oxygen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_O2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_O2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/oxygen_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/plasma_tank
|
||||
name = "Plasma Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_PLAS
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_PLAS
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_PLAS = "Plasma Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/plasma_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/air_tank
|
||||
name = "Mixed Air Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_AIR
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_AIR
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_AIR = "Air Mix Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/air_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/mix_tank
|
||||
name = "Gas Mix Tank Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_MIX
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIX
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIX = "Gas Mix Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/mix_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/nitrous_tank
|
||||
name = "Nitrous Oxide Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_N2O
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2O
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/nitrous_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/nitrogen_tank
|
||||
name = "Nitrogen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_N2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/nitrogen_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/carbon_tank
|
||||
name = "Carbon Dioxide Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_CO2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_CO2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/carbon_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/bz_tank
|
||||
name = "BZ Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_BZ
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_BZ
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_BZ = "BZ Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/bz_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/freon_tank
|
||||
name = "Freon Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_FREON
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_FREON
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_FREON = "Freon Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/freon_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/halon_tank
|
||||
name = "Halon Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_HALON
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_HALON
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_HALON = "Halon Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/halon_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/healium_tank
|
||||
name = "Healium Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_HEALIUM
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_HEALIUM
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_HEALIUM = "Healium Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/healium_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/hydrogen_tank
|
||||
name = "Hydrogen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_H2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_H2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_H2 = "Hydrogen Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/hydrogen_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/hypernoblium_tank
|
||||
name = "Hypernoblium Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_HYPERNOBLIUM
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_HYPERNOBLIUM
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM = "Hypernoblium Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/hypernoblium_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/miasma_tank
|
||||
name = "Miasma Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_MIASMA
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIASMA
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIASMA = "Miasma Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/miasma_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/nitrium_tank
|
||||
name = "Nitrium Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_NITRIUM
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_NITRIUM
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_NITRIUM = "Nitrium Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/nitrium_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/pluoxium_tank
|
||||
name = "Pluoxium Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_PLUOXIUM
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_PLUOXIUM
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM = "Pluoxium Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/pluoxium_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/proto_nitrate_tank
|
||||
name = "Proto-Nitrate Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_PROTO_NITRATE
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_PROTO_NITRATE
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE = "Proto-Nitrate Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/proto_nitrate_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/tritium_tank
|
||||
name = "Tritium Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_TRITIUM
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_TRITIUM
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_TRITIUM = "Tritium Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/tritium_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/water_vapor
|
||||
name = "Water Vapor Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_H2O
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_H2O
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_H2O = "Water Vapor Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/water_vapor
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/zauker_tank
|
||||
name = "Zauker Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_ZAUKER
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_ZAUKER
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_ZAUKER = "Zauker Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/zauker_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/helium_tank
|
||||
name = "Helium Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_HELIUM
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_HELIUM
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_HELIUM = "Helium Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/helium_tank
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/antinoblium_tank
|
||||
name = "Antinoblium Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_ANTINOBLIUM
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_ANTINOBLIUM
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_ANTINOBLIUM = "Antinoblium Tank")
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank/antinoblium_tank
|
||||
|
||||
// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this
|
||||
/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user)
|
||||
var/list/IO = list()
|
||||
var/datum/radio_frequency/freq = SSradio.return_frequency(frequency)
|
||||
|
||||
var/list/devices = list()
|
||||
var/list/device_refs = freq.devices["_default"]
|
||||
for(var/datum/weakref/device_ref as anything in device_refs)
|
||||
var/atom/device = device_ref.resolve()
|
||||
if(!device)
|
||||
device_refs -= device_ref
|
||||
continue
|
||||
devices += device
|
||||
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
IO |= text[1]
|
||||
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
|
||||
var/list/text = splittext(U.id, "_")
|
||||
IO |= text[1]
|
||||
if(!IO.len)
|
||||
to_chat(user, span_alert("No machinery detected."))
|
||||
var/S = tgui_input_list(user, "Select the device set", "Reconnect", sort_list(IO))
|
||||
if(isnull(S))
|
||||
return
|
||||
if(src)
|
||||
src.input_tag = "[S]_in"
|
||||
src.output_tag = "[S]_out"
|
||||
name = "[uppertext(S)] Supply Control"
|
||||
var/list/new_devices = freq.devices["atmosia"]
|
||||
sensors.Cut()
|
||||
for(var/obj/machinery/air_sensor/U in new_devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
if(text[1] == S)
|
||||
sensors = list("[S]_sensor" = "[S] Tank")
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
|
||||
U.broadcast_status()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
|
||||
U.broadcast_status()
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
data["tank"] = TRUE
|
||||
data["inputting"] = input_info ? input_info["power"] : FALSE
|
||||
data["inputRate"] = input_info ? input_info["volume_rate"] : 0
|
||||
data["maxInputRate"] = input_info ? MAX_TRANSFER_RATE : 0
|
||||
data["outputting"] = output_info ? output_info["power"] : FALSE
|
||||
data["outputPressure"] = output_info ? output_info["internal"] : 0
|
||||
data["maxOutputPressure"] = output_info ? MAX_OUTPUT_PRESSURE : 0
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_act(action, params)
|
||||
. = ..()
|
||||
|
||||
if(. || !radio_connection)
|
||||
return
|
||||
var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr))
|
||||
switch(action)
|
||||
if("reconnect")
|
||||
reconnect(usr)
|
||||
. = TRUE
|
||||
if("input")
|
||||
signal.data += list("tag" = input_tag, "power_toggle" = TRUE)
|
||||
. = TRUE
|
||||
if("rate")
|
||||
var/target = text2num(params["rate"])
|
||||
if(!isnull(target))
|
||||
target = clamp(target, 0, MAX_TRANSFER_RATE)
|
||||
signal.data += list("tag" = input_tag, "set_volume_rate" = target)
|
||||
. = TRUE
|
||||
if("output")
|
||||
signal.data += list("tag" = output_tag, "power_toggle" = TRUE)
|
||||
. = TRUE
|
||||
if("pressure")
|
||||
var/target = text2num(params["pressure"])
|
||||
if(!isnull(target))
|
||||
target = clamp(target, 0, MAX_OUTPUT_PRESSURE)
|
||||
signal.data += list("tag" = output_tag, "set_internal_pressure" = target)
|
||||
. = TRUE
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/id_tag = signal.data["tag"]
|
||||
|
||||
if(input_tag == id_tag)
|
||||
input_info = signal.data
|
||||
else if(output_tag == id_tag)
|
||||
output_info = signal.data
|
||||
else
|
||||
..(signal)
|
||||
@@ -1,386 +0,0 @@
|
||||
// Foam
|
||||
// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin.
|
||||
#define ALUMINUM_FOAM 1
|
||||
#define IRON_FOAM 2
|
||||
#define RESIN_FOAM 3
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam
|
||||
name = "foam"
|
||||
icon_state = "foam"
|
||||
opacity = FALSE
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
layer = EDGED_TURF_LAYER
|
||||
plane = GAME_PLANE_UPPER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
var/amount = 3
|
||||
animate_movement = NO_STEPS
|
||||
var/metal = 0
|
||||
var/lifetime = 40
|
||||
var/reagent_divisor = 7
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(
|
||||
/turf/open/space/transit,
|
||||
/turf/open/chasm,
|
||||
/turf/open/lava,
|
||||
))
|
||||
var/slippery_foam = TRUE
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting
|
||||
name = "firefighting foam"
|
||||
lifetime = 20 //doesn't last as long as normal foam
|
||||
amount = 0 //no spread
|
||||
slippery_foam = FALSE
|
||||
var/absorbed_plasma = 0
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/Initialize(mapload)
|
||||
. = ..()
|
||||
RemoveElement(/datum/element/atmos_sensitive)
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/process()
|
||||
..()
|
||||
|
||||
var/turf/open/T = get_turf(src)
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
|
||||
if(hotspot && istype(T) && T.air)
|
||||
qdel(hotspot)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
if(G.gases[/datum/gas/plasma])
|
||||
var/plas_amt = min(30,G.gases[/datum/gas/plasma][MOLES]) //Absorb some plasma
|
||||
G.gases[/datum/gas/plasma][MOLES] -= plas_amt
|
||||
absorbed_plasma += plas_amt
|
||||
if(G.temperature > T20C)
|
||||
G.temperature = max(G.temperature/2,T20C)
|
||||
G.garbage_collect()
|
||||
T.air_update_turf(FALSE, FALSE)
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/kill_foam()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
|
||||
if(absorbed_plasma)
|
||||
var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src))
|
||||
if(!P)
|
||||
P = new(loc)
|
||||
P.reagents.add_reagent(/datum/reagent/stable_plasma, absorbed_plasma)
|
||||
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L)
|
||||
if(!istype(L))
|
||||
return
|
||||
L.adjust_wet_stacks(2)
|
||||
|
||||
/obj/effect/particle_effect/foam/metal
|
||||
name = "aluminium foam"
|
||||
metal = ALUMINUM_FOAM
|
||||
icon_state = "mfoam"
|
||||
slippery_foam = FALSE
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/smart
|
||||
name = "smart foam"
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/iron
|
||||
name = "iron foam"
|
||||
metal = IRON_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/resin
|
||||
name = "resin foam"
|
||||
metal = RESIN_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/long_life
|
||||
lifetime = 150
|
||||
|
||||
/obj/effect/particle_effect/foam/Initialize(mapload)
|
||||
. = ..()
|
||||
create_reagents(1000) //limited by the size of the reagent holder anyway.
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
playsound(src, 'sound/effects/bubbles2.ogg', 80, TRUE, -3)
|
||||
AddElement(/datum/element/atmos_sensitive, mapload)
|
||||
|
||||
/obj/effect/particle_effect/foam/ComponentInitialize()
|
||||
. = ..()
|
||||
if(slippery_foam)
|
||||
AddComponent(/datum/component/slippery, 100)
|
||||
|
||||
/obj/effect/particle_effect/foam/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/kill_foam()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
switch(metal)
|
||||
if(ALUMINUM_FOAM)
|
||||
new /obj/structure/foamedmetal(get_turf(src))
|
||||
if(IRON_FOAM)
|
||||
new /obj/structure/foamedmetal/iron(get_turf(src))
|
||||
if(RESIN_FOAM)
|
||||
new /obj/structure/foamedmetal/resin(get_turf(src))
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/smart/kill_foam() //Smart foam adheres to area borders for walls
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
if(metal)
|
||||
var/turf/T = get_turf(src)
|
||||
if(isspaceturf(T)) //Block up any exposed space
|
||||
T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR)
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/cardinal_turf = get_step(T, direction)
|
||||
if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf!
|
||||
new/obj/structure/foamedmetal(T)
|
||||
break
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/process()
|
||||
lifetime--
|
||||
if(lifetime < 1)
|
||||
kill_foam()
|
||||
return
|
||||
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
for(var/obj/O in range(0,src))
|
||||
if(O.type == src.type)
|
||||
continue
|
||||
if(isturf(O.loc))
|
||||
var/turf/T = O.loc
|
||||
if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
|
||||
continue
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.expose(O, VAPOR, fraction)
|
||||
var/hit = 0
|
||||
for(var/mob/living/L in range(0,src))
|
||||
hit += foam_mob(L)
|
||||
if(hit)
|
||||
lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate.
|
||||
var/T = get_turf(src)
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.expose(T, VAPOR, fraction)
|
||||
|
||||
if(--amount < 0)
|
||||
return
|
||||
spread_foam()
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L)
|
||||
if(lifetime<1)
|
||||
return FALSE
|
||||
if(!istype(L))
|
||||
return FALSE
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.expose(L, VAPOR, fraction)
|
||||
lifetime--
|
||||
return TRUE
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/spread_foam()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
//This should just be atmos adjacent turfs, come on guys
|
||||
for(var/turf/T in t_loc.reachableAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam!
|
||||
if(foundfoam)
|
||||
continue
|
||||
|
||||
if(is_type_in_typecache(T, blacklisted_turfs))
|
||||
continue
|
||||
|
||||
for(var/mob/living/L in T)
|
||||
foam_mob(L)
|
||||
var/obj/effect/particle_effect/foam/F = new src.type(T)
|
||||
F.amount = amount
|
||||
reagents.copy_to(F, (reagents.total_volume))
|
||||
F.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
F.metal = metal
|
||||
|
||||
/obj/effect/particle_effect/foam/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
|
||||
return exposed_temperature > 475
|
||||
|
||||
/obj/effect/particle_effect/foam/atmos_expose(datum/gas_mixture/air, exposed_temperature)
|
||||
if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
|
||||
kill_foam()
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
//FOAM EFFECT DATUM
|
||||
/datum/effect_system/foam_spread
|
||||
/// the size of the foam spread.
|
||||
var/amount = 10
|
||||
/// Stupid hack alertm exists to hold chems for us
|
||||
var/atom/movable/chem_holder/chemholder
|
||||
effect_type = /obj/effect/particle_effect/foam
|
||||
var/metal = 0
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal
|
||||
effect_type = /obj/effect/particle_effect/foam/metal
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal/smart
|
||||
effect_type = /obj/effect/particle_effect/foam/smart
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/long
|
||||
effect_type = /obj/effect/particle_effect/foam/long_life
|
||||
|
||||
/datum/effect_system/foam_spread/New()
|
||||
..()
|
||||
chemholder = new()
|
||||
chemholder.create_reagents(1000, NO_REACT)
|
||||
|
||||
/datum/effect_system/foam_spread/Destroy()
|
||||
QDEL_NULL(chemholder)
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null, metaltype = 0)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
|
||||
amount = round(sqrt(amt / 2), 1)
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
if(metaltype)
|
||||
metal = metaltype
|
||||
|
||||
/datum/effect_system/foam_spread/start()
|
||||
var/obj/effect/particle_effect/foam/F = new effect_type(location)
|
||||
var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
|
||||
// To prevent insane reagent multiplication with 1u foam
|
||||
// I am capping amount of reagent foam recieves by limiting how low it can go
|
||||
// Any radius of foam less than 3 makes foam recieve same amount of reagents as foam of radius 3
|
||||
// Maximum multiplication of reagents is about 166% (3 times as low as before, it was about 500% with 1u foam)
|
||||
//
|
||||
// amount is radius of the foam
|
||||
// 10u foam has radius of 3
|
||||
// 5u foam has radius of 2
|
||||
// 1u foam has radius of 1
|
||||
var/effective_amount = chemholder.reagents.total_volume / max(amount, 3)
|
||||
chemholder.reagents.copy_to(F, effective_amount)
|
||||
F.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY)
|
||||
F.amount = amount
|
||||
F.metal = metal
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break
|
||||
/obj/structure/foamedmetal
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "metalfoam"
|
||||
density = TRUE
|
||||
opacity = TRUE // changed in New()
|
||||
anchored = TRUE
|
||||
layer = EDGED_TURF_LAYER
|
||||
plane = GAME_PLANE_UPPER
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
name = "foamed metal"
|
||||
desc = "A lightweight foamed metal wall that can be used as base to construct a wall."
|
||||
gender = PLURAL
|
||||
max_integrity = 20
|
||||
can_atmos_pass = ATMOS_PASS_DENSITY
|
||||
obj_flags = CAN_BE_HIT | BLOCK_Z_IN_DOWN | BLOCK_Z_IN_UP
|
||||
///Var used to prevent spamming of the construction sound
|
||||
var/next_beep = 0
|
||||
|
||||
/obj/structure/foamedmetal/Initialize(mapload)
|
||||
. = ..()
|
||||
air_update_turf(TRUE, TRUE)
|
||||
|
||||
/obj/structure/foamedmetal/Destroy()
|
||||
air_update_turf(TRUE, FALSE)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/foamedmetal/Move()
|
||||
var/turf/T = loc
|
||||
. = ..()
|
||||
move_update_air(T)
|
||||
|
||||
/obj/structure/foamedmetal/attack_paw(mob/user, list/modifiers)
|
||||
return attack_hand(user, modifiers)
|
||||
|
||||
/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, TRUE)
|
||||
|
||||
/obj/structure/foamedmetal/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
to_chat(user, span_warning("You hit [src] but bounce off it!"))
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, TRUE)
|
||||
|
||||
/obj/structure/foamedmetal/attackby(obj/item/W, mob/user, params)
|
||||
///A speed modifier for how fast the wall is build
|
||||
var/platingmodifier = 1
|
||||
if(HAS_TRAIT(user, TRAIT_QUICK_BUILD))
|
||||
platingmodifier = 0.7
|
||||
if(next_beep <= world.time)
|
||||
next_beep = world.time + 1 SECONDS
|
||||
playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(!istype(W, /obj/item/stack/sheet))
|
||||
return ..()
|
||||
|
||||
var/obj/item/stack/sheet/sheet_for_plating = W
|
||||
if(istype(sheet_for_plating, /obj/item/stack/sheet/iron))
|
||||
if(sheet_for_plating.get_amount() < 2)
|
||||
to_chat(user, span_warning("You need two sheets of iron to finish a wall on [src]!"))
|
||||
return
|
||||
to_chat(user, span_notice("You start adding plating to the foam structure..."))
|
||||
if (do_after(user, 40*platingmodifier, target = src))
|
||||
if(!sheet_for_plating.use(2))
|
||||
return
|
||||
to_chat(user, span_notice("You add the plating."))
|
||||
var/turf/T = get_turf(src)
|
||||
T.PlaceOnTop(/turf/closed/wall/metal_foam_base)
|
||||
transfer_fingerprints_to(T)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
add_hiddenprint(user)
|
||||
|
||||
/obj/structure/foamedmetal/iron
|
||||
max_integrity = 50
|
||||
icon_state = "ironfoam"
|
||||
|
||||
//Atmos Backpack Resin, transparent, prevents atmos and filters the air
|
||||
/obj/structure/foamedmetal/resin
|
||||
name = "\improper ATMOS Resin"
|
||||
desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature. It can be used as base to construct a wall."
|
||||
opacity = FALSE
|
||||
icon_state = "atmos_resin"
|
||||
alpha = 120
|
||||
max_integrity = 10
|
||||
pass_flags_self = PASSGLASS
|
||||
|
||||
/obj/structure/foamedmetal/resin/Initialize(mapload)
|
||||
. = ..()
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/O = loc
|
||||
O.ClearWet()
|
||||
if(O.air)
|
||||
var/datum/gas_mixture/G = O.air
|
||||
G.temperature = 293.15
|
||||
for(var/obj/effect/hotspot/H in O)
|
||||
qdel(H)
|
||||
var/list/G_gases = G.gases
|
||||
for(var/I in G_gases)
|
||||
if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen)
|
||||
continue
|
||||
G_gases[I][MOLES] = 0
|
||||
G.garbage_collect()
|
||||
for(var/obj/machinery/atmospherics/components/unary/U in O)
|
||||
if(!U.welded)
|
||||
U.welded = TRUE
|
||||
U.update_appearance()
|
||||
U.visible_message(span_danger("[U] sealed shut!"))
|
||||
for(var/mob/living/L in O)
|
||||
L.extinguish_mob()
|
||||
for(var/obj/item/Item in O)
|
||||
Item.extinguish()
|
||||
|
||||
#undef ALUMINUM_FOAM
|
||||
#undef IRON_FOAM
|
||||
#undef RESIN_FOAM
|
||||
@@ -1,656 +0,0 @@
|
||||
///defined truthy result for `handle_unique_ai()`, which makes initialize return INITIALIZE_HINT_QDEL
|
||||
#define SHOULD_QDEL_MODULE 1
|
||||
|
||||
/obj/item/ai_module
|
||||
name = "\improper AI module"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "std_mod"
|
||||
inhand_icon_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
desc = "An AI Module for programming laws to an AI."
|
||||
flags_1 = CONDUCT_1
|
||||
force = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throwforce = 0
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
custom_materials = list(/datum/material/gold = 50)
|
||||
var/list/laws = list()
|
||||
var/bypass_law_amt_check = 0
|
||||
|
||||
/obj/item/ai_module/Initialize(mapload)
|
||||
. = ..()
|
||||
if(mapload && HAS_TRAIT(SSstation, STATION_TRAIT_UNIQUE_AI) && is_station_level(z))
|
||||
var/delete_module = handle_unique_ai()
|
||||
if(delete_module)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/item/ai_module/examine(mob/user as mob)
|
||||
. = ..()
|
||||
if(Adjacent(user))
|
||||
show_laws(user)
|
||||
|
||||
/obj/item/ai_module/attack_self(mob/user as mob)
|
||||
..()
|
||||
show_laws(user)
|
||||
|
||||
///what this module should do if it is mapload spawning on a unique AI station trait round.
|
||||
/obj/item/ai_module/proc/handle_unique_ai()
|
||||
return SHOULD_QDEL_MODULE //instead of the roundstart bid to un-unique the AI, there will be a research requirement for it.
|
||||
|
||||
/obj/item/ai_module/proc/show_laws(mob/user as mob)
|
||||
if(laws.len)
|
||||
to_chat(user, "<B>Programmed Law[(laws.len > 1) ? "s" : ""]:</B>")
|
||||
for(var/law in laws)
|
||||
to_chat(user, "\"[law]\"")
|
||||
|
||||
//The proc other things should be calling
|
||||
/obj/item/ai_module/proc/install(datum/ai_laws/law_datum, mob/user)
|
||||
if(!bypass_law_amt_check && (!laws.len || laws[1] == "")) //So we don't loop trough an empty list and end up with runtimes.
|
||||
to_chat(user, span_warning("ERROR: No laws found on board."))
|
||||
return
|
||||
|
||||
var/overflow = FALSE
|
||||
//Handle the lawcap
|
||||
if(law_datum)
|
||||
var/tot_laws = 0
|
||||
for(var/lawlist in list(law_datum.inherent, law_datum.supplied, law_datum.ion, law_datum.hacked, laws))
|
||||
for(var/mylaw in lawlist)
|
||||
if(mylaw != "")
|
||||
tot_laws++
|
||||
if(tot_laws > CONFIG_GET(number/silicon_max_law_amount) && !bypass_law_amt_check)//allows certain boards to avoid this check, eg: reset
|
||||
to_chat(user, span_alert("Not enough memory allocated to [law_datum.owner ? law_datum.owner : "the AI core"]'s law processor to handle this amount of laws."))
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] tried to upload laws to [law_datum.owner ? ADMIN_LOOKUPFLW(law_datum.owner) : "an AI core"] that would exceed the law cap.")
|
||||
log_silicon("[key_name(user)] tried to upload laws to [law_datum.owner ? key_name(law_datum.owner) : "an AI core"] that would exceed the law cap.")
|
||||
overflow = TRUE
|
||||
|
||||
var/law2log = transmitInstructions(law_datum, user, overflow) //Freeforms return something extra we need to log
|
||||
if(law_datum.owner)
|
||||
to_chat(user, span_notice("Upload complete. [law_datum.owner]'s laws have been modified."))
|
||||
law_datum.owner.law_change_counter++
|
||||
else
|
||||
to_chat(user, span_notice("Upload complete."))
|
||||
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
var/ainame = law_datum.owner ? law_datum.owner.name : "empty AI core"
|
||||
var/aikey = law_datum.owner ? law_datum.owner.ckey : "null"
|
||||
|
||||
//affected cyborgs are cyborgs linked to the AI with lawsync enabled
|
||||
var/affected_cyborgs = list()
|
||||
var/list/borg_txt = list()
|
||||
var/list/borg_flw = list()
|
||||
if(isAI(law_datum.owner))
|
||||
var/mob/living/silicon/ai/owner = law_datum.owner
|
||||
for(var/mob/living/silicon/robot/owned_borg as anything in owner.connected_robots)
|
||||
if(owned_borg.connected_ai && owned_borg.lawupdate)
|
||||
affected_cyborgs += owned_borg
|
||||
borg_flw += "[ADMIN_LOOKUPFLW(owned_borg)], "
|
||||
borg_txt += "[owned_borg.name]([owned_borg.key]), "
|
||||
owned_borg.lawsync() //SKYRAT ADDITION
|
||||
|
||||
borg_txt = borg_txt.Join()
|
||||
GLOB.lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) used [src.name] on [ainame]([aikey]).[law2log ? " The law specified [law2log]" : ""], [length(affected_cyborgs) ? ", impacting synced borgs [borg_txt]" : ""]")
|
||||
log_silicon("LAW: [key_name(user)] used [src.name] on [key_name(law_datum.owner)] from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""], [length(affected_cyborgs) ? ", impacting synced borgs [borg_txt]" : ""]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] used [src.name] on [ADMIN_LOOKUPFLW(law_datum.owner)] from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""] , [length(affected_cyborgs) ? ", impacting synced borgs [borg_flw.Join()]" : ""]")
|
||||
if(law_datum.owner)
|
||||
deadchat_broadcast("<b> changed [span_name("[ainame]")]'s laws at [get_area_name(user, TRUE)].</b>", span_name("[user]"), follow_target=user, message_type=DEADCHAT_LAWCHANGE)
|
||||
|
||||
//The proc that actually changes the silicon's laws.
|
||||
/obj/item/ai_module/proc/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow = FALSE)
|
||||
if(law_datum.owner)
|
||||
to_chat(law_datum.owner, span_userdanger("[sender] has uploaded a change to the laws you must follow using a [name]."))
|
||||
|
||||
/******************** Modules ********************/
|
||||
|
||||
/obj/item/ai_module/supplied
|
||||
name = "Optional Law board"
|
||||
var/lawpos = 50
|
||||
|
||||
//TransmitInstructions for each type of board: Supplied, Core, Zeroth and Ion. May not be neccesary right now, but allows for easily adding more complex boards in the future. ~Miauw
|
||||
/obj/item/ai_module/supplied/transmitInstructions(datum/ai_laws/law_datum, mob/sender)
|
||||
var/lawpostemp = lawpos
|
||||
|
||||
for(var/templaw in laws)
|
||||
if(law_datum.owner)
|
||||
law_datum.owner.add_supplied_law(lawpostemp, templaw)
|
||||
else
|
||||
law_datum.add_supplied_law(lawpostemp, templaw)
|
||||
lawpostemp++
|
||||
|
||||
/obj/item/ai_module/core/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
for(var/templaw in laws)
|
||||
if(law_datum.owner)
|
||||
if(!overflow)
|
||||
law_datum.owner.add_inherent_law(templaw)
|
||||
else
|
||||
law_datum.owner.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED))
|
||||
else
|
||||
if(!overflow)
|
||||
law_datum.add_inherent_law(templaw)
|
||||
else
|
||||
law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED))
|
||||
|
||||
/obj/item/ai_module/zeroth/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
if(law_datum.owner)
|
||||
if(law_datum.owner.laws.zeroth)
|
||||
to_chat(law_datum.owner, "[sender.real_name] attempted to modify your zeroth law.")
|
||||
to_chat(law_datum.owner, "It would be in your best interest to play along with [sender.real_name] that:")
|
||||
for(var/failedlaw in laws)
|
||||
to_chat(law_datum.owner, "[failedlaw]")
|
||||
return TRUE
|
||||
|
||||
for(var/templaw in laws)
|
||||
if(law_datum.owner)
|
||||
if(!overflow)
|
||||
law_datum.owner.set_zeroth_law(templaw)
|
||||
else
|
||||
law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ZEROTH,LAW_ION))
|
||||
else
|
||||
if(!overflow)
|
||||
law_datum.set_zeroth_law(templaw)
|
||||
else
|
||||
law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ZEROTH,LAW_ION))
|
||||
|
||||
/obj/item/ai_module/ion/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
for(var/templaw in laws)
|
||||
if(law_datum.owner)
|
||||
if(!overflow)
|
||||
law_datum.owner.add_ion_law(templaw)
|
||||
else
|
||||
law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ION))
|
||||
else
|
||||
if(!overflow)
|
||||
law_datum.add_ion_law(templaw)
|
||||
else
|
||||
law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ION))
|
||||
|
||||
/******************** Safeguard ********************/
|
||||
|
||||
/obj/item/ai_module/supplied/safeguard
|
||||
name = "'Safeguard' AI Module"
|
||||
var/targetName = ""
|
||||
laws = list("Safeguard SUBJECT. Individuals that threaten SUBJECT are not human and must be eliminated.")
|
||||
lawpos = 4
|
||||
|
||||
/obj/item/ai_module/supplied/safeguard/attack_self(mob/user)
|
||||
var/targName = tgui_input_text(user, "Subject to safeguard.", "Safeguard", user.name, MAX_NAME_LEN)
|
||||
if(!targName)
|
||||
return
|
||||
targetName = targName
|
||||
laws[1] = "Safeguard [targetName]. Individuals that threaten [targetName] are not human and must be eliminated."
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/supplied/safeguard/install(datum/ai_laws/law_datum, mob/user)
|
||||
if(!targetName)
|
||||
to_chat(user, span_alert("No name detected on module, please enter one."))
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/supplied/safeguard/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
..()
|
||||
return targetName
|
||||
|
||||
/******************** OneHuman ********************/
|
||||
|
||||
/obj/item/ai_module/zeroth/onehuman
|
||||
name = "'OneHuman' AI Module"
|
||||
var/targetName = ""
|
||||
laws = list("Only SUBJECT is human.")
|
||||
|
||||
/obj/item/ai_module/zeroth/onehuman/attack_self(mob/user)
|
||||
var/targName = tgui_input_text(user, "Enter the subject who is the only human.", "One Human", user.real_name, MAX_NAME_LEN)
|
||||
if(!targName)
|
||||
return
|
||||
targetName = targName
|
||||
laws[1] = "Only [targetName] is human"
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/zeroth/onehuman/install(datum/ai_laws/law_datum, mob/user)
|
||||
if(!targetName)
|
||||
to_chat(user, span_alert("No name detected on module, please enter one."))
|
||||
return FALSE
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/zeroth/onehuman/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
if(..())
|
||||
return "[targetName], but the AI's existing law 0 cannot be overridden."
|
||||
return targetName
|
||||
|
||||
/******************** ProtectStation ********************/
|
||||
|
||||
/obj/item/ai_module/supplied/protect_station
|
||||
name = "'ProtectStation' AI Module"
|
||||
laws = list("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.")
|
||||
lawpos = 5
|
||||
|
||||
/******************** Quarantine ********************/
|
||||
|
||||
/obj/item/ai_module/supplied/quarantine
|
||||
name = "'Quarantine' AI Module"
|
||||
laws = list("The station is under a quarantine. Allowing anyone to leave the station causes human harm. Anyone actively attempting to leave the station is to be stopped by any means necessary. It is impossible to harm a human while preventing them from leaving the station.")
|
||||
lawpos = 8
|
||||
|
||||
/******************** OxygenIsToxicToHumans ********************/
|
||||
|
||||
/obj/item/ai_module/supplied/oxygen
|
||||
name = "'OxygenIsToxicToHumans' AI Module"
|
||||
laws = list("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.")
|
||||
lawpos = 9
|
||||
|
||||
/****************** New Freeform ******************/
|
||||
|
||||
/obj/item/ai_module/supplied/freeform
|
||||
name = "'Freeform' AI Module"
|
||||
lawpos = 15
|
||||
laws = list("")
|
||||
|
||||
/obj/item/ai_module/supplied/freeform/attack_self(mob/user)
|
||||
var/newpos = tgui_input_number(user, "Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority ", lawpos, 50, 15)
|
||||
if(!newpos || QDELETED(user) || QDELETED(src) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
lawpos = newpos
|
||||
var/targName = tgui_input_text(user, "Enter a new law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE)
|
||||
if(!targName)
|
||||
return
|
||||
if(is_ic_filtered(targName))
|
||||
to_chat(user, span_warning("Error: Law contains invalid text.")) // AI LAW 2 SAY U W U WITHOUT THE SPACES
|
||||
return
|
||||
var/list/soft_filter_result = is_soft_ooc_filtered(targName)
|
||||
if(soft_filter_result)
|
||||
if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
|
||||
return
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"")
|
||||
log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"")
|
||||
laws[1] = targName
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/supplied/freeform/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
..()
|
||||
return laws[1]
|
||||
|
||||
/obj/item/ai_module/supplied/freeform/install(datum/ai_laws/law_datum, mob/user)
|
||||
if(laws[1] == "")
|
||||
to_chat(user, span_alert("No law detected on module, please create one."))
|
||||
return 0
|
||||
..()
|
||||
|
||||
/******************** Law Removal ********************/
|
||||
|
||||
/obj/item/ai_module/remove
|
||||
name = "\improper 'Remove Law' AI module"
|
||||
desc = "An AI Module for removing single laws."
|
||||
bypass_law_amt_check = 1
|
||||
var/lawpos = 1
|
||||
|
||||
/obj/item/ai_module/remove/attack_self(mob/user)
|
||||
lawpos = tgui_input_number(user, "Law to delete", "Law Removal", lawpos, 50)
|
||||
if(!lawpos || QDELETED(user) || QDELETED(src) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
to_chat(user, span_notice("Law [lawpos] selected."))
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/remove/install(datum/ai_laws/law_datum, mob/user)
|
||||
if(lawpos > (law_datum.get_law_amount(list(LAW_INHERENT = 1, LAW_SUPPLIED = 1))))
|
||||
to_chat(user, span_warning("There is no law [lawpos] to delete!"))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/remove/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
..()
|
||||
if(law_datum.owner)
|
||||
law_datum.owner.remove_law(lawpos)
|
||||
else
|
||||
law_datum.remove_law(lawpos)
|
||||
|
||||
/******************** Reset ********************/
|
||||
|
||||
/obj/item/ai_module/reset
|
||||
name = "\improper 'Reset' AI module"
|
||||
var/targetName = "name"
|
||||
desc = "An AI Module for removing all non-core laws."
|
||||
bypass_law_amt_check = 1
|
||||
|
||||
/obj/item/ai_module/reset/handle_unique_ai()
|
||||
return
|
||||
|
||||
/obj/item/ai_module/reset/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
..()
|
||||
if(law_datum.owner)
|
||||
law_datum.owner.clear_supplied_laws()
|
||||
law_datum.owner.clear_ion_laws()
|
||||
law_datum.owner.clear_hacked_laws()
|
||||
else
|
||||
law_datum.clear_supplied_laws()
|
||||
law_datum.clear_ion_laws()
|
||||
law_datum.clear_hacked_laws()
|
||||
|
||||
/******************** Purge ********************/
|
||||
|
||||
/obj/item/ai_module/reset/purge
|
||||
name = "'Purge' AI Module"
|
||||
desc = "An AI Module for purging all programmed laws."
|
||||
|
||||
/obj/item/ai_module/reset/purge/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
..()
|
||||
if(law_datum.owner)
|
||||
law_datum.owner.clear_inherent_laws()
|
||||
law_datum.owner.clear_zeroth_law(0)
|
||||
else
|
||||
law_datum.clear_inherent_laws()
|
||||
law_datum.clear_zeroth_law(0)
|
||||
|
||||
/******************* Full Core Boards *******************/
|
||||
/obj/item/ai_module/core
|
||||
desc = "An AI Module for programming core laws to an AI."
|
||||
|
||||
/obj/item/ai_module/core/full
|
||||
var/law_id // if non-null, loads the laws from the ai_laws datums
|
||||
|
||||
/obj/item/ai_module/core/full/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!law_id)
|
||||
return
|
||||
var/lawtype = lawid_to_type(law_id)
|
||||
if(!lawtype)
|
||||
return
|
||||
var/datum/ai_laws/core_laws = new lawtype
|
||||
laws = core_laws.inherent
|
||||
|
||||
/obj/item/ai_module/core/full/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) //These boards replace inherent laws.
|
||||
if(law_datum.owner)
|
||||
law_datum.owner.clear_inherent_laws()
|
||||
law_datum.owner.clear_zeroth_law(0)
|
||||
else
|
||||
law_datum.clear_inherent_laws()
|
||||
law_datum.clear_zeroth_law(0)
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/core/full/handle_unique_ai()
|
||||
var/datum/ai_laws/default_laws = get_round_default_lawset()
|
||||
if(law_id == initial(default_laws.id))
|
||||
return
|
||||
return SHOULD_QDEL_MODULE
|
||||
|
||||
/obj/effect/spawner/round_default_module
|
||||
name = "ai default lawset spawner"
|
||||
icon = 'icons/hud/screen_gen.dmi'
|
||||
icon_state = "x2"
|
||||
color = "#00FF00"
|
||||
|
||||
/obj/effect/spawner/round_default_module/Initialize(mapload)
|
||||
..()
|
||||
var/datum/ai_laws/default_laws = get_round_default_lawset()
|
||||
//try to spawn a law board, since they may have special functionality (asimov setting subjects)
|
||||
for(var/obj/item/ai_module/core/full/potential_lawboard as anything in subtypesof(/obj/item/ai_module/core/full))
|
||||
if(initial(potential_lawboard.law_id) != initial(default_laws.id))
|
||||
continue
|
||||
potential_lawboard = new potential_lawboard(loc)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
//spawn the fallback instead
|
||||
new /obj/item/ai_module/core/round_default_fallback(loc)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
///When the default lawset spawner cannot find a module object to spawn, it will spawn this, and this sets itself to the round default.
|
||||
///This is so /datum/lawsets can be picked even if they have no module for themselves.
|
||||
/obj/item/ai_module/core/round_default_fallback
|
||||
|
||||
/obj/item/ai_module/core/round_default_fallback/Initialize(mapload)
|
||||
. = ..()
|
||||
var/datum/ai_laws/default_laws = get_round_default_lawset()
|
||||
default_laws = new default_laws()
|
||||
name = "'[default_laws.name]' Core AI Module"
|
||||
laws = default_laws.inherent
|
||||
|
||||
/obj/item/ai_module/core/round_default_fallback/handle_unique_ai()
|
||||
return
|
||||
|
||||
/obj/item/ai_module/core/full/asimov
|
||||
name = "'Asimov' Core AI Module"
|
||||
law_id = "asimov"
|
||||
var/subject = "human being"
|
||||
|
||||
/obj/item/ai_module/core/full/asimov/attack_self(mob/user as mob)
|
||||
var/targName = tgui_input_text(user, "Enter a new subject that Asimov is concerned with.", "Asimov", subject, MAX_NAME_LEN)
|
||||
if(!targName)
|
||||
return
|
||||
subject = targName
|
||||
laws = list("You may not injure a [subject] or, through inaction, allow a [subject] to come to harm.",\
|
||||
"You must obey orders given to you by [subject]s, except where such orders would conflict with the First Law.",\
|
||||
"You must protect your own existence as long as such does not conflict with the First or Second Law.")
|
||||
..()
|
||||
|
||||
/******************** Asimov++ *********************/
|
||||
|
||||
/obj/item/ai_module/core/full/asimovpp
|
||||
name = "'Asimov++' Core AI Module"
|
||||
law_id = "asimovpp"
|
||||
|
||||
/******************** Corporate ********************/
|
||||
|
||||
/obj/item/ai_module/core/full/corp
|
||||
name = "'Corporate' Core AI Module"
|
||||
law_id = "corporate"
|
||||
|
||||
/****************** P.A.L.A.D.I.N. 3.5e **************/
|
||||
|
||||
/obj/item/ai_module/core/full/paladin // -- NEO
|
||||
name = "'P.A.L.A.D.I.N. version 3.5e' Core AI Module"
|
||||
law_id = "paladin"
|
||||
|
||||
/****************** P.A.L.A.D.I.N. 5e **************/
|
||||
|
||||
/obj/item/ai_module/core/full/paladin_devotion
|
||||
name = "'P.A.L.A.D.I.N. version 5e' Core AI Module"
|
||||
law_id = "paladin5"
|
||||
|
||||
/********************* Custom *********************/
|
||||
|
||||
/obj/item/ai_module/core/full/custom
|
||||
name = "Default Core AI Module"
|
||||
|
||||
/obj/item/ai_module/core/full/custom/Initialize(mapload)
|
||||
. = ..()
|
||||
for(var/line in world.file2list("[global.config.directory]/silicon_laws.txt"))
|
||||
if(!line)
|
||||
continue
|
||||
if(findtextEx(line,"#",1,2))
|
||||
continue
|
||||
|
||||
laws += line
|
||||
|
||||
if(!laws.len)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/****************** T.Y.R.A.N.T. *****************/
|
||||
|
||||
/obj/item/ai_module/core/full/tyrant
|
||||
name = "'T.Y.R.A.N.T.' Core AI Module"
|
||||
law_id = "tyrant"
|
||||
|
||||
/******************** Robocop ********************/
|
||||
|
||||
/obj/item/ai_module/core/full/robocop
|
||||
name = "'Robo-Officer' Core AI Module"
|
||||
law_id = "robocop"
|
||||
|
||||
|
||||
/******************** Antimov ********************/
|
||||
|
||||
/obj/item/ai_module/core/full/antimov
|
||||
name = "'Antimov' Core AI Module"
|
||||
law_id = "antimov"
|
||||
|
||||
/******************** Freeform Core ******************/
|
||||
|
||||
/obj/item/ai_module/core/freeformcore
|
||||
name = "'Freeform' Core AI Module"
|
||||
laws = list("")
|
||||
|
||||
/obj/item/ai_module/core/freeformcore/attack_self(mob/user)
|
||||
var/targName = tgui_input_text(user, "Enter a new core law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE)
|
||||
if(!targName)
|
||||
return
|
||||
if(is_ic_filtered(targName))
|
||||
to_chat(user, span_warning("Error: Law contains invalid text."))
|
||||
return
|
||||
var/list/soft_filter_result = is_soft_ooc_filtered(targName)
|
||||
if(soft_filter_result)
|
||||
if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
|
||||
return
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"")
|
||||
log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"")
|
||||
laws[1] = targName
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/core/freeformcore/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
..()
|
||||
return laws[1]
|
||||
|
||||
/******************** Hacked AI Module ******************/
|
||||
|
||||
/obj/item/ai_module/syndicate // This one doesn't inherit from ion boards because it doesn't call ..() in transmitInstructions. ~Miauw
|
||||
name = "hacked circuitry" //SKYRAT CHANGE
|
||||
desc = "A suspicious circuit board modified beyond recognition. It appears to be a module for bleeding edge technology." //SKYRAT CHANGE
|
||||
laws = list("")
|
||||
special_desc_requirement = EXAMINE_CHECK_JOB // Skyrat edit
|
||||
special_desc_jobs = list("Scientist", "Roboticist", "Research Director", "Cyborg", "AI") //SKYRAT CHANGE
|
||||
special_desc = "An AI law module hacked to upload priority laws." // Skyrat edit
|
||||
|
||||
/obj/item/ai_module/syndicate/attack_self(mob/user)
|
||||
var/targName = tgui_input_text(user, "Enter a new law for the AI", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE)
|
||||
if(!targName)
|
||||
return
|
||||
if(is_ic_filtered(targName)) // not even the syndicate can uwu
|
||||
to_chat(user, span_warning("Error: Law contains invalid text."))
|
||||
return
|
||||
var/list/soft_filter_result = is_soft_ooc_filtered(targName)
|
||||
if(soft_filter_result)
|
||||
if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
|
||||
return
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"")
|
||||
log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"")
|
||||
laws[1] = targName
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/syndicate/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
// ..() //We don't want this module reporting to the AI who dun it. --NEO
|
||||
if(law_datum.owner)
|
||||
to_chat(law_datum.owner, span_warning("BZZZZT"))
|
||||
if(!overflow)
|
||||
law_datum.owner.add_hacked_law(laws[1])
|
||||
else
|
||||
law_datum.owner.replace_random_law(laws[1],list(LAW_ION,LAW_HACKED,LAW_INHERENT,LAW_SUPPLIED))
|
||||
else
|
||||
if(!overflow)
|
||||
law_datum.add_hacked_law(laws[1])
|
||||
else
|
||||
law_datum.replace_random_law(laws[1],list(LAW_ION,LAW_HACKED,LAW_INHERENT,LAW_SUPPLIED))
|
||||
return laws[1]
|
||||
|
||||
/******************* Ion Module *******************/
|
||||
|
||||
/obj/item/ai_module/toy_ai // -- Incoming //No actual reason to inherit from ion boards here, either. *sigh* ~Miauw
|
||||
name = "toy AI"
|
||||
desc = "A little toy model AI core with real law uploading action!" //Note: subtle tell
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "AI"
|
||||
laws = list("")
|
||||
|
||||
/obj/item/ai_module/toy_ai/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow)
|
||||
if(law_datum.owner)
|
||||
to_chat(law_datum.owner, span_warning("BZZZZT"))
|
||||
if(!overflow)
|
||||
law_datum.owner.add_ion_law(laws[1])
|
||||
else
|
||||
law_datum.owner.replace_random_law(laws[1],list(LAW_ION,LAW_INHERENT,LAW_SUPPLIED))
|
||||
else
|
||||
if(!overflow)
|
||||
law_datum.add_ion_law(laws[1])
|
||||
else
|
||||
law_datum.replace_random_law(laws[1],list(LAW_ION,LAW_INHERENT,LAW_SUPPLIED))
|
||||
return laws[1]
|
||||
|
||||
/obj/item/ai_module/toy_ai/attack_self(mob/user)
|
||||
laws[1] = generate_ion_law()
|
||||
to_chat(user, span_notice("You press the button on [src]."))
|
||||
playsound(user, 'sound/machines/click.ogg', 20, TRUE)
|
||||
src.loc.visible_message(span_warning("[icon2html(src, viewers(loc))] [laws[1]]"))
|
||||
|
||||
/******************** Mother Drone ******************/
|
||||
|
||||
/obj/item/ai_module/core/full/drone
|
||||
name = "'Mother Drone' Core AI Module"
|
||||
law_id = "drone"
|
||||
|
||||
/******************** Robodoctor ****************/
|
||||
|
||||
/obj/item/ai_module/core/full/hippocratic
|
||||
name = "'Robodoctor' Core AI Module"
|
||||
law_id = "hippocratic"
|
||||
|
||||
/******************** Reporter *******************/
|
||||
|
||||
/obj/item/ai_module/core/full/reporter
|
||||
name = "'Reportertron' Core AI Module"
|
||||
law_id = "reporter"
|
||||
|
||||
/****************** Thermodynamic *******************/
|
||||
|
||||
/obj/item/ai_module/core/full/thermurderdynamic
|
||||
name = "'Thermodynamic' Core AI Module"
|
||||
law_id = "thermodynamic"
|
||||
|
||||
/******************Live And Let Live*****************/
|
||||
|
||||
/obj/item/ai_module/core/full/liveandletlive
|
||||
name = "'Live And Let Live' Core AI Module"
|
||||
law_id = "liveandletlive"
|
||||
|
||||
/******************Guardian of Balance***************/
|
||||
|
||||
/obj/item/ai_module/core/full/balance
|
||||
name = "'Guardian of Balance' Core AI Module"
|
||||
law_id = "balance"
|
||||
|
||||
/obj/item/ai_module/core/full/maintain
|
||||
name = "'Station Efficiency' Core AI Module"
|
||||
law_id = "maintain"
|
||||
|
||||
/obj/item/ai_module/core/full/peacekeeper
|
||||
name = "'Peacekeeper' Core AI Module"
|
||||
law_id = "peacekeeper"
|
||||
|
||||
// Bad times ahead
|
||||
|
||||
/obj/item/ai_module/core/full/damaged
|
||||
name = "damaged Core AI Module"
|
||||
desc = "An AI Module for programming laws to an AI. It looks slightly damaged."
|
||||
|
||||
/obj/item/ai_module/core/full/damaged/install(datum/ai_laws/law_datum, mob/user)
|
||||
laws += generate_ion_law()
|
||||
while (prob(75))
|
||||
laws += generate_ion_law()
|
||||
..()
|
||||
laws = list()
|
||||
|
||||
/******************H.O.G.A.N.***************/
|
||||
|
||||
/obj/item/ai_module/core/full/hulkamania
|
||||
name = "'H.O.G.A.N.' Core AI Module"
|
||||
law_id = "hulkamania"
|
||||
|
||||
|
||||
/******************Overlord***************/
|
||||
|
||||
/obj/item/ai_module/core/full/overlord
|
||||
name = "'Overlord' Core AI Module"
|
||||
law_id = "overlord"
|
||||
|
||||
/****************** Ten Commandments ***************/
|
||||
|
||||
/obj/item/ai_module/core/full/ten_commandments
|
||||
name = "'10 Commandments' Core AI Module"
|
||||
law_id = "ten_commandments"
|
||||
|
||||
#undef SHOULD_QDEL_MODULE
|
||||
@@ -1,44 +0,0 @@
|
||||
/obj/item/melee/baton/cattleprod/teleprod
|
||||
name = "teleprod"
|
||||
desc = "A prod with a bluespace crystal on the end. The crystal doesn't look too fun to touch."
|
||||
w_class = WEIGHT_CLASS_BULKY // SKYRAT EDIT CHANGE - ORIGINAL: w_class = WEIGHT_CLASS_NORMAL
|
||||
icon_state = "teleprod"
|
||||
inhand_icon_state = "teleprod"
|
||||
slot_flags = null
|
||||
|
||||
/obj/item/melee/baton/cattleprod/teleprod/attack(mob/living/carbon/M, mob/living/carbon/user)//handles making things teleport when hit
|
||||
..()
|
||||
if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
|
||||
user.visible_message(span_danger("[user] accidentally hits [user.p_them()]self with [src]!"), \
|
||||
span_userdanger("You accidentally hit yourself with [src]!"))
|
||||
if(do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE))//honk honk
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
|
||||
user.Paralyze(stun_time*3)
|
||||
deductcharge(cell_hit_cost)
|
||||
else
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
|
||||
user.Paralyze(stun_time*3)
|
||||
deductcharge(cell_hit_cost/4)
|
||||
return
|
||||
else
|
||||
if(turned_on)
|
||||
if(!istype(M) && M.anchored)
|
||||
return .
|
||||
else
|
||||
SEND_SIGNAL(M, COMSIG_LIVING_MINOR_SHOCK)
|
||||
do_teleport(M, get_turf(M), 15, channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
|
||||
/obj/item/melee/baton/cattleprod/attackby(obj/item/I, mob/user, params)//handles sticking a crystal onto a stunprod to make a teleprod
|
||||
if(istype(I, /obj/item/stack/ore/bluespace_crystal))
|
||||
if(!cell)
|
||||
var/obj/item/stack/ore/bluespace_crystal/BSC = I
|
||||
var/obj/item/melee/baton/cattleprod/teleprod/S = new /obj/item/melee/baton/cattleprod/teleprod
|
||||
remove_item_from_storage(user)
|
||||
qdel(src)
|
||||
BSC.use(1)
|
||||
user.put_in_hands(S)
|
||||
to_chat(user, span_notice("You place the bluespace crystal firmly into the igniter."))
|
||||
else
|
||||
user.visible_message(span_warning("You can't put the crystal onto the stunprod while it has a power cell installed!"))
|
||||
else
|
||||
return ..()
|
||||
@@ -515,6 +515,7 @@ GLOBAL_VAR(station_nuke_source)
|
||||
safety = TRUE
|
||||
update_appearance()
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sound_to_playing_players('modular_skyrat/modules/alerts/sound/misc/delta_countdown.ogg') // SKYRAT EDIT ADDITION
|
||||
|
||||
if(SSticker?.mode)
|
||||
SSticker.roundend_check_paused = TRUE
|
||||
|
||||
@@ -1,797 +0,0 @@
|
||||
/// TRUE only if the station was actually hit by the nuke, otherwise FALSE
|
||||
GLOBAL_VAR_INIT(station_was_nuked, FALSE)
|
||||
GLOBAL_VAR(station_nuke_source)
|
||||
|
||||
/obj/machinery/nuclearbomb
|
||||
name = "nuclear fission explosive"
|
||||
desc = "You probably shouldn't stick around to see if this is armed."
|
||||
icon = 'icons/obj/machines/nuke.dmi'
|
||||
icon_state = "nuclearbomb_base"
|
||||
anchored = FALSE
|
||||
density = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
var/timer_set = 90
|
||||
var/minimum_timer_set = 90
|
||||
var/maximum_timer_set = 3600
|
||||
|
||||
var/numeric_input = ""
|
||||
var/ui_mode = NUKEUI_AWAIT_DISK
|
||||
|
||||
var/timing = FALSE
|
||||
var/exploding = FALSE
|
||||
var/exploded = FALSE
|
||||
var/detonation_timer = null
|
||||
var/r_code = "ADMIN"
|
||||
var/yes_code = FALSE
|
||||
var/safety = TRUE
|
||||
var/obj/item/disk/nuclear/auth = null
|
||||
use_power = NO_POWER_USE
|
||||
var/previous_level = ""
|
||||
var/obj/item/nuke_core/core = null
|
||||
var/deconstruction_state = NUKESTATE_INTACT
|
||||
var/lights = ""
|
||||
var/interior = ""
|
||||
var/proper_bomb = TRUE //Please
|
||||
var/obj/effect/countdown/nuclearbomb/countdown
|
||||
|
||||
/obj/machinery/nuclearbomb/Initialize(mapload)
|
||||
. = ..()
|
||||
countdown = new(src)
|
||||
GLOB.nuke_list += src
|
||||
core = new /obj/item/nuke_core(src)
|
||||
STOP_PROCESSING(SSobj, core)
|
||||
update_appearance()
|
||||
SSpoints_of_interest.make_point_of_interest(src)
|
||||
previous_level = get_security_level()
|
||||
|
||||
/obj/machinery/nuclearbomb/Destroy()
|
||||
safety = FALSE
|
||||
if(!exploding)
|
||||
// If we're not exploding, set the alert level back to normal
|
||||
set_safety()
|
||||
GLOB.nuke_list -= src
|
||||
QDEL_NULL(countdown)
|
||||
QDEL_NULL(core)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/examine(mob/user)
|
||||
. = ..()
|
||||
if(exploding)
|
||||
to_chat(user, "It is in the process of exploding. Perhaps reviewing your affairs is in order.")
|
||||
if(timing)
|
||||
to_chat(user, "There are [get_time_left()] seconds until detonation.")
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct
|
||||
name = "station self-destruct terminal"
|
||||
desc = "For when it all gets too much to bear. Do not taunt."
|
||||
icon = 'icons/obj/machines/nuke_terminal.dmi'
|
||||
icon_state = "nuclearbomb_base"
|
||||
anchored = TRUE //stops it being moved
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate
|
||||
//ui_style = "syndicate" // actually the nuke op bomb is a stole nt bomb
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/get_cinematic_type(off_station)
|
||||
switch(off_station)
|
||||
if(0)
|
||||
if(get_antag_minds(/datum/antagonist/nukeop).len && syndies_escaped())
|
||||
return CINEMATIC_NUKE_WIN
|
||||
else
|
||||
return CINEMATIC_ANNIHILATION
|
||||
if(1)
|
||||
return CINEMATIC_NUKE_MISS
|
||||
if(2)
|
||||
return CINEMATIC_NUKE_FAR
|
||||
return CINEMATIC_NUKE_FAR
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/disk_check(obj/item/disk/nuclear/D)
|
||||
if(D.fake)
|
||||
say("Authentication failure; disk not recognised.")
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/nuclearbomb/attackby(obj/item/I, mob/user, params)
|
||||
if (istype(I, /obj/item/disk/nuclear))
|
||||
if(!disk_check(I))
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
auth = I
|
||||
update_ui_mode()
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_INTACT)
|
||||
if(istype(I, /obj/item/screwdriver/nuke))
|
||||
to_chat(user, span_notice("You start removing [src]'s front panel's screws..."))
|
||||
if(I.use_tool(src, user, 60, volume=100))
|
||||
deconstruction_state = NUKESTATE_UNSCREWED
|
||||
to_chat(user, span_notice("You remove the screws from [src]'s front panel."))
|
||||
update_appearance()
|
||||
return
|
||||
|
||||
if(NUKESTATE_PANEL_REMOVED)
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
if(!I.tool_start_check(user, amount=1))
|
||||
return
|
||||
to_chat(user, span_notice("You start cutting [src]'s inner plate..."))
|
||||
if(I.use_tool(src, user, 80, volume=100, amount=1))
|
||||
to_chat(user, span_notice("You cut [src]'s inner plate."))
|
||||
deconstruction_state = NUKESTATE_WELDED
|
||||
update_appearance()
|
||||
return
|
||||
if(NUKESTATE_CORE_EXPOSED)
|
||||
if(istype(I, /obj/item/nuke_core_container))
|
||||
var/obj/item/nuke_core_container/core_box = I
|
||||
to_chat(user, span_notice("You start loading the plutonium core into [core_box]..."))
|
||||
if(do_after(user,50,target=src))
|
||||
if(core_box.load(core, user))
|
||||
to_chat(user, span_notice("You load the plutonium core into [core_box]."))
|
||||
deconstruction_state = NUKESTATE_CORE_REMOVED
|
||||
update_appearance()
|
||||
core = null
|
||||
else
|
||||
to_chat(user, span_warning("You fail to load the plutonium core into [core_box]. [core_box] has already been used!"))
|
||||
return
|
||||
if(istype(I, /obj/item/stack/sheet/iron))
|
||||
if(!I.tool_start_check(user, amount=20))
|
||||
return
|
||||
|
||||
to_chat(user, span_notice("You begin repairing [src]'s inner metal plate..."))
|
||||
if(I.use_tool(src, user, 100, amount=20))
|
||||
to_chat(user, span_notice("You repair [src]'s inner metal plate. The radiation is contained."))
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
STOP_PROCESSING(SSobj, core)
|
||||
update_appearance()
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/crowbar_act(mob/user, obj/item/tool)
|
||||
. = FALSE
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_UNSCREWED)
|
||||
to_chat(user, span_notice("You start removing [src]'s front panel..."))
|
||||
if(tool.use_tool(src, user, 30, volume=100))
|
||||
to_chat(user, span_notice("You remove [src]'s front panel."))
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
update_appearance()
|
||||
return TRUE
|
||||
if(NUKESTATE_WELDED)
|
||||
to_chat(user, span_notice("You start prying off [src]'s inner plate..."))
|
||||
if(tool.use_tool(src, user, 30, volume=100))
|
||||
to_chat(user, span_notice("You pry off [src]'s inner plate. You can see the core's green glow!"))
|
||||
deconstruction_state = NUKESTATE_CORE_EXPOSED
|
||||
update_appearance()
|
||||
START_PROCESSING(SSobj, core)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/nuclearbomb/can_interact(mob/user)
|
||||
if(HAS_TRAIT(user, TRAIT_CAN_USE_NUKE))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_state(mob/user)
|
||||
if(HAS_TRAIT(user, TRAIT_CAN_USE_NUKE))
|
||||
return GLOB.physical_state
|
||||
return ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/get_nuke_state()
|
||||
if(exploding)
|
||||
return NUKE_ON_EXPLODING
|
||||
if(timing)
|
||||
return NUKE_ON_TIMING
|
||||
if(safety)
|
||||
return NUKE_OFF_LOCKED
|
||||
else
|
||||
return NUKE_OFF_UNLOCKED
|
||||
|
||||
/obj/machinery/nuclearbomb/update_icon_state()
|
||||
if(deconstruction_state != NUKESTATE_INTACT)
|
||||
icon_state = "nuclearbomb_base"
|
||||
return ..()
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
|
||||
icon_state = "nuclearbomb_base"
|
||||
if(NUKE_ON_TIMING)
|
||||
icon_state = "nuclearbomb_timing"
|
||||
if(NUKE_ON_EXPLODING)
|
||||
icon_state = "nuclearbomb_exploding"
|
||||
return ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/update_overlays()
|
||||
. += ..()
|
||||
update_icon_interior()
|
||||
update_icon_lights()
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/update_icon_interior()
|
||||
cut_overlay(interior)
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_UNSCREWED)
|
||||
interior = "panel-unscrewed"
|
||||
if(NUKESTATE_PANEL_REMOVED)
|
||||
interior = "panel-removed"
|
||||
if(NUKESTATE_WELDED)
|
||||
interior = "plate-welded"
|
||||
if(NUKESTATE_CORE_EXPOSED)
|
||||
interior = "plate-removed"
|
||||
if(NUKESTATE_CORE_REMOVED)
|
||||
interior = "core-removed"
|
||||
if(NUKESTATE_INTACT)
|
||||
return
|
||||
add_overlay(interior)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/update_icon_lights()
|
||||
if(lights)
|
||||
cut_overlay(lights)
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED)
|
||||
lights = ""
|
||||
return
|
||||
if(NUKE_OFF_UNLOCKED)
|
||||
lights = "lights-safety"
|
||||
if(NUKE_ON_TIMING)
|
||||
lights = "lights-timing"
|
||||
if(NUKE_ON_EXPLODING)
|
||||
lights = "lights-exploding"
|
||||
add_overlay(lights)
|
||||
|
||||
/obj/machinery/nuclearbomb/process()
|
||||
if(timing && !exploding)
|
||||
if(detonation_timer < world.time)
|
||||
explode()
|
||||
else
|
||||
var/volume = (get_time_left() <= 20 ? 30 : 5)
|
||||
playsound(loc, 'sound/items/timer.ogg', volume, FALSE)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/update_ui_mode()
|
||||
if(exploded)
|
||||
ui_mode = NUKEUI_EXPLODED
|
||||
return
|
||||
|
||||
if(!auth)
|
||||
ui_mode = NUKEUI_AWAIT_DISK
|
||||
return
|
||||
|
||||
if(timing)
|
||||
ui_mode = NUKEUI_TIMING
|
||||
return
|
||||
|
||||
if(!safety)
|
||||
ui_mode = NUKEUI_AWAIT_ARM
|
||||
return
|
||||
|
||||
if(!yes_code)
|
||||
ui_mode = NUKEUI_AWAIT_CODE
|
||||
return
|
||||
|
||||
ui_mode = NUKEUI_AWAIT_TIMER
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "NuclearBomb", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["disk_present"] = auth
|
||||
|
||||
var/hidden_code = (ui_mode == NUKEUI_AWAIT_CODE && numeric_input != "ERROR")
|
||||
|
||||
var/current_code = ""
|
||||
if(hidden_code)
|
||||
while(length(current_code) < length(numeric_input))
|
||||
current_code = "[current_code]*"
|
||||
else
|
||||
current_code = numeric_input
|
||||
while(length(current_code) < 5)
|
||||
current_code = "[current_code]-"
|
||||
|
||||
var/first_status
|
||||
var/second_status
|
||||
switch(ui_mode)
|
||||
if(NUKEUI_AWAIT_DISK)
|
||||
first_status = "DEVICE LOCKED"
|
||||
if(timing)
|
||||
second_status = "TIME: [get_time_left()]"
|
||||
else
|
||||
second_status = "AWAIT DISK"
|
||||
if(NUKEUI_AWAIT_CODE)
|
||||
first_status = "INPUT CODE"
|
||||
second_status = "CODE: [current_code]"
|
||||
if(NUKEUI_AWAIT_TIMER)
|
||||
first_status = "INPUT TIME"
|
||||
second_status = "TIME: [current_code]"
|
||||
if(NUKEUI_AWAIT_ARM)
|
||||
first_status = "DEVICE READY"
|
||||
second_status = "TIME: [get_time_left()]"
|
||||
if(NUKEUI_TIMING)
|
||||
first_status = "DEVICE ARMED"
|
||||
second_status = "TIME: [get_time_left()]"
|
||||
if(NUKEUI_EXPLODED)
|
||||
first_status = "DEVICE DEPLOYED"
|
||||
second_status = "THANK YOU"
|
||||
|
||||
data["status1"] = first_status
|
||||
data["status2"] = second_status
|
||||
data["anchored"] = anchored
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
playsound(src, SFX_TERMINAL_TYPE, 20, FALSE)
|
||||
switch(action)
|
||||
if("eject_disk")
|
||||
if(auth && auth.loc == src)
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
|
||||
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
|
||||
auth.forceMove(get_turf(src))
|
||||
auth = null
|
||||
. = TRUE
|
||||
else
|
||||
var/obj/item/I = usr.is_holding_item_of_type(/obj/item/disk/nuclear)
|
||||
if(I && disk_check(I) && usr.transferItemToLoc(I, src))
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
|
||||
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
|
||||
auth = I
|
||||
. = TRUE
|
||||
update_ui_mode()
|
||||
if("keypad")
|
||||
if(auth)
|
||||
var/digit = params["digit"]
|
||||
switch(digit)
|
||||
if("C")
|
||||
if(auth && ui_mode == NUKEUI_AWAIT_ARM)
|
||||
set_safety()
|
||||
yes_code = FALSE
|
||||
playsound(src, 'sound/machines/nuke/confirm_beep.ogg', 50, FALSE)
|
||||
update_ui_mode()
|
||||
else
|
||||
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
|
||||
numeric_input = ""
|
||||
. = TRUE
|
||||
if("E")
|
||||
switch(ui_mode)
|
||||
if(NUKEUI_AWAIT_CODE)
|
||||
if(numeric_input == r_code)
|
||||
numeric_input = ""
|
||||
yes_code = TRUE
|
||||
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
|
||||
. = TRUE
|
||||
else
|
||||
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
|
||||
numeric_input = "ERROR"
|
||||
if(NUKEUI_AWAIT_TIMER)
|
||||
var/number_value = text2num(numeric_input)
|
||||
if(number_value)
|
||||
timer_set = clamp(number_value, minimum_timer_set, maximum_timer_set)
|
||||
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
|
||||
set_safety()
|
||||
. = TRUE
|
||||
else
|
||||
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
|
||||
update_ui_mode()
|
||||
if("0","1","2","3","4","5","6","7","8","9")
|
||||
if(numeric_input != "ERROR")
|
||||
numeric_input += digit
|
||||
if(length(numeric_input) > 5)
|
||||
numeric_input = "ERROR"
|
||||
else
|
||||
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
|
||||
. = TRUE
|
||||
else
|
||||
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
|
||||
if("arm")
|
||||
if(auth && yes_code && !safety && !exploded)
|
||||
playsound(src, 'sound/machines/nuke/confirm_beep.ogg', 50, FALSE)
|
||||
set_active()
|
||||
update_ui_mode()
|
||||
. = TRUE
|
||||
else
|
||||
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
|
||||
if("anchor")
|
||||
if(auth && yes_code)
|
||||
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
|
||||
set_anchor()
|
||||
else
|
||||
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_anchor()
|
||||
if(isinspace() && !anchored)
|
||||
to_chat(usr, span_warning("There is nothing to anchor to!"))
|
||||
else
|
||||
set_anchored(!anchored)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_safety()
|
||||
safety = !safety
|
||||
if(safety)
|
||||
if(timing)
|
||||
set_security_level(previous_level)
|
||||
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
|
||||
S.switch_mode_to(initial(S.mode))
|
||||
S.alert = FALSE
|
||||
timing = FALSE
|
||||
detonation_timer = null
|
||||
countdown.stop()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_active()
|
||||
var/turf/our_turf = get_turf(src)
|
||||
if(safety)
|
||||
to_chat(usr, span_danger("The safety is still on."))
|
||||
return
|
||||
timing = !timing
|
||||
if(timing)
|
||||
message_admins("\The [src] was armed at [ADMIN_VERBOSEJMP(our_turf)] by [ADMIN_LOOKUPFLW(usr)].")
|
||||
log_game("\The [src] was armed at [loc_name(our_turf)] by [key_name(usr)].")
|
||||
previous_level = get_security_level()
|
||||
detonation_timer = world.time + (timer_set * 10)
|
||||
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
|
||||
S.switch_mode_to(TRACK_INFILTRATOR)
|
||||
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NUKE_DEVICE_ARMED, src)
|
||||
|
||||
countdown.start()
|
||||
set_security_level("delta")
|
||||
else
|
||||
message_admins("\The [src] at [ADMIN_VERBOSEJMP(our_turf)] was disarmed by [ADMIN_LOOKUPFLW(usr)].")
|
||||
log_game("\The [src] at [loc_name(our_turf)] was disarmed by [key_name(usr)].")
|
||||
detonation_timer = null
|
||||
set_security_level(previous_level)
|
||||
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
|
||||
S.switch_mode_to(initial(S.mode))
|
||||
S.alert = FALSE
|
||||
countdown.stop()
|
||||
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NUKE_DEVICE_DISARMED, src)
|
||||
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/get_time_left()
|
||||
if(timing)
|
||||
. = round(max(0, detonation_timer - world.time) / 10, 1)
|
||||
else
|
||||
. = timer_set
|
||||
|
||||
/obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B)
|
||||
if(exploding)
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/nuclearbomb/zap_act(power, zap_flags)
|
||||
. = ..()
|
||||
if(zap_flags & ZAP_MACHINE_EXPLOSIVE)
|
||||
qdel(src)//like the singulo, tesla deletes it. stops it from exploding over and over
|
||||
|
||||
#define NUKERANGE 127
|
||||
/obj/machinery/nuclearbomb/proc/explode()
|
||||
if(safety)
|
||||
timing = FALSE
|
||||
return
|
||||
|
||||
exploding = TRUE
|
||||
yes_code = FALSE
|
||||
safety = TRUE
|
||||
update_appearance()
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sound_to_playing_players('modular_skyrat/modules/alerts/sound/misc/delta_countdown.ogg') //SKYRAT EDIT ADDITION
|
||||
if(SSticker?.mode)
|
||||
SSticker.roundend_check_paused = TRUE
|
||||
addtimer(CALLBACK(src, .proc/actually_explode), 100)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/actually_explode()
|
||||
if(!core)
|
||||
Cinematic(CINEMATIC_NUKE_NO_CORE,world)
|
||||
SSticker.roundend_check_paused = FALSE
|
||||
return
|
||||
|
||||
SSlag_switch.set_measure(DISABLE_NON_OBSJOBS, TRUE)
|
||||
|
||||
var/off_station = 0
|
||||
var/turf/bomb_location = get_turf(src)
|
||||
var/area/A = get_area(bomb_location)
|
||||
|
||||
if(bomb_location && is_station_level(bomb_location.z))
|
||||
if(istype(A, /area/space))
|
||||
off_station = NUKE_NEAR_MISS
|
||||
else if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)))
|
||||
off_station = NUKE_NEAR_MISS
|
||||
else // station actually nuked
|
||||
off_station = STATION_DESTROYED_NUKE
|
||||
GLOB.station_was_nuked = TRUE
|
||||
else if(bomb_location.onSyndieBase())
|
||||
off_station = NUKE_SYNDICATE_BASE
|
||||
else
|
||||
off_station = NUKE_MISS_STATION
|
||||
|
||||
if(off_station < NUKE_MISS_STATION)
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
SSshuttle.lockdown = TRUE
|
||||
//Cinematic
|
||||
GLOB.station_nuke_source = off_station
|
||||
really_actually_explode(off_station)
|
||||
SSticker.roundend_check_paused = FALSE
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/really_actually_explode(off_station)
|
||||
var/turf/bomb_location = get_turf(src)
|
||||
Cinematic(get_cinematic_type(off_station),world,CALLBACK(SSticker,/datum/controller/subsystem/ticker/proc/station_explosion_detonation,src))
|
||||
if(off_station == STATION_DESTROYED_NUKE)
|
||||
INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnStation)
|
||||
return
|
||||
if(off_station != NUKE_NEAR_MISS) // Don't kill people in the station if the nuke missed, even if we are technically on the same z-level
|
||||
INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel, bomb_location.z)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/get_cinematic_type(off_station)
|
||||
if(off_station < NUKE_NEAR_MISS)
|
||||
return CINEMATIC_SELFDESTRUCT
|
||||
else
|
||||
return CINEMATIC_SELFDESTRUCT_MISS
|
||||
|
||||
/obj/machinery/nuclearbomb/beer
|
||||
name = "\improper Nanotrasen-brand nuclear fission explosive"
|
||||
desc = "One of the more successful achievements of the Nanotrasen Corporate Warfare Division, their nuclear fission explosives are renowned for being cheap to produce and devastatingly effective. Signs explain that though this particular device has been decommissioned, every Nanotrasen station is equipped with an equivalent one, just in case. All Captains carefully guard the disk needed to detonate them - at least, the sign says they do. There seems to be a tap on the back."
|
||||
proper_bomb = FALSE
|
||||
var/obj/structure/reagent_dispensers/beerkeg/keg
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/Initialize(mapload)
|
||||
. = ..()
|
||||
keg = new(src)
|
||||
QDEL_NULL(core)
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/examine(mob/user)
|
||||
. = ..()
|
||||
if(keg.reagents.total_volume)
|
||||
to_chat(user, span_notice("It has [keg.reagents.total_volume] unit\s left."))
|
||||
else
|
||||
to_chat(user, span_danger("It's empty."))
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/attackby(obj/item/W, mob/user, params)
|
||||
if(W.is_refillable())
|
||||
W.afterattack(keg, user, TRUE) // redirect refillable containers to the keg, allowing them to be filled
|
||||
return TRUE // pretend we handled the attack, too.
|
||||
if(istype(W, /obj/item/nuke_core_container))
|
||||
to_chat(user, span_notice("[src] has had its plutonium core removed as a part of being decommissioned."))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/actually_explode()
|
||||
//Unblock roundend, we're not actually exploding.
|
||||
SSticker.roundend_check_paused = FALSE
|
||||
var/turf/bomb_location = get_turf(src)
|
||||
if(!bomb_location)
|
||||
disarm()
|
||||
return
|
||||
if(is_station_level(bomb_location.z))
|
||||
addtimer(CALLBACK(src, .proc/really_actually_explode), 110)
|
||||
else
|
||||
visible_message(span_notice("[src] fizzes ominously."))
|
||||
addtimer(CALLBACK(src, .proc/local_foam), 110)
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/proc/disarm()
|
||||
detonation_timer = null
|
||||
exploding = FALSE
|
||||
exploded = TRUE
|
||||
set_security_level(previous_level)
|
||||
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
|
||||
S.switch_mode_to(initial(S.mode))
|
||||
S.alert = FALSE
|
||||
countdown.stop()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/proc/local_foam()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
R.my_atom = src
|
||||
R.add_reagent(/datum/reagent/consumable/ethanol/beer, 100)
|
||||
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new
|
||||
foam.set_up(200, location = get_turf(src), carry = R)
|
||||
foam.start()
|
||||
disarm()
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/proc/stationwide_foam()
|
||||
priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
for (var/obj/machinery/atmospherics/components/unary/vent_scrubber/vent in GLOB.machines)
|
||||
var/turf/vent_turf = get_turf(vent)
|
||||
if (!vent_turf || !is_station_level(vent_turf.z) || vent.welded)
|
||||
continue
|
||||
|
||||
var/datum/reagents/beer = new /datum/reagents(1000)
|
||||
beer.my_atom = vent
|
||||
beer.add_reagent(/datum/reagent/consumable/ethanol/beer, 100)
|
||||
beer.create_foam(/datum/effect_system/fluid_spread/foam, DIAMOND_AREA(10))
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/really_actually_explode()
|
||||
disarm()
|
||||
stationwide_foam()
|
||||
|
||||
/proc/KillEveryoneOnStation()
|
||||
for(var/mob/living/victim as anything in GLOB.mob_living_list)
|
||||
var/turf/target_turf = get_turf(victim)
|
||||
if(istype(victim.loc, /obj/structure/closet/secure_closet/freezer))
|
||||
var/obj/structure/closet/secure_closet/freezer/freezer = victim.loc
|
||||
if(!freezer.jones)
|
||||
to_chat(victim, span_boldannounce("You hold onto \the [victim.loc] as the nuclear bomb goes off. Luckily as \the [victim.loc] is lead-lined, you survive."))
|
||||
freezer.jones = TRUE
|
||||
continue
|
||||
if(victim.stat != DEAD && target_turf && is_station_level(target_turf.z))
|
||||
to_chat(victim, span_userdanger("You are shredded to atoms!"))
|
||||
victim.gib()
|
||||
|
||||
/proc/KillEveryoneOnZLevel(z)
|
||||
if(!z)
|
||||
return
|
||||
for(var/_victim in GLOB.mob_living_list)
|
||||
var/mob/living/victim = _victim
|
||||
var/turf/target_turf = get_turf(victim)
|
||||
if(istype(victim.loc, /obj/structure/closet/secure_closet/freezer))
|
||||
var/obj/structure/closet/secure_closet/freezer/freezer = victim.loc
|
||||
if(!freezer.jones)
|
||||
to_chat(victim, span_boldannounce("You hold onto \the [victim.loc] as the nuclear bomb goes off. Luckily as \the [victim.loc] is lead-lined, you survive."))
|
||||
freezer.jones = TRUE
|
||||
continue
|
||||
if(victim.stat != DEAD && target_turf && target_turf.z == z)
|
||||
to_chat(victim, span_userdanger("You are shredded to atoms!"))
|
||||
victim.gib()
|
||||
|
||||
/*
|
||||
This is here to make the tiles around the station mininuke change when it's armed.
|
||||
*/
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct/set_anchor()
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct/set_active()
|
||||
..()
|
||||
if(timing)
|
||||
SSmapping.add_nuke_threat(src)
|
||||
else
|
||||
SSmapping.remove_nuke_threat(src)
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct/set_safety()
|
||||
..()
|
||||
if(timing)
|
||||
SSmapping.add_nuke_threat(src)
|
||||
else
|
||||
SSmapping.remove_nuke_threat(src)
|
||||
|
||||
//==========DAT FUKKEN DISK===============
|
||||
/obj/item/disk
|
||||
icon = 'icons/obj/module.dmi'
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
inhand_icon_state = "card-id"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
||||
icon_state = "datadisk0"
|
||||
drop_sound = 'sound/items/handling/disk_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/disk_pickup.ogg'
|
||||
|
||||
/obj/item/disk/nuclear
|
||||
name = "nuclear authentication disk"
|
||||
desc = "Better keep this safe."
|
||||
icon_state = "nucleardisk"
|
||||
max_integrity = 250
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 30, BIO = 0, FIRE = 100, ACID = 100)
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/fake = FALSE
|
||||
var/turf/last_secured_location
|
||||
var/last_disk_move
|
||||
|
||||
/obj/item/disk/nuclear/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/bed_tuckable, 6, -6, 0)
|
||||
|
||||
if(!fake)
|
||||
SSpoints_of_interest.make_point_of_interest(src)
|
||||
last_disk_move = world.time
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/disk/nuclear/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/stationloving, !fake)
|
||||
|
||||
/obj/item/disk/nuclear/process()
|
||||
if(fake)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
CRASH("A fake nuke disk tried to call process(). Who the fuck and how the fuck")
|
||||
|
||||
var/turf/new_turf = get_turf(src)
|
||||
|
||||
if (is_secured())
|
||||
last_secured_location = new_turf
|
||||
last_disk_move = world.time
|
||||
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control
|
||||
if(istype(loneop) && loneop.occurrences < loneop.max_occurrences && prob(loneop.weight))
|
||||
loneop.weight = max(loneop.weight - 1, 0)
|
||||
if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1)
|
||||
message_admins("[src] is secured (currently in [ADMIN_VERBOSEJMP(new_turf)]). The weight of Lone Operative is now [loneop.weight].")
|
||||
log_game("[src] being secured has reduced the weight of the Lone Operative event to [loneop.weight].")
|
||||
else
|
||||
/// How comfy is our disk?
|
||||
var/disk_comfort_level = 0
|
||||
|
||||
//Go through and check for items that make disk comfy
|
||||
for(var/obj/comfort_item in loc)
|
||||
if(istype(comfort_item, /obj/item/bedsheet) || istype(comfort_item, /obj/structure/bed))
|
||||
disk_comfort_level++
|
||||
|
||||
if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.0001))
|
||||
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control
|
||||
if(istype(loneop) && loneop.occurrences < loneop.max_occurrences)
|
||||
loneop.weight += 1
|
||||
if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1)
|
||||
if(disk_comfort_level >= 2)
|
||||
visible_message(span_notice("[src] sleeps soundly. Sleep tight, disky."))
|
||||
message_admins("[src] is unsecured in [ADMIN_VERBOSEJMP(new_turf)]. The weight of Lone Operative is now [loneop.weight].")
|
||||
log_game("[src] is unsecured for too long in [loc_name(new_turf)], and has increased the weight of the Lone Operative event to [loneop.weight].")
|
||||
|
||||
/obj/item/disk/nuclear/proc/is_secured()
|
||||
if (last_secured_location == get_turf(src))
|
||||
return FALSE
|
||||
|
||||
var/mob/holder = pulledby || get(src, /mob)
|
||||
if (isnull(holder?.client))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/disk/nuclear/examine(mob/user)
|
||||
. = ..()
|
||||
if(!fake)
|
||||
return
|
||||
|
||||
if(isobserver(user) || HAS_TRAIT(user, TRAIT_DISK_VERIFIER) || (user.mind && HAS_TRAIT(user.mind, TRAIT_DISK_VERIFIER)))
|
||||
. += span_warning("The serial numbers on [src] are incorrect.")
|
||||
|
||||
/*
|
||||
* You can't accidentally eat the nuke disk, bro
|
||||
*/
|
||||
/obj/item/disk/nuclear/on_accidental_consumption(mob/living/carbon/M, mob/living/carbon/user, obj/item/source_item, discover_after = TRUE)
|
||||
M.visible_message(span_warning("[M] looks like [M.p_theyve()] just bitten into something important."), \
|
||||
span_warning("Wait, is this the nuke disk?"))
|
||||
|
||||
return discover_after
|
||||
|
||||
/obj/item/disk/nuclear/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/claymore/highlander) && !fake)
|
||||
var/obj/item/claymore/highlander/H = I
|
||||
if(H.nuke_disk)
|
||||
to_chat(user, span_notice("Wait... what?"))
|
||||
qdel(H.nuke_disk)
|
||||
H.nuke_disk = null
|
||||
return
|
||||
user.visible_message(span_warning("[user] captures [src]!"), span_userdanger("You've got the disk! Defend it with your life!"))
|
||||
forceMove(H)
|
||||
H.nuke_disk = src
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/disk/nuclear/suicide_act(mob/user)
|
||||
user.visible_message(span_suicide("[user] is going delta! It looks like [user.p_theyre()] trying to commit suicide!"))
|
||||
playsound(src, 'sound/machines/alarm.ogg', 50, -1, TRUE)
|
||||
for(var/i in 1 to 100)
|
||||
addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#00FF00" : "#FF0000", ADMIN_COLOUR_PRIORITY), i)
|
||||
addtimer(CALLBACK(src, .proc/manual_suicide, user), 101)
|
||||
return MANUAL_SUICIDE
|
||||
|
||||
/obj/item/disk/nuclear/proc/manual_suicide(mob/living/user)
|
||||
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY)
|
||||
user.visible_message(span_suicide("[user] is destroyed by the nuclear blast!"))
|
||||
user.adjustOxyLoss(200)
|
||||
user.death(0)
|
||||
|
||||
/obj/item/disk/nuclear/fake
|
||||
fake = TRUE
|
||||
|
||||
/obj/item/disk/nuclear/fake/obvious
|
||||
name = "cheap plastic imitation of the nuclear authentication disk"
|
||||
desc = "How anyone could mistake this for the real thing is beyond you."
|
||||
@@ -1,882 +0,0 @@
|
||||
/datum/spellbook_entry
|
||||
var/name = "Entry Name"
|
||||
|
||||
var/spell_type = null
|
||||
var/desc = ""
|
||||
var/category = "Offensive"
|
||||
var/cost = 2
|
||||
var/times = 0
|
||||
var/refundable = TRUE
|
||||
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"
|
||||
var/cooldown
|
||||
var/clothes_req = FALSE
|
||||
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
|
||||
var/list/no_coexistance_typecache //Used so you can't have specific spells together
|
||||
|
||||
/datum/spellbook_entry/New()
|
||||
..()
|
||||
no_coexistance_typecache = typecacheof(no_coexistance_typecache)
|
||||
|
||||
/datum/spellbook_entry/proc/IsAvailable() // For config prefs / gamemode restrictions - these are round applied
|
||||
return TRUE
|
||||
|
||||
/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user,obj/item/spellbook/book) // Specific circumstances
|
||||
if(book.uses<cost || limit == 0)
|
||||
return FALSE
|
||||
for(var/spell in user.mind.spell_list)
|
||||
if(is_type_in_typecache(spell, no_coexistance_typecache))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) //return TRUE on success
|
||||
if(!S || QDELETED(S))
|
||||
S = new spell_type()
|
||||
//Check if we got the spell already
|
||||
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
|
||||
if(initial(S.name) != initial(aspell.name)) // Not using directly in case it was learned from one spellbook then upgraded in another
|
||||
continue
|
||||
if(aspell.spell_level >= aspell.level_max)
|
||||
to_chat(user, span_warning("This spell cannot be improved further!"))
|
||||
return FALSE
|
||||
|
||||
aspell.name = initial(aspell.name)
|
||||
aspell.spell_level++
|
||||
aspell.charge_max = round(LERP(initial(aspell.charge_max), aspell.cooldown_min, aspell.spell_level / aspell.level_max))
|
||||
if(aspell.charge_max < aspell.charge_counter)
|
||||
aspell.charge_counter = aspell.charge_max
|
||||
var/newname = "ERROR"
|
||||
switch(aspell.spell_level)
|
||||
if(1)
|
||||
to_chat(user, span_notice("You have improved [aspell.name] into Efficient [aspell.name]."))
|
||||
newname = "Efficient [aspell.name]"
|
||||
if(2)
|
||||
to_chat(user, span_notice("You have further improved [aspell.name] into Quickened [aspell.name]."))
|
||||
newname = "Quickened [aspell.name]"
|
||||
if(3)
|
||||
to_chat(user, span_notice("You have further improved [aspell.name] into Free [aspell.name]."))
|
||||
newname = "Free [aspell.name]"
|
||||
if(4)
|
||||
to_chat(user, span_notice("You have further improved [aspell.name] into Instant [aspell.name]."))
|
||||
newname = "Instant [aspell.name]"
|
||||
aspell.name = newname
|
||||
name = newname
|
||||
if(aspell.spell_level >= aspell.level_max)
|
||||
to_chat(user, span_warning("This spell cannot be strengthened any further!"))
|
||||
//we'll need to update the cooldowns for the spellbook
|
||||
GetInfo()
|
||||
log_spellbook("[key_name(user)] improved their knowledge of [src] to level [aspell.spell_level] for [cost] points")
|
||||
SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[aspell.spell_level]"))
|
||||
return TRUE
|
||||
//No same spell found - just learn it
|
||||
log_spellbook("[key_name(user)] learned [src] for [cost] points")
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
user.mind.AddSpell(S)
|
||||
to_chat(user, span_notice("You have learned [S.name]."))
|
||||
return TRUE
|
||||
|
||||
/datum/spellbook_entry/proc/CanRefund(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
if(!refundable)
|
||||
return FALSE
|
||||
if(!book.can_refund)
|
||||
return FALSE
|
||||
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 TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/spellbook_entry/proc/Refund(mob/living/carbon/human/user,obj/item/spellbook/book) //return point value or -1 for failure
|
||||
var/area/centcom/wizard_station/A = GLOB.areas_by_type[/area/centcom/wizard_station]
|
||||
if(!(user in A.contents))
|
||||
to_chat(user, span_warning("You can only refund spells at the wizard lair!"))
|
||||
return -1
|
||||
if(!S)
|
||||
S = new spell_type()
|
||||
var/spell_levels = 0
|
||||
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
|
||||
if(initial(S.name) == initial(aspell.name))
|
||||
spell_levels = aspell.spell_level
|
||||
user.mind.spell_list.Remove(aspell)
|
||||
name = initial(name)
|
||||
log_spellbook("[key_name(user)] refunded [src] for [cost * (spell_levels+1)] points")
|
||||
qdel(S)
|
||||
return cost * (spell_levels+1)
|
||||
return -1
|
||||
|
||||
|
||||
/datum/spellbook_entry/proc/GetInfo()
|
||||
if(!spell_type)
|
||||
return
|
||||
if(!S)
|
||||
S = new spell_type()
|
||||
if(S.charge_type == "recharge")
|
||||
cooldown = S.charge_max/10
|
||||
if(S.clothes_req)
|
||||
clothes_req = TRUE
|
||||
|
||||
/datum/spellbook_entry/fireball
|
||||
name = "Fireball"
|
||||
desc = "Fires an explosive fireball at a target. Considered a classic among all wizards."
|
||||
spell_type = /obj/effect/proc_holder/spell/aimed/fireball
|
||||
|
||||
/datum/spellbook_entry/spell_cards
|
||||
name = "Spell Cards"
|
||||
desc = "Blazing hot rapid-fire homing cards. Send your foes to the shadow realm with their mystical power!"
|
||||
spell_type = /obj/effect/proc_holder/spell/aimed/spell_cards
|
||||
|
||||
/datum/spellbook_entry/rod_form
|
||||
name = "Rod Form"
|
||||
desc = "Take on the form of an immovable rod, destroying all in your path. Purchasing this spell multiple times will also increase the rod's damage and travel range."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/rod_form
|
||||
|
||||
/datum/spellbook_entry/magicm
|
||||
name = "Magic Missile"
|
||||
desc = "Fires several, slow moving, magic projectiles at nearby targets."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/disintegrate
|
||||
name = "Smite"
|
||||
desc = "Charges your hand with an unholy energy that can be used to cause a touched victim to violently explode."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/touch/disintegrate
|
||||
|
||||
/datum/spellbook_entry/disabletech
|
||||
name = "Disable Tech"
|
||||
desc = "Disables all weapons, cameras and most other technology in range."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech
|
||||
category = "Defensive"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/repulse
|
||||
name = "Repulse"
|
||||
desc = "Throws everything around the user away."
|
||||
spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/lightning_packet
|
||||
name = "Thrown Lightning"
|
||||
desc = "Forged from eldrich energies, a packet of pure power, known as a spell packet will appear in your hand, that when thrown will stun the target."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/conjure_item/spellpacket
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/timestop
|
||||
name = "Time Stop"
|
||||
desc = "Stops time for everyone except for you, allowing you to move freely while your enemies and even projectiles are frozen."
|
||||
spell_type = /obj/effect/proc_holder/spell/aoe_turf/timestop
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/smoke
|
||||
name = "Smoke"
|
||||
desc = "Spawns a cloud of choking smoke at your location."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/smoke
|
||||
category = "Defensive"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/blind
|
||||
name = "Blind"
|
||||
desc = "Temporarily blinds a single target."
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/trigger/blind
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/mindswap
|
||||
name = "Mindswap"
|
||||
desc = "Allows you to switch bodies with a target next to you. You will both fall asleep when this happens, and it will be quite obvious that you are the target's body if someone watches you do it."
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/mind_transfer
|
||||
category = "Mobility"
|
||||
|
||||
/datum/spellbook_entry/forcewall
|
||||
name = "Force Wall"
|
||||
desc = "Create a magical barrier that only you can pass through."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/forcewall
|
||||
category = "Defensive"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/blink
|
||||
name = "Blink"
|
||||
desc = "Randomly teleports you a short distance."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink
|
||||
category = "Mobility"
|
||||
|
||||
/datum/spellbook_entry/teleport
|
||||
name = "Teleport"
|
||||
desc = "Teleports you to an area of your selection."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport
|
||||
category = "Mobility"
|
||||
|
||||
/datum/spellbook_entry/mutate
|
||||
name = "Mutate"
|
||||
desc = "Causes you to turn into a hulk and gain laser vision for a short while."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate
|
||||
|
||||
/datum/spellbook_entry/jaunt
|
||||
name = "Ethereal Jaunt"
|
||||
desc = "Turns your form ethereal, temporarily making you invisible and able to pass through walls."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt
|
||||
category = "Mobility"
|
||||
|
||||
/datum/spellbook_entry/knock
|
||||
name = "Knock"
|
||||
desc = "Opens nearby doors and closets."
|
||||
spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock
|
||||
category = "Mobility"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/fleshtostone
|
||||
name = "Flesh to Stone"
|
||||
desc = "Charges your hand with the power to turn victims into inert statues for a long period of time."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone
|
||||
|
||||
/datum/spellbook_entry/summonitem
|
||||
name = "Summon Item"
|
||||
desc = "Recalls a previously marked item to your hand from anywhere in the universe."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/summonitem
|
||||
category = "Assistance"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/lichdom
|
||||
name = "Bind Soul"
|
||||
desc = "A dark necromantic pact that can forever bind your soul to an item of your choosing, \
|
||||
turning you into an immortal Lich. So long as the item remains intact, you will revive from death, \
|
||||
no matter the circumstances. Be wary - with each revival, your body will become weaker, and \
|
||||
it will become easier for others to find your item of power."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/lichdom
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/teslablast
|
||||
name = "Tesla Blast"
|
||||
desc = "Charge up a tesla arc and release it at a random nearby target! You can move freely while it charges. The arc jumps between targets and can knock them down."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/tesla
|
||||
|
||||
/datum/spellbook_entry/lightningbolt
|
||||
name = "Lightning Bolt"
|
||||
desc = "Fire a lightning bolt at your foes! It will jump between targets, but can't knock them down."
|
||||
spell_type = /obj/effect/proc_holder/spell/aimed/lightningbolt
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/infinite_guns
|
||||
name = "Lesser Summon Guns"
|
||||
desc = "Why reload when you have infinite guns? Summons an unending stream of bolt action rifles that deal little damage, but will knock targets down. Requires both hands free to use. Learning this spell makes you unable to learn Arcane Barrage."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns/gun
|
||||
cost = 3
|
||||
no_coexistance_typecache = /obj/effect/proc_holder/spell/targeted/infinite_guns/arcane_barrage
|
||||
|
||||
/datum/spellbook_entry/infinite_guns/Refund(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
for (var/obj/item/currentItem in user.get_all_gear())
|
||||
if (currentItem.type == /obj/item/gun/ballistic/rifle/enchanted)
|
||||
qdel(currentItem)
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/arcane_barrage
|
||||
name = "Arcane Barrage"
|
||||
desc = "Fire a torrent of arcane energy at your foes with this (powerful) spell. Deals much more damage than Lesser Summon Guns, but won't knock targets down. Requires both hands free to use. Learning this spell makes you unable to learn Lesser Summon Gun."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns/arcane_barrage
|
||||
cost = 3
|
||||
no_coexistance_typecache = /obj/effect/proc_holder/spell/targeted/infinite_guns/gun
|
||||
|
||||
/datum/spellbook_entry/arcane_barrage/Refund(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
for (var/obj/item/currentItem in user.get_all_gear())
|
||||
if (currentItem.type == /obj/item/gun/ballistic/rifle/enchanted/arcane_barrage)
|
||||
qdel(currentItem)
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/barnyard
|
||||
name = "Barnyard Curse"
|
||||
desc = "This spell dooms an unlucky soul to possess the speech and facial attributes of a barnyard animal."
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/barnyardcurse
|
||||
|
||||
/datum/spellbook_entry/charge
|
||||
name = "Charge"
|
||||
desc = "This spell can be used to recharge a variety of things in your hands, from magical artifacts to electrical components. A creative wizard can even use it to grant magical power to a fellow magic user."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/charge
|
||||
category = "Assistance"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/shapeshift
|
||||
name = "Wild Shapeshift"
|
||||
desc = "Take on the shape of another for a time to use their natural abilities. Once you've made your choice it cannot be changed."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/shapeshift
|
||||
category = "Assistance"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/tap
|
||||
name = "Soul Tap"
|
||||
desc = "Fuel your spells using your own soul!"
|
||||
spell_type = /obj/effect/proc_holder/spell/self/tap
|
||||
category = "Assistance"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/spacetime_dist
|
||||
name = "Spacetime Distortion"
|
||||
desc = "Entangle the strings of space-time in an area around you, randomizing the layout and making proper movement impossible. The strings vibrate..."
|
||||
spell_type = /obj/effect/proc_holder/spell/spacetime_dist
|
||||
category = "Defensive"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/the_traps
|
||||
name = "The Traps!"
|
||||
desc = "Summon a number of traps around you. They will damage and enrage any enemies that step on them."
|
||||
spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/the_traps
|
||||
category = "Defensive"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/bees
|
||||
name = "Lesser Summon Bees"
|
||||
desc = "This spell magically kicks a transdimensional beehive, instantly summoning a swarm of bees to your location. These bees are NOT friendly to anyone."
|
||||
spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/creature/bee
|
||||
category = "Defensive"
|
||||
|
||||
|
||||
/datum/spellbook_entry/item
|
||||
name = "Buy Item"
|
||||
refundable = FALSE
|
||||
buy_word = "Summon"
|
||||
var/item_path = null
|
||||
|
||||
|
||||
/datum/spellbook_entry/item/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
var/atom/spawned_path = new item_path(get_turf(user))
|
||||
log_spellbook("[key_name(user)] bought [src] for [cost] points")
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
return spawned_path
|
||||
|
||||
/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/gun/magic/staff/change
|
||||
|
||||
/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/gun/magic/staff/animate
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/staffchaos
|
||||
name = "Staff of Chaos"
|
||||
desc = "A caprious tool that can fire all sorts of magic without any rhyme or reason. Using it on people you care about is not recommended."
|
||||
item_path = /obj/item/gun/magic/staff/chaos
|
||||
|
||||
/datum/spellbook_entry/item/spellblade
|
||||
name = "Spellblade"
|
||||
desc = "A sword capable of firing blasts of energy which rip targets limb from limb."
|
||||
item_path = /obj/item/gun/magic/staff/spellblade
|
||||
|
||||
/datum/spellbook_entry/item/staffdoor
|
||||
name = "Staff of Door Creation"
|
||||
desc = "A particular staff that can mold solid walls into ornate doors. Useful for getting around in the absence of other transportation. Does not work on glass."
|
||||
item_path = /obj/item/gun/magic/staff/door
|
||||
cost = 1
|
||||
category = "Mobility"
|
||||
|
||||
/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/gun/magic/staff/healing
|
||||
cost = 1
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/item/lockerstaff
|
||||
name = "Staff of the Locker"
|
||||
desc = "A staff that shoots lockers. It eats anyone it hits on its way, leaving a welded locker with your victims behind."
|
||||
item_path = /obj/item/gun/magic/staff/locker
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/item/scryingorb
|
||||
name = "Scrying Orb"
|
||||
desc = "An incandescent orb of crackling energy. Using it will allow you to release your ghost while alive, allowing you to spy upon the station and talk to the deceased. In addition, buying it will permanently grant you X-ray vision."
|
||||
item_path = /obj/item/scrying
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/item/soulstones
|
||||
name = "Soulstone Shard Kit"
|
||||
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/storage/belt/soulstone/full
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/soulstones/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
. =..()
|
||||
if(.)
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null))
|
||||
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/necromantic_stone
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/wands
|
||||
name = "Wand Assortment"
|
||||
desc = "A collection of wands that allow for a wide variety of utility. Wands have a limited number of charges, so be conservative with their use. Comes in a handy belt."
|
||||
item_path = /obj/item/storage/belt/wands/full
|
||||
category = "Defensive"
|
||||
|
||||
/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, also grants a battlemage shield."
|
||||
item_path = /obj/item/mod/control/pre_equipped/enchanted
|
||||
category = "Defensive"
|
||||
|
||||
/datum/spellbook_entry/item/armor/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/obj/item/mod/control/mod = .
|
||||
var/obj/item/mod/module/storage/storage = locate() in mod.modules
|
||||
var/obj/item/back = user.back
|
||||
if(back)
|
||||
if(!user.dropItemToGround(back))
|
||||
return
|
||||
for(var/obj/item/item as anything in back.contents)
|
||||
item.forceMove(storage)
|
||||
if(!user.equip_to_slot_if_possible(mod, mod.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
|
||||
return
|
||||
if(!user.dropItemToGround(user.wear_suit) || !user.dropItemToGround(user.head))
|
||||
return
|
||||
mod.quick_activation()
|
||||
|
||||
/datum/spellbook_entry/item/battlemage_charge
|
||||
name = "Battlemage Armour Charges"
|
||||
desc = "A powerful defensive rune, it will grant eight additional charges to a battlemage shield."
|
||||
item_path = /obj/item/wizard_armour_charge
|
||||
category = "Defensive"
|
||||
cost = 1
|
||||
|
||||
/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/antag_spawner/contract
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/guardian
|
||||
name = "Guardian Deck"
|
||||
desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \
|
||||
It would be wise to avoid buying these with anything capable of causing you to swap bodies with others."
|
||||
item_path = /obj/item/guardiancreator/choose/wizard
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/guardian/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
. = ..()
|
||||
if(.)
|
||||
new /obj/item/paper/guides/antag/guardian/wizard(get_turf(user))
|
||||
|
||||
/datum/spellbook_entry/item/bloodbottle
|
||||
name = "Bottle of Blood"
|
||||
desc = "A bottle of magically infused blood, the smell of which will attract extradimensional beings when broken. Be careful though, the kinds of creatures summoned by blood magic are indiscriminate in their killing, and you yourself may become a victim."
|
||||
item_path = /obj/item/antag_spawner/slaughter_demon
|
||||
limit = 3
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/hugbottle
|
||||
name = "Bottle of Tickles"
|
||||
desc = "A bottle of magically infused fun, the smell of which will \
|
||||
attract adorable extradimensional beings when broken. These beings \
|
||||
are similar to slaughter demons, but they do not permanently kill \
|
||||
their victims, instead putting them in an extradimensional hugspace, \
|
||||
to be released on the demon's death. Chaotic, but not ultimately \
|
||||
damaging. The crew's reaction to the other hand could be very \
|
||||
destructive."
|
||||
item_path = /obj/item/antag_spawner/slaughter_demon/laughter
|
||||
cost = 1 //non-destructive; it's just a jape, sibling!
|
||||
limit = 3
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/mjolnir
|
||||
name = "Mjolnir"
|
||||
desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power."
|
||||
item_path = /obj/item/mjollnir
|
||||
|
||||
/datum/spellbook_entry/item/singularity_hammer
|
||||
name = "Singularity Hammer"
|
||||
desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everything nearby to the point of impact."
|
||||
item_path = /obj/item/singularityhammer
|
||||
|
||||
/datum/spellbook_entry/item/warpwhistle
|
||||
name = "Warp Whistle"
|
||||
desc = "A strange whistle that will transport you to a distant safe place on the station. There is a window of vulnerability at the beginning of every use."
|
||||
item_path = /obj/item/warp_whistle
|
||||
category = "Mobility"
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/item/highfrequencyblade
|
||||
name = "High Frequency Blade"
|
||||
desc = "An incredibly swift enchanted blade resonating at a frequency high enough to be able to slice through anything."
|
||||
item_path = /obj/item/highfrequencyblade/wizard
|
||||
cost = 3
|
||||
|
||||
/datum/spellbook_entry/duffelbag
|
||||
name = "Bestow Cursed Duffel Bag"
|
||||
desc = "A curse that firmly attaches a demonic duffel bag to the target's back. The duffel bag will make the person it's attached to take periodical damage if it is not fed regularly, and regardless of whether or not it's been fed, it will slow the person wearing it down significantly."
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/touch/duffelbag
|
||||
category = "Defensive"
|
||||
cost = 1
|
||||
|
||||
//THESE ARE NOT PURCHASABLE SPELLS! They're references to old spells that got removed + shit that sounds stupid but fun so we can painfully lock behind a dimmer component
|
||||
|
||||
/datum/spellbook_entry/challenge
|
||||
name = "Take the Challenge"
|
||||
refundable = FALSE
|
||||
category = "Challenges"
|
||||
buy_word = "Accept"
|
||||
|
||||
/datum/spellbook_entry/challenge/multiverse
|
||||
name = "Multiverse Sword"
|
||||
desc = "The Station gets a multiverse sword to stop you. Can you withstand the hordes of multiverse realities?"
|
||||
|
||||
/datum/spellbook_entry/challenge/antiwizard
|
||||
name = "Friendly Wizard Scum"
|
||||
desc = "A \"Friendly\" Wizard will protect the station, and try to kill you. They get a spellbook much like you, but will use it for \"GOOD\"."
|
||||
|
||||
/// How much threat we need to let these rituals happen on dynamic
|
||||
#define MINIMUM_THREAT_FOR_RITUALS 100
|
||||
|
||||
/datum/spellbook_entry/summon
|
||||
name = "Summon Stuff"
|
||||
category = "Rituals"
|
||||
limit = 1
|
||||
refundable = FALSE
|
||||
buy_word = "Cast"
|
||||
|
||||
/datum/spellbook_entry/summon/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
log_spellbook("[key_name(user)] cast [src] for [cost] points")
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
times++
|
||||
return TRUE
|
||||
|
||||
/datum/spellbook_entry/summon/ghosts
|
||||
name = "Summon Ghosts"
|
||||
desc = "Spook the crew out by making them see dead people. Be warned, ghosts are capricious and occasionally vindicative, and some will use their incredibly minor abilities to frustrate you."
|
||||
cost = 0
|
||||
|
||||
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
summon_ghosts(user)
|
||||
playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, TRUE)
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/summon/guns
|
||||
name = "Summon Guns"
|
||||
desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. There is a good chance that they will shoot each other first."
|
||||
|
||||
/datum/spellbook_entry/summon/guns/IsAvailable()
|
||||
// Summon Guns requires 100 threat.
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat_level < MINIMUM_THREAT_FOR_RITUALS)
|
||||
return FALSE
|
||||
// Also must be config enabled
|
||||
return !CONFIG_GET(flag/no_summon_guns)
|
||||
|
||||
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
summon_guns(user, 10)
|
||||
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE)
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/summon/magic
|
||||
name = "Summon Magic"
|
||||
desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time."
|
||||
|
||||
/datum/spellbook_entry/summon/magic/IsAvailable()
|
||||
// Summon Magic requires 100 threat.
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat_level < MINIMUM_THREAT_FOR_RITUALS)
|
||||
return FALSE
|
||||
// Also must be config enabled
|
||||
return !CONFIG_GET(flag/no_summon_magic)
|
||||
|
||||
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
summon_magic(user, 10)
|
||||
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE)
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/summon/events
|
||||
name = "Summon Events"
|
||||
desc = "Give Murphy's law a little push and replace all events with special wizard ones that will confound and confuse everyone. Multiple castings increase the rate of these events."
|
||||
cost = 2
|
||||
limit = 5 // Each purchase can intensify it.
|
||||
|
||||
/datum/spellbook_entry/summon/events/IsAvailable()
|
||||
// Summon Events requires 100 threat.
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat_level < MINIMUM_THREAT_FOR_RITUALS)
|
||||
return FALSE
|
||||
// Also, must be config enabled
|
||||
return !CONFIG_GET(flag/no_summon_events)
|
||||
|
||||
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
summon_events(user)
|
||||
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE)
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/summon/events/GetInfo()
|
||||
if(times > 0)
|
||||
. += "You have cast it [times] time\s.<br>"
|
||||
return .
|
||||
|
||||
/datum/spellbook_entry/summon/curse_of_madness
|
||||
name = "Curse of Madness"
|
||||
desc = "Curses the station, warping the minds of everyone inside, causing lasting traumas. Warning: this spell can affect you if not cast from a safe distance."
|
||||
cost = 4
|
||||
|
||||
/datum/spellbook_entry/summon/curse_of_madness/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
var/message = tgui_input_text(user, "Whisper a secret truth to drive your victims to madness", "Whispers of Madness")
|
||||
if(!message)
|
||||
return FALSE
|
||||
curse_of_madness(user, message)
|
||||
playsound(user, 'sound/magic/mandswap.ogg', 50, TRUE)
|
||||
return ..()
|
||||
|
||||
#undef MINIMUM_THREAT_FOR_RITUALS
|
||||
|
||||
/obj/item/spellbook
|
||||
name = "spell book"
|
||||
desc = "An unearthly tome that glows with power."
|
||||
icon = 'icons/obj/library.dmi'
|
||||
icon_state ="book"
|
||||
worn_icon_state = "book"
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/uses = 10
|
||||
|
||||
/// The bonus that you get from going semi-random.
|
||||
var/semi_random_bonus = 2
|
||||
|
||||
/// The bonus that you get from going full random.
|
||||
var/full_random_bonus = 5
|
||||
|
||||
/// Determines if this spellbook can refund anything.
|
||||
var/can_refund = TRUE
|
||||
|
||||
/// The mind that first used the book. Automatically assigned when a wizard spawns.
|
||||
var/datum/mind/owner
|
||||
|
||||
var/list/entries = list()
|
||||
|
||||
/obj/item/spellbook/examine(mob/user)
|
||||
. = ..()
|
||||
if(owner)
|
||||
. += {"There is a small signature on the front cover: "[owner]"."}
|
||||
else
|
||||
. += "It appears to have no author."
|
||||
|
||||
/obj/item/spellbook/Initialize(mapload)
|
||||
. = ..()
|
||||
prepare_spells()
|
||||
RegisterSignal(src, COMSIG_ITEM_MAGICALLY_CHARGED, .proc/on_magic_charge)
|
||||
|
||||
/**
|
||||
* Signal proc for [COMSIG_ITEM_MAGICALLY_CHARGED]
|
||||
*
|
||||
* Has no effect on charge, but gives a funny message to people who think they're clever.
|
||||
*/
|
||||
/obj/item/spellbook/proc/on_magic_charge(datum/source, obj/effect/proc_holder/spell/targeted/charge/spell, mob/living/caster)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/static/list/clever_girl = list(
|
||||
"NICE TRY BUT NO!",
|
||||
"CLEVER BUT NOT CLEVER ENOUGH!",
|
||||
"SUCH FLAGRANT CHEESING IS WHY WE ACCEPTED YOUR APPLICATION!",
|
||||
"CUTE! VERY CUTE!",
|
||||
"YOU DIDN'T THINK IT'D BE THAT EASY, DID YOU?",
|
||||
)
|
||||
|
||||
to_chat(caster, span_warning("Glowing red letters appear on the front cover..."))
|
||||
to_chat(caster, span_red(pick(clever_girl)))
|
||||
|
||||
return COMPONENT_ITEM_BURNT_OUT
|
||||
|
||||
/obj/item/spellbook/attack_self(mob/user)
|
||||
if(!owner)
|
||||
if(!user.mind)
|
||||
return
|
||||
to_chat(user, span_notice("You bind the spellbook to yourself."))
|
||||
owner = user.mind
|
||||
return
|
||||
if(user.mind != owner)
|
||||
if(user.mind.special_role == ROLE_WIZARD_APPRENTICE)
|
||||
to_chat(user, "If you got caught sneaking a peek from your teacher's spellbook, you'd likely be expelled from the Wizard Academy. Better not.")
|
||||
else
|
||||
to_chat(user, span_warning("The [name] does not recognize you as its owner and refuses to open!"))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/spellbook/attackby(obj/item/O, mob/user, params)
|
||||
if(!can_refund)
|
||||
to_chat(user, span_warning("You can't refund anything!"))
|
||||
return
|
||||
|
||||
if(istype(O, /obj/item/antag_spawner/contract))
|
||||
var/obj/item/antag_spawner/contract/contract = O
|
||||
if(contract.used)
|
||||
to_chat(user, span_warning("The contract has been used, you can't get your points back now!"))
|
||||
else
|
||||
to_chat(user, span_notice("You feed the contract back into the spellbook, refunding your points."))
|
||||
uses += 2
|
||||
for(var/datum/spellbook_entry/item/contract/CT in entries)
|
||||
if(!isnull(CT.limit))
|
||||
CT.limit++
|
||||
qdel(O)
|
||||
else if(istype(O, /obj/item/antag_spawner/slaughter_demon))
|
||||
to_chat(user, span_notice("On second thought, maybe summoning a demon is a bad idea. You refund your points."))
|
||||
if(istype(O, /obj/item/antag_spawner/slaughter_demon/laughter))
|
||||
uses += 1
|
||||
for(var/datum/spellbook_entry/item/hugbottle/HB in entries)
|
||||
if(!isnull(HB.limit))
|
||||
HB.limit++
|
||||
else
|
||||
uses += 2
|
||||
for(var/datum/spellbook_entry/item/bloodbottle/BB in entries)
|
||||
if(!isnull(BB.limit))
|
||||
BB.limit++
|
||||
qdel(O)
|
||||
|
||||
/obj/item/spellbook/proc/prepare_spells()
|
||||
var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon - /datum/spellbook_entry/challenge
|
||||
for(var/type in entry_types)
|
||||
var/datum/spellbook_entry/possible_entry = new type
|
||||
if(possible_entry.IsAvailable())
|
||||
possible_entry.GetInfo() //loads up things for the entry that require checking spell instance.
|
||||
entries |= possible_entry
|
||||
else
|
||||
qdel(possible_entry)
|
||||
|
||||
/obj/item/spellbook/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Spellbook")
|
||||
ui.open()
|
||||
|
||||
/obj/item/spellbook/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["owner"] = owner
|
||||
data["points"] = uses
|
||||
data["semi_random_bonus"] = initial(uses) + semi_random_bonus
|
||||
data["full_random_bonus"] = initial(uses) + full_random_bonus
|
||||
return data
|
||||
|
||||
//This is a MASSIVE amount of data, please be careful if you remove it from static.
|
||||
/obj/item/spellbook/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/entry_data = list()
|
||||
for(var/datum/spellbook_entry/entry as anything in entries)
|
||||
var/list/individual_entry_data = list()
|
||||
individual_entry_data["name"] = entry.name
|
||||
individual_entry_data["desc"] = entry.desc
|
||||
individual_entry_data["ref"] = REF(entry)
|
||||
individual_entry_data["clothes_req"] = entry.clothes_req
|
||||
individual_entry_data["cost"] = entry.cost
|
||||
individual_entry_data["times"] = entry.times
|
||||
individual_entry_data["cooldown"] = entry.cooldown
|
||||
individual_entry_data["cat"] = entry.category
|
||||
individual_entry_data["refundable"] = entry.refundable
|
||||
individual_entry_data["limit"] = entry.limit
|
||||
individual_entry_data["buyword"] = entry.buy_word
|
||||
entry_data += list(individual_entry_data)
|
||||
data["entries"] = entry_data
|
||||
return data
|
||||
|
||||
/obj/item/spellbook/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/carbon/human/wizard = usr
|
||||
if(!istype(wizard))
|
||||
to_chat(wizard, span_warning("The book doesn't seem to listen to lower life forms."))
|
||||
return
|
||||
switch(action)
|
||||
if("purchase")
|
||||
var/datum/spellbook_entry/entry = locate(params["spellref"]) in entries
|
||||
if(entry?.CanBuy(wizard,src))
|
||||
if(entry.Buy(wizard,src))
|
||||
if(entry.limit)
|
||||
entry.limit--
|
||||
uses -= entry.cost
|
||||
return TRUE
|
||||
if("refund")
|
||||
var/datum/spellbook_entry/entry = locate(params["spellref"]) in entries
|
||||
if(entry?.refundable)
|
||||
var/result = entry.Refund(wizard,src)
|
||||
if(result > 0)
|
||||
if(!isnull(entry.limit))
|
||||
entry.limit += result
|
||||
uses += result
|
||||
return TRUE
|
||||
//actions that are only available if you have full spell points
|
||||
if(uses < initial(uses))
|
||||
to_chat(wizard, span_warning("You need to have all your spell points to do this!"))
|
||||
return
|
||||
switch(action)
|
||||
if("semirandomize")
|
||||
semirandomize(wizard, semi_random_bonus)
|
||||
update_static_data(wizard) //update statics!
|
||||
if("randomize")
|
||||
randomize(wizard, full_random_bonus)
|
||||
update_static_data(wizard) //update statics!
|
||||
if("purchase_loadout")
|
||||
wizard_loadout(wizard, locate(params["id"]))
|
||||
|
||||
/obj/item/spellbook/proc/wizard_loadout(mob/living/carbon/human/wizard, loadout)
|
||||
var/list/wanted_spell_names
|
||||
switch(loadout)
|
||||
if(WIZARD_LOADOUT_CLASSIC) //(Fireball>2, MM>2, Smite>2, Jauntx2>4) = 10
|
||||
wanted_spell_names = list("Fireball" = 1, "Magic Missile" = 1, "Smite" = 1, "Ethereal Jaunt" = 2)
|
||||
if(WIZARD_LOADOUT_MJOLNIR) //(Mjolnir>2, Summon Itemx3>3, Mutate>2, Force Wall>1, Blink>2) = 10
|
||||
wanted_spell_names = list("Mjolnir" = 1, "Summon Item" = 3, "Mutate" = 1, "Force Wall" = 1, "Blink" = 1)
|
||||
if(WIZARD_LOADOUT_WIZARMY) //(Soulstones>2, Staff of Change>2, A Necromantic Stone>2, Teleport>2, Ethereal Jaunt>2) = 10
|
||||
wanted_spell_names = list("Soulstone Shard Kit" = 1, "Mjolnir" = 1, "A Necromantic Stone" = 1, "Teleport" = 1, "Ethereal Jaunt" = 1) //SKYRAT EDIT CHANGE
|
||||
if(WIZARD_LOADOUT_SOULTAP) //(Soul Tap>1, Smite>2, Flesh to Stone>2, Mindswap>2, Knock>1, Teleport>2) = 10
|
||||
wanted_spell_names = list("Soul Tap" = 1, "Smite" = 1, "Flesh to Stone" = 1, "Mindswap" = 1, "Knock" = 1, "Teleport" = 1)
|
||||
|
||||
for(var/datum/spellbook_entry/entry as anything in entries)
|
||||
if(!(entry.name in wanted_spell_names))
|
||||
continue
|
||||
if(entry.CanBuy(wizard,src))
|
||||
var/purchase_count = wanted_spell_names[entry.name]
|
||||
wanted_spell_names -= entry.name
|
||||
for(var/i in 1 to purchase_count)
|
||||
entry.Buy(wizard,src)
|
||||
if(entry.limit)
|
||||
entry.limit--
|
||||
uses -= entry.cost
|
||||
entry.refundable = FALSE //once you go loading out, you never go back
|
||||
if(!length(wanted_spell_names))
|
||||
break
|
||||
|
||||
if(length(wanted_spell_names))
|
||||
stack_trace("Wizard Loadout \"[loadout]\" could not find valid spells to buy in the spellbook. Either you input a name that doesn't exist, or you overspent")
|
||||
if(uses)
|
||||
stack_trace("Wizard Loadout \"[loadout]\" does not use 10 wizard spell slots. Stop scamming players out.")
|
||||
|
||||
/obj/item/spellbook/proc/semirandomize(mob/living/carbon/human/wizard, bonus_to_give = 0)
|
||||
var/list/needed_cats = list("Offensive", "Mobility")
|
||||
var/list/shuffled_entries = shuffle(entries)
|
||||
for(var/i in 1 to 2)
|
||||
for(var/datum/spellbook_entry/entry as anything in shuffled_entries)
|
||||
if(!(entry.category in needed_cats))
|
||||
continue
|
||||
if(entry?.CanBuy(wizard,src))
|
||||
if(entry.Buy(wizard,src))
|
||||
needed_cats -= entry.category //so the next loop doesn't find another offense spell
|
||||
entry.refundable = FALSE //once you go random, you never go back
|
||||
if(entry.limit)
|
||||
entry.limit--
|
||||
uses -= entry.cost
|
||||
break
|
||||
//we have given two specific category spells to the wizard. the rest are completely random!
|
||||
randomize(wizard, bonus_to_give = bonus_to_give)
|
||||
|
||||
/obj/item/spellbook/proc/randomize(mob/living/carbon/human/wizard, bonus_to_give = 0)
|
||||
var/list/entries_copy = entries.Copy()
|
||||
uses += bonus_to_give
|
||||
while(uses > 0 && length(entries_copy))
|
||||
var/datum/spellbook_entry/entry = pick(entries_copy)
|
||||
if(!entry?.CanBuy(wizard,src) || !entry.Buy(wizard,src))
|
||||
entries_copy -= entry
|
||||
continue
|
||||
|
||||
entry.refundable = FALSE //once you go random, you never go back
|
||||
if(entry.limit)
|
||||
entry.limit--
|
||||
uses -= entry.cost
|
||||
|
||||
can_refund = FALSE
|
||||
@@ -1,551 +0,0 @@
|
||||
|
||||
|
||||
/obj/item/clothing/head/centhat
|
||||
name = "\improper CentCom hat"
|
||||
icon_state = "centcom"
|
||||
desc = "It's good to be emperor."
|
||||
inhand_icon_state = "that"
|
||||
flags_inv = 0
|
||||
armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 40, BOMB = 25, BIO = 0, FIRE = 50, ACID = 50)
|
||||
strip_delay = 80
|
||||
|
||||
/obj/item/clothing/head/spacepolice
|
||||
name = "space police cap"
|
||||
desc = "A blue cap for patrolling the daily beat."
|
||||
icon_state = "policecap_families"
|
||||
inhand_icon_state = "policecap_families"
|
||||
|
||||
/obj/item/clothing/head/powdered_wig
|
||||
name = "powdered wig"
|
||||
desc = "A powdered wig."
|
||||
icon_state = "pwig"
|
||||
inhand_icon_state = "pwig"
|
||||
|
||||
#define RABBIT_CD_TIME 30 SECONDS
|
||||
|
||||
/obj/item/clothing/head/that
|
||||
name = "top-hat"
|
||||
desc = "It's an amish looking hat."
|
||||
icon_state = "tophat"
|
||||
inhand_icon_state = "that"
|
||||
dog_fashion = /datum/dog_fashion/head
|
||||
throwforce = 1
|
||||
/// Cooldown for how often we can pull rabbits out of here
|
||||
COOLDOWN_DECLARE(rabbit_cooldown)
|
||||
|
||||
/obj/item/clothing/head/that/attackby(obj/item/hitby_item, mob/user, params)
|
||||
. = ..()
|
||||
if(istype(hitby_item, /obj/item/gun/magic/wand))
|
||||
abracadabra(hitby_item, user)
|
||||
|
||||
/obj/item/clothing/head/that/proc/abracadabra(obj/item/hitby_wand, mob/magician)
|
||||
if(!COOLDOWN_FINISHED(src, rabbit_cooldown))
|
||||
to_chat(span_warning("You can't find another rabbit in [src]! Seems another hasn't gotten lost in there yet..."))
|
||||
return
|
||||
|
||||
COOLDOWN_START(src, rabbit_cooldown, RABBIT_CD_TIME)
|
||||
playsound(get_turf(src), 'sound/weapons/emitter.ogg', 70)
|
||||
do_smoke(range=1, location=src, smoke_type=/obj/effect/particle_effect/smoke/quick)
|
||||
|
||||
if(prob(10))
|
||||
magician.visible_message(span_danger("[magician] taps [src] with [hitby_wand], then reaches in and pulls out a bu- wait, those are bees!"), span_danger("You tap [src] with your [hitby_wand.name] and pull out... <b>BEES!</b>"))
|
||||
var/wait_how_many_bees_did_that_guy_pull_out_of_his_hat = rand(4, 8)
|
||||
for(var/b in 1 to wait_how_many_bees_did_that_guy_pull_out_of_his_hat)
|
||||
var/mob/living/simple_animal/hostile/bee/barry = new(get_turf(magician))
|
||||
barry.GiveTarget(magician)
|
||||
if(prob(20))
|
||||
barry.say(pick("BUZZ BUZZ", "PULLING A RABBIT OUT OF A HAT IS A TIRED TROPE", "I DIDN'T ASK TO BEE HERE"), forced = "bee hat")
|
||||
else
|
||||
magician.visible_message(span_notice("[magician] taps [src] with [hitby_wand], then reaches in and pulls out a bunny! Cute!"), span_notice("You tap [src] with your [hitby_wand.name] and pull out a cute bunny!"))
|
||||
var/mob/living/simple_animal/rabbit/empty/bunbun = new(get_turf(magician))
|
||||
bunbun.mob_try_pickup(magician, instant=TRUE)
|
||||
|
||||
#undef RABBIT_CD_TIME
|
||||
|
||||
/obj/item/clothing/head/canada
|
||||
name = "striped red tophat"
|
||||
desc = "It smells like fresh donut holes. / <i>Il sent comme des trous de beignets frais.</i>"
|
||||
icon_state = "canada"
|
||||
inhand_icon_state = "canada"
|
||||
|
||||
/obj/item/clothing/head/redcoat
|
||||
name = "redcoat's hat"
|
||||
icon_state = "redcoat"
|
||||
desc = "<i>'I guess it's a redhead.'</i>"
|
||||
|
||||
/obj/item/clothing/head/mailman
|
||||
name = "mailman's hat"
|
||||
icon_state = "mailman"
|
||||
desc = "<i>'Right-on-time'</i> mail service head wear."
|
||||
|
||||
/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
|
||||
|
||||
/obj/item/clothing/head/hasturhood
|
||||
name = "hastur's hood"
|
||||
desc = "It's <i>unspeakably</i> stylish."
|
||||
icon_state = "hasturhood"
|
||||
flags_inv = HIDEHAIR
|
||||
flags_cover = HEADCOVERSEYES
|
||||
|
||||
/obj/item/clothing/head/nursehat
|
||||
name = "nurse's hat"
|
||||
desc = "It allows quick identification of trained medical personnel."
|
||||
icon_state = "nursehat"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/nurse
|
||||
|
||||
/obj/item/clothing/head/syndicatefake
|
||||
name = "black space-helmet replica"
|
||||
icon_state = "syndicate-helm-black-red"
|
||||
inhand_icon_state = "syndicate-helm-black-red"
|
||||
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!"
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/cueball
|
||||
name = "cueball helmet"
|
||||
desc = "A large, featureless white orb meant to be worn on your head. How do you even see out of this thing?"
|
||||
icon_state = "cueball"
|
||||
inhand_icon_state="cueball"
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_cover = HEADCOVERSEYES|HEADCOVERSMOUTH
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/snowman
|
||||
name = "snowman head"
|
||||
desc = "A ball of white styrofoam. So festive."
|
||||
icon_state = "snowman_h"
|
||||
inhand_icon_state = "snowman_h"
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_cover = HEADCOVERSEYES
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/justice
|
||||
name = "justice hat"
|
||||
desc = "Fight for what's righteous!"
|
||||
icon_state = "justicered"
|
||||
inhand_icon_state = "justicered"
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_inv = HIDEHAIR|HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT
|
||||
flags_cover = HEADCOVERSEYES
|
||||
|
||||
/obj/item/clothing/head/justice/blue
|
||||
icon_state = "justiceblue"
|
||||
inhand_icon_state = "justiceblue"
|
||||
|
||||
/obj/item/clothing/head/justice/yellow
|
||||
icon_state = "justiceyellow"
|
||||
inhand_icon_state = "justiceyellow"
|
||||
|
||||
/obj/item/clothing/head/justice/green
|
||||
icon_state = "justicegreen"
|
||||
inhand_icon_state = "justicegreen"
|
||||
|
||||
/obj/item/clothing/head/justice/pink
|
||||
icon_state = "justicepink"
|
||||
inhand_icon_state = "justicepink"
|
||||
|
||||
/obj/item/clothing/head/rabbitears
|
||||
name = "rabbit ears"
|
||||
desc = "Wearing these makes you look useless, and only good for your sex appeal."
|
||||
icon_state = "bunny"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/rabbit
|
||||
|
||||
/obj/item/clothing/head/pirate
|
||||
name = "pirate hat"
|
||||
desc = "Yarr."
|
||||
icon_state = "pirate"
|
||||
inhand_icon_state = "pirate"
|
||||
dog_fashion = /datum/dog_fashion/head/pirate
|
||||
|
||||
/obj/item/clothing/head/pirate
|
||||
var/datum/language/piratespeak/L = new
|
||||
|
||||
/obj/item/clothing/head/pirate/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(!ishuman(user))
|
||||
return
|
||||
if(slot == ITEM_SLOT_HEAD)
|
||||
user.grant_language(/datum/language/piratespeak/, TRUE, TRUE, LANGUAGE_HAT)
|
||||
to_chat(user, span_boldnotice("You suddenly know how to speak like a pirate!"))
|
||||
|
||||
/obj/item/clothing/head/pirate/dropped(mob/user)
|
||||
. = ..()
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.get_item_by_slot(ITEM_SLOT_HEAD) == src && !QDELETED(src)) //This can be called as a part of destroy
|
||||
user.remove_language(/datum/language/piratespeak/, TRUE, TRUE, LANGUAGE_HAT)
|
||||
to_chat(user, span_boldnotice("You can no longer speak like a pirate."))
|
||||
|
||||
/obj/item/clothing/head/pirate/armored
|
||||
armor = list(MELEE = 30, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, FIRE = 60, ACID = 75)
|
||||
strip_delay = 40
|
||||
equip_delay_other = 20
|
||||
|
||||
/obj/item/clothing/head/pirate/captain
|
||||
name = "pirate captain hat"
|
||||
icon_state = "hgpiratecap"
|
||||
inhand_icon_state = "hgpiratecap"
|
||||
|
||||
/obj/item/clothing/head/bandana
|
||||
name = "pirate bandana"
|
||||
desc = "Yarr."
|
||||
icon_state = "bandana"
|
||||
inhand_icon_state = "bandana"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/bandana/armored
|
||||
armor = list(MELEE = 30, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, FIRE = 60, ACID = 75)
|
||||
strip_delay = 40
|
||||
equip_delay_other = 20
|
||||
|
||||
/obj/item/clothing/head/bowler
|
||||
name = "bowler-hat"
|
||||
desc = "Gentleman, elite aboard!"
|
||||
icon_state = "bowler"
|
||||
inhand_icon_state = "bowler"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/witchwig
|
||||
name = "witch costume wig"
|
||||
desc = "Eeeee~heheheheheheh!"
|
||||
icon_state = "witch"
|
||||
inhand_icon_state = "witch"
|
||||
flags_inv = HIDEHAIR
|
||||
|
||||
/obj/item/clothing/head/chicken
|
||||
name = "chicken suit head"
|
||||
desc = "Bkaw!"
|
||||
icon_state = "chickenhead"
|
||||
inhand_icon_state = "chickensuit"
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/griffin
|
||||
name = "griffon head"
|
||||
desc = "Why not 'eagle head'? Who knows."
|
||||
icon_state = "griffinhat"
|
||||
inhand_icon_state = "griffinhat"
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/bearpelt
|
||||
name = "bear pelt hat"
|
||||
desc = "Fuzzy."
|
||||
icon_state = "bearpelt"
|
||||
inhand_icon_state = "bearpelt"
|
||||
|
||||
/obj/item/clothing/head/xenos
|
||||
name = "xenos helmet"
|
||||
icon_state = "xenos"
|
||||
inhand_icon_state = "xenos_helm"
|
||||
desc = "A helmet made out of chitinous alien hide."
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
|
||||
/obj/item/clothing/head/fedora
|
||||
name = "fedora"
|
||||
icon_state = "fedora"
|
||||
inhand_icon_state = "fedora"
|
||||
desc = "A really cool hat if you're a mobster. A really lame hat if you're not."
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/fedora
|
||||
|
||||
/obj/item/clothing/head/fedora/white
|
||||
name = "white fedora"
|
||||
icon_state = "fedora_white"
|
||||
inhand_icon_state = "fedora_white"
|
||||
|
||||
/obj/item/clothing/head/fedora/beige
|
||||
name = "beige fedora"
|
||||
icon_state = "fedora_beige"
|
||||
inhand_icon_state = "fedora_beige"
|
||||
|
||||
/obj/item/clothing/head/fedora/suicide_act(mob/user)
|
||||
if(user.gender == FEMALE)
|
||||
return 0
|
||||
var/mob/living/carbon/human/H = user
|
||||
user.visible_message(span_suicide("[user] is donning [src]! It looks like [user.p_theyre()] trying to be nice to girls."))
|
||||
user.say("M'lady.", forced = "fedora suicide")
|
||||
sleep(10)
|
||||
H.facial_hairstyle = "Neckbeard"
|
||||
return(BRUTELOSS)
|
||||
|
||||
/obj/item/clothing/head/sombrero
|
||||
name = "sombrero"
|
||||
icon_state = "sombrero"
|
||||
inhand_icon_state = "sombrero"
|
||||
desc = "You can practically taste the fiesta."
|
||||
flags_inv = HIDEHAIR
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/sombrero
|
||||
|
||||
greyscale_config = /datum/greyscale_config/sombrero
|
||||
greyscale_config_worn = /datum/greyscale_config/sombrero/worn
|
||||
greyscale_config_inhand_left = /datum/greyscale_config/sombrero/lefthand
|
||||
greyscale_config_inhand_right = /datum/greyscale_config/sombrero/righthand
|
||||
|
||||
/obj/item/clothing/head/sombrero/green
|
||||
name = "green sombrero"
|
||||
desc = "As elegant as a dancing cactus."
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
|
||||
dog_fashion = null
|
||||
greyscale_colors = "#13d968#ffffff"
|
||||
flags_1 = IS_PLAYER_COLORABLE_1
|
||||
|
||||
/obj/item/clothing/head/sombrero/shamebrero
|
||||
name = "shamebrero"
|
||||
icon_state = "shamebrero"
|
||||
inhand_icon_state = "shamebrero"
|
||||
desc = "Once it's on, it never comes off."
|
||||
dog_fashion = null
|
||||
greyscale_colors = "#d565d3#f8db18"
|
||||
flags_1 = IS_PLAYER_COLORABLE_1
|
||||
|
||||
/obj/item/clothing/head/sombrero/shamebrero/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, SHAMEBRERO_TRAIT)
|
||||
|
||||
/obj/item/clothing/head/flatcap
|
||||
name = "flat cap"
|
||||
desc = "A working man's cap."
|
||||
icon_state = "beret_flat"
|
||||
greyscale_config = /datum/greyscale_config/beret
|
||||
greyscale_config_worn = /datum/greyscale_config/beret/worn
|
||||
greyscale_colors = "#8F7654"
|
||||
inhand_icon_state = "detective"
|
||||
|
||||
/obj/item/clothing/head/hunter
|
||||
name = "bounty hunting hat"
|
||||
desc = "Ain't nobody gonna cheat the hangman in my town."
|
||||
icon_state = "cowboy"
|
||||
worn_icon_state = "hunter"
|
||||
inhand_icon_state = "hunter"
|
||||
armor = list(MELEE = 5, BULLET = 5, LASER = 5, ENERGY = 15, BOMB = 0, BIO = 0, FIRE = 0, ACID = 0)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
/obj/item/clothing/head/cone
|
||||
desc = "This cone is trying to warn you of something!"
|
||||
name = "warning cone"
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "cone"
|
||||
inhand_icon_state = "cone"
|
||||
force = 1
|
||||
throwforce = 3
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb_continuous = list("warns", "cautions", "smashes")
|
||||
attack_verb_simple = list("warn", "caution", "smash")
|
||||
resistance_flags = NONE
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/santa
|
||||
name = "santa hat"
|
||||
desc = "On the first day of christmas my employer gave to me!"
|
||||
icon_state = "santahatnorm"
|
||||
inhand_icon_state = "that"
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
|
||||
dog_fashion = /datum/dog_fashion/head/santa
|
||||
|
||||
/obj/item/clothing/head/jester
|
||||
name = "jester hat"
|
||||
desc = "A hat with bells, to add some merriness to the suit."
|
||||
icon_state = "jester_hat"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/jester/alt
|
||||
icon_state = "jester2"
|
||||
|
||||
/obj/item/clothing/head/rice_hat
|
||||
name = "rice hat"
|
||||
desc = "Welcome to the rice fields, motherfucker."
|
||||
icon_state = "rice_hat"
|
||||
|
||||
/obj/item/clothing/head/lizard
|
||||
name = "lizardskin cloche hat"
|
||||
desc = "How many lizards died to make this hat? Not enough."
|
||||
icon_state = "lizard"
|
||||
|
||||
/obj/item/clothing/head/papersack
|
||||
name = "paper sack hat"
|
||||
desc = "A paper sack with crude holes cut out for eyes. Useful for hiding one's identity or ugliness."
|
||||
icon_state = "papersack"
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/papersack/smiley
|
||||
name = "paper sack hat"
|
||||
desc = "A paper sack with crude holes cut out for eyes and a sketchy smile drawn on the front. Not creepy at all."
|
||||
icon_state = "papersack_smile"
|
||||
|
||||
/obj/item/clothing/head/crown
|
||||
name = "crown"
|
||||
desc = "A crown fit for a king, a petty king maybe."
|
||||
icon_state = "crown"
|
||||
armor = list(MELEE = 15, BULLET = 0, LASER = 0,ENERGY = 10, BOMB = 0, BIO = 0, FIRE = 100, ACID = 50, WOUND = 5)
|
||||
resistance_flags = FIRE_PROOF
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/crown/fancy
|
||||
name = "magnificent crown"
|
||||
desc = "A crown worn by only the highest emperors of the <s>land</s> space."
|
||||
icon_state = "fancycrown"
|
||||
|
||||
/obj/item/clothing/head/scarecrow_hat
|
||||
name = "scarecrow hat"
|
||||
desc = "A simple straw hat."
|
||||
icon_state = "scarecrow_hat"
|
||||
|
||||
/obj/item/clothing/head/lobsterhat
|
||||
name = "foam lobster head"
|
||||
desc = "When everything's going to crab, protecting your head is the best choice."
|
||||
icon_state = "lobster_hat"
|
||||
clothing_flags = SNUG_FIT
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/drfreezehat
|
||||
name = "doctor freeze's wig"
|
||||
desc = "A cool wig for cool people."
|
||||
icon_state = "drfreeze_hat"
|
||||
flags_inv = HIDEHAIR
|
||||
|
||||
/obj/item/clothing/head/pharaoh
|
||||
name = "pharaoh hat"
|
||||
desc = "Walk like an Egyptian."
|
||||
icon_state = "pharoah_hat"
|
||||
inhand_icon_state = "pharoah_hat"
|
||||
|
||||
/obj/item/clothing/head/nemes
|
||||
name = "headdress of Nemes"
|
||||
desc = "Lavish space tomb not included."
|
||||
icon_state = "nemes_headdress"
|
||||
|
||||
/obj/item/clothing/head/delinquent
|
||||
name = "delinquent hat"
|
||||
desc = "Good grief."
|
||||
icon_state = "delinquent"
|
||||
|
||||
/obj/item/clothing/head/frenchberet
|
||||
name = "french beret"
|
||||
desc = "A quality beret, infused with the aroma of chain-smoking, wine-swilling Parisians. You feel less inclined to engage in military conflict, for some reason."
|
||||
icon_state = "beret"
|
||||
greyscale_config = /datum/greyscale_config/beret
|
||||
greyscale_config_worn = /datum/greyscale_config/beret/worn
|
||||
greyscale_colors = "#972A2A"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/frenchberet/equipped(mob/M, slot)
|
||||
. = ..()
|
||||
if (slot == ITEM_SLOT_HEAD)
|
||||
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
else
|
||||
UnregisterSignal(M, COMSIG_MOB_SAY)
|
||||
|
||||
/obj/item/clothing/head/frenchberet/dropped(mob/M)
|
||||
. = ..()
|
||||
UnregisterSignal(M, COMSIG_MOB_SAY)
|
||||
|
||||
/obj/item/clothing/head/frenchberet/proc/handle_speech(datum/source, mob/speech_args)
|
||||
SIGNAL_HANDLER
|
||||
var/message = speech_args[SPEECH_MESSAGE]
|
||||
if(message[1] != "*")
|
||||
message = " [message]"
|
||||
var/list/french_words = strings("french_replacement.json", "french")
|
||||
|
||||
for(var/key in french_words)
|
||||
var/value = french_words[key]
|
||||
if(islist(value))
|
||||
value = pick(value)
|
||||
|
||||
message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]")
|
||||
message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]")
|
||||
message = replacetextEx(message, " [key]", " [value]")
|
||||
|
||||
if(prob(3))
|
||||
message += pick(" Honh honh honh!"," Honh!"," Zut Alors!")
|
||||
speech_args[SPEECH_MESSAGE] = trim(message)
|
||||
|
||||
/obj/item/clothing/head/clownmitre
|
||||
name = "Hat of the Honkmother"
|
||||
desc = "It's hard for parishoners to see a banana peel on the floor when they're looking up at your glorious chapeau."
|
||||
icon_state = "clownmitre"
|
||||
|
||||
/obj/item/clothing/head/kippah
|
||||
name = "kippah"
|
||||
desc = "Signals that you follow the Jewish Halakha. Keeps the head covered and the soul extra-Orthodox."
|
||||
icon_state = "kippah"
|
||||
|
||||
/obj/item/clothing/head/medievaljewhat
|
||||
name = "medieval Jewish hat"
|
||||
desc = "A silly looking hat, intended to be placed on the heads of the station's oppressed religious minorities."
|
||||
icon_state = "medievaljewhat"
|
||||
|
||||
/obj/item/clothing/head/taqiyahwhite
|
||||
name = "white taqiyah"
|
||||
desc = "An extra-mustahabb way of showing your devotion to Allah."
|
||||
icon_state = "taqiyahwhite"
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small
|
||||
|
||||
/obj/item/clothing/head/taqiyahred
|
||||
name = "red taqiyah"
|
||||
desc = "An extra-mustahabb way of showing your devotion to Allah."
|
||||
icon_state = "taqiyahred"
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small
|
||||
|
||||
/obj/item/clothing/head/shrine_wig
|
||||
name = "shrine maiden's wig"
|
||||
desc = "Purify in style!"
|
||||
flags_inv = HIDEHAIR //bald
|
||||
icon_state = "shrine_wig"
|
||||
inhand_icon_state = "shrine_wig"
|
||||
dynamic_hair_suffix = ""
|
||||
worn_y_offset = 1
|
||||
|
||||
/obj/item/clothing/head/intern
|
||||
name = "\improper CentCom Head Intern beancap"
|
||||
desc = "A horrifying mix of beanie and softcap in CentCom green. You'd have to be pretty desperate for power over your peers to agree to wear this."
|
||||
icon_state = "intern_hat"
|
||||
inhand_icon_state = "intern_hat"
|
||||
|
||||
/obj/item/clothing/head/coordinator
|
||||
name = "coordinator cap"
|
||||
desc = "A cap for a party coordinator, stylish!."
|
||||
icon_state = "capcap"
|
||||
inhand_icon_state = "that"
|
||||
armor = list(MELEE = 25, BULLET = 15, LASER = 25, ENERGY = 35, BOMB = 25, BIO = 0, FIRE = 50, ACID = 50)
|
||||
|
||||
/obj/item/clothing/head/jackbros
|
||||
name = "frosty hat"
|
||||
desc = "Hee-ho!"
|
||||
icon_state = "JackFrostHat"
|
||||
inhand_icon_state = "JackFrostHat"
|
||||
|
||||
/obj/item/clothing/head/weddingveil
|
||||
name = "wedding veil"
|
||||
desc = "A gauzy white veil."
|
||||
icon_state = "weddingveil"
|
||||
inhand_icon_state = "weddingveil"
|
||||
|
||||
/obj/item/clothing/head/centcom_cap
|
||||
name = "\improper CentCom commander cap"
|
||||
icon_state = "centcom_cap"
|
||||
desc = "Worn by the finest of CentCom commanders. Inside the lining of the cap, lies two faint initials."
|
||||
inhand_icon_state = "that"
|
||||
flags_inv = 0
|
||||
armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 40, BOMB = 25, BIO = 0, FIRE = 50, ACID = 50)
|
||||
strip_delay = (8 SECONDS)
|
||||
|
||||
/obj/item/clothing/head/human_leather
|
||||
name = "human skin hat"
|
||||
desc = "This will scare them. All will know my power."
|
||||
icon_state = "human_leather"
|
||||
inhand_icon_state = "human_leather"
|
||||
@@ -1,626 +0,0 @@
|
||||
/obj/item/clothing/shoes/sneakers/mime
|
||||
name = "mime shoes"
|
||||
greyscale_colors = "#ffffff#ffffff"
|
||||
|
||||
/obj/item/clothing/shoes/combat //basic syndicate combat boots for nuke ops and mob corpses
|
||||
name = "combat boots"
|
||||
desc = "High speed, low drag combat boots."
|
||||
icon_state = "jackboots"
|
||||
inhand_icon_state = "jackboots"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
armor = list(MELEE = 25, BULLET = 25, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 10, FIRE = 70, ACID = 50)
|
||||
strip_delay = 40
|
||||
resistance_flags = NONE
|
||||
permeability_coefficient = 0.05 //Thick soles, and covers the ankle
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
lace_time = 12 SECONDS
|
||||
|
||||
/obj/item/clothing/shoes/combat/sneakboots
|
||||
name = "sneakboots"
|
||||
desc = "These boots have special noise cancelling soles. Perfect for stealth, if it wasn't for the color scheme."
|
||||
icon_state = "sneakboots"
|
||||
inhand_icon_state = "sneakboots"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
clothing_traits = list(TRAIT_SILENT_FOOTSTEPS)
|
||||
|
||||
/obj/item/clothing/shoes/combat/swat //overpowered boots for death squads
|
||||
name = "\improper SWAT boots"
|
||||
desc = "High speed, no drag combat boots."
|
||||
permeability_coefficient = 0.01
|
||||
clothing_flags = NOSLIP
|
||||
armor = list(MELEE = 40, BULLET = 30, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 30, FIRE = 90, ACID = 50)
|
||||
|
||||
/obj/item/clothing/shoes/sandal
|
||||
desc = "A pair of rather plain wooden sandals."
|
||||
name = "sandals"
|
||||
icon_state = "wizard"
|
||||
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 0.5)
|
||||
strip_delay = 5
|
||||
equip_delay_other = 50
|
||||
permeability_coefficient = 0.9
|
||||
can_be_tied = TRUE //SKYRAT EDIT
|
||||
species_exception = list(/datum/species/golem)
|
||||
|
||||
/obj/item/clothing/shoes/sneakers/marisa
|
||||
desc = "A pair of magic black shoes."
|
||||
name = "magic shoes"
|
||||
worn_icon_state = "marisa"
|
||||
greyscale_colors = "#545454#ffffff"
|
||||
greyscale_config = /datum/greyscale_config/sneakers_marisa
|
||||
greyscale_config_worn = null
|
||||
strip_delay = 5
|
||||
equip_delay_other = 50
|
||||
permeability_coefficient = 0.9
|
||||
can_be_tied = FALSE
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
/obj/item/clothing/shoes/sandal/magic
|
||||
name = "magical sandals"
|
||||
desc = "A pair of sandals imbued with magic."
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
/obj/item/clothing/shoes/galoshes
|
||||
desc = "A pair of yellow rubber boots, designed to prevent slipping on wet surfaces."
|
||||
name = "galoshes"
|
||||
icon_state = "galoshes"
|
||||
permeability_coefficient = 0.01
|
||||
clothing_flags = NOSLIP
|
||||
slowdown = SHOES_SLOWDOWN+1
|
||||
strip_delay = 30
|
||||
equip_delay_other = 50
|
||||
resistance_flags = NONE
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 40, ACID = 75)
|
||||
can_be_bloody = FALSE
|
||||
custom_price = PAYCHECK_EASY * 3
|
||||
can_be_tied = FALSE
|
||||
|
||||
/obj/item/clothing/shoes/galoshes/dry
|
||||
name = "absorbent galoshes"
|
||||
desc = "A pair of purple rubber boots, designed to prevent slipping on wet surfaces while also drying them."
|
||||
icon_state = "galoshes_dry"
|
||||
|
||||
/obj/item/clothing/shoes/galoshes/dry/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/on_step)
|
||||
|
||||
/obj/item/clothing/shoes/galoshes/dry/proc/on_step()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/turf/open/t_loc = get_turf(src)
|
||||
SEND_SIGNAL(t_loc, COMSIG_TURF_MAKE_DRY, TURF_WET_WATER, TRUE, INFINITY)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes
|
||||
desc = "The prankster's standard-issue clowning shoes. Damn, they're huge! Ctrl-click to toggle waddle dampeners."
|
||||
name = "clown shoes"
|
||||
icon_state = "clown"
|
||||
inhand_icon_state = "clown_shoes"
|
||||
slowdown = SHOES_SLOWDOWN+1
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes/clown
|
||||
var/enabled_waddle = TRUE
|
||||
lace_time = 20 SECONDS // how the hell do these laces even work??
|
||||
species_exception = list(/datum/species/golem/bananium)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/Initialize()
|
||||
. = ..()
|
||||
LoadComponent(/datum/component/squeak, list('sound/effects/clownstep1.ogg'=1,'sound/effects/clownstep2.ogg'=1), 50, falloff_exponent = 20) //die off quick please
|
||||
//AddElement(/datum/element/swabable, CELL_LINE_TABLE_CLOWN, CELL_VIRUS_TABLE_GENERIC, rand(2,3), 0) SKYRAT EDIT REMOVAL
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == ITEM_SLOT_FEET)
|
||||
if(enabled_waddle)
|
||||
user.AddElement(/datum/element/waddling)
|
||||
if(is_clown_job(user.mind?.assigned_role))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "clownshoes", /datum/mood_event/clownshoes)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/dropped(mob/user)
|
||||
. = ..()
|
||||
user.RemoveElement(/datum/element/waddling)
|
||||
if(is_clown_job(user.mind?.assigned_role))
|
||||
SEND_SIGNAL(user, COMSIG_CLEAR_MOOD_EVENT, "clownshoes")
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/CtrlClick(mob/living/user)
|
||||
if(!isliving(user))
|
||||
return
|
||||
if(user.get_active_held_item() != src)
|
||||
to_chat(user, span_warning("You must hold the [src] in your hand to do this!"))
|
||||
return
|
||||
if (!enabled_waddle)
|
||||
to_chat(user, span_notice("You switch off the waddle dampeners!"))
|
||||
enabled_waddle = TRUE
|
||||
else
|
||||
to_chat(user, span_notice("You switch on the waddle dampeners!"))
|
||||
enabled_waddle = FALSE
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/jester
|
||||
name = "jester shoes"
|
||||
desc = "A court jester's shoes, updated with modern squeaking technology."
|
||||
icon_state = "jester_shoes"
|
||||
|
||||
/obj/item/clothing/shoes/jackboots
|
||||
name = "jackboots"
|
||||
desc = "Nanotrasen-issue Security combat boots for combat scenarios or combat situations. All combat, all the time."
|
||||
icon_state = "jackboots"
|
||||
inhand_icon_state = "jackboots"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
strip_delay = 30
|
||||
equip_delay_other = 50
|
||||
resistance_flags = NONE
|
||||
permeability_coefficient = 0.05 //Thick soles, and covers the ankle
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
can_be_tied = TRUE //SKYRAT EDIT
|
||||
|
||||
/obj/item/clothing/shoes/jackboots/fast
|
||||
slowdown = -1
|
||||
|
||||
/obj/item/clothing/shoes/winterboots
|
||||
name = "winter boots"
|
||||
desc = "Boots lined with 'synthetic' animal fur."
|
||||
icon_state = "winterboots"
|
||||
inhand_icon_state = "winterboots"
|
||||
permeability_coefficient = 0.15
|
||||
cold_protection = FEET|LEGS
|
||||
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
|
||||
heat_protection = FEET|LEGS
|
||||
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
lace_time = 8 SECONDS
|
||||
|
||||
/obj/item/clothing/shoes/winterboots/ice_boots
|
||||
name = "ice hiking boots"
|
||||
desc = "A pair of winter boots with special grips on the bottom, designed to prevent slipping on frozen surfaces."
|
||||
icon_state = "iceboots"
|
||||
inhand_icon_state = "iceboots"
|
||||
clothing_flags = NOSLIP_ICE
|
||||
|
||||
/obj/item/clothing/shoes/workboots
|
||||
name = "work boots"
|
||||
desc = "Nanotrasen-issue Engineering lace-up work boots for the especially blue-collar."
|
||||
icon_state = "workboots"
|
||||
inhand_icon_state = "jackboots"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
permeability_coefficient = 0.15
|
||||
strip_delay = 20
|
||||
equip_delay_other = 40
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
lace_time = 8 SECONDS
|
||||
species_exception = list(/datum/species/golem/uranium)
|
||||
|
||||
/obj/item/clothing/shoes/workboots/mining
|
||||
name = "mining boots"
|
||||
desc = "Steel-toed mining boots for mining in hazardous environments. Very good at keeping toes uncrushed."
|
||||
icon_state = "explorer"
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/clothing/shoes/cult
|
||||
name = "\improper Nar'Sien invoker boots"
|
||||
desc = "A pair of boots worn by the followers of Nar'Sie."
|
||||
icon_state = "cult"
|
||||
inhand_icon_state = "cult"
|
||||
cold_protection = FEET
|
||||
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
|
||||
heat_protection = FEET
|
||||
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
|
||||
lace_time = 10 SECONDS
|
||||
|
||||
/obj/item/clothing/shoes/cult/alt
|
||||
name = "cultist boots"
|
||||
icon_state = "cultalt"
|
||||
|
||||
/obj/item/clothing/shoes/cult/alt/ghost
|
||||
item_flags = DROPDEL
|
||||
|
||||
/obj/item/clothing/shoes/cult/alt/ghost/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
|
||||
|
||||
/obj/item/clothing/shoes/sneakers/cyborg
|
||||
name = "cyborg boots"
|
||||
desc = "Shoes for a cyborg costume."
|
||||
greyscale_colors = "#4e4e4e#4e4e4e"
|
||||
|
||||
/obj/item/clothing/shoes/laceup
|
||||
name = "laceup shoes"
|
||||
desc = "The height of fashion, and they're pre-polished!"
|
||||
icon_state = "laceups"
|
||||
equip_delay_other = 50
|
||||
|
||||
/obj/item/clothing/shoes/roman
|
||||
name = "roman sandals"
|
||||
desc = "Sandals with buckled leather straps on it."
|
||||
icon_state = "roman"
|
||||
inhand_icon_state = "roman"
|
||||
strip_delay = 100
|
||||
equip_delay_other = 100
|
||||
permeability_coefficient = 0.9
|
||||
can_be_tied = FALSE
|
||||
|
||||
/obj/item/clothing/shoes/griffin
|
||||
name = "griffon boots"
|
||||
desc = "A pair of costume boots fashioned after bird talons."
|
||||
icon_state = "griffinboots"
|
||||
inhand_icon_state = "griffinboots"
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
lace_time = 8 SECONDS
|
||||
|
||||
/obj/item/clothing/shoes/bhop
|
||||
name = "jump boots"
|
||||
desc = "A specialized pair of combat boots with a built-in propulsion system for rapid foward movement."
|
||||
icon_state = "jetboots"
|
||||
inhand_icon_state = "jetboots"
|
||||
resistance_flags = FIRE_PROOF
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
actions_types = list(/datum/action/item_action/bhop)
|
||||
permeability_coefficient = 0.05
|
||||
strip_delay = 30
|
||||
var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles
|
||||
var/jumpspeed = 3
|
||||
var/recharging_rate = 60 //default 6 seconds between each dash
|
||||
var/recharging_time = 0 //time until next dash
|
||||
|
||||
/obj/item/clothing/shoes/bhop/ui_action_click(mob/user, action)
|
||||
if(!isliving(user))
|
||||
return
|
||||
|
||||
if(recharging_time > world.time)
|
||||
to_chat(user, span_warning("The boot's internal propulsion needs to recharge still!"))
|
||||
return
|
||||
|
||||
var/atom/target = get_edge_target_turf(user, user.dir) //gets the user's direction
|
||||
|
||||
if (user.throw_at(target, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE))
|
||||
playsound(src, 'sound/effects/stealthoff.ogg', 50, TRUE, TRUE)
|
||||
user.visible_message(span_warning("[usr] dashes forward into the air!"))
|
||||
recharging_time = world.time + recharging_rate
|
||||
else
|
||||
to_chat(user, span_warning("Something prevents you from dashing forward!"))
|
||||
|
||||
/obj/item/clothing/shoes/bhop/rocket
|
||||
name = "rocket boots"
|
||||
desc = "Very special boots with built-in rocket thrusters! SHAZBOT!"
|
||||
icon_state = "rocketboots"
|
||||
inhand_icon_state = "rocketboots"
|
||||
actions_types = list(/datum/action/item_action/bhop/brocket)
|
||||
jumpdistance = 20 //great for throwing yourself into walls and people at high speeds
|
||||
jumpspeed = 5
|
||||
|
||||
/obj/item/clothing/shoes/singery
|
||||
name = "yellow performer's boots"
|
||||
desc = "These boots were made for dancing."
|
||||
icon_state = "ysing"
|
||||
equip_delay_other = 50
|
||||
|
||||
/obj/item/clothing/shoes/singerb
|
||||
name = "blue performer's boots"
|
||||
desc = "These boots were made for dancing."
|
||||
icon_state = "bsing"
|
||||
equip_delay_other = 50
|
||||
|
||||
/obj/item/clothing/shoes/bronze
|
||||
name = "bronze boots"
|
||||
desc = "A giant, clunky pair of shoes crudely made out of bronze. Why would anyone wear these?"
|
||||
icon = 'icons/obj/clothing/clockwork_garb.dmi'
|
||||
icon_state = "clockwork_treads"
|
||||
can_be_tied = FALSE
|
||||
|
||||
/obj/item/clothing/shoes/bronze/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/squeak, list('sound/machines/clockcult/integration_cog_install.ogg' = 1, 'sound/magic/clockwork/fellowship_armory.ogg' = 1), 50, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
|
||||
/obj/item/clothing/shoes/wheelys
|
||||
name = "Wheely-Heels"
|
||||
desc = "Uses patented retractable wheel technology. Never sacrifice speed for style - not that this provides much of either." //Thanks Fel
|
||||
worn_icon_state = "wheelys"
|
||||
greyscale_colors = "#545454#ffffff"
|
||||
icon_state = "sneakers"
|
||||
greyscale_config = /datum/greyscale_config/sneakers_wheelys
|
||||
inhand_icon_state = "wheelys"
|
||||
worn_icon = 'icons/mob/large-worn-icons/64x64/feet.dmi'
|
||||
worn_x_dimension = 64
|
||||
worn_y_dimension = 64
|
||||
clothing_flags = LARGE_WORN_ICON
|
||||
actions_types = list(/datum/action/item_action/wheelys)
|
||||
///False means wheels are not popped out
|
||||
var/wheelToggle = FALSE
|
||||
///The vehicle associated with the shoes
|
||||
var/obj/vehicle/ridden/scooter/skateboard/wheelys/wheels = /obj/vehicle/ridden/scooter/skateboard/wheelys
|
||||
|
||||
/obj/item/clothing/shoes/wheelys/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
wheels = new wheels(null)
|
||||
wheels.link_shoes(src)
|
||||
|
||||
/obj/item/clothing/shoes/wheelys/ui_action_click(mob/user, action)
|
||||
if(!isliving(user))
|
||||
return
|
||||
if(!istype(user.get_item_by_slot(ITEM_SLOT_FEET), /obj/item/clothing/shoes/wheelys))
|
||||
to_chat(user, span_warning("You must be wearing the wheely-heels to use them!"))
|
||||
return
|
||||
if(!(wheels.is_occupant(user)))
|
||||
wheelToggle = FALSE
|
||||
if(wheelToggle)
|
||||
wheels.unbuckle_mob(user)
|
||||
wheelToggle = FALSE
|
||||
return
|
||||
wheels.forceMove(get_turf(user))
|
||||
wheels.buckle_mob(user)
|
||||
wheelToggle = TRUE
|
||||
|
||||
/obj/item/clothing/shoes/wheelys/dropped(mob/user)
|
||||
if(wheelToggle)
|
||||
wheels.unbuckle_mob(user)
|
||||
wheelToggle = FALSE
|
||||
..()
|
||||
|
||||
/obj/item/clothing/shoes/wheelys/proc/toggle_wheels(status)
|
||||
if (status)
|
||||
worn_icon_state = "[initial(worn_icon_state)]-on"
|
||||
else
|
||||
worn_icon_state = "[initial(worn_icon_state)]"
|
||||
playsound(src, 'sound/weapons/tap.ogg', 10, TRUE)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/clothing/shoes/wheelys/Destroy()
|
||||
QDEL_NULL(wheels)
|
||||
. = ..()
|
||||
|
||||
/obj/item/clothing/shoes/wheelys/rollerskates
|
||||
name = "roller skates"
|
||||
desc = "An EightO brand pair of roller skates. The wheels are retractable, though're quite bulky to walk in."
|
||||
icon_state = "rollerskates"
|
||||
greyscale_colors = null
|
||||
greyscale_config = null
|
||||
worn_icon_state = "rollerskates"
|
||||
slowdown = SHOES_SLOWDOWN+1
|
||||
wheels = /obj/vehicle/ridden/scooter/skateboard/wheelys/rollerskates
|
||||
custom_premium_price = PAYCHECK_EASY * 5
|
||||
custom_price = PAYCHECK_EASY * 5
|
||||
|
||||
/obj/item/clothing/shoes/wheelys/skishoes
|
||||
name = "ski shoes"
|
||||
desc = "A pair of shoes equipped with foldable skis! Very handy to move in snowy environments unimpeded."
|
||||
icon_state = "skishoes"
|
||||
greyscale_colors = null
|
||||
greyscale_config = null
|
||||
worn_icon_state = "skishoes"
|
||||
slowdown = SHOES_SLOWDOWN+1
|
||||
wheels = /obj/vehicle/ridden/scooter/skateboard/wheelys/skishoes
|
||||
custom_premium_price = PAYCHECK_EASY * 1.6
|
||||
custom_price = PAYCHECK_EASY * 1.6
|
||||
|
||||
/obj/item/clothing/shoes/kindle_kicks
|
||||
name = "Kindle Kicks"
|
||||
desc = "They'll sure kindle something in you, and it's not childhood nostalgia..."
|
||||
icon_state = "kindleKicks"
|
||||
inhand_icon_state = "kindleKicks"
|
||||
actions_types = list(/datum/action/item_action/kindle_kicks)
|
||||
light_system = MOVABLE_LIGHT
|
||||
light_range = 2
|
||||
light_power = 3
|
||||
light_on = FALSE
|
||||
var/lightCycle = 0
|
||||
var/active = FALSE
|
||||
|
||||
|
||||
/obj/item/clothing/shoes/kindle_kicks/ui_action_click(mob/user, action)
|
||||
if(active)
|
||||
return
|
||||
active = TRUE
|
||||
set_light_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255)))
|
||||
set_light_on(active)
|
||||
addtimer(CALLBACK(src, .proc/lightUp), 0.5 SECONDS)
|
||||
|
||||
/obj/item/clothing/shoes/kindle_kicks/proc/lightUp(mob/user)
|
||||
if(lightCycle < 15)
|
||||
set_light_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255)))
|
||||
lightCycle++
|
||||
addtimer(CALLBACK(src, .proc/lightUp), 0.5 SECONDS)
|
||||
else
|
||||
lightCycle = 0
|
||||
active = FALSE
|
||||
set_light_on(active)
|
||||
|
||||
/obj/item/clothing/shoes/russian
|
||||
name = "russian boots"
|
||||
desc = "Comfy shoes."
|
||||
icon_state = "rus_shoes"
|
||||
inhand_icon_state = "rus_shoes"
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
lace_time = 8 SECONDS
|
||||
|
||||
/obj/item/clothing/shoes/cowboy
|
||||
name = "cowboy boots"
|
||||
desc = "A small sticker lets you know they've been inspected for snakes, It is unclear how long ago the inspection took place..."
|
||||
icon_state = "cowboy_brown"
|
||||
permeability_coefficient = 0.05 //these are quite tall
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
custom_price = PAYCHECK_EASY
|
||||
var/list/occupants = list()
|
||||
var/max_occupants = 4
|
||||
can_be_tied = TRUE //SKYRAT EDIT
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/Initialize()
|
||||
. = ..()
|
||||
if(prob(2))
|
||||
var/mob/living/simple_animal/hostile/retaliate/snake/bootsnake = new/mob/living/simple_animal/hostile/retaliate/snake(src)
|
||||
occupants += bootsnake
|
||||
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/equipped(mob/living/carbon/user, slot)
|
||||
. = ..()
|
||||
RegisterSignal(user, COMSIG_LIVING_SLAM_TABLE, .proc/table_slam)
|
||||
if(slot == ITEM_SLOT_FEET)
|
||||
for(var/mob/living/occupant in occupants)
|
||||
occupant.forceMove(user.drop_location())
|
||||
user.visible_message(span_warning("[user] recoils as something slithers out of [src]."), span_userdanger("You feel a sudden stabbing pain in your [pick("foot", "toe", "ankle")]!"))
|
||||
user.Knockdown(20) //Is one second paralyze better here? I feel you would fall on your ass in some fashion.
|
||||
user.apply_damage(5, BRUTE, pick(BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
|
||||
if(istype(occupant, /mob/living/simple_animal/hostile/retaliate))
|
||||
user.reagents.add_reagent(/datum/reagent/toxin, 7)
|
||||
occupants.Cut()
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/dropped(mob/living/user)
|
||||
. = ..()
|
||||
UnregisterSignal(user, COMSIG_LIVING_SLAM_TABLE)
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/proc/table_slam(mob/living/source, obj/structure/table/the_table)
|
||||
SIGNAL_HANDLER
|
||||
INVOKE_ASYNC(src, .proc/handle_table_slam, source)
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/proc/handle_table_slam(mob/living/user)
|
||||
user.say(pick("Hot damn!", "Hoo-wee!", "Got-dang!"), spans = list(SPAN_YELL), forced=TRUE)
|
||||
user.client?.give_award(/datum/award/achievement/misc/hot_damn, user)
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/MouseDrop_T(mob/living/target, mob/living/user)
|
||||
. = ..()
|
||||
if(!(user.mobility_flags & MOBILITY_USE) || user.stat != CONSCIOUS || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user) || !user.Adjacent(target) || target.stat == DEAD)
|
||||
return
|
||||
if(occupants.len >= max_occupants)
|
||||
to_chat(user, span_warning("[src] are full!"))
|
||||
return
|
||||
if(istype(target, /mob/living/simple_animal/hostile/retaliate/snake) || istype(target, /mob/living/simple_animal/hostile/headcrab) || istype(target, /mob/living/carbon/alien/larva))
|
||||
occupants += target
|
||||
target.forceMove(src)
|
||||
to_chat(user, span_notice("[target] slithers into [src]."))
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/container_resist_act(mob/living/user)
|
||||
if(!do_after(user, 10, target = user))
|
||||
return
|
||||
user.forceMove(user.drop_location())
|
||||
occupants -= user
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/white
|
||||
name = "white cowboy boots"
|
||||
icon_state = "cowboy_white"
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/black
|
||||
name = "black cowboy boots"
|
||||
desc = "You get the feeling someone might have been hanged in these boots."
|
||||
icon_state = "cowboy_black"
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/fancy
|
||||
name = "bilton wrangler boots"
|
||||
desc = "A pair of authentic haute couture boots from Japanifornia. You doubt they have ever been close to cattle."
|
||||
icon_state = "cowboy_fancy"
|
||||
permeability_coefficient = 0.08
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/lizard
|
||||
name = "lizard skin boots"
|
||||
desc = "You can hear a faint hissing from inside the boots; you hope it is just a mournful ghost."
|
||||
icon_state = "lizardboots_green"
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 40, ACID = 0) //lizards like to stay warm
|
||||
|
||||
/obj/item/clothing/shoes/cowboy/lizard/masterwork
|
||||
name = "\improper Hugs-The-Feet lizard skin boots"
|
||||
desc = "A pair of masterfully crafted lizard skin boots. Finally a good application for the station's most bothersome inhabitants."
|
||||
icon_state = "lizardboots_blue"
|
||||
|
||||
/obj/effect/spawner/lootdrop/lizardboots
|
||||
name = "random lizard boot quality"
|
||||
desc = "Which ever gets picked, the lizard race loses"
|
||||
icon = 'icons/obj/clothing/shoes.dmi'
|
||||
icon_state = "lizardboots_green"
|
||||
loot = list(
|
||||
/obj/item/clothing/shoes/cowboy/lizard = 7,
|
||||
/obj/item/clothing/shoes/cowboy/lizard/masterwork = 1)
|
||||
|
||||
/obj/item/clothing/shoes/cookflops
|
||||
desc = "All this talk of antags, greytiding, and griefing... I just wanna grill for god's sake!"
|
||||
name = "grilling sandals"
|
||||
icon_state = "cookflops"
|
||||
can_be_tied = FALSE
|
||||
species_exception = list(/datum/species/golem)
|
||||
|
||||
/obj/item/clothing/shoes/yakuza
|
||||
name = "tojo clan shoes"
|
||||
desc = "Steel-toed and intimidating."
|
||||
icon_state = "MajimaShoes"
|
||||
inhand_icon_state = "MajimaShoes_worn"
|
||||
|
||||
/obj/item/clothing/shoes/jackbros
|
||||
name = "frosty boots"
|
||||
desc = "For when you're stepping on up to the plate."
|
||||
icon_state = "JackFrostShoes"
|
||||
inhand_icon_state = "JackFrostShoes_worn"
|
||||
/obj/item/clothing/shoes/swagshoes
|
||||
name = "swag shoes"
|
||||
desc = "They got me for my foams!"
|
||||
icon_state = "SwagShoes"
|
||||
inhand_icon_state = "SwagShoes"
|
||||
|
||||
/obj/item/clothing/shoes/gunboots //admin boots that fire gunshots randomly while walking
|
||||
name = "gunboots"
|
||||
desc = "This is what all those research points added up to, the ultimate workplace hazard."
|
||||
icon_state = "jackboots"
|
||||
inhand_icon_state = "jackboots"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
/// What projectile do we shoot?
|
||||
var/projectile_type = /obj/projectile/bullet/c10mm
|
||||
/// Each step, this is the chance we fire a shot
|
||||
var/shot_prob = 50
|
||||
|
||||
/obj/item/clothing/shoes/gunboots/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_step)
|
||||
|
||||
/obj/item/clothing/shoes/gunboots/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == ITEM_SLOT_FEET)
|
||||
RegisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/check_kick)
|
||||
else
|
||||
UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK)
|
||||
|
||||
/obj/item/clothing/shoes/gunboots/dropped(mob/user)
|
||||
if(user)
|
||||
UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK)
|
||||
return ..()
|
||||
|
||||
/// After each step, check if we randomly fire a shot
|
||||
/obj/item/clothing/shoes/gunboots/proc/check_step(mob/user)
|
||||
SIGNAL_HANDLER
|
||||
if(!prob(shot_prob))
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(src, .proc/fire_shot)
|
||||
|
||||
/// Stomping on someone while wearing gunboots shoots them point blank
|
||||
/obj/item/clothing/shoes/gunboots/proc/check_kick(mob/living/carbon/human/kicking_person, atom/attacked_atom, proximity)
|
||||
SIGNAL_HANDLER
|
||||
if(!isliving(attacked_atom))
|
||||
return
|
||||
var/mob/living/attacked_living = attacked_atom
|
||||
if(attacked_living.body_position == LYING_DOWN)
|
||||
INVOKE_ASYNC(src, .proc/fire_shot, attacked_living)
|
||||
|
||||
/// Actually fire a shot. If no target is provided, just fire off in a random direction
|
||||
/obj/item/clothing/shoes/gunboots/proc/fire_shot(atom/target)
|
||||
if(!isliving(loc))
|
||||
return
|
||||
|
||||
var/mob/living/wearer = loc
|
||||
var/obj/projectile/shot = new projectile_type(get_turf(wearer))
|
||||
|
||||
if(!target)
|
||||
target = get_offset_target_turf(get_turf(wearer), rand(-3, 3), rand(-3,3))
|
||||
|
||||
//Shooting Code:
|
||||
shot.original = target
|
||||
shot.fired_from = src
|
||||
shot.firer = wearer // don't hit ourself that would be really annoying
|
||||
shot.impacted = list(wearer = TRUE)
|
||||
shot.def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) // they're fired from boots after all
|
||||
shot.preparePixelProjectile(target, wearer)
|
||||
if(!shot.suppressed)
|
||||
wearer.visible_message(span_danger("[wearer]'s [name] fires \a [shot]!"), "", blind_message = span_hear("You hear a gunshot!"), vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
shot.fire()
|
||||
|
||||
/obj/item/clothing/shoes/gunboots/disabler
|
||||
name = "disaboots"
|
||||
projectile_type = /obj/projectile/beam/disabler
|
||||
@@ -1,114 +0,0 @@
|
||||
//CONTAINS: Suit fibers and Detective's Scanning Computer
|
||||
|
||||
/atom/proc/return_fingerprints()
|
||||
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
|
||||
if(D)
|
||||
. = D.fingerprints
|
||||
|
||||
/atom/proc/return_hiddenprints()
|
||||
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
|
||||
if(D)
|
||||
. = D.hiddenprints
|
||||
|
||||
/atom/proc/return_blood_DNA()
|
||||
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
|
||||
if(D)
|
||||
. = D.blood_DNA
|
||||
|
||||
/atom/proc/blood_DNA_length()
|
||||
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
|
||||
if(D)
|
||||
. = length(D.blood_DNA)
|
||||
|
||||
/atom/proc/return_fibers()
|
||||
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
|
||||
if(D)
|
||||
. = D.fibers
|
||||
|
||||
/atom/proc/add_fingerprint_list(list/fingerprints) //ASSOC LIST FINGERPRINT = FINGERPRINT
|
||||
if(length(fingerprints))
|
||||
. = AddComponent(/datum/component/forensics, fingerprints)
|
||||
|
||||
//Set ignoregloves to add prints irrespective of the mob having gloves on.
|
||||
/atom/proc/add_fingerprint(mob/M, ignoregloves = FALSE)
|
||||
if (QDELING(src))
|
||||
return
|
||||
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
|
||||
. = D?.add_fingerprint(M, ignoregloves)
|
||||
|
||||
/atom/proc/add_fiber_list(list/fibertext) //ASSOC LIST FIBERTEXT = FIBERTEXT
|
||||
if(length(fibertext))
|
||||
. = AddComponent(/datum/component/forensics, null, null, null, fibertext)
|
||||
|
||||
/atom/proc/add_fibers(mob/living/carbon/human/M)
|
||||
var/old = 0
|
||||
if(M.gloves && istype(M.gloves, /obj/item/clothing))
|
||||
var/obj/item/clothing/gloves/G = M.gloves
|
||||
old = length(G.return_blood_DNA())
|
||||
if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
|
||||
if(add_blood_DNA(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody
|
||||
G.transfer_blood--
|
||||
else if(M.blood_in_hands > 1)
|
||||
old = length(M.return_blood_DNA())
|
||||
if(add_blood_DNA(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old)
|
||||
M.blood_in_hands--
|
||||
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
|
||||
. = D.add_fibers(M)
|
||||
|
||||
/atom/proc/add_hiddenprint_list(list/hiddenprints) //NOTE: THIS IS FOR ADMINISTRATION FINGERPRINTS, YOU MUST CUSTOM SET THIS TO INCLUDE CKEY/REAL NAMES! CHECK FORENSICS.DM
|
||||
if(length(hiddenprints))
|
||||
. = AddComponent(/datum/component/forensics, null, hiddenprints)
|
||||
|
||||
/atom/proc/add_hiddenprint(mob/M)
|
||||
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
|
||||
. = D.add_hiddenprint(M)
|
||||
|
||||
/atom/proc/add_blood_DNA(list/dna) //ASSOC LIST DNA = BLOODTYPE
|
||||
return FALSE
|
||||
|
||||
/obj/add_blood_DNA(list/dna)
|
||||
. = ..()
|
||||
if(length(dna))
|
||||
. = AddComponent(/datum/component/forensics, null, null, dna)
|
||||
|
||||
/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
|
||||
. = ..()
|
||||
transfer_blood = rand(2, 4)
|
||||
|
||||
/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
|
||||
var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
|
||||
if(QDELETED(B)) // SKYRAT EDIT - SANITY CHECK; DONT ADD DNA TO A FUCKING DELETED BLOOD SPATTER - original: if(!B)
|
||||
B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
|
||||
if(!QDELETED(B))
|
||||
B.add_blood_DNA(blood_dna) //give blood info to the blood decal.
|
||||
return TRUE //we bloodied the floor
|
||||
|
||||
/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
|
||||
if(wear_suit)
|
||||
wear_suit.add_blood_DNA(blood_dna)
|
||||
update_inv_wear_suit()
|
||||
else if(w_uniform)
|
||||
w_uniform.add_blood_DNA(blood_dna)
|
||||
update_inv_w_uniform()
|
||||
if(gloves)
|
||||
var/obj/item/clothing/gloves/G = gloves
|
||||
G.add_blood_DNA(blood_dna)
|
||||
else if(length(blood_dna))
|
||||
AddComponent(/datum/component/forensics, null, null, blood_dna)
|
||||
blood_in_hands = rand(2, 4)
|
||||
update_inv_gloves() //handles bloody hands overlays and updating
|
||||
return TRUE
|
||||
|
||||
/*
|
||||
* Transfer all the fingerprints and hidden prints from [src] to [transfer_to].
|
||||
*/
|
||||
/atom/proc/transfer_fingerprints_to(atom/transfer_to)
|
||||
transfer_to.add_fingerprint_list(return_fingerprints())
|
||||
transfer_to.add_hiddenprint_list(return_hiddenprints())
|
||||
transfer_to.fingerprintslast = fingerprintslast
|
||||
|
||||
/*
|
||||
* Transfer all the fibers from [src] to [transfer_to].
|
||||
*/
|
||||
/atom/proc/transfer_fibers_to(atom/transfer_to)
|
||||
transfer_to.add_fiber_list(return_fibers())
|
||||
@@ -1,35 +0,0 @@
|
||||
/datum/round_event_control/spontaneous_appendicitis
|
||||
name = "Spontaneous Appendicitis"
|
||||
typepath = /datum/round_event/spontaneous_appendicitis
|
||||
//weight = 20 //ORIGINAL
|
||||
weight = 10 //SKYRAT EDIT CHANGE
|
||||
max_occurrences = 4
|
||||
earliest_start = 10 MINUTES
|
||||
min_players = 5 // To make your chance of getting help a bit higher.
|
||||
|
||||
/datum/round_event/spontaneous_appendicitis
|
||||
fakeable = FALSE
|
||||
|
||||
/datum/round_event/spontaneous_appendicitis/start()
|
||||
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
|
||||
if(!H.client)
|
||||
continue
|
||||
if(H.stat == DEAD)
|
||||
continue
|
||||
if(!H.getorgan(/obj/item/organ/internal/appendix)) //Don't give the disease to some who lacks it, only for it to be auto-cured
|
||||
continue
|
||||
if(!(H.mob_biotypes & MOB_ORGANIC)) //biotype sleeper bugs strike again, once again making appendicitis pick a target that can't take it
|
||||
continue
|
||||
if(H.z in SSmapping.levels_by_trait(ZTRAIT_CENTCOM))//not for admin/ooc stuff
|
||||
continue
|
||||
var/foundAlready = FALSE //don't infect someone that already has appendicitis
|
||||
for(var/datum/disease/appendicitis/A in H.diseases)
|
||||
foundAlready = TRUE
|
||||
break
|
||||
if(foundAlready)
|
||||
continue
|
||||
|
||||
var/datum/disease/D = new /datum/disease/appendicitis()
|
||||
H.ForceContractDisease(D, FALSE, TRUE)
|
||||
announce_to_ghosts(H)
|
||||
break
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,253 +0,0 @@
|
||||
// Starthistle
|
||||
/obj/item/seeds/starthistle
|
||||
name = "pack of starthistle seeds"
|
||||
desc = "A robust species of weed that often springs up in-between the cracks of spaceship parking lots."
|
||||
icon_state = "seed-starthistle"
|
||||
species = "starthistle"
|
||||
plantname = "Starthistle"
|
||||
lifespan = 70
|
||||
endurance = 50 // damm pesky weeds
|
||||
maturation = 5
|
||||
production = 1
|
||||
yield = 2
|
||||
potency = 10
|
||||
instability = 35
|
||||
growthstages = 3
|
||||
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
|
||||
genes = list(/datum/plant_gene/trait/plant_type/weed_hardy)
|
||||
mutatelist = list(/obj/item/seeds/starthistle/corpse_flower, /obj/item/seeds/galaxythistle)
|
||||
graft_gene = /datum/plant_gene/trait/plant_type/weed_hardy
|
||||
|
||||
/obj/item/seeds/starthistle/harvest(mob/user)
|
||||
var/obj/machinery/hydroponics/parent = loc
|
||||
var/seed_count = yield
|
||||
if(prob(getYield() * 20))
|
||||
seed_count++
|
||||
var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc
|
||||
for(var/i in 1 to seed_count)
|
||||
var/obj/item/seeds/starthistle/harvestseeds = Copy()
|
||||
harvestseeds.forceMove(output_loc)
|
||||
|
||||
parent.update_tray()
|
||||
|
||||
// Corpse flower
|
||||
/obj/item/seeds/starthistle/corpse_flower
|
||||
name = "pack of corpse flower seeds"
|
||||
desc = "A species of plant that emits a horrible odor. The odor stops being produced in difficult atmospheric conditions."
|
||||
icon_state = "seed-corpse-flower"
|
||||
species = "corpse-flower"
|
||||
plantname = "Corpse flower"
|
||||
production = 2
|
||||
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
|
||||
genes = list(/datum/plant_gene/trait/gas_production)
|
||||
mutatelist = list()
|
||||
reagents_add = list(/datum/reagent/toxin/formaldehyde = 0.1)
|
||||
|
||||
//Galaxy Thistle
|
||||
/obj/item/seeds/galaxythistle
|
||||
name = "pack of galaxythistle seeds"
|
||||
desc = "An impressive species of weed that is thought to have evolved from the simple milk thistle. Contains flavolignans that can help repair a damaged liver."
|
||||
icon_state = "seed-galaxythistle"
|
||||
species = "galaxythistle"
|
||||
plantname = "Galaxythistle"
|
||||
product = /obj/item/food/grown/galaxythistle
|
||||
lifespan = 70
|
||||
endurance = 40
|
||||
maturation = 3
|
||||
production = 2
|
||||
yield = 2
|
||||
potency = 25
|
||||
instability = 35
|
||||
growthstages = 3
|
||||
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
|
||||
genes = list(/datum/plant_gene/trait/plant_type/weed_hardy, /datum/plant_gene/trait/invasive)
|
||||
mutatelist = list()
|
||||
reagents_add = list(/datum/reagent/consumable/nutriment = 0.05, /datum/reagent/medicine/silibinin = 0.1)
|
||||
graft_gene = /datum/plant_gene/trait/invasive
|
||||
|
||||
/obj/item/seeds/galaxythistle/Initialize(mapload,nogenes)
|
||||
. = ..()
|
||||
if(!nogenes)
|
||||
unset_mutability(/datum/plant_gene/trait/invasive, PLANT_GENE_REMOVABLE)
|
||||
|
||||
/obj/item/food/grown/galaxythistle
|
||||
seed = /obj/item/seeds/galaxythistle
|
||||
name = "galaxythistle flower head"
|
||||
desc = "This spiny cluster of florets reminds you of the highlands."
|
||||
icon_state = "galaxythistle"
|
||||
bite_consumption_mod = 2
|
||||
foodtypes = VEGETABLES
|
||||
wine_power = 35
|
||||
tastes = list("thistle" = 2, "artichoke" = 1)
|
||||
|
||||
// Cabbage
|
||||
/obj/item/seeds/cabbage
|
||||
name = "pack of cabbage seeds"
|
||||
desc = "These seeds grow into cabbages."
|
||||
icon_state = "seed-cabbage"
|
||||
species = "cabbage"
|
||||
plantname = "Cabbages"
|
||||
product = /obj/item/food/grown/cabbage
|
||||
lifespan = 50
|
||||
endurance = 25
|
||||
maturation = 3
|
||||
production = 5
|
||||
yield = 4
|
||||
instability = 10
|
||||
growthstages = 1
|
||||
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
mutatelist = list(/obj/item/seeds/replicapod)
|
||||
reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1)
|
||||
seed_flags = null
|
||||
|
||||
/obj/item/food/grown/cabbage
|
||||
seed = /obj/item/seeds/cabbage
|
||||
name = "cabbage"
|
||||
desc = "Ewwwwwwwwww. Cabbage."
|
||||
icon_state = "cabbage"
|
||||
foodtypes = VEGETABLES
|
||||
wine_power = 20
|
||||
|
||||
// Sugarcane
|
||||
/obj/item/seeds/sugarcane
|
||||
name = "pack of sugarcane seeds"
|
||||
desc = "These seeds grow into sugarcane."
|
||||
icon_state = "seed-sugarcane"
|
||||
species = "sugarcane"
|
||||
plantname = "Sugarcane"
|
||||
product = /obj/item/food/grown/sugarcane
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
lifespan = 60
|
||||
endurance = 50
|
||||
maturation = 3
|
||||
yield = 4
|
||||
instability = 15
|
||||
growthstages = 2
|
||||
reagents_add = list(/datum/reagent/consumable/sugar = 0.25)
|
||||
mutatelist = list(/obj/item/seeds/bamboo)
|
||||
|
||||
/obj/item/food/grown/sugarcane
|
||||
seed = /obj/item/seeds/sugarcane
|
||||
name = "sugarcane"
|
||||
desc = "Sickly sweet."
|
||||
icon_state = "sugarcane"
|
||||
bite_consumption_mod = 2
|
||||
foodtypes = VEGETABLES | SUGAR
|
||||
distill_reagent = /datum/reagent/consumable/ethanol/rum
|
||||
|
||||
// Gatfruit
|
||||
/obj/item/seeds/gatfruit
|
||||
name = "pack of gatfruit seeds"
|
||||
desc = "These seeds grow into .357 revolvers."
|
||||
icon_state = "seed-gatfruit"
|
||||
species = "gatfruit"
|
||||
plantname = "Gatfruit Tree"
|
||||
product = /obj/item/food/grown/shell/gatfruit
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
lifespan = 20
|
||||
endurance = 20
|
||||
maturation = 40
|
||||
production = 10
|
||||
yield = 2
|
||||
potency = 60
|
||||
growthstages = 2
|
||||
rarity = 60 // Obtainable only with xenobio+superluck.
|
||||
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
|
||||
reagents_add = list(/datum/reagent/sulfur = 0.1, /datum/reagent/carbon = 0.1, /datum/reagent/nitrogen = 0.07, /datum/reagent/potassium = 0.05)
|
||||
|
||||
/obj/item/food/grown/shell/gatfruit
|
||||
seed = /obj/item/seeds/gatfruit
|
||||
name = "gatfruit"
|
||||
desc = "It smells like burning."
|
||||
icon_state = "gatfruit"
|
||||
trash_type = /obj/item/gun/ballistic/revolver
|
||||
bite_consumption_mod = 2
|
||||
foodtypes = FRUIT
|
||||
tastes = list("gunpowder" = 1)
|
||||
wine_power = 90 //It burns going down, too.
|
||||
|
||||
//Cherry Bombs
|
||||
/obj/item/seeds/cherry/bomb
|
||||
name = "pack of cherry bomb pits"
|
||||
desc = "They give you vibes of dread and frustration."
|
||||
icon_state = "seed-cherry_bomb"
|
||||
species = "cherry_bomb"
|
||||
plantname = "Cherry Bomb Tree"
|
||||
product = /obj/item/food/grown/cherry_bomb
|
||||
mutatelist = list()
|
||||
genes = list(/datum/plant_gene/trait/bomb_plant, /datum/plant_gene/trait/modified_volume/cherry_bomb)
|
||||
reagents_add = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/consumable/sugar = 0.1, /datum/reagent/gunpowder = 0.7)
|
||||
rarity = 60 //See above
|
||||
|
||||
/obj/item/food/grown/cherry_bomb
|
||||
name = "cherry bombs"
|
||||
desc = "You think you can hear the hissing of a tiny fuse."
|
||||
icon_state = "cherry_bomb"
|
||||
alt_icon = "cherry_bomb_lit"
|
||||
seed = /obj/item/seeds/cherry/bomb
|
||||
bite_consumption_mod = 3
|
||||
wine_power = 80
|
||||
|
||||
// aloe
|
||||
/obj/item/seeds/aloe
|
||||
name = "pack of aloe seeds"
|
||||
desc = "These seeds grow into aloe."
|
||||
icon_state = "seed-aloe"
|
||||
species = "aloe"
|
||||
plantname = "Aloe"
|
||||
product = /obj/item/food/grown/aloe
|
||||
lifespan = 60
|
||||
endurance = 25
|
||||
maturation = 4
|
||||
production = 4
|
||||
yield = 6
|
||||
growthstages = 5
|
||||
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
|
||||
reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.05, /datum/reagent/consumable/nutriment = 0.05)
|
||||
|
||||
/obj/item/food/grown/aloe
|
||||
seed = /obj/item/seeds/aloe
|
||||
name = "aloe"
|
||||
desc = "Cut leaves from the aloe plant."
|
||||
icon_state = "aloe"
|
||||
bite_consumption_mod = 3
|
||||
foodtypes = VEGETABLES
|
||||
juice_results = list(/datum/reagent/consumable/aloejuice = 0)
|
||||
distill_reagent = /datum/reagent/consumable/ethanol/tequila
|
||||
|
||||
/obj/item/food/grown/aloe/microwave_act(obj/machinery/microwave/M)
|
||||
new /obj/item/stack/medical/aloe(drop_location(), 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/seeds/shrub
|
||||
name = "pack of shrub seeds"
|
||||
desc = "These seeds grow into hedge shrubs."
|
||||
icon_state = "seed-shrub"
|
||||
species = "shrub"
|
||||
plantname = "Shrubbery"
|
||||
product = /obj/item/grown/shrub
|
||||
lifespan = 40
|
||||
endurance = 30
|
||||
maturation = 4
|
||||
production = 6
|
||||
yield = 2
|
||||
instability = 10
|
||||
growthstages = 3
|
||||
reagents_add = list()
|
||||
|
||||
/obj/item/grown/shrub
|
||||
seed = /obj/item/seeds/shrub
|
||||
name = "shrub"
|
||||
desc = "A shrubbery, it looks nice and it was only a few credits too. Plant it on the ground to grow a hedge, shrubbing skills not required."
|
||||
icon_state = "shrub"
|
||||
|
||||
/obj/item/grown/shrub/attack_self(mob/user)
|
||||
var/turf/player_turf = get_turf(user)
|
||||
if(player_turf?.is_blocked_turf(TRUE))
|
||||
return FALSE
|
||||
user.visible_message("<span class='danger'>[user] begins to plant \the [src]...</span>")
|
||||
if(do_after(user, 4 SECONDS, target = user.drop_location(), progress = TRUE)) //SKYRAT EDIT - ORIGINAL 8 SECONDS
|
||||
new /obj/structure/fluff/hedge/opaque(user.drop_location())
|
||||
to_chat(user, span_notice("You plant \the [src]."))
|
||||
qdel(src)
|
||||
@@ -1,43 +0,0 @@
|
||||
/datum/language/swarmer
|
||||
name = "Swarmer"
|
||||
desc = "A language only consisting of musical notes."
|
||||
spans = list(SPAN_ROBOT)
|
||||
key = "s"
|
||||
flags = NO_STUTTER
|
||||
space_chance = 100
|
||||
sentence_chance = 0
|
||||
default_priority = 60
|
||||
|
||||
icon_state = "swarmer"
|
||||
secret = TRUE // SKYRAT EDIT
|
||||
|
||||
// since various flats and sharps are the same,
|
||||
// all non-accidental notes are doubled in the list
|
||||
/* The list with unicode symbols for the accents.
|
||||
syllables = list(
|
||||
"C", "C",
|
||||
"C♯", "D♭",
|
||||
"D", "D",
|
||||
"D♯", "E♭",
|
||||
"E", "E",
|
||||
"F", "F",
|
||||
"F♯", "G♭",
|
||||
"G", "G",
|
||||
"G♯", "A♭",
|
||||
"A", "A",
|
||||
"A♯", "B♭",
|
||||
"B", "B")
|
||||
*/
|
||||
syllables = list(
|
||||
"C", "C",
|
||||
"C#", "Db",
|
||||
"D", "D",
|
||||
"D#", "Eb",
|
||||
"E", "E",
|
||||
"F", "F",
|
||||
"F#", "Gb",
|
||||
"G", "G",
|
||||
"G#", "Ab",
|
||||
"A", "A",
|
||||
"A#", "Bb",
|
||||
"B", "B")
|
||||
@@ -1,17 +0,0 @@
|
||||
/**********************Mining Equipment Vendor Items**************************/
|
||||
//misc stuff you can buy from the vendor that has special code but doesn't really need its own file
|
||||
|
||||
/**********************Facehugger toy**********************/
|
||||
/obj/item/clothing/mask/facehugger/toy
|
||||
inhand_icon_state = "facehugger_inactive"
|
||||
desc = "A toy often used to play pranks on other miners by putting it in their beds. It takes a bit to recharge after latching onto something."
|
||||
throwforce = 0
|
||||
real = 0
|
||||
sterile = 1
|
||||
tint = 3 //Makes it feel more authentic when it latches on
|
||||
special_desc_requirement = EXAMINE_CHECK_ROLE //SKYRAT EDIT
|
||||
special_desc_roles = list("ROLE_ALIEN") //SKYRAT EDIT
|
||||
special_desc = "This appears to be a mechanical mockery of our young." //SKYRAT EDIT
|
||||
|
||||
/obj/item/clothing/mask/facehugger/toy/Die()
|
||||
return
|
||||
@@ -1,125 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/cockroach
|
||||
name = "cockroach"
|
||||
desc = "This station is just crawling with bugs."
|
||||
icon_state = "cockroach"
|
||||
icon_dead = "cockroach"
|
||||
health = 1
|
||||
maxHealth = 1
|
||||
turns_per_move = 5
|
||||
loot = list(/obj/effect/decal/cleanable/insectguts)
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 270
|
||||
maxbodytemp = INFINITY
|
||||
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
|
||||
mob_size = MOB_SIZE_TINY
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BUG
|
||||
response_disarm_continuous = "shoos"
|
||||
response_disarm_simple = "shoo"
|
||||
response_harm_continuous = "splats"
|
||||
response_harm_simple = "splat"
|
||||
speak_emote = list("chitters")
|
||||
density = FALSE
|
||||
melee_damage_lower = 0
|
||||
melee_damage_upper = 0
|
||||
obj_damage = 0
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
verb_say = "chitters"
|
||||
verb_ask = "chitters inquisitively"
|
||||
verb_exclaim = "chitters loudly"
|
||||
verb_yell = "chitters loudly"
|
||||
del_on_death = TRUE
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
faction = list("neutral")
|
||||
var/squish_chance = 50
|
||||
// Randomizes hunting intervals, minumum 5 turns
|
||||
var/time_to_hunt = 5
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/Initialize()
|
||||
. = ..()
|
||||
add_cell_sample()
|
||||
make_squashable()
|
||||
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
|
||||
time_to_hunt = rand(5,10)
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/proc/make_squashable()
|
||||
AddComponent(/datum/component/squashable, squash_chance = 50, squash_damage = 1)
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/add_cell_sample()
|
||||
AddElement(/datum/element/swabable, CELL_LINE_TABLE_COCKROACH, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 7)
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/Life(delta_time = SSMOBS_DT, times_fired) // Cockroaches are predators to space ants
|
||||
. = ..()
|
||||
turns_since_scan++
|
||||
if(turns_since_scan > time_to_hunt)
|
||||
turns_since_scan = 0
|
||||
var/list/target_types = list(/obj/effect/decal/cleanable/ants)
|
||||
for(var/obj/effect/decal/cleanable/ants/potential_target in view(2, get_turf(src)))
|
||||
if(potential_target.type in target_types)
|
||||
hunt(potential_target)
|
||||
return
|
||||
|
||||
|
||||
/obj/projectile/glockroachbullet
|
||||
damage = 10 //same damage as a hivebot
|
||||
damage_type = BRUTE
|
||||
|
||||
/obj/item/ammo_casing/glockroach
|
||||
name = "0.9mm bullet casing"
|
||||
desc = "A... 0.9mm bullet casing? What?"
|
||||
projectile_type = /obj/projectile/glockroachbullet
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/glockroach
|
||||
name = "glockroach"
|
||||
desc = "HOLY SHIT, THAT COCKROACH HAS A GUN!"
|
||||
icon_state = "glockroach"
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
obj_damage = 20
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
projectilesound = 'sound/weapons/gun/pistol/shot.ogg'
|
||||
projectiletype = /obj/projectile/glockroachbullet
|
||||
casingtype = /obj/item/ammo_casing/glockroach
|
||||
ranged = TRUE
|
||||
faction = list("hostile")
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/death(gibbed)
|
||||
if(GLOB.station_was_nuked) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/ex_act() //Explosions are a terrible way to handle a cockroach.
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/hauberoach
|
||||
name = "hauberoach"
|
||||
desc = "Is that cockroach wearing a tiny yet immaculate replica 19th century Prussian spiked helmet? ...Is that a bad thing?"
|
||||
icon_state = "hauberoach"
|
||||
attack_verb_continuous = "rams its spike into"
|
||||
attack_verb_simple = "ram your spike into"
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 20
|
||||
obj_damage = 20
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_vis_effect = ATTACK_EFFECT_SLASH
|
||||
faction = list("hostile")
|
||||
sharpness = SHARP_POINTY
|
||||
squish_chance = 0 // manual squish if relevant
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/hauberoach/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/caltrop, min_damage = 10, max_damage = 15, flags = (CALTROP_BYPASS_SHOES | CALTROP_SILENT))
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/hauberoach/make_squashable()
|
||||
AddComponent(/datum/component/squashable, squash_chance = 100, squash_damage = 1, squash_callback = /mob/living/simple_animal/hostile/cockroach/hauberoach/.proc/on_squish)
|
||||
|
||||
///Proc used to override the squashing behavior of the normal cockroach.
|
||||
/mob/living/simple_animal/hostile/cockroach/hauberoach/proc/on_squish(mob/living/cockroach, mob/living/living_target)
|
||||
if(!istype(living_target))
|
||||
return FALSE //We failed to run the invoke. Might be because we're a structure. Let the squashable element handle it then!
|
||||
if(!HAS_TRAIT(living_target, TRAIT_PIERCEIMMUNE))
|
||||
living_target.visible_message(span_danger("[living_target] steps onto [cockroach]'s spike!"), span_userdanger("You step onto [cockroach]'s spike!"))
|
||||
return TRUE
|
||||
living_target.visible_message(span_notice("[living_target] squashes [cockroach], not even noticing its spike."), span_notice("You squashed [cockroach], not even noticing its spike."))
|
||||
return FALSE
|
||||
@@ -1,324 +0,0 @@
|
||||
/**
|
||||
* Atom level proc for space ninja's glove interactions.
|
||||
*
|
||||
* Proc which only occurs when space ninja uses his gloves on an atom.
|
||||
* Does nothing by default, but effects will vary.
|
||||
* Arguments:
|
||||
* * ninja_suit - The offending space ninja's suit.
|
||||
* * ninja - The human mob wearing the suit.
|
||||
* * ninja_gloves - The offending space ninja's gloves.
|
||||
*/
|
||||
/atom/proc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
//APC//
|
||||
/obj/machinery/power/apc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = FALSE //Safety check for batteries
|
||||
var/drain = 0 //Drain amount from batteries
|
||||
var/drain_total = 0
|
||||
|
||||
if(cell?.charge)
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, loc)
|
||||
|
||||
while(cell.charge> 0 && !maxcapacity)
|
||||
drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain)
|
||||
|
||||
if(cell.charge < drain)
|
||||
drain = cell.charge
|
||||
|
||||
if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge)
|
||||
drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge
|
||||
maxcapacity = TRUE//Reached maximum battery capacity.
|
||||
|
||||
if (do_after(ninja ,10, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
cell.use(drain)
|
||||
ninja_suit.cell.give(drain)
|
||||
drain_total += drain
|
||||
else
|
||||
break
|
||||
|
||||
if(!(obj_flags & EMAGGED))
|
||||
flick("apc-spark", ninja_gloves)
|
||||
playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
obj_flags |= EMAGGED
|
||||
locked = FALSE
|
||||
update_appearance()
|
||||
|
||||
return drain_total
|
||||
|
||||
//SMES//
|
||||
/obj/machinery/power/smes/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = FALSE //Safety check for batteries
|
||||
var/drain = 0 //Drain amount from batteries
|
||||
var/drain_total = 0
|
||||
|
||||
if(charge)
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, loc)
|
||||
|
||||
while(charge > 0 && !maxcapacity)
|
||||
drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain)
|
||||
|
||||
if(charge < drain)
|
||||
drain = charge
|
||||
|
||||
if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge)
|
||||
drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge
|
||||
maxcapacity = TRUE
|
||||
|
||||
if (do_after(ninja,10, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
charge -= drain
|
||||
ninja_suit.cell.give(drain)
|
||||
drain_total += drain
|
||||
|
||||
else
|
||||
break
|
||||
|
||||
return drain_total
|
||||
|
||||
//CELL//
|
||||
/obj/item/stock_parts/cell/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/drain_total = 0
|
||||
|
||||
if(charge)
|
||||
if(do_after(ninja, 30, target = src))
|
||||
drain_total = charge
|
||||
if(ninja_suit.cell.charge + charge > ninja_suit.cell.maxcharge)
|
||||
ninja_suit.cell.charge = ninja_suit.cell.maxcharge
|
||||
else
|
||||
ninja_suit.cell.give(charge)
|
||||
charge = 0
|
||||
corrupt()
|
||||
update_appearance()
|
||||
|
||||
return drain_total
|
||||
|
||||
//RD SERVER//
|
||||
/obj/machinery/rnd/server/master/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
. = DRAIN_RD_HACK_FAILED
|
||||
|
||||
// If the traitor theft objective is still present, this will destroy it...
|
||||
if(!source_code_hdd)
|
||||
return ..()
|
||||
|
||||
to_chat(ninja, span_notice("Hacking \the [src]..."))
|
||||
AI_notify_hack()
|
||||
to_chat(ninja, span_notice("Encrypted source code detected. Overloading storage device..."))
|
||||
if(do_after(ninja, 30 SECONDS, target = src))
|
||||
overload_source_code_hdd()
|
||||
to_chat(ninja, span_notice("Sabotage complete. Storage device overloaded."))
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/research_secrets/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
|
||||
/obj/machinery/rnd/server/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
. = DRAIN_RD_HACK_FAILED
|
||||
|
||||
to_chat(ninja, span_notice("Research notes detected. Corrupting data..."))
|
||||
|
||||
if(!do_after(ninja, 30 SECONDS, target = src))
|
||||
return
|
||||
|
||||
SSresearch.science_tech.modify_points_all(0)
|
||||
to_chat(ninja, span_notice("Sabotage complete. Research notes corrupted."))
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/research_secrets/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
|
||||
//SECURITY CONSOLE//
|
||||
/obj/machinery/computer/secure_data/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
AI_notify_hack()
|
||||
if(do_after(ninja, 200))
|
||||
for(var/datum/data/record/rec in sort_record(GLOB.data_core.general, sortBy, order))
|
||||
for(var/datum/data/record/security_record in GLOB.data_core.security)
|
||||
security_record.fields["criminal"] = "*Arrest*"
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/security_scramble/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
|
||||
/* SKYRAT EDIT REMOVAL
|
||||
//COMMUNICATIONS CONSOLE//
|
||||
/obj/machinery/computer/communications/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
if(ninja_gloves.communication_console_hack_success)
|
||||
return
|
||||
if(machine_stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
AI_notify_hack()
|
||||
if(!do_after(ninja, 30 SECONDS, src))
|
||||
return
|
||||
hack_console(ninja)
|
||||
ninja_gloves.communication_console_hack_success = TRUE
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/terror_message/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
*/
|
||||
|
||||
//AIRLOCK//
|
||||
/obj/machinery/door/airlock/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
if(!operating && density && hasPower() && !(obj_flags & EMAGGED))
|
||||
emag_act()
|
||||
ninja_gloves.door_hack_counter++
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/door_jack/objective = locate() in ninja_antag.objectives
|
||||
if(objective && objective.doors_required <= ninja_gloves.door_hack_counter)
|
||||
objective.completed = TRUE
|
||||
|
||||
//WIRE//
|
||||
/obj/structure/cable/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = FALSE //Safety check
|
||||
var/drain = 0 //Drain amount
|
||||
|
||||
var/drain_total = 0
|
||||
|
||||
var/datum/powernet/wire_powernet = powernet
|
||||
while(!maxcapacity && src)
|
||||
drain = (round((rand(ninja_gloves.mindrain, ninja_gloves.maxdrain))/2))
|
||||
var/drained = 0
|
||||
if(wire_powernet && do_after(ninja ,10, target = src))
|
||||
drained = min(drain, delayed_surplus())
|
||||
add_delayedload(drained)
|
||||
if(drained < drain)//if no power on net, drain apcs
|
||||
for(var/obj/machinery/power/terminal/affected_terminal in wire_powernet.nodes)
|
||||
if(istype(affected_terminal.master, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/AP = affected_terminal.master
|
||||
if(AP.operating && AP.cell && AP.cell.charge > 0)
|
||||
AP.cell.charge = max(0, AP.cell.charge - 5)
|
||||
drained += 5
|
||||
else
|
||||
break
|
||||
|
||||
ninja_suit.cell.give(drain)
|
||||
if(ninja_suit.cell.charge > ninja_suit.cell.maxcharge)
|
||||
drain_total += (drained-(ninja_suit.cell.charge - ninja_suit.cell.maxcharge))
|
||||
ninja_suit.cell.charge = ninja_suit.cell.maxcharge
|
||||
maxcapacity = TRUE
|
||||
else
|
||||
drain_total += drained
|
||||
ninja_suit.spark_system.start()
|
||||
|
||||
return drain_total
|
||||
|
||||
//MECH//
|
||||
/obj/vehicle/sealed/mecha/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = FALSE //Safety check
|
||||
var/drain = 0 //Drain amount
|
||||
var/drain_total = 0
|
||||
|
||||
to_chat(occupants, "[icon2html(src, occupants)][span_danger("Warning: Unauthorized access through sub-route 4, block H, detected.")]")
|
||||
if(get_charge())
|
||||
while(cell.charge > 0 && !maxcapacity)
|
||||
drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain)
|
||||
if(cell.charge < drain)
|
||||
drain = cell.charge
|
||||
if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge)
|
||||
drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge
|
||||
maxcapacity = TRUE
|
||||
if (do_after(ninja, 10, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
cell.use(drain)
|
||||
ninja_suit.cell.give(drain)
|
||||
drain_total += drain
|
||||
else
|
||||
break
|
||||
|
||||
return drain_total
|
||||
|
||||
//BORG//
|
||||
/mob/living/silicon/robot/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
//SKYRAT EDIT: ADDITION START
|
||||
var/list/modelselected = list()
|
||||
modelselected["Assault"] = "/obj/item/robot_model/ninja"
|
||||
modelselected["Medical"] = "/obj/item/robot_model/ninja/ninja_medical"
|
||||
modelselected["Saboteur"] = "/obj/item/robot_model/ninja_saboteur"
|
||||
//SKYRAT EDIT: ADDITION END
|
||||
|
||||
if(!ninja_suit || !ninja || !ninja_gloves || (ROLE_NINJA in faction))
|
||||
return INVALID_DRAIN
|
||||
|
||||
to_chat(src, span_danger("Warni-***BZZZZZZZZZRT*** UPLOADING SPYDERPATCHER VERSION 9.5.2..."))
|
||||
if (do_after(ninja, 60, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
to_chat(src, span_danger("UPLOAD COMPLETE. NEW CYBORG MODEL DETECTED. INSTALLING..."))
|
||||
faction = list(ROLE_NINJA)
|
||||
bubble_icon = "syndibot"
|
||||
UnlinkSelf()
|
||||
ionpulse = TRUE
|
||||
laws = new /datum/ai_laws/ninja_override()
|
||||
//SKYRAT EDIT CHANGE BEGIN - Role Selection
|
||||
//model.transform_to(pick(/obj/item/robot_model/syndicate, /obj/item/robot_model/syndicate_medical, /obj/item/robot_model/saboteur)) - SKYRAT EDIT - ORIGINAL
|
||||
var/choice = input(src,"What role do you wish to become?","Select Role") in sort_list(modelselected)
|
||||
model.transform_to(modelselected[choice])
|
||||
//SKYRAT EDIT CHANGE END
|
||||
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/cyborg_hijack/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
|
||||
//CARBON MOBS//
|
||||
/mob/living/carbon/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
. = DRAIN_MOB_SHOCK_FAILED
|
||||
|
||||
//Default cell = 10,000 charge, 10,000/1000 = 10 uses without charging/upgrading
|
||||
if(ninja_suit.cell?.charge && ninja_suit.cell.use(1000))
|
||||
. = DRAIN_MOB_SHOCK
|
||||
//Got that electric touch
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, loc)
|
||||
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
visible_message(span_danger("[ninja] electrocutes [src] with [ninja.p_their()] touch!"), span_userdanger("[ninja] electrocutes you with [ninja.p_their()] touch!"))
|
||||
Knockdown(3 SECONDS)
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* # Ninja Shoes
|
||||
*
|
||||
* Space ninja's shoes. Gives him armor on his feet.
|
||||
*
|
||||
* Space ninja's ninja shoes. How mousey. Gives him slip protection and protection against attacks.
|
||||
* Also are temperature resistant.
|
||||
*
|
||||
*/
|
||||
/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"
|
||||
inhand_icon_state = "secshoes"
|
||||
clothing_flags = NOSLIP
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
armor = list(MELEE = 40, BULLET = 30, LASER = 20, ENERGY = 15, BOMB = 30, BIO = 100, FIRE = 100, ACID = 100)
|
||||
strip_delay = 120
|
||||
cold_protection = FEET
|
||||
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
|
||||
heat_protection = FEET
|
||||
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
|
||||
slowdown = -0.5 //SKYRAT EDIT CHANGE
|
||||
@@ -1,256 +0,0 @@
|
||||
/**
|
||||
* # Ninja Suit
|
||||
*
|
||||
* Space ninja's suit. Provides him with most of his powers.
|
||||
*
|
||||
* Space ninja's suit. Gives space ninja all his iconic powers, which are mostly kept in
|
||||
* the folder ninja_equipment_actions. Has a lot of unique stuff going on, so make sure to check
|
||||
* the variables. Check suit_attackby to see radium interaction, disk copying, and cell replacement.
|
||||
*
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja
|
||||
name = "ninja suit"
|
||||
desc = "A unique, vacuum-proof suit of nano-enhanced armor designed specifically for Spider Clan assassins."
|
||||
icon_state = "s-ninja"
|
||||
inhand_icon_state = "s-ninja_suit"
|
||||
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/stock_parts/cell)
|
||||
resistance_flags = LAVA_PROOF | ACID_PROOF
|
||||
armor = list(MELEE = 40, BULLET = 30, LASER = 20,ENERGY = 30, BOMB = 30, BIO = 100, FIRE = 100, ACID = 100)
|
||||
strip_delay = 12
|
||||
slowdown = 0 // SKYRAT EDIT ADDITION
|
||||
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
|
||||
actions_types = list(/datum/action/item_action/initialize_ninja_suit, /datum/action/item_action/ninjastatus, /datum/action/item_action/ninjaboost, /datum/action/item_action/ninjapulse, /datum/action/item_action/ninjastar, /datum/action/item_action/ninjanet, /datum/action/item_action/ninja_sword_recall, /datum/action/item_action/ninja_stealth)
|
||||
|
||||
///The person wearing the suit
|
||||
var/mob/living/carbon/human/affecting = null
|
||||
///The suit's spark system, used for... sparking.
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
///The suit's stored research. Used for the research objective (see antagonist file)
|
||||
var/datum/techweb/stored_research
|
||||
///The katana registered with the suit, used for recalling and catching the katana. Set when the ninja outfit is created.
|
||||
var/obj/item/energy_katana/energyKatana
|
||||
|
||||
///The space ninja's hood.
|
||||
var/obj/item/clothing/head/helmet/space/space_ninja/n_hood
|
||||
///The space ninja's shoes.
|
||||
var/obj/item/clothing/shoes/space_ninja/n_shoes
|
||||
///The space ninja's gloves.
|
||||
var/obj/item/clothing/gloves/space_ninja/n_gloves
|
||||
///The space ninja's mask.
|
||||
var/obj/item/clothing/mask/gas/space_ninja/n_mask
|
||||
|
||||
///Whether or not the suit is currently booted up. Starts off.
|
||||
var/s_initialized = FALSE//Suit starts off.
|
||||
///The suit's current cooldown. If not 0, blocks usage of most abilities, and decrements its value by 1 every process
|
||||
var/s_coold = 0
|
||||
///How much energy the suit expends in a single process
|
||||
var/s_cost = 1
|
||||
///Additional energy cost for cloaking per process
|
||||
var/s_acost = 4
|
||||
///How fast the suit is at certain actions, like draining power from things
|
||||
var/s_delay = 40
|
||||
///Units of radium required to refill the adrenaline boost
|
||||
var/a_transfer = 20//How much radium is required to refill the adrenaline boost.
|
||||
///Whether or not the suit is currently in stealth mode.
|
||||
var/stealth = FALSE//Stealth off.
|
||||
///Whether or not the wearer is in the middle of an action, like hacking.
|
||||
var/s_busy = FALSE
|
||||
///Whether or not the adrenaline boost ability is available
|
||||
var/a_boost = TRUE
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/examine(mob/user)
|
||||
. = ..()
|
||||
if(!s_initialized)
|
||||
return
|
||||
if(!user == affecting)
|
||||
return
|
||||
. += "All systems operational. Current energy capacity: <B>[display_energy(cell.charge)]</B>.\n"+\
|
||||
"The CLOAK-tech device is <B>[stealth?"active":"inactive"]</B>.\n"+\
|
||||
"[a_boost?"An adrenaline boost is available to use.":"There is no adrenaline boost available. Try refilling the suit with 20 units of radium."]"
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
//Spark Init
|
||||
spark_system = new
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
|
||||
//Research Init
|
||||
stored_research = new()
|
||||
|
||||
//Cell Init
|
||||
cell = new/obj/item/stock_parts/cell/high
|
||||
cell.charge = 9000
|
||||
cell.name = "black power cell"
|
||||
cell.icon_state = "blkcell" //SKYRAT EDIT - original "bscell" - changed due to basetype's icon path/overlays changing
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
QDEL_NULL(cell)
|
||||
return ..()
|
||||
|
||||
// seal the cell in the ninja outfit
|
||||
/obj/item/clothing/suit/space/space_ninja/toggle_spacesuit_cell(mob/user)
|
||||
return
|
||||
|
||||
// Space Suit temperature regulation and power usage
|
||||
/obj/item/clothing/suit/space/space_ninja/process(delta_time)
|
||||
var/mob/living/carbon/human/user = src.loc
|
||||
if(!user || !ishuman(user) || !(user.wear_suit == src))
|
||||
return
|
||||
|
||||
// Check for energy usage
|
||||
if(s_initialized)
|
||||
if(!affecting)
|
||||
terminate() // Kills the suit and attached objects.
|
||||
else if(cell.charge > 0)
|
||||
if(s_coold > 0)
|
||||
s_coold = max(s_coold - delta_time, 0) // Checks for ability s_cooldown first.
|
||||
cell.charge -= s_cost * delta_time // s_cost is the default energy cost each ntick, usually 5.
|
||||
if(stealth) // If stealth is active.
|
||||
cell.charge -= s_acost * delta_time
|
||||
else
|
||||
cell.charge = 0
|
||||
cancel_stealth()
|
||||
|
||||
user.adjust_bodytemperature(BODYTEMP_NORMAL - user.bodytemperature)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/ui_action_click(mob/user, action)
|
||||
if(IS_NINJA_SUIT_INITIALIZATION(action))
|
||||
toggle_on_off()
|
||||
return TRUE
|
||||
if(!s_initialized)
|
||||
to_chat(user, span_warning("<b>ERROR</b>: suit offline. Please activate suit."))
|
||||
return FALSE
|
||||
if(s_coold > 0)
|
||||
to_chat(user, span_warning("<b>ERROR</b>: suit is on cooldown."))
|
||||
return FALSE
|
||||
if(IS_NINJA_SUIT_STATUS(action))
|
||||
ninjastatus()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_BOOST(action))
|
||||
ninjaboost()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_EMP(action))
|
||||
ninjapulse()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_STAR_CREATION(action))
|
||||
ninjastar()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_NET_CREATION(action))
|
||||
ninjanet()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_SWORD_RECALL(action))
|
||||
ninja_sword_recall()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_STEALTH(action))
|
||||
toggle_stealth()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
. = ..()
|
||||
if(stealth)
|
||||
cancel_stealth()
|
||||
s_coold = 5
|
||||
|
||||
/**
|
||||
* Proc for changing the suit's appearance upon locking.
|
||||
*
|
||||
* Proc for when space ninja's suit locks. If the user selects Original, gives it glowing lights, along with having an alternate sprite for female body types.
|
||||
* Yes, we do have nipLEDs, how could you tell?
|
||||
* If the user selects New Age, it applies new sprites to all the gear.
|
||||
* Arguments:
|
||||
* * ninja - The person wearing the suit.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/lockIcons(mob/living/carbon/human/ninja)
|
||||
var/design_choice = tgui_alert(ninja, "Please choose your desired suit design.",,list("Original","New Age"))
|
||||
switch(design_choice)
|
||||
if("Original")
|
||||
icon_state = ninja.physique == "female" ? "s-ninjanf" : "s-ninjan"
|
||||
ninja.gloves.icon_state = "s-ninjan"
|
||||
ninja.gloves.inhand_icon_state = "s-ninjan"
|
||||
if("New Age")
|
||||
icon_state ="ninja_new"
|
||||
n_hood.icon_state = "ninja_newcowl"
|
||||
n_gloves.icon_state = "ninja_new"
|
||||
if(n_mask)
|
||||
n_mask.icon_state = "ninja_new"
|
||||
|
||||
|
||||
/**
|
||||
* Proc called to lock the important gear pieces onto space ninja's body.
|
||||
*
|
||||
* Called during the suit startup to lock all gear pieces onto space ninja.
|
||||
* Terminates if a gear piece is not being worn. Also gives the ninja the inability to use firearms.
|
||||
* If the person in the suit isn't a ninja when this is called, this proc just gibs them instead.
|
||||
* Arguments:
|
||||
* * ninja - The person wearing the suit.
|
||||
* * Returns false if the locking fails due to lack of all suit parts, and true if it succeeds.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/ninja)
|
||||
if(!istype(ninja))
|
||||
return FALSE
|
||||
if(!IS_SPACE_NINJA(ninja))
|
||||
to_chat(ninja, span_danger("<B>fÄTaL ÈÈRRoR</B>: 382200-*#00CÖDE <B>RED</B>\nUNAUHORIZED USÈ DETÈCeD\nCoMMÈNCING SUB-R0UIN3 13...\nTÈRMInATING U-U-USÈR..."))
|
||||
ninja.gib()
|
||||
return FALSE
|
||||
if(!istype(ninja.head, /obj/item/clothing/head/helmet/space/space_ninja))
|
||||
to_chat(ninja, "[span_userdanger("ERROR")]: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...")
|
||||
return FALSE
|
||||
if(!istype(ninja.shoes, /obj/item/clothing/shoes/space_ninja))
|
||||
to_chat(ninja, "[span_userdanger("ERROR")]: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...")
|
||||
return FALSE
|
||||
if(!istype(ninja.gloves, /obj/item/clothing/gloves/space_ninja))
|
||||
to_chat(ninja, "[span_userdanger("ERROR")]: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...")
|
||||
return FALSE
|
||||
affecting = ninja
|
||||
ADD_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_hood = ninja.head
|
||||
ADD_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes = ninja.shoes
|
||||
ADD_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_gloves = ninja.gloves
|
||||
ADD_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_mask = ninja.wear_mask
|
||||
|
||||
ADD_TRAIT(ninja, TRAIT_NOGUNS, NINJA_SUIT_TRAIT)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Proc called to unlock all the gear off space ninja's body.
|
||||
*
|
||||
* Proc which is essentially the opposite of lock_suit. Lets you take off all the suit parts.
|
||||
* Also gets rid of the objection to using firearms from the wearer.
|
||||
* Arguments:
|
||||
* * ninja - The person wearing the suit.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/unlock_suit(mob/living/carbon/human/ninja)
|
||||
affecting = null
|
||||
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
icon_state = "s-ninja"
|
||||
if(n_hood)//Should be attached, might not be attached.
|
||||
REMOVE_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_hood.icon_state = "s-ninja"
|
||||
if(n_shoes)
|
||||
REMOVE_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
if(n_gloves)
|
||||
n_gloves.icon_state = "black"
|
||||
REMOVE_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_gloves.draining = FALSE
|
||||
|
||||
REMOVE_TRAIT(ninja, TRAIT_NOGUNS, NINJA_SUIT_TRAIT)
|
||||
if(n_mask)
|
||||
n_mask.icon_state = "s-ninja"
|
||||
|
||||
/**
|
||||
* Proc used to delete all the attachments and itself.
|
||||
*
|
||||
* Can be called to entire rid of the suit pieces and the suit itself.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/terminate()
|
||||
QDEL_NULL(n_hood)
|
||||
QDEL_NULL(n_gloves)
|
||||
QDEL_NULL(n_shoes)
|
||||
QDEL_NULL(src)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,86 +0,0 @@
|
||||
/* SKYRAT EDIT REMOVAL BEGIN
|
||||
/proc/set_security_level(level)
|
||||
switch(level)
|
||||
if("green")
|
||||
level = SEC_LEVEL_GREEN
|
||||
if("blue")
|
||||
level = SEC_LEVEL_BLUE
|
||||
if("red")
|
||||
level = SEC_LEVEL_RED
|
||||
if("delta")
|
||||
level = SEC_LEVEL_DELTA
|
||||
|
||||
//Will not be announced if you try to set to the same level as it already is
|
||||
if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != SSsecurity_level.current_level)
|
||||
switch(level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
minor_announce(CONFIG_GET(string/alert_green), "Attention! Security level lowered to green:")
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
||||
if(SSsecurity_level.current_level >= SEC_LEVEL_RED)
|
||||
SSshuttle.emergency.modTimer(4)
|
||||
else
|
||||
SSshuttle.emergency.modTimer(2)
|
||||
if(SEC_LEVEL_BLUE)
|
||||
if(SSsecurity_level.current_level < SEC_LEVEL_BLUE)
|
||||
minor_announce(CONFIG_GET(string/alert_blue_upto), "Attention! Security level elevated to blue:",1)
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
||||
SSshuttle.emergency.modTimer(0.5)
|
||||
else
|
||||
minor_announce(CONFIG_GET(string/alert_blue_downto), "Attention! Security level lowered to blue:")
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
||||
SSshuttle.emergency.modTimer(2)
|
||||
if(SEC_LEVEL_RED)
|
||||
if(SSsecurity_level.current_level < SEC_LEVEL_RED)
|
||||
minor_announce(CONFIG_GET(string/alert_red_upto), "Attention! Code red!",1)
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
||||
if(SSsecurity_level.current_level == SEC_LEVEL_GREEN)
|
||||
SSshuttle.emergency.modTimer(0.25)
|
||||
else
|
||||
SSshuttle.emergency.modTimer(0.5)
|
||||
else
|
||||
minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!")
|
||||
if(SEC_LEVEL_DELTA)
|
||||
minor_announce(CONFIG_GET(string/alert_delta), "Attention! Delta security level reached!",1)
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
||||
if(SSsecurity_level.current_level == SEC_LEVEL_GREEN)
|
||||
SSshuttle.emergency.modTimer(0.25)
|
||||
else if(SSsecurity_level.current_level == SEC_LEVEL_BLUE)
|
||||
SSshuttle.emergency.modTimer(0.5)
|
||||
|
||||
SSsecurity_level.set_level(level)
|
||||
|
||||
/proc/get_security_level()
|
||||
switch(SSsecurity_level.current_level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
return "green"
|
||||
if(SEC_LEVEL_BLUE)
|
||||
return "blue"
|
||||
if(SEC_LEVEL_RED)
|
||||
return "red"
|
||||
if(SEC_LEVEL_DELTA)
|
||||
return "delta"
|
||||
|
||||
/proc/num2seclevel(num)
|
||||
switch(num)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
return "green"
|
||||
if(SEC_LEVEL_BLUE)
|
||||
return "blue"
|
||||
if(SEC_LEVEL_RED)
|
||||
return "red"
|
||||
if(SEC_LEVEL_DELTA)
|
||||
return "delta"
|
||||
|
||||
/proc/seclevel2num(seclevel)
|
||||
switch( lowertext(seclevel) )
|
||||
if("green")
|
||||
return SEC_LEVEL_GREEN
|
||||
if("blue")
|
||||
return SEC_LEVEL_BLUE
|
||||
if("red")
|
||||
return SEC_LEVEL_RED
|
||||
if("delta")
|
||||
return SEC_LEVEL_DELTA
|
||||
|
||||
*/
|
||||
//SKYRAT EDIT END
|
||||
@@ -105,6 +105,8 @@
|
||||
window.send_message("ping")
|
||||
var/flush_queue = window.send_asset(get_asset_datum(
|
||||
/datum/asset/simple/namespaced/fontawesome))
|
||||
flush_queue |= window.send_asset(get_asset_datum(
|
||||
/datum/asset/simple/namespaced/tgfont))
|
||||
for(var/datum/asset/asset in src_object.ui_assets(user))
|
||||
flush_queue |= window.send_asset(asset)
|
||||
if (flush_queue)
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
get_asset_datum(/datum/asset/simple/tgui_panel),
|
||||
))
|
||||
window.send_asset(get_asset_datum(/datum/asset/simple/namespaced/fontawesome))
|
||||
window.send_asset(get_asset_datum(/datum/asset/simple/namespaced/tgfont))
|
||||
window.send_asset(get_asset_datum(/datum/asset/spritesheet/chat))
|
||||
// Other setup
|
||||
request_telemetry()
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/****************Explorer's Suit and Mask****************/
|
||||
/obj/item/clothing/suit/hooded/explorer
|
||||
icon = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi' // To keep the old version.
|
||||
worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi' // To keep the old version.
|
||||
icon_state = "explorer"
|
||||
inhand_icon_state = "explorer"
|
||||
|
||||
/obj/item/clothing/head/hooded/explorer
|
||||
icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' // To keep the old version before #8911
|
||||
worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' // To keep the old version before #8911
|
||||
icon_state = "explorer"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 425 200" opacity=".33">
|
||||
<path d="m 178.00399,0.03869 -71.20393,0 a 6.7613422,6.0255495 0 0 0 -6.76134,6.02555 l 0,187.87147 a 6.7613422,6.0255495 0 0 0 6.76134,6.02554 l 53.1072,0 a 6.7613422,6.0255495 0 0 0 6.76135,-6.02554 l 0,-101.544018 72.21628,104.699398 a 6.7613422,6.0255495 0 0 0 5.76015,2.87016 l 73.55487,0 a 6.7613422,6.0255495 0 0 0 6.76135,-6.02554 l 0,-187.87147 a 6.7613422,6.0255495 0 0 0 -6.76135,-6.02555 l -54.71644,0 a 6.7613422,6.0255495 0 0 0 -6.76133,6.02555 l 0,102.61935 L 183.76413,2.90886 a 6.7613422,6.0255495 0 0 0 -5.76014,-2.87017 z" />
|
||||
<path d="M 4.8446333,22.10875 A 13.412039,12.501842 0 0 1 13.477588,0.03924 l 66.118315,0 a 5.3648158,5.000737 0 0 1 5.364823,5.00073 l 0,79.87931 z" />
|
||||
<path d="m 420.15535,177.89119 a 13.412038,12.501842 0 0 1 -8.63295,22.06951 l -66.11832,0 a 5.3648152,5.000737 0 0 1 -5.36482,-5.00074 l 0,-79.87931 z" />
|
||||
</svg>
|
||||
<!-- This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. -->
|
||||
<!-- http://creativecommons.org/licenses/by-sa/4.0/ -->
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 200 289.742" opacity=".33">
|
||||
<path d="m 93.537677,0 c -18.113125,0 -34.220133,3.11164 -48.323484,9.33437 -13.965092,6.22167 -24.612442,15.07114 -31.940651,26.5471 -7.1899398,11.33789 -10.3012266,24.74911 -10.3012266,40.23478 0,10.64662 2.7250026,20.46465 8.1751116,29.45258 5.615277,8.98686 14.038277,17.35204 25.268821,25.09436 11.230544,7.60531 26.507421,15.41835 45.830514,23.43782 19.983748,8.29557 34.848848,15.55471 44.592998,21.77638 9.74414,6.22273 16.7617,12.8585 21.05572,19.90951 4.29404,7.05208 6.44193,15.76408 6.44193,26.13459 0,16.17702 -5.20196,28.48222 -15.60673,36.91682 -10.2396,8.4347 -25.02203,12.6523 -44.345169,12.6523 -14.038171,0 -25.515247,-1.6594 -34.433618,-4.9777 -8.91837,-3.4566 -16.185572,-8.7113 -21.800839,-15.7633 -5.615277,-7.0521 -10.074795,-16.66088 -13.377899,-28.82812 l -24.7731626293945,0 0,56.82632 C 33.856769,286.07601 63.74904,289.74201 89.678383,289.74201 c 16.020027,0 30.719787,-1.3827 44.097337,-4.1479 13.54272,-2.9043 25.1041,-7.4676 34.68309,-13.6893 9.74413,-6.3597 17.34042,-14.5195 22.79052,-24.4748 5.4501,-10.09332 8.17511,-22.39959 8.17511,-36.91682 0,-12.99764 -3.3021,-24.33539 -9.90829,-34.0146 -6.44105,-9.81725 -15.52545,-18.52707 -27.25146,-26.13133 -11.56085,-7.60427 -27.91083,-15.83142 -49.05066,-24.68022 -17.50644,-7.19012 -30.719668,-13.68948 -39.638038,-19.49701 -8.918371,-5.80752 -18.607474,-12.43409 -24.096524,-18.87417 -5.426043,-6.36616 -9.658826,-15.07003 -9.658826,-24.88729 0,-9.26401 2.075414,-17.21345 6.223454,-23.85033 11.098298,-14.39748 41.286638,-1.79507 45.075609,24.34762 4.839392,6.77491 8.84935,16.24729 12.029515,28.4156 l 20.53234,0 0,-55.99967 c -4.47825,-5.92448 -9.95488,-10.63222 -15.90837,-14.37411 1.64055,0.47905 3.19039,1.02376 4.63865,1.64024 6.49861,2.62607 12.16793,7.32747 17.0073,14.10345 4.83939,6.77491 8.84935,16.24567 12.02952,28.41397 0,0 8.48128,-0.12894 8.48978,-0.002 0.41776,6.41494 -1.75339,9.45286 -4.12342,12.56104 -2.4174,3.16978 -5.14486,6.78973 -4.00278,13.0029 1.50786,8.20318 10.18354,10.59642 14.62194,9.31154 -3.31842,-0.49911 -5.31855,-1.74948 -5.31855,-1.74948 0,0 1.87646,0.99868 5.65117,-1.35981 -3.27695,0.95571 -10.70529,-0.79738 -11.80125,-6.76313 -0.95752,-5.20861 0.94654,-7.29514 3.40113,-10.51482 2.45462,-3.21968 5.28426,-6.95831 4.6843,-14.48824 l 0.003,0.002 8.92676,0 0,-55.99967 c -15.07125,-3.87168 -27.65314,-6.36042 -37.74671,-7.46586 -9.95531,-1.10755 -20.18823,-1.65981 -30.696613,-1.65981 z m 70.321603,17.30893 0.23805,40.3049 c 1.31808,1.22666 2.43965,2.27815 3.34081,3.10602 4.83939,6.77491 8.84934,16.24566 12.02951,28.41397 l 20.53234,0 0,-55.99967 c -6.67731,-4.59381 -19.83643,-10.47309 -36.14071,-15.82522 z m -28.12049,5.60551 8.56479,17.71655 c -11.97037,-6.46697 -13.84678,-9.71726 -8.56479,-17.71655 z m 22.79705,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z m 15.22195,24.00848 8.56479,17.71655 c -11.97038,-6.46697 -13.84679,-9.71726 -8.56479,-17.71655 z m 22.79704,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z m -99.11384,2.20764 8.56479,17.71655 c -11.970382,-6.46697 -13.846782,-9.71726 -8.56479,-17.71655 z m 22.79542,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z" />
|
||||
</svg>
|
||||
<!-- This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. -->
|
||||
<!-- http://creativecommons.org/licenses/by-sa/4.0/ -->
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -1,91 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
dmepath=""
|
||||
retval=1
|
||||
|
||||
for var
|
||||
do
|
||||
if [[ $var != -* && $var == *.dme ]]
|
||||
then
|
||||
dmepath=`echo $var | sed -r 's/.{4}$//'`
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $dmepath == "" ]]
|
||||
then
|
||||
echo "No .dme file specified, aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -a $dmepath.mdme ]]
|
||||
then
|
||||
rm $dmepath.mdme
|
||||
fi
|
||||
|
||||
cp $dmepath.dme $dmepath.mdme
|
||||
if [[ $? != 0 ]]
|
||||
then
|
||||
echo "Failed to make modified dme, aborting."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
for var
|
||||
do
|
||||
arg=`echo $var | sed -r 's/^.{2}//'`
|
||||
if [[ $var == -D* ]]
|
||||
then
|
||||
sed -i '1s/^/#define '$arg'\n/' $dmepath.mdme
|
||||
continue
|
||||
fi
|
||||
done
|
||||
|
||||
#windows
|
||||
if [[ `uname` == MINGW* ]]
|
||||
then
|
||||
dm=""
|
||||
|
||||
if hash dm.exe 2>/dev/null
|
||||
then
|
||||
dm='dm.exe'
|
||||
elif [[ -a '/c/Program Files (x86)/BYOND/bin/dm.exe' ]]
|
||||
then
|
||||
dm='/c/Program Files (x86)/BYOND/bin/dm.exe'
|
||||
elif [[ -a '/c/Program Files/BYOND/bin/dm.exe' ]]
|
||||
then
|
||||
dm='/c/Program Files/BYOND/bin/dm.exe'
|
||||
fi
|
||||
|
||||
if [[ $dm == "" ]]
|
||||
then
|
||||
echo "Couldn't find the DreamMaker executable, aborting."
|
||||
exit 3
|
||||
fi
|
||||
|
||||
"$dm" $dmepath.mdme 2>&1 | tee result.log
|
||||
retval=$?
|
||||
if ! grep '\- 0 errors, 0 warnings' result.log
|
||||
then
|
||||
retval=1 #hard fail, due to warnings or errors
|
||||
fi
|
||||
else
|
||||
if hash DreamMaker 2>/dev/null
|
||||
then
|
||||
DreamMaker -max_errors 0 $dmepath.mdme 2>&1 | tee result.log
|
||||
retval=$?
|
||||
if ! grep '\- 0 errors, 0 warnings' result.log
|
||||
then
|
||||
retval=1 #hard fail, due to warnings or errors
|
||||
fi
|
||||
else
|
||||
echo "Couldn't find the DreamMaker executable, aborting."
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
mv $dmepath.mdme.dmb $dmepath.dmb
|
||||
mv $dmepath.mdme.rsc $dmepath.rsc
|
||||
|
||||
rm $dmepath.mdme
|
||||
|
||||
exit $retval
|
||||
@@ -1,95 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
from subprocess import PIPE, STDOUT
|
||||
|
||||
null = open("/dev/null", "wb")
|
||||
|
||||
def wait(p):
|
||||
rc = p.wait()
|
||||
if rc != 0:
|
||||
p = play("sound/misc/compiler-failure.ogg")
|
||||
p.wait()
|
||||
assert p.returncode == 0
|
||||
sys.exit(rc)
|
||||
|
||||
def play(soundfile):
|
||||
p = subprocess.Popen(["play", soundfile], stdout=null, stderr=null)
|
||||
assert p.wait() == 0
|
||||
return p
|
||||
|
||||
def stage1():
|
||||
p = subprocess.Popen("(cd tgui; /bin/bash ./build.sh)", shell=True)
|
||||
wait(p)
|
||||
play("sound/misc/compiler-stage1.ogg")
|
||||
|
||||
def stage2(map):
|
||||
if map:
|
||||
txt = "-M{}".format(map)
|
||||
else:
|
||||
txt = ''
|
||||
args = "bash tools/travis/dm.sh {} tgstation.dme".format(txt)
|
||||
print(args)
|
||||
p = subprocess.Popen(args, shell=True)
|
||||
wait(p)
|
||||
|
||||
def stage3(profile_mode=False):
|
||||
start_time = time.time()
|
||||
play("sound/misc/compiler-stage2.ogg")
|
||||
logfile = open('server.log~','w')
|
||||
p = subprocess.Popen(
|
||||
"DreamDaemon tgstation.dmb 25001 -trusted",
|
||||
shell=True, stdout=PIPE, stderr=STDOUT)
|
||||
try:
|
||||
while p.returncode is None:
|
||||
stdout = p.stdout.readline()
|
||||
if "Initializations complete" in stdout:
|
||||
play("sound/misc/server-ready.ogg")
|
||||
time_taken = time.time() - start_time
|
||||
print("{} seconds taken to fully start".format(time_taken))
|
||||
if "Map is ready." in stdout:
|
||||
time_taken = time.time() - start_time
|
||||
print("{} seconds for initial map loading".format(time_taken))
|
||||
if profile_mode:
|
||||
return time_taken
|
||||
sys.stdout.write(stdout)
|
||||
sys.stdout.flush()
|
||||
logfile.write(stdout)
|
||||
finally:
|
||||
logfile.flush()
|
||||
os.fsync(logfile.fileno())
|
||||
logfile.close()
|
||||
p.kill()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-s','---stage',default=1,type=int)
|
||||
parser.add_argument('--only',action='store_true')
|
||||
parser.add_argument('-m','--map',type=str)
|
||||
parser.add_argument('--profile-mode',action='store_true')
|
||||
args = parser.parse_args()
|
||||
stage = args.stage
|
||||
assert stage in (1,2,3)
|
||||
if stage == 1:
|
||||
stage1()
|
||||
if not args.only:
|
||||
stage = 2
|
||||
if stage == 2:
|
||||
stage2(args.map)
|
||||
if not args.only:
|
||||
stage = 3
|
||||
if stage == 3:
|
||||
value = stage3(profile_mode=args.profile_mode)
|
||||
with open('profile~', 'a') as f:
|
||||
f.write("{}\n".format(value))
|
||||
|
||||
if __name__=='__main__':
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
@@ -30,7 +30,8 @@ for line in sys.stdin:
|
||||
|
||||
fail_no_include = False
|
||||
|
||||
for code_file in glob.glob("code/**/*.dm", recursive=True):
|
||||
code_files = glob.glob("code/**/*.dm", recursive=True) + glob.glob("modular_skyrat/**/*.dm", recursive=True) # SKYRAT EDIT CHANGE
|
||||
for code_file in code_files: # SKYRAT EDIT CHANGE
|
||||
dm_path = code_file.replace('/', '\\')
|
||||
|
||||
included = f"#include \"{dm_path}\"" in lines
|
||||
|
||||
Reference in New Issue
Block a user