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:
Gandalf
2022-07-02 01:16:15 +01:00
committed by GitHub
co-authored by Style Mistake Mothblocks AnturK
parent 865ae82d66
commit de8807eee2
33 changed files with 28 additions and 10523 deletions
+6 -5
View File
@@ -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') }}
-399
View File
@@ -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)
-925
View File
@@ -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
+2
View File
@@ -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
-656
View File
@@ -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
-44
View File
@@ -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
-551
View File
@@ -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
-253
View File
@@ -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)
-43
View File
@@ -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
-324
View File
@@ -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)
-23
View File
@@ -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
-256
View File
@@ -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>\nUNAU†HORIZED USÈ DETÈC†††eD\nCoMMÈNCING SUB-R0U†IN3 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
+2
View File
@@ -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)
+1
View File
@@ -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

-91
View File
@@ -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
-95
View File
@@ -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
+2 -1
View File
@@ -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