Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into ninjasarecum
# Conflicts: # icons/mob/clothing/suit.dmi # icons/obj/clothing/suits.dmi
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
// Shipping methods
|
||||
|
||||
#define SHIPPING_METHOD_LTSRBT "LTSRBT" // The BEST way of shipping items: accurate, "undetectable"
|
||||
#define SHIPPING_METHOD_TELEPORT "Teleport" // Picks a random area to teleport the item to and gives you a minute to get there before it is sent.
|
||||
#define SHIPPING_METHOD_LAUNCH "Launch" // Throws the item from somewhere at the station.
|
||||
@@ -87,12 +87,15 @@
|
||||
|
||||
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
|
||||
#define MAX_MESSAGE_LEN 4096 //Citadel edit: What's the WORST that could happen?
|
||||
#define MAX_FLAVOR_LEN 4096
|
||||
#define MAX_FLAVOR_LEN 4096
|
||||
#define MAX_TASTE_LEN 40 //lick... vore... ew...
|
||||
#define MAX_NAME_LEN 42
|
||||
#define MAX_BROADCAST_LEN 512
|
||||
#define MAX_CHARTER_LEN 80
|
||||
|
||||
// Is something in the IC chat filter? This is config dependent.
|
||||
#define CHAT_FILTER_CHECK(T) (config.ic_filter_regex && findtext(T, config.ic_filter_regex))
|
||||
|
||||
// Audio/Visual Flags. Used to determine what sense are required to notice a message.
|
||||
#define MSG_VISUAL (1<<0)
|
||||
#define MSG_AUDIBLE (1<<1)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
var/motd
|
||||
// var/policy
|
||||
|
||||
// var/static/regex/ic_filter_regex
|
||||
var/static/regex/ic_filter_regex
|
||||
|
||||
/datum/controller/configuration/proc/admin_reload()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
@@ -53,7 +53,7 @@
|
||||
loadmaplist(CONFIG_MAPS_FILE)
|
||||
LoadMOTD()
|
||||
// LoadPolicy()
|
||||
// LoadChatFilter()
|
||||
LoadChatFilter()
|
||||
|
||||
if (Master)
|
||||
Master.OnConfigLoad()
|
||||
@@ -486,7 +486,7 @@ Example config:
|
||||
continue
|
||||
runnable_modes[M] = probabilities[M.config_tag]
|
||||
return runnable_modes
|
||||
/*
|
||||
|
||||
/datum/controller/configuration/proc/LoadChatFilter()
|
||||
var/list/in_character_filter = list()
|
||||
if(!fexists("[directory]/in_character_filter.txt"))
|
||||
@@ -499,7 +499,7 @@ Example config:
|
||||
continue
|
||||
in_character_filter += REGEX_QUOTE(line)
|
||||
ic_filter_regex = in_character_filter.len ? regex("\\b([jointext(in_character_filter, "|")])\\b", "i") : null
|
||||
*/
|
||||
|
||||
//Message admins when you can.
|
||||
/datum/controller/configuration/proc/DelayedMessageAdmins(text)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, /proc/message_admins, text), 0)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
SUBSYSTEM_DEF(blackmarket)
|
||||
name = "Blackmarket"
|
||||
flags = SS_BACKGROUND
|
||||
init_order = INIT_ORDER_DEFAULT
|
||||
|
||||
// Descriptions for each shipping method.
|
||||
var/shipping_method_descriptions = list(
|
||||
SHIPPING_METHOD_LAUNCH="Launches the item at the station from space, cheap but you might not recieve your item at all.",
|
||||
SHIPPING_METHOD_LTSRBT="Long-To-Short-Range-Bluespace-Transceiver, a machine that recieves items outside the station and then teleports them to the location of the uplink.",
|
||||
SHIPPING_METHOD_TELEPORT="Teleports the item in a random area in the station, you get 60 seconds to get there first though."
|
||||
)
|
||||
|
||||
var/list/datum/blackmarket_market/markets = list() // List of all existing markets.
|
||||
var/list/obj/machinery/ltsrbt/telepads = list() // List of existing ltsrbts.
|
||||
var/list/queued_purchases = list() // Currently queued purchases.
|
||||
|
||||
/datum/controller/subsystem/blackmarket/Initialize(timeofday)
|
||||
for(var/market in subtypesof(/datum/blackmarket_market))
|
||||
markets[market] += new market
|
||||
for(var/item in subtypesof(/datum/blackmarket_item))
|
||||
var/datum/blackmarket_item/I = new item()
|
||||
if(!I.item)
|
||||
continue
|
||||
for(var/M in I.markets)
|
||||
if(!markets[M])
|
||||
stack_trace("SSblackmarket: Item [I] available in market that does not exist.")
|
||||
continue
|
||||
markets[M].add_item(item)
|
||||
qdel(I)
|
||||
. = ..()
|
||||
|
||||
/datum/controller/subsystem/blackmarket/fire(resumed)
|
||||
while(length(queued_purchases))
|
||||
var/datum/blackmarket_purchase/purchase = queued_purchases[1]
|
||||
queued_purchases.Cut(1,2)
|
||||
if(!purchase.uplink || QDELETED(purchase.uplink)) // Uh oh, uplink is gone. We will just keep the money and you will not get your order.
|
||||
queued_purchases -= purchase
|
||||
qdel(purchase)
|
||||
continue
|
||||
switch(purchase.method)
|
||||
if(SHIPPING_METHOD_LTSRBT) // Find a ltsrbt pad and make it handle the shipping.
|
||||
if(!telepads.len)
|
||||
continue
|
||||
var/free_pad_found = FALSE // Prioritize pads that don't have a cooldown active.
|
||||
for(var/obj/machinery/ltsrbt/pad in telepads)
|
||||
if(pad.recharge_cooldown)
|
||||
continue
|
||||
pad.add_to_queue(purchase)
|
||||
queued_purchases -= purchase
|
||||
free_pad_found = TRUE
|
||||
break
|
||||
if(free_pad_found)
|
||||
continue
|
||||
var/obj/machinery/ltsrbt/pad = pick(telepads)
|
||||
to_chat(recursive_loc_check(purchase.uplink.loc, /mob), "<span class='notice'>[purchase.uplink] flashes a message noting that the order is being processed by [pad].</span>")
|
||||
queued_purchases -= purchase
|
||||
pad.add_to_queue(purchase)
|
||||
if(SHIPPING_METHOD_TELEPORT) // Get random area, throw it somewhere there.
|
||||
var/turf/targetturf = get_safe_random_station_turf()
|
||||
if (!targetturf) // This shouldn't happen.
|
||||
continue
|
||||
to_chat(recursive_loc_check(purchase.uplink.loc, /mob), "<span class='notice'>[purchase.uplink] flashes a message noting that the order is being teleported to [get_area(targetturf)] in 60 seconds.</span>")
|
||||
addtimer(CALLBACK(src, /datum/controller/subsystem/blackmarket/proc/fake_teleport, purchase.entry.spawn_item(), targetturf), 60 SECONDS) // do_teleport does not want to teleport items from nullspace, so it just forceMoves and does sparks.
|
||||
queued_purchases -= purchase
|
||||
qdel(purchase)
|
||||
if(SHIPPING_METHOD_LAUNCH) // Get the current location of the uplink if it exists, then throws the item from space at the station from a random direction.
|
||||
var/startSide = pick(GLOB.cardinals)
|
||||
var/turf/T = get_turf(purchase.uplink)
|
||||
var/pickedloc = spaceDebrisStartLoc(startSide, T.z)
|
||||
var/atom/movable/item = purchase.entry.spawn_item(pickedloc)
|
||||
item.throw_at(purchase.uplink, 3, 3, spin = FALSE)
|
||||
to_chat(recursive_loc_check(purchase.uplink.loc, /mob), "<span class='notice'>[purchase.uplink] flashes a message noting the order is being launched at the station from [dir2text(startSide)].</span>")
|
||||
queued_purchases -= purchase
|
||||
qdel(purchase)
|
||||
if(MC_TICK_CHECK)
|
||||
break
|
||||
|
||||
/datum/controller/subsystem/blackmarket/proc/fake_teleport(atom/movable/item, turf/target) // Used to make a teleportation effect as do_teleport does not like moving items from nullspace.
|
||||
item.forceMove(target)
|
||||
var/datum/effect_system/spark_spread/sparks = new
|
||||
sparks.set_up(5, 1, target)
|
||||
sparks.attach(item)
|
||||
sparks.start()
|
||||
|
||||
/datum/controller/subsystem/blackmarket/proc/queue_item(datum/blackmarket_purchase/P) // Used to add /datum/blackmarket_purchase to queued_purchases var. Returns TRUE when queued.
|
||||
if(P.method == SHIPPING_METHOD_LTSRBT && !telepads.len)
|
||||
return FALSE
|
||||
queued_purchases += P
|
||||
return TRUE
|
||||
@@ -490,42 +490,29 @@ SUBSYSTEM_DEF(job)
|
||||
job.after_spawn(H, M, joined_late) // note: this happens before the mob has a key! M will always have a client, H might not.
|
||||
equip_loadout(N, H, TRUE)//CIT CHANGE - makes players spawn with in-backpack loadout items properly. A little hacky but it works
|
||||
|
||||
if(ishuman(H) && H.client && N)
|
||||
if(H.client && H.client.prefs && length(H.client.prefs.tcg_cards))
|
||||
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
|
||||
H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)
|
||||
for(var/card_type in H.client.prefs.tcg_cards)
|
||||
if(card_type)
|
||||
if(islist(H.client.prefs.tcg_cards[card_type]))
|
||||
for(var/duplicate in H.client.prefs.tcg_cards[card_type])
|
||||
var/obj/item/tcg_card/card = new(get_turf(H), card_type, duplicate)
|
||||
card.forceMove(binder)
|
||||
binder.cards.Add(card)
|
||||
else
|
||||
var/obj/item/tcg_card/card = new(get_turf(H), card_type, H.client.prefs.tcg_cards[card_type])
|
||||
var/list/tcg_cards
|
||||
if(ishuman(H))
|
||||
if(length(H.client?.prefs?.tcg_cards))
|
||||
tcg_cards = H.client.prefs.tcg_cards
|
||||
else if(length(N?.client?.prefs?.tcg_cards))
|
||||
tcg_cards = N.client.prefs.tcg_cards
|
||||
if(tcg_cards)
|
||||
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
|
||||
H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)
|
||||
for(var/card_type in N.client.prefs.tcg_cards)
|
||||
if(card_type)
|
||||
if(islist(H.client.prefs.tcg_cards[card_type]))
|
||||
for(var/duplicate in N.client.prefs.tcg_cards[card_type])
|
||||
var/obj/item/tcg_card/card = new(get_turf(H), card_type, duplicate)
|
||||
card.forceMove(binder)
|
||||
binder.cards.Add(card)
|
||||
binder.check_for_exodia()
|
||||
if(length(H.client.prefs.tcg_decks))
|
||||
binder.decks = H.client.prefs.tcg_decks
|
||||
else
|
||||
if(H && N.client.prefs && length(N.client.prefs.tcg_cards))
|
||||
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
|
||||
H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)
|
||||
for(var/card_type in N.client.prefs.tcg_cards)
|
||||
if(card_type)
|
||||
if(islist(H.client.prefs.tcg_cards[card_type]))
|
||||
for(var/duplicate in N.client.prefs.tcg_cards[card_type])
|
||||
var/obj/item/tcg_card/card = new(get_turf(H), card_type, duplicate)
|
||||
card.forceMove(binder)
|
||||
binder.cards.Add(card)
|
||||
else
|
||||
var/obj/item/tcg_card/card = new(get_turf(H), card_type, N.client.prefs.tcg_cards[card_type])
|
||||
card.forceMove(binder)
|
||||
binder.cards.Add(card)
|
||||
binder.check_for_exodia()
|
||||
if(length(N.client.prefs.tcg_decks))
|
||||
binder.decks = N.client.prefs.tcg_decks
|
||||
else
|
||||
var/obj/item/tcg_card/card = new(get_turf(H), card_type, N.client.prefs.tcg_cards[card_type])
|
||||
card.forceMove(binder)
|
||||
binder.cards.Add(card)
|
||||
binder.check_for_exodia()
|
||||
if(length(N.client.prefs.tcg_decks))
|
||||
binder.decks = N.client.prefs.tcg_decks
|
||||
|
||||
return H
|
||||
/*
|
||||
|
||||
@@ -609,9 +609,9 @@ SUBSYSTEM_DEF(ticker)
|
||||
var/list/ded = SSblackbox.first_death
|
||||
if(ded.len)
|
||||
var/last_words = ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""
|
||||
news_message += " NT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
|
||||
news_message += "\nNT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
|
||||
else
|
||||
news_message += " NT Sanctioned Psykers proudly confirm reports that nobody died this shift!"
|
||||
news_message += "\nNT Sanctioned Psykers proudly confirm reports that nobody died this shift!"
|
||||
|
||||
if(news_message)
|
||||
send2otherserver(news_source, news_message,"News_Report")
|
||||
|
||||
@@ -336,6 +336,18 @@
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/blackmarket_uplink
|
||||
name = "Black Market Uplink"
|
||||
result = /obj/item/blackmarket_uplink
|
||||
time = 20
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
reqs = list(/obj/item/stock_parts/subspace/amplifier = 1,
|
||||
/obj/item/stack/cable_coil = 15,
|
||||
/obj/item/radio = 1,
|
||||
/obj/item/analyzer = 1)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/heretic/codex
|
||||
name = "Codex Cicatrix"
|
||||
result = /obj/item/forbidden_book
|
||||
|
||||
@@ -204,12 +204,11 @@
|
||||
// first 10 minutes only
|
||||
return world.time - SSticker.round_start_time < 6000
|
||||
|
||||
// this is broken and does not work. Thanks TG
|
||||
// /datum/map_template/shuttle/emergency/airless/post_load()
|
||||
// . = ..()
|
||||
// //enable buying engines from cargo
|
||||
// var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
|
||||
// P.special_enabled = TRUE
|
||||
/datum/map_template/shuttle/emergency/construction/post_load()
|
||||
. = ..()
|
||||
//enable buying engines from cargo
|
||||
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
|
||||
P.special_enabled = TRUE
|
||||
|
||||
|
||||
/datum/map_template/shuttle/emergency/asteroid
|
||||
|
||||
@@ -48,13 +48,14 @@
|
||||
)
|
||||
|
||||
/obj/machinery/autolathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID], 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autolathe(src)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
|
||||
matching_designs = list()
|
||||
|
||||
/obj/machinery/autolathe/ComponentInitialize()
|
||||
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID], 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
|
||||
/obj/machinery/autolathe/Destroy()
|
||||
QDEL_NULL(wires)
|
||||
return ..()
|
||||
@@ -439,6 +440,9 @@
|
||||
|
||||
/obj/machinery/autolathe/secure/Initialize()
|
||||
. = ..()
|
||||
// let's not leave the parent datum floating, right?
|
||||
if(stored_research)
|
||||
QDEL_NULL(stored_research)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/public
|
||||
|
||||
/obj/machinery/autolathe/toy
|
||||
@@ -457,8 +461,18 @@
|
||||
"Misc",
|
||||
"Imported"
|
||||
)
|
||||
/obj/machinery/autolathe/toy/Initialize()
|
||||
. = ..()
|
||||
// let's not leave the parent datum floating, right?
|
||||
if(stored_research)
|
||||
QDEL_NULL(stored_research)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/toy
|
||||
|
||||
/obj/machinery/autolathe/toy/hacked/Initialize()
|
||||
. = ..()
|
||||
adjust_hacked(TRUE)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/toy
|
||||
|
||||
// override the base to allow plastics
|
||||
/obj/machinery/autolathe/ComponentInitialize()
|
||||
var/list/extra_mats = list(/datum/material/plastic)
|
||||
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID] + extra_mats, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/obj/structure/frame/machine/examine(user)
|
||||
. = ..()
|
||||
if(state == 3 && req_components && req_component_names)
|
||||
var/hasContent = 0
|
||||
var/hasContent = FALSE
|
||||
var/requires = "It requires"
|
||||
|
||||
for(var/i = 1 to req_components.len)
|
||||
@@ -46,10 +46,10 @@
|
||||
continue
|
||||
var/use_and = i == req_components.len
|
||||
requires += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]"
|
||||
hasContent = 1
|
||||
hasContent = TRUE
|
||||
|
||||
if(hasContent)
|
||||
. += requires + "."
|
||||
. += "[requires]."
|
||||
else
|
||||
. += "It does not require any more components."
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
amt += req_components[path]
|
||||
return amt
|
||||
|
||||
/obj/structure/frame/machine/attackby(obj/item/P, mob/user, params)
|
||||
/obj/structure/frame/machine/attackby(obj/item/P, mob/living/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
if(istype(P, /obj/item/circuitboard/machine))
|
||||
@@ -88,6 +88,7 @@
|
||||
if(istype(P, /obj/item/stack/cable_coil))
|
||||
if(!P.tool_start_check(user, amount=5))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You start to add cables to the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50, amount=5, extra_checks = CALLBACK(src, .proc/check_state, 1)))
|
||||
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
|
||||
@@ -97,39 +98,41 @@
|
||||
return
|
||||
if(P.tool_behaviour == TOOL_SCREWDRIVER && !anchored)
|
||||
user.visible_message("<span class='warning'>[user] disassembles the frame.</span>", \
|
||||
"<span class='notice'>You start to disassemble the frame...</span>", "You hear banging and clanking.")
|
||||
"<span class='notice'>You start to disassemble the frame...</span>", "<span class='hear'>You hear banging and clanking.</span>")
|
||||
if(P.use_tool(src, user, 40, volume=50, extra_checks = CALLBACK(src, .proc/check_state, 1)))
|
||||
to_chat(user, "<span class='notice'>You disassemble the frame.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new (loc, 5)
|
||||
M.add_fingerprint(user)
|
||||
qdel(src)
|
||||
if(state == 1)
|
||||
to_chat(user, "<span class='notice'>You disassemble the frame.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new (loc, 5)
|
||||
M.add_fingerprint(user)
|
||||
qdel(src)
|
||||
return
|
||||
if(P.tool_behaviour == TOOL_WRENCH)
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [src]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75, extra_checks = CALLBACK(src, .proc/check_state, 1)))
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
if(state == 1)
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
|
||||
set_anchored(!anchored)
|
||||
return
|
||||
|
||||
if(2)
|
||||
if(P.tool_behaviour == TOOL_WRENCH)
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [src]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75, extra_checks = CALLBACK(src, .proc/check_state, 2)))
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
|
||||
set_anchored(!anchored)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/circuitboard/machine))
|
||||
var/obj/item/circuitboard/machine/B = P
|
||||
if(!B.build_path)
|
||||
to_chat(user, "<span class'warning'>This circuitboard seems to be broken.</span>")
|
||||
to_chat(user, "<span class='warning'>This circuitboard seems to be broken.</span>")
|
||||
return
|
||||
if(!anchored && B.needs_anchored)
|
||||
to_chat(user, "<span class='warning'>The frame needs to be secured first!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(B, src))
|
||||
return
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
to_chat(user, "<span class='notice'>You add the circuit board to the frame.</span>")
|
||||
circuit = B
|
||||
icon_state = "box_2"
|
||||
@@ -171,34 +174,49 @@
|
||||
return
|
||||
|
||||
if(P.tool_behaviour == TOOL_WRENCH && !circuit.needs_anchored)
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [src]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75, extra_checks = CALLBACK(src, .proc/check_state, 3)))
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
|
||||
set_anchored(!anchored)
|
||||
return
|
||||
|
||||
if(P.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
var/component_check = 1
|
||||
var/component_check = TRUE
|
||||
for(var/R in req_components)
|
||||
if(req_components[R] > 0)
|
||||
component_check = 0
|
||||
component_check = FALSE
|
||||
break
|
||||
if(component_check)
|
||||
P.play_tool_sound(src)
|
||||
var/obj/machinery/new_machine = new circuit.build_path(loc)
|
||||
if(new_machine.circuit)
|
||||
QDEL_NULL(new_machine.circuit)
|
||||
new_machine.circuit = circuit
|
||||
new_machine.setAnchored(anchored)
|
||||
new_machine.on_construction()
|
||||
for(var/obj/O in new_machine.component_parts)
|
||||
qdel(O)
|
||||
new_machine.component_parts = list()
|
||||
for(var/obj/O in src)
|
||||
O.moveToNullspace()
|
||||
new_machine.component_parts += O
|
||||
circuit.moveToNullspace()
|
||||
new_machine.RefreshParts()
|
||||
if(istype(new_machine))
|
||||
// Machines will init with a set of default components. Move to nullspace so we don't trigger handle_atom_del, then qdel.
|
||||
// Finally, replace with this frame's parts.
|
||||
if(new_machine.circuit)
|
||||
// Move to nullspace and delete.
|
||||
new_machine.circuit.moveToNullspace()
|
||||
QDEL_NULL(new_machine.circuit)
|
||||
for(var/obj/old_part in new_machine.component_parts)
|
||||
// Move to nullspace and delete.
|
||||
old_part.moveToNullspace()
|
||||
qdel(old_part)
|
||||
|
||||
// Set anchor state and move the frame's parts over to the new machine.
|
||||
// Then refresh parts and call on_construction().
|
||||
|
||||
new_machine.set_anchored(anchored)
|
||||
new_machine.component_parts = list()
|
||||
|
||||
circuit.forceMove(new_machine)
|
||||
new_machine.component_parts += circuit
|
||||
new_machine.circuit = circuit
|
||||
|
||||
for(var/obj/new_part in src)
|
||||
new_part.forceMove(new_machine)
|
||||
new_machine.component_parts += new_part
|
||||
new_machine.RefreshParts()
|
||||
|
||||
new_machine.on_construction()
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
@@ -232,12 +250,15 @@
|
||||
|
||||
for(var/obj/item/part in added_components)
|
||||
if(istype(part,/obj/item/stack))
|
||||
var/obj/item/stack/S = part
|
||||
var/obj/item/stack/NS = locate(S.merge_type) in components //find a stack to merge with
|
||||
if(NS)
|
||||
S.merge(NS)
|
||||
var/obj/item/stack/incoming_stack = part
|
||||
for(var/obj/item/stack/merge_stack in components)
|
||||
if(incoming_stack.can_merge(merge_stack))
|
||||
incoming_stack.merge(merge_stack)
|
||||
if(QDELETED(incoming_stack))
|
||||
break
|
||||
if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore
|
||||
components += part
|
||||
part.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>[part.name] applied.</span>")
|
||||
if(added_components.len)
|
||||
replacer.play_rped_sound()
|
||||
@@ -267,9 +288,9 @@
|
||||
to_chat(user, "<span class='notice'>You add [P] to [src].</span>")
|
||||
components += P
|
||||
req_components[I]--
|
||||
return 1
|
||||
return TRUE
|
||||
to_chat(user, "<span class='warning'>You cannot add that to the machine!</span>")
|
||||
return 0
|
||||
return FALSE
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
@@ -280,5 +301,4 @@
|
||||
for(var/X in components)
|
||||
var/obj/item/I = X
|
||||
I.forceMove(loc)
|
||||
|
||||
..()
|
||||
|
||||
@@ -79,7 +79,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
var/secure = FALSE
|
||||
/// If we are currently calling another holopad
|
||||
var/calling = FALSE
|
||||
/*
|
||||
|
||||
/obj/machinery/holopad/secure
|
||||
name = "secure holopad"
|
||||
desc = "It's a floor-mounted device for projecting holographic images. This one will refuse to auto-connect incoming calls."
|
||||
@@ -90,7 +90,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
var/obj/item/circuitboard/machine/holopad/board = circuit
|
||||
board.secure = TRUE
|
||||
board.build_path = /obj/machinery/holopad/secure
|
||||
*/
|
||||
|
||||
/obj/machinery/holopad/tutorial
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
@@ -372,7 +372,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(!secure) //HC.head_call &&
|
||||
if(HC.head_call && !secure)
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(outgoing_call)
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/* BALLS - GLORIOUS BALLS
|
||||
//
|
||||
// Includes:-
|
||||
// 1) Tennis balls, lines 10 - 92
|
||||
//
|
||||
//
|
||||
//
|
||||
*/
|
||||
|
||||
/obj/item/toy/tennis
|
||||
name = "tennis ball"
|
||||
desc = "A classical tennis ball. It appears to have faint bite marks scattered all over its surface."
|
||||
icon = 'modular_citadel/icons/obj/balls.dmi'
|
||||
icon_state = "tennis_classic"
|
||||
lefthand_file = 'modular_citadel/icons/mob/inhands/balls_left.dmi'
|
||||
righthand_file = 'modular_citadel/icons/mob/inhands/balls_right.dmi'
|
||||
item_state = "tennis_classic"
|
||||
mob_overlay_icon = 'modular_citadel/icons/mob/mouthball.dmi'
|
||||
slot_flags = ITEM_SLOT_HEAD | ITEM_SLOT_NECK | ITEM_SLOT_EARS //Fluff item, put it wherever you want!
|
||||
throw_range = 14
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/toy/tennis/alt_pre_attack(atom/A, mob/living/user, params) //checks if it can do right click memes
|
||||
altafterattack(A, user, TRUE, params)
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/tennis/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
|
||||
if(istype(user))
|
||||
user.visible_message("<span class='notice'>[user] waggles [src] at [target].</span>", "<span class='notice'>You waggle [src] at [target].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/tennis/rainbow
|
||||
name = "pseudo-euclidean interdimensional tennis sphere"
|
||||
desc = "A tennis ball from another plane of existance. Really groovy."
|
||||
icon_state = "tennis_rainbow"
|
||||
item_state = "tennis_rainbow"
|
||||
actions_types = list(/datum/action/item_action/squeeze) //Giving the masses easy access to unilimted honks would be annoying
|
||||
|
||||
/obj/item/toy/tennis/rainbow/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/squeak)
|
||||
|
||||
/obj/item/toy/tennis/rainbow/izzy //izzyinbox's donator item
|
||||
name = "Katlin's Ball"
|
||||
desc = "A tennis ball that's seen a good bit of love, being covered in a few black and white hairs and slobber."
|
||||
icon_state = "tennis_izzy"
|
||||
item_state = "tennis_izzy"
|
||||
|
||||
/obj/item/toy/tennis/red //da red wuns go fasta
|
||||
name = "red tennis ball"
|
||||
desc = "A red tennis ball. It goes three times faster!"
|
||||
icon_state = "tennis_red"
|
||||
item_state = "tennis_red"
|
||||
throw_speed = 9
|
||||
|
||||
/obj/item/toy/tennis/yellow //because yellow is hot I guess
|
||||
name = "yellow tennis ball"
|
||||
desc = "A yellow tennis ball. It seems to have a flame-retardant coating."
|
||||
icon_state = "tennis_yellow"
|
||||
item_state = "tennis_yellow"
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/toy/tennis/green //pestilence
|
||||
name = "green tennis ball"
|
||||
desc = "A green tennis ball. It seems to have an impermeable coating."
|
||||
icon_state = "tennis_green"
|
||||
item_state = "tennis_green"
|
||||
permeability_coefficient = 0.9
|
||||
|
||||
/obj/item/toy/tennis/cyan //electric
|
||||
name = "cyan tennis ball"
|
||||
desc = "A cyan tennis ball. It seems to have odd electrical properties."
|
||||
icon_state = "tennis_cyan"
|
||||
item_state = "tennis_cyan"
|
||||
siemens_coefficient = 0.9
|
||||
|
||||
/obj/item/toy/tennis/blue //reliability
|
||||
name = "blue tennis ball"
|
||||
desc = "A blue tennis ball. It seems ever so slightly more robust than normal."
|
||||
icon_state = "tennis_blue"
|
||||
item_state = "tennis_blue"
|
||||
max_integrity = 300
|
||||
|
||||
/obj/item/toy/tennis/purple //because purple dyes have high pH and would neutralize acids I guess
|
||||
name = "purple tennis ball"
|
||||
desc = "A purple tennis ball. It seems to have an acid-resistant coating."
|
||||
icon_state = "tennis_purple"
|
||||
item_state = "tennis_purple"
|
||||
resistance_flags = ACID_PROOF
|
||||
|
||||
/datum/action/item_action/squeeze
|
||||
name = "Squeak!"
|
||||
@@ -16,6 +16,9 @@
|
||||
if(isopenturf(target))
|
||||
deploy_bodybag(user, target)
|
||||
|
||||
/obj/item/bodybag/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
|
||||
return (user in src)
|
||||
|
||||
/obj/item/bodybag/proc/deploy_bodybag(mob/user, atom/location)
|
||||
var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
|
||||
R.open(user)
|
||||
|
||||
@@ -549,6 +549,7 @@
|
||||
contraband = TRUE
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='notice'>You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/configure_machine(obj/machinery/computer/cargo/machine)
|
||||
if(!istype(machine))
|
||||
@@ -565,10 +566,12 @@
|
||||
build_path = /obj/machinery/computer/cargo/express
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
|
||||
. = ..()
|
||||
if(!(obj_flags & EMAGGED))
|
||||
contraband = TRUE
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='notice'>You change the routing protocols, allowing the Drop Pod to land anywhere on the station.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express/multitool_act(mob/living/user)
|
||||
if (!(obj_flags & EMAGGED))
|
||||
|
||||
@@ -472,7 +472,7 @@
|
||||
build_path = /obj/machinery/holopad
|
||||
secure = FALSE
|
||||
else
|
||||
build_path = /obj/machinery/holopad //secure
|
||||
build_path = /obj/machinery/holopad/secure //secure
|
||||
secure = TRUE
|
||||
to_chat(user, "<span class='notice'>You [secure? "en" : "dis"]able the security on the [src]</span>")
|
||||
. = ..()
|
||||
@@ -609,6 +609,7 @@
|
||||
/obj/machinery/vending/cigarette = "ShadyCigs Deluxe",
|
||||
/obj/machinery/vending/games = "\improper Good Clean Fun",
|
||||
/obj/machinery/vending/kink = "KinkMate",
|
||||
/obj/machinery/vending/barkbox = "Bark Box",
|
||||
/obj/machinery/vending/autodrobe = "AutoDrobe",
|
||||
/obj/machinery/vending/wardrobe/sec_wardrobe = "SecDrobe",
|
||||
/obj/machinery/vending/wardrobe/det_wardrobe = "DetDrobe",
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/* Balls, Bones, and Bountiful Fun
|
||||
//
|
||||
// Includes:-
|
||||
// 1) Fluff Content, lines 12 - 131
|
||||
//
|
||||
// 1) Tennis balls, lines 39 - 99
|
||||
// 2) Chew bones, lines 101 - 138
|
||||
// 3) Frisbee, lines 140 - 166
|
||||
*/
|
||||
|
||||
/obj/item/toy/fluff
|
||||
name = "Fluff Item"
|
||||
desc = "You shouldn't be seeing this."
|
||||
icon = 'icons/obj/barkbox_fluff.dmi'
|
||||
icon_state = "poly_tennis"
|
||||
item_state = "poly_tennis"
|
||||
lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/fluff_righthand.dmi'
|
||||
mob_overlay_icon = 'icons/mob/mouthfluff.dmi'
|
||||
slot_flags = ITEM_SLOT_HEAD | ITEM_SLOT_NECK | ITEM_SLOT_EARS
|
||||
var/poly_states = 0
|
||||
var/poly_colors = list()
|
||||
|
||||
/obj/item/toy/fluff/alt_pre_attack(atom/A, mob/living/user, params) //checks if it can do right click memes
|
||||
altafterattack(A, user, TRUE, params)
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/fluff/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
|
||||
if(istype(user))
|
||||
user.visible_message("<span class='notice'>[user] waggles [src] at [target].</span>", "<span class='notice'>You waggle [src] at [target].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/fluff/ComponentInitialize()
|
||||
. = ..()
|
||||
if(!poly_states)
|
||||
return
|
||||
AddElement(/datum/element/polychromic, poly_colors, poly_states, _flags = POLYCHROMIC_ACTION)
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly
|
||||
name = "polychromic tennis ball"
|
||||
desc = "A polychromic tennis ball. There's a half torn tag read: WARNIN-, surely it means nothing. Right?"
|
||||
throw_range = 14
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
poly_states = 2
|
||||
poly_colors = list("#CCFF00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/red
|
||||
poly_colors = list("#FF4C00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/yellow
|
||||
poly_colors = list("#FFCC00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/green
|
||||
poly_colors = list("#99FF00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/cyan
|
||||
poly_colors = list("#00FFB2", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/blue
|
||||
poly_colors = list("#007FFF", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/purple
|
||||
poly_colors = list("#CC00FF", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/tri
|
||||
name = "tricolor-polychromic tennis ball"
|
||||
desc = "A tricolor-polychromic tennis ball. Triple the shocking!"
|
||||
icon_state = "tripoly_tennis"
|
||||
item_state = "tripoly_tennis"
|
||||
poly_states = 3
|
||||
poly_colors = list("#FFFFFF", "#FFFFFF", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/tri/squeak
|
||||
name = "tricolor-polychromic tennis sphere"
|
||||
desc = "A tricolor-polychromic tennis ball. This one seems to emit a squeak when squeezed."
|
||||
actions_types = list(/datum/action/item_action/squeeze)
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/tri/squeak/izzy //izzyinbox's donator item
|
||||
name = "Katlin's Ball"
|
||||
desc = "A tennis ball that's seen a good bit of love, being covered in a few black and white hairs and slobber."
|
||||
poly_colors = list("#8FED56", "#51cfde", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/tri/squeak/rainbow
|
||||
name = "pseudo-euclidean interdimensional tennis sphere"
|
||||
desc = "A tennis ball from another plane of existance. Really groovy."
|
||||
icon_state = "tennis_rainbow"
|
||||
item_state = "tennis_rainbow"
|
||||
poly_states = 0
|
||||
actions_types = list(/datum/action/item_action/squeeze)
|
||||
|
||||
/obj/item/toy/fluff/tennis_poly/tri/squeak/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/squeak)
|
||||
|
||||
/obj/item/toy/fluff/bone_poly
|
||||
name = "polychromic bone"
|
||||
desc = "A polychromic chew bone. Nothing like a good bone to chew on."
|
||||
icon_state = "poly_bone"
|
||||
item_state = "poly_bone"
|
||||
throw_range = 7
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
poly_states = 1
|
||||
poly_colors = list("#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/red
|
||||
poly_colors = list("#FF4C00")
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/yellow
|
||||
poly_colors = list("#FFCC00")
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/green
|
||||
poly_colors = list("#99FF00")
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/cyan
|
||||
poly_colors = list("#00FFB2")
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/blue
|
||||
poly_colors = list("#007FFF")
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/purple
|
||||
poly_colors = list("#CC00FF")
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/squeak
|
||||
name = "polychromic bone"
|
||||
desc = "A polychromic chew bone. Makes a small squeak when squeezed."
|
||||
|
||||
/obj/item/toy/fluff/bone_poly/squeak/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/squeak)
|
||||
|
||||
/datum/action/item_action/squeeze
|
||||
name = "Squeak!"
|
||||
|
||||
/obj/item/toy/fluff/frisbee_poly
|
||||
name = "polychromic frisbee"
|
||||
desc = "A polychromic frisbee. Warning: May induce shock."
|
||||
icon_state = "poly_frisbee"
|
||||
item_state = "poly_frisbee"
|
||||
throw_range = 14
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
poly_states = 2
|
||||
poly_colors = list("#CCFF00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/frisbee_poly/red
|
||||
poly_colors = list("#FF4C00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/frisbee_poly/yellow
|
||||
poly_colors = list("#FFCC00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/frisbee_poly/green
|
||||
poly_colors = list("#99FF00", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/frisbee_poly/cyan
|
||||
poly_colors = list("#00FFB2", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/frisbee_poly/blue
|
||||
poly_colors = list("#007FFF", "#FFFFFF")
|
||||
|
||||
/obj/item/toy/fluff/frisbee_poly/purple
|
||||
poly_colors = list("#CC00FF", "#FFFFFF")
|
||||
@@ -459,8 +459,8 @@
|
||||
|
||||
/obj/item/stack/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(isturf(loc)) // to prevent people that are alt clicking a tile to see its content from getting undesidered pop ups
|
||||
return
|
||||
// if(isturf(loc)) // to prevent people that are alt clicking a tile to see its content from getting undesidered pop ups
|
||||
// return
|
||||
if(is_cyborg || !user.canUseTopic(src, BE_CLOSE, TRUE, FALSE) || zero_amount()) //, !iscyborg(user)
|
||||
return
|
||||
//get amount from user
|
||||
|
||||
@@ -435,6 +435,20 @@
|
||||
STR.max_items = 6
|
||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/nugget))
|
||||
|
||||
/obj/item/storage/fancy/treat_box
|
||||
name = "treat box"
|
||||
desc = "A cardboard box used for holding dog treats."
|
||||
icon = 'icons/obj/food/containers.dmi'
|
||||
icon_state = "treatbox"
|
||||
icon_type = "treat"
|
||||
spawn_type = /obj/item/reagent_containers/food/snacks/dogtreat
|
||||
|
||||
/obj/item/storage/fancy/treat_box/ComponentInitialize()
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.max_items = 6
|
||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/dogtreat))
|
||||
|
||||
/obj/item/storage/fancy/cracker_pack
|
||||
name = "cracker pack"
|
||||
desc = "A pack of delicious crackers. Keep away from parrots!"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var/datum/effect_system/trail_follow/ion/ion_trail
|
||||
|
||||
/obj/item/tank/jetpack/Initialize()
|
||||
..()
|
||||
. = ..()
|
||||
ion_trail = new
|
||||
ion_trail.set_up(src)
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/item/tank/jetpack/suicide_act(mob/user)
|
||||
if (istype(user, /mob/living/carbon/human/))
|
||||
if (ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.forcesay("WHAT THE FUCK IS CARBON DIOXIDE?")
|
||||
H.visible_message("<span class='suicide'>[user] is suffocating [user.p_them()]self with [src]! It looks like [user.p_they()] didn't read what that jetpack says!</span>")
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
icon = 'icons/obj/closet.dmi'
|
||||
icon_state = "generic"
|
||||
density = TRUE
|
||||
max_integrity = 200
|
||||
integrity_failure = 0.25
|
||||
armor = list("melee" = 20, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
|
||||
|
||||
var/icon_door = null
|
||||
var/icon_door_override = FALSE //override to have open overlay use icon different to its base's
|
||||
var/secure = FALSE //secure locker or not, also used if overriding a non-secure locker with a secure door overlay to add fancy lights
|
||||
@@ -12,9 +16,6 @@
|
||||
var/locked = FALSE
|
||||
var/large = TRUE
|
||||
var/wall_mounted = 0 //never solid (You can always pass over it)
|
||||
max_integrity = 200
|
||||
integrity_failure = 0.25
|
||||
armor = list("melee" = 20, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
|
||||
var/breakout_time = 1200
|
||||
var/message_cooldown
|
||||
var/can_weld_shut = TRUE
|
||||
@@ -40,12 +41,12 @@
|
||||
var/should_populate_contents = TRUE
|
||||
|
||||
/obj/structure/closet/Initialize(mapload)
|
||||
if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents
|
||||
addtimer(CALLBACK(src, .proc/take_contents), 0)
|
||||
. = ..()
|
||||
update_icon()
|
||||
if(should_populate_contents)
|
||||
PopulateContents()
|
||||
if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents
|
||||
addtimer(CALLBACK(src, .proc/take_contents), 0)
|
||||
if(secure)
|
||||
lockerelectronics = new(src)
|
||||
lockerelectronics.accesses = req_access
|
||||
@@ -60,10 +61,10 @@
|
||||
|
||||
/obj/structure/closet/update_icon()
|
||||
. = ..()
|
||||
if(!opened)
|
||||
layer = OBJ_LAYER
|
||||
else
|
||||
layer = BELOW_OBJ_LAYER
|
||||
if(istype(src, /obj/structure/closet/supplypod))
|
||||
return
|
||||
|
||||
layer = opened ? BELOW_OBJ_LAYER : OBJ_LAYER
|
||||
|
||||
/obj/structure/closet/update_overlays()
|
||||
. = ..()
|
||||
@@ -71,61 +72,57 @@
|
||||
|
||||
/obj/structure/closet/proc/closet_update_overlays(list/new_overlays)
|
||||
. = new_overlays
|
||||
if(!opened)
|
||||
if(icon_door)
|
||||
. += "[icon_door]_door"
|
||||
else
|
||||
. += "[icon_state]_door"
|
||||
if(welded)
|
||||
. += "welded"
|
||||
if(!secure)
|
||||
return
|
||||
if(broken)
|
||||
. += "off"
|
||||
. += "sparking"
|
||||
else if(locked)
|
||||
. += "locked"
|
||||
else
|
||||
. += "unlocked"
|
||||
else
|
||||
if(icon_door_override)
|
||||
. += "[icon_door]_open"
|
||||
else
|
||||
. += "[icon_state]_open"
|
||||
if(opened)
|
||||
. += "[icon_door_override ? icon_door : icon_state]_open"
|
||||
return
|
||||
|
||||
. += "[icon_door || icon_state]_door"
|
||||
if(welded)
|
||||
. += icon_welded
|
||||
|
||||
if(!secure)
|
||||
return
|
||||
if(broken)
|
||||
. += "off"
|
||||
. += "sparking"
|
||||
//Overlay is similar enough for both that we can use the same mask for both
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "locked", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
|
||||
. += locked ? "locked" : "unlocked"
|
||||
|
||||
|
||||
/obj/structure/closet/examine(mob/user)
|
||||
. = ..()
|
||||
if(welded)
|
||||
. += "<span class='notice'>It's <b>welded</b> shut.</span>"
|
||||
. += "<span class='notice'>It's welded shut.</span>"
|
||||
if(anchored)
|
||||
. += "<span class='notice'>It is <b>bolted</b> to the ground.</span>"
|
||||
if(opened)
|
||||
. += "<span class='notice'>The parts are <b>welded</b> together.</span>"
|
||||
else if(secure && !opened)
|
||||
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"].</span>"
|
||||
else if(broken)
|
||||
. += "<span class='notice'>The lock is <b>screwed</b> in.</span>"
|
||||
else if(secure)
|
||||
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"].</span>"
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(HAS_TRAIT(L, TRAIT_SKITTISH))
|
||||
. += "<span class='notice'>Ctrl-Shift-click [src] to jump inside.</span>"
|
||||
|
||||
if(isobserver(user))
|
||||
. += "<span class='info'>It contains: [english_list(contents)].</span>"
|
||||
investigate_log("had its contents examined by [user] as a ghost.", INVESTIGATE_GHOST)
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_SKITTISH))
|
||||
. += "<span class='notice'>If you bump into [p_them()] while running, you will jump inside.</span>"
|
||||
|
||||
/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
|
||||
if(wall_mounted)
|
||||
return TRUE
|
||||
return !density
|
||||
|
||||
/obj/structure/closet/proc/can_open(mob/living/user)
|
||||
/obj/structure/closet/proc/can_open(mob/living/user, force = FALSE)
|
||||
if(force)
|
||||
return TRUE
|
||||
if(welded || locked)
|
||||
return FALSE
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/L in T)
|
||||
if(L.move_resist >= MOVE_FORCE_VERY_STRONG || (horizontal && L.mob_size > MOB_SIZE_TINY && L.density))
|
||||
if(L.anchored || L.move_resist >= MOVE_FORCE_VERY_STRONG || (horizontal && L.mob_size > MOB_SIZE_TINY && L.density))
|
||||
if(user)
|
||||
to_chat(user, "<span class='danger'>There's something large on top of [src], preventing it from opening.</span>" )
|
||||
return FALSE
|
||||
@@ -137,44 +134,16 @@
|
||||
if(closet != src && !closet.wall_mounted)
|
||||
return FALSE
|
||||
for(var/mob/living/L in T)
|
||||
if(L.move_resist >= MOVE_FORCE_VERY_STRONG || horizontal && L.mob_size > MOB_SIZE_TINY && L.density)
|
||||
if(L.anchored || L.move_resist >= MOVE_FORCE_VERY_STRONG || (horizontal && L.mob_size > MOB_SIZE_TINY && L.density))
|
||||
if(user)
|
||||
to_chat(user, "<span class='danger'>There's something too large in [src], preventing it from closing.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/closet/proc/can_lock(mob/living/user, var/check_access = TRUE) //set check_access to FALSE if you only need to check if a locker has a functional lock rather than access
|
||||
if(!secure)
|
||||
return FALSE
|
||||
if(broken)
|
||||
to_chat(user, "<span class='notice'>[src] is broken!</span>")
|
||||
return FALSE
|
||||
if(QDELETED(lockerelectronics) && !locked) //We want to be able to unlock it regardless of electronics, but only lockable with electronics
|
||||
to_chat(user, "<span class='notice'>[src] is missing locker electronics!</span>")
|
||||
return FALSE
|
||||
if(!check_access)
|
||||
return TRUE
|
||||
if(allowed(user))
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>Access denied.</span>")
|
||||
|
||||
/obj/structure/closet/proc/togglelock(mob/living/user)
|
||||
add_fingerprint(user)
|
||||
if(eigen_target)
|
||||
return
|
||||
if(opened)
|
||||
return
|
||||
if(!can_lock(user))
|
||||
return
|
||||
locked = !locked
|
||||
user.visible_message("<span class='notice'>[user] [locked ? null : "un"]locks [src].</span>",
|
||||
"<span class='notice'>You [locked ? null : "un"]lock [src].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/structure/closet/proc/dump_contents(var/override = TRUE) //Override is for not revealing the locker electronics when you open the locker, for example
|
||||
/obj/structure/closet/proc/dump_contents(override = TRUE) //Override is for not revealing the locker electronics when you open the locker, for example
|
||||
var/atom/L = drop_location()
|
||||
for(var/atom/movable/AM in src)
|
||||
if(AM == lockerelectronics && override)
|
||||
if(AM == lockerelectronics && override) // this stops the electronics from being dumped out? huh
|
||||
continue
|
||||
AM.forceMove(L)
|
||||
if(throwing) // you keep some momentum when getting out of a thrown closet
|
||||
@@ -187,18 +156,30 @@
|
||||
for(var/atom/movable/AM in L)
|
||||
if(AM != src && insert(AM) == -1) // limit reached
|
||||
break
|
||||
// for(var/i in reverseRange(L.GetAllContents()))
|
||||
// var/atom/movable/thing = i
|
||||
// SEND_SIGNAL(thing, COMSIG_TRY_STORAGE_HIDE_ALL)
|
||||
|
||||
/obj/structure/closet/proc/open(mob/living/user)
|
||||
if(opened || !can_open(user))
|
||||
/obj/structure/closet/proc/open(mob/living/user, force = FALSE)
|
||||
if(!can_open(user, force))
|
||||
return
|
||||
playsound(loc, open_sound, 15, 1, -3)
|
||||
if(opened)
|
||||
return
|
||||
welded = FALSE
|
||||
locked = FALSE // if you manage to open it, then its not welded/locked, hello?!
|
||||
playsound(loc, open_sound, 15, TRUE, -3)
|
||||
opened = TRUE
|
||||
if(!dense_when_open)
|
||||
density = FALSE
|
||||
climb_time *= 0.5 //it's faster to climb onto an open thing
|
||||
dump_contents()
|
||||
update_icon()
|
||||
return 1
|
||||
after_open(user, force)
|
||||
return TRUE
|
||||
|
||||
///Proc to override for effects after opening a door
|
||||
/obj/structure/closet/proc/after_open(mob/living/user, force = FALSE)
|
||||
return
|
||||
|
||||
/obj/structure/closet/proc/insert(atom/movable/AM)
|
||||
if(contents.len >= storage_capacity)
|
||||
@@ -208,19 +189,19 @@
|
||||
do_teleport(AM, get_turf(eigen_target), 0)
|
||||
if(eigen_target.opened == FALSE)
|
||||
eigen_target.bust_open()
|
||||
else
|
||||
AM.forceMove(src)
|
||||
return TRUE
|
||||
|
||||
AM.forceMove(src)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/structure/closet/proc/insertion_allowed(atom/movable/AM)
|
||||
if(ismob(AM))
|
||||
if(!isliving(AM)) //let's not put ghosts or camera mobs inside closets...
|
||||
return FALSE
|
||||
var/mob/living/L = AM
|
||||
if(L.move_resist >= MOVE_FORCE_VERY_STRONG || L.buckled || L.incorporeal_move || L.has_buckled_mobs())
|
||||
if(L.anchored || L.move_resist >= MOVE_FORCE_VERY_STRONG || L.buckled || L.incorporeal_move || L.has_buckled_mobs())
|
||||
return FALSE
|
||||
if(L.mob_size > MOB_SIZE_TINY) // Tiny mobs are treated as items.
|
||||
if(horizontal && L.density)
|
||||
@@ -236,13 +217,13 @@
|
||||
else if(istype(AM, /obj/structure/closet))
|
||||
return FALSE
|
||||
|
||||
else if(istype(AM, /obj/effect))
|
||||
else if(iseffect(AM)) // todo: move to atom/movable
|
||||
return FALSE
|
||||
|
||||
else if(isobj(AM))
|
||||
if((!allow_dense && AM.density) || AM.anchored || AM.has_buckled_mobs())
|
||||
return FALSE
|
||||
if(isitem(AM) && !HAS_TRAIT(AM, TRAIT_NODROP))
|
||||
else if(isitem(AM) && !HAS_TRAIT(AM, TRAIT_NODROP))
|
||||
return TRUE
|
||||
else if(!allow_objects && !istype(AM, /obj/effect/dummy/chameleon))
|
||||
return FALSE
|
||||
@@ -255,25 +236,356 @@
|
||||
if(!opened || !can_close(user))
|
||||
return FALSE
|
||||
take_contents()
|
||||
playsound(loc, close_sound, 15, 1, -3)
|
||||
climb_time = initial(climb_time)
|
||||
playsound(loc, close_sound, 15, TRUE, -3)
|
||||
opened = FALSE
|
||||
density = TRUE
|
||||
update_icon()
|
||||
after_close(user)
|
||||
return TRUE
|
||||
|
||||
///Proc to override for effects after closing a door
|
||||
/obj/structure/closet/proc/after_close(mob/living/user)
|
||||
return
|
||||
|
||||
|
||||
/obj/structure/closet/proc/toggle(mob/living/user)
|
||||
if(opened)
|
||||
return close(user)
|
||||
else
|
||||
return open(user)
|
||||
|
||||
|
||||
/obj/structure/closet/deconstruct(disassembled = TRUE)
|
||||
if(ispath(material_drop) && material_drop_amount && !(flags_1 & NODECONSTRUCT_1))
|
||||
new material_drop(loc, material_drop_amount)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/closet/obj_break(damage_flag)
|
||||
if(!broken && !(flags_1 & NODECONSTRUCT_1))
|
||||
bust_open()
|
||||
|
||||
/obj/structure/closet/attackby(obj/item/W, mob/user, params)
|
||||
if(user in src)
|
||||
return
|
||||
if(src.tool_interact(W,user))
|
||||
return 1 // No afterattack
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/proc/tool_interact(obj/item/W, mob/living/user)//returns TRUE if attackBy call shouldn't be continued (because tool was used/closet was of wrong type), FALSE if otherwise
|
||||
. = TRUE
|
||||
if(opened)
|
||||
if(istype(W, /obj/item/weldingtool))
|
||||
if(W.tool_behaviour == TOOL_WELDER)
|
||||
// eigen check
|
||||
if(eigen_teleport)
|
||||
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to deconstruct!</span>")
|
||||
return
|
||||
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin cutting \the [src] apart...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
if(!opened)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] slices apart \the [src].</span>",
|
||||
"<span class='notice'>You cut \the [src] apart with \the [W].</span>",
|
||||
"<span class='hear'>You hear welding.</span>")
|
||||
deconstruct(TRUE)
|
||||
return
|
||||
else // for example cardboard box is cut with wirecutters
|
||||
user.visible_message("<span class='notice'>[user] cut apart \the [src].</span>", \
|
||||
"<span class='notice'>You cut \the [src] apart with \the [W].</span>")
|
||||
deconstruct(TRUE)
|
||||
return
|
||||
if(user.transferItemToLoc(W, drop_location())) // so we put in unlit welder too
|
||||
return
|
||||
else if(W.tool_behaviour == TOOL_WELDER && can_weld_shut)
|
||||
// eigen check
|
||||
if(eigen_teleport)
|
||||
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to deconstruct!</span>")
|
||||
return
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin [welded ? "unwelding":"welding"] \the [src]...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
if(opened)
|
||||
return
|
||||
welded = !welded
|
||||
after_weld(welded)
|
||||
user.visible_message("<span class='notice'>[user] [welded ? "welds shut" : "unwelded"] \the [src].</span>",
|
||||
"<span class='notice'>You [welded ? "weld" : "unwelded"] \the [src] with \the [W].</span>",
|
||||
"<span class='hear'>You hear welding.</span>")
|
||||
log_game("[key_name(user)] [welded ? "welded":"unwelded"] closet [src] with [W] at [AREACOORD(src)]")
|
||||
update_icon()
|
||||
else if(W.tool_behaviour == TOOL_WRENCH && anchorable)
|
||||
if(isinspace() && !anchored)
|
||||
return
|
||||
set_anchored(!anchored)
|
||||
W.play_tool_sound(src, 75)
|
||||
user.visible_message("<span class='notice'>[user] [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.</span>", \
|
||||
"<span class='notice'>You [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.</span>", \
|
||||
"<span class='hear'>You hear a ratchet.</span>")
|
||||
else if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON))
|
||||
var/item_is_id = W.GetID()
|
||||
if(!item_is_id)
|
||||
return FALSE
|
||||
if(item_is_id || !toggle(user))
|
||||
togglelock(user)
|
||||
// cit addons
|
||||
else if(istype(W, /obj/item/electronics/airlock))
|
||||
handle_lock_addition(user, W)
|
||||
else if(W.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
handle_lock_removal(user, W)
|
||||
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/structure/closet/proc/after_weld(weld_state)
|
||||
return
|
||||
|
||||
/obj/structure/closet/MouseDrop_T(atom/movable/O, mob/living/user)
|
||||
if(!istype(O) || O.anchored || istype(O, /obj/screen))
|
||||
return
|
||||
if(!istype(user) || user.incapacitated() || user.lying)
|
||||
return
|
||||
if(!Adjacent(user) || !user.Adjacent(O))
|
||||
return
|
||||
if(user == O) //try to climb onto it
|
||||
return ..()
|
||||
if(!opened)
|
||||
return
|
||||
if(!isturf(O.loc))
|
||||
return
|
||||
|
||||
var/actuallyismob = 0
|
||||
if(isliving(O))
|
||||
actuallyismob = 1
|
||||
else if(!isitem(O))
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/list/targets = list(O, src)
|
||||
add_fingerprint(user)
|
||||
user.visible_message("<span class='warning'>[user] [actuallyismob ? "tries to ":""]stuff [O] into [src].</span>", \
|
||||
"<span class='warning'>You [actuallyismob ? "try to ":""]stuff [O] into [src].</span>", \
|
||||
"<span class='hear'>You hear clanging.</span>")
|
||||
if(actuallyismob)
|
||||
if(do_after_mob(user, targets, 40))
|
||||
user.visible_message("<span class='notice'>[user] stuffs [O] into [src].</span>", \
|
||||
"<span class='notice'>You stuff [O] into [src].</span>", \
|
||||
"<span class='hear'>You hear a loud metal bang.</span>")
|
||||
var/mob/living/L = O
|
||||
if(!issilicon(L))
|
||||
L.DefaultCombatKnockdown(40)
|
||||
if(istype(src, /obj/structure/closet/supplypod/extractionpod))
|
||||
O.forceMove(src)
|
||||
else
|
||||
O.forceMove(T)
|
||||
close()
|
||||
else
|
||||
O.forceMove(T)
|
||||
return 1
|
||||
|
||||
/obj/structure/closet/relaymove(mob/living/user, direction)
|
||||
if(user.stat || !isturf(loc))
|
||||
return
|
||||
if(locked)
|
||||
if(message_cooldown <= world.time)
|
||||
message_cooldown = world.time + 50
|
||||
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
|
||||
return
|
||||
container_resist(user)
|
||||
|
||||
/obj/structure/closet/on_attack_hand(mob/user)
|
||||
if(user.lying && get_dist(src, user) > 0)
|
||||
return
|
||||
|
||||
if(!toggle(user))
|
||||
togglelock(user)
|
||||
|
||||
|
||||
/obj/structure/closet/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/closet/attack_robot(mob/user)
|
||||
if(user.Adjacent(src))
|
||||
return attack_hand(user)
|
||||
|
||||
// tk grab then use on self
|
||||
/obj/structure/closet/attack_self_tk(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/closet/verb/verb_toggleopen()
|
||||
set src in view(1)
|
||||
set category = "Object"
|
||||
set name = "Toggle Open"
|
||||
|
||||
if(!usr.canUseTopic(src, BE_CLOSE) || !isturf(loc))
|
||||
return
|
||||
|
||||
if(iscarbon(usr) || issilicon(usr) || isdrone(usr))
|
||||
return toggle(usr)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>This mob type can't use this verb.</span>")
|
||||
|
||||
// Objects that try to exit a locker by stepping were doing so successfully,
|
||||
// and due to an oversight in turf/Enter() were going through walls. That
|
||||
// should be independently resolved, but this is also an interesting twist.
|
||||
/obj/structure/closet/Exit(atom/movable/AM)
|
||||
open()
|
||||
if(AM.loc == src)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/closet/container_resist(mob/living/user)
|
||||
if(opened)
|
||||
return
|
||||
if(ismovable(loc))
|
||||
// user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
// user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
var/atom/movable/AM = loc
|
||||
AM.relay_container_resist(user, src)
|
||||
return
|
||||
if(!welded && !locked)
|
||||
open()
|
||||
return
|
||||
|
||||
//okay, so the closet is either welded or locked... resist!!!
|
||||
// user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
// user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='warning'>[src] begins to shake violently!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='hear'>You hear banging from [src].</span>")
|
||||
if(do_after(user,(breakout_time), target = src, required_mobility_flags = MOBILITY_RESIST))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) )
|
||||
return
|
||||
//we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting
|
||||
user.visible_message("<span class='danger'>[user] successfully broke out of [src]!</span>",
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
bust_open()
|
||||
else
|
||||
if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded.
|
||||
to_chat(user, "<span class='warning'>You fail to break out of [src]!</span>")
|
||||
|
||||
/obj/structure/closet/proc/bust_open()
|
||||
welded = FALSE //applies to all lockers
|
||||
locked = FALSE //applies to critter crates and secure lockers only
|
||||
broken = TRUE //applies to secure lockers only
|
||||
open()
|
||||
|
||||
/obj/structure/closet/AltClick(mob/user)
|
||||
..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE) || !isturf(loc))
|
||||
return
|
||||
if(opened || !secure)
|
||||
return
|
||||
else
|
||||
togglelock(user)
|
||||
|
||||
/obj/structure/closet/proc/togglelock(mob/living/user, silent)
|
||||
if(secure && !broken)
|
||||
if(allowed(user))
|
||||
if(iscarbon(user))
|
||||
add_fingerprint(user)
|
||||
locked = !locked
|
||||
user.visible_message("<span class='notice'>[user] [locked ? null : "un"]locks [src].</span>",
|
||||
"<span class='notice'>You [locked ? null : "un"]lock [src].</span>")
|
||||
update_icon()
|
||||
else if(!silent)
|
||||
to_chat(user, "<span class='alert'>Access Denied.</span>")
|
||||
else if(secure && broken)
|
||||
to_chat(user, "<span class='warning'>\The [src] is broken!</span>")
|
||||
|
||||
/obj/structure/closet/CtrlShiftClick(mob/living/user)
|
||||
if(!HAS_TRAIT(user, TRAIT_SKITTISH))
|
||||
return ..()
|
||||
if(!user.canUseTopic(src) || !isturf(user.loc) || !user.Adjacent(src) || !user.CanReach(src))
|
||||
return
|
||||
dive_into(user)
|
||||
|
||||
/obj/structure/closet/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(!secure || broken)
|
||||
return
|
||||
if(user)
|
||||
user.visible_message("<span class='warning'>Sparks fly from [src]!</span>",
|
||||
"<span class='warning'>You scramble [src]'s lock, breaking it open!</span>",
|
||||
"<span class='hear'>You hear a faint electrical spark.</span>")
|
||||
playsound(src, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
broken = TRUE
|
||||
locked = FALSE
|
||||
if(!QDELETED(lockerelectronics))
|
||||
QDEL_NULL(lockerelectronics)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/closet/get_remote_view_fullscreens(mob/user)
|
||||
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
||||
user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1)
|
||||
|
||||
/obj/structure/closet/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if (!(. & EMP_PROTECT_CONTENTS))
|
||||
for(var/obj/O in src)
|
||||
O.emp_act(severity)
|
||||
if(secure && !broken && !(. & EMP_PROTECT_SELF))
|
||||
if(prob(50 / severity))
|
||||
locked = !locked
|
||||
update_icon()
|
||||
if(prob(20 / severity) && !opened)
|
||||
if(!locked)
|
||||
open()
|
||||
else
|
||||
req_access = list()
|
||||
req_access += pick(get_all_accesses())
|
||||
if(!QDELETED(lockerelectronics))
|
||||
lockerelectronics.accesses = req_access
|
||||
|
||||
/obj/structure/closet/contents_explosion(severity, target)
|
||||
for(var/atom/A in contents)
|
||||
A.ex_act(severity, target)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/structure/closet/singularity_act()
|
||||
dump_contents()
|
||||
..()
|
||||
|
||||
/obj/structure/closet/AllowDrop()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/structure/closet/return_temperature()
|
||||
return
|
||||
|
||||
/obj/structure/closet/proc/dive_into(mob/living/user)
|
||||
var/turf/T1 = get_turf(user)
|
||||
var/turf/T2 = get_turf(src)
|
||||
if(!opened)
|
||||
if(locked)
|
||||
togglelock(user, TRUE)
|
||||
if(!open(user))
|
||||
to_chat(user, "<span class='warning'>It won't budge!</span>")
|
||||
return
|
||||
step_towards(user, T2)
|
||||
T1 = get_turf(user)
|
||||
if(T1 == T2)
|
||||
user.set_resting(TRUE, TRUE)
|
||||
if(!close(user))
|
||||
to_chat(user, "<span class='warning'>You can't get [src] to close!</span>")
|
||||
user.set_resting(FALSE, TRUE)
|
||||
return
|
||||
user.set_resting(FALSE, TRUE)
|
||||
togglelock(user)
|
||||
T1.visible_message("<span class='warning'>[user] dives into [src]!</span>")
|
||||
|
||||
/obj/structure/closet/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
|
||||
return (user in src)
|
||||
|
||||
/// cit specific ///
|
||||
|
||||
/obj/structure/closet/proc/handle_lock_addition(mob/user, obj/item/electronics/airlock/E)
|
||||
add_fingerprint(user)
|
||||
if(lock_in_use)
|
||||
@@ -336,294 +648,17 @@
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/structure/closet/deconstruct(disassembled = TRUE)
|
||||
if(ispath(material_drop) && material_drop_amount && !(flags_1 & NODECONSTRUCT_1))
|
||||
new material_drop(loc, material_drop_amount)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/closet/obj_break(damage_flag)
|
||||
if(!broken && !(flags_1 & NODECONSTRUCT_1))
|
||||
bust_open()
|
||||
|
||||
/obj/structure/closet/attackby(obj/item/W, mob/user, params)
|
||||
if(user in src)
|
||||
return
|
||||
if(src.tool_interact(W,user))
|
||||
return 1 // No afterattack
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/proc/tool_interact(obj/item/W, mob/user)//returns TRUE if attackBy call shouldnt be continued (because tool was used/closet was of wrong type), FALSE if otherwise
|
||||
. = TRUE
|
||||
if(opened)
|
||||
if(istype(W, cutting_tool))
|
||||
var/welder = FALSE
|
||||
if(W.tool_behaviour == TOOL_WELDER)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You begin [welder ? "slicing" : "deconstructing"] \the [src] apart...</span>")
|
||||
welder = TRUE
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
if(eigen_teleport)
|
||||
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to [welder ? "slice" : "deconstruct"]!</span>")
|
||||
return
|
||||
if(!opened)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] [welder ? "slice" : "deconstruct"]s apart \the [src].</span>",
|
||||
"<span class='notice'>You [welder ? "slice" : "deconstruct"] \the [src] apart with \the [W].</span>",
|
||||
"<span class='italics'>You hear [welder ? "welding" : "rustling of screws and metal"].</span>")
|
||||
deconstruct(TRUE)
|
||||
return
|
||||
if(user.a_intent != INTENT_HARM && user.transferItemToLoc(W, drop_location())) // so we put in unlit welder too
|
||||
return TRUE
|
||||
else if(istype(W, /obj/item/electronics/airlock))
|
||||
handle_lock_addition(user, W)
|
||||
else if(W.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
handle_lock_removal(user, W)
|
||||
else if(W.tool_behaviour == TOOL_WELDER && can_weld_shut)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin [welded ? "unwelding":"welding"] \the [src]...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
if(eigen_teleport)
|
||||
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to weld!</span>")
|
||||
return
|
||||
if(opened)
|
||||
return
|
||||
welded = !welded
|
||||
after_weld(welded)
|
||||
user.visible_message("<span class='notice'>[user] [welded ? "welds shut" : "unwelds"] \the [src].</span>",
|
||||
"<span class='notice'>You [welded ? "weld" : "unwelded"] \the [src] with \the [W].</span>",
|
||||
"<span class='italics'>You hear welding.</span>")
|
||||
update_icon()
|
||||
else if(W.tool_behaviour == TOOL_WRENCH && anchorable)
|
||||
if(isinspace() && !anchored)
|
||||
return
|
||||
setAnchored(!anchored)
|
||||
W.play_tool_sound(src, 75)
|
||||
user.visible_message("<span class='notice'>[user] [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.</span>", \
|
||||
"<span class='notice'>You [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.</span>", \
|
||||
"<span class='italics'>You hear a ratchet.</span>")
|
||||
else if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON))
|
||||
if(W.GetID() || !toggle(user))
|
||||
togglelock(user)
|
||||
else
|
||||
/obj/structure/closet/proc/can_lock(mob/living/user, var/check_access = TRUE) //set check_access to FALSE if you only need to check if a locker has a functional lock rather than access
|
||||
if(!secure)
|
||||
return FALSE
|
||||
|
||||
/obj/structure/closet/proc/after_weld(weld_state)
|
||||
return
|
||||
|
||||
/obj/structure/closet/MouseDrop_T(atom/movable/O, mob/living/user)
|
||||
if(!istype(O) || O.anchored || istype(O, /obj/screen))
|
||||
return
|
||||
if(!istype(user) || user.incapacitated() || user.lying)
|
||||
return
|
||||
if(!Adjacent(user) || !user.Adjacent(O))
|
||||
return
|
||||
if(user == O) //try to climb onto it
|
||||
return ..()
|
||||
if(!opened)
|
||||
return
|
||||
if(!isturf(O.loc))
|
||||
return
|
||||
|
||||
var/actuallyismob = 0
|
||||
if(isliving(O))
|
||||
actuallyismob = 1
|
||||
else if(!isitem(O))
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/list/targets = list(O, src)
|
||||
add_fingerprint(user)
|
||||
user.visible_message("<span class='warning'>[user] [actuallyismob ? "tries to ":""]stuff [O] into [src].</span>", \
|
||||
"<span class='warning'>You [actuallyismob ? "try to ":""]stuff [O] into [src].</span>", \
|
||||
"<span class='italics'>You hear clanging.</span>")
|
||||
if(actuallyismob)
|
||||
if(do_after_mob(user, targets, 40))
|
||||
user.visible_message("<span class='notice'>[user] stuffs [O] into [src].</span>", \
|
||||
"<span class='notice'>You stuff [O] into [src].</span>", \
|
||||
"<span class='italics'>You hear a loud metal bang.</span>")
|
||||
var/mob/living/L = O
|
||||
if(!issilicon(L))
|
||||
L.DefaultCombatKnockdown(40)
|
||||
if(istype(src, /obj/structure/closet/supplypod/extractionpod))
|
||||
O.forceMove(src)
|
||||
else
|
||||
O.forceMove(T)
|
||||
close()
|
||||
else
|
||||
O.forceMove(T)
|
||||
return 1
|
||||
|
||||
/obj/structure/closet/relaymove(mob/user)
|
||||
if(user.stat || !isturf(loc) || !isliving(user))
|
||||
return
|
||||
if(locked || welded)
|
||||
if(message_cooldown <= world.time)
|
||||
message_cooldown = world.time + 50
|
||||
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
|
||||
return
|
||||
container_resist(user)
|
||||
|
||||
/obj/structure/closet/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(user.lying && get_dist(src, user) > 0)
|
||||
return
|
||||
|
||||
if(!toggle(user))
|
||||
togglelock(user)
|
||||
|
||||
/obj/structure/closet/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/closet/attack_robot(mob/user)
|
||||
if(user.Adjacent(src))
|
||||
return attack_hand(user)
|
||||
|
||||
// tk grab then use on self
|
||||
/obj/structure/closet/attack_self_tk(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/closet/verb/verb_toggleopen()
|
||||
set src in oview(1)
|
||||
set category = "Object"
|
||||
set name = "Toggle Open"
|
||||
|
||||
var/mob/living/L = usr
|
||||
if(!istype(L) || !CHECK_MOBILITY(L, MOBILITY_USE))
|
||||
if(broken)
|
||||
to_chat(user, "<span class='notice'>[src] is broken!</span>")
|
||||
return FALSE
|
||||
|
||||
if(iscarbon(usr) || issilicon(usr) || isdrone(usr))
|
||||
return attack_hand(usr)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>This mob type can't use this verb.</span>")
|
||||
|
||||
// Objects that try to exit a locker by stepping were doing so successfully,
|
||||
// and due to an oversight in turf/Enter() were going through walls. That
|
||||
// should be independently resolved, but this is also an interesting twist.
|
||||
/obj/structure/closet/Exit(atom/movable/AM)
|
||||
open()
|
||||
if(AM.loc == src)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/structure/closet/container_resist(mob/living/user)
|
||||
if(opened)
|
||||
return
|
||||
if(ismovable(loc))
|
||||
var/atom/movable/AM = loc
|
||||
AM.relay_container_resist(user, src)
|
||||
return
|
||||
if(!welded && !locked)
|
||||
open()
|
||||
return
|
||||
|
||||
//okay, so the closet is either welded or locked... resist!!!
|
||||
user.visible_message("<span class='warning'>[src] begins to shake violently!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear banging from [src].</span>")
|
||||
if(do_after(user,(breakout_time), target = src, required_mobility_flags = MOBILITY_RESIST))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) )
|
||||
return
|
||||
//we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting
|
||||
user.visible_message("<span class='danger'>[user] successfully broke out of [src]!</span>",
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
bust_open()
|
||||
else
|
||||
if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded.
|
||||
to_chat(user, "<span class='warning'>You fail to break out of [src]!</span>")
|
||||
|
||||
/obj/structure/closet/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, be_close=TRUE) || !isturf(loc))
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
if(QDELETED(lockerelectronics) && !locked) //We want to be able to unlock it regardless of electronics, but only lockable with electronics
|
||||
to_chat(user, "<span class='notice'>[src] is missing locker electronics!</span>")
|
||||
return FALSE
|
||||
if(!check_access)
|
||||
return TRUE
|
||||
togglelock(user)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/closet/CtrlShiftClick(mob/living/user)
|
||||
if(!HAS_TRAIT(user, TRAIT_SKITTISH))
|
||||
return ..()
|
||||
if(!user.canUseTopic(src) || !isturf(user.loc) || !user.Adjacent(src) || !user.CanReach(src))
|
||||
return
|
||||
dive_into(user)
|
||||
|
||||
/obj/structure/closet/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(!secure || broken)
|
||||
return
|
||||
user.visible_message("<span class='warning'>Sparks fly from [src]!</span>",
|
||||
"<span class='warning'>You scramble [src]'s lock, breaking it open!</span>",
|
||||
"<span class='italics'>You hear a faint electrical spark.</span>")
|
||||
playsound(src, "sparks", 50, 1)
|
||||
broken = TRUE
|
||||
locked = FALSE
|
||||
if(!QDELETED(lockerelectronics))
|
||||
QDEL_NULL(lockerelectronics)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/closet/get_remote_view_fullscreens(mob/user)
|
||||
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
||||
user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1)
|
||||
|
||||
/obj/structure/closet/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if (!(. & EMP_PROTECT_CONTENTS))
|
||||
for(var/obj/O in src)
|
||||
O.emp_act(severity)
|
||||
if(!secure || broken)
|
||||
return ..()
|
||||
if(prob(severity/2))
|
||||
locked = !locked
|
||||
update_icon()
|
||||
if(prob(severity/5) && !opened)
|
||||
if(!locked)
|
||||
open()
|
||||
else
|
||||
req_access = list()
|
||||
req_access += pick(get_all_accesses())
|
||||
if(!QDELETED(lockerelectronics))
|
||||
lockerelectronics.accesses = req_access
|
||||
|
||||
/obj/structure/closet/contents_explosion(severity, target)
|
||||
for(var/atom/A in contents)
|
||||
A.ex_act(severity, target)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/structure/closet/singularity_act()
|
||||
dump_contents()
|
||||
..()
|
||||
|
||||
/obj/structure/closet/AllowDrop()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/structure/closet/return_temperature()
|
||||
return
|
||||
|
||||
/obj/structure/closet/proc/dive_into(mob/living/user)
|
||||
var/turf/T1 = get_turf(user)
|
||||
var/turf/T2 = get_turf(src)
|
||||
if(!opened)
|
||||
if(locked)
|
||||
togglelock(user, TRUE)
|
||||
if(!open(user))
|
||||
to_chat(user, "<span class='warning'>It won't budge!</span>")
|
||||
return
|
||||
step_towards(user, T2)
|
||||
T1 = get_turf(user)
|
||||
if(T1 == T2)
|
||||
user.set_resting(TRUE, TRUE)
|
||||
if(!close(user))
|
||||
to_chat(user, "<span class='warning'>You can't get [src] to close!</span>")
|
||||
user.set_resting(FALSE, TRUE)
|
||||
return
|
||||
user.set_resting(FALSE, TRUE)
|
||||
togglelock(user)
|
||||
T1.visible_message("<span class='warning'>[user] dives into [src]!</span>")
|
||||
|
||||
/obj/structure/closet/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
|
||||
return ..() && opened
|
||||
if(allowed(user))
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>Access denied.</span>")
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
material_drop_amount = 5
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/manifest
|
||||
|
||||
/obj/structure/closet/crate/New()
|
||||
..()
|
||||
/obj/structure/closet/crate/Initialize()
|
||||
. = ..()
|
||||
if(icon_state == "[initial(icon_state)]open")
|
||||
opened = TRUE
|
||||
// AddElement(/datum/element/climbable, climb_time = crate_climb_time * 0.5, climb_stun = 0)
|
||||
// else
|
||||
// AddElement(/datum/element/climbable, climb_time = crate_climb_time, climb_stun = 0)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/closet/crate/CanPass(atom/movable/mover, turf/target)
|
||||
@@ -46,21 +49,16 @@
|
||||
if(manifest)
|
||||
tear_manifest(user)
|
||||
|
||||
/obj/structure/closet/crate/tool_interact(obj/item/W, mob/user)
|
||||
if(W.tool_behaviour == TOOL_WIRECUTTER && manifest)
|
||||
tear_manifest(user)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/crate/open(mob/living/user)
|
||||
/obj/structure/closet/crate/open(mob/living/user, force = FALSE)
|
||||
. = ..()
|
||||
if(. && manifest)
|
||||
to_chat(user, "<span class='notice'>The manifest is torn off [src].</span>")
|
||||
playsound(src, 'sound/items/poster_ripped.ogg', 75, 1)
|
||||
playsound(src, 'sound/items/poster_ripped.ogg', 75, TRUE)
|
||||
manifest.forceMove(get_turf(src))
|
||||
manifest = null
|
||||
update_icon()
|
||||
|
||||
// cit specific
|
||||
/obj/structure/closet/crate/handle_lock_addition()
|
||||
return
|
||||
|
||||
@@ -69,7 +67,7 @@
|
||||
|
||||
/obj/structure/closet/crate/proc/tear_manifest(mob/user)
|
||||
to_chat(user, "<span class='notice'>You tear the manifest off of [src].</span>")
|
||||
playsound(src, 'sound/items/poster_ripped.ogg', 75, 1)
|
||||
playsound(src, 'sound/items/poster_ripped.ogg', 75, TRUE)
|
||||
|
||||
manifest.forceMove(loc)
|
||||
if(ishuman(user))
|
||||
|
||||
@@ -80,16 +80,25 @@
|
||||
name = "private crate"
|
||||
desc = "A crate cover designed to only open for who purchased its contents."
|
||||
icon_state = "privatecrate"
|
||||
///Account of the person buying the crate if private purchasing.
|
||||
var/datum/bank_account/buyer_account
|
||||
///Department of the person buying the crate if buying via the NIRN app.
|
||||
var/datum/bank_account/department/department_account
|
||||
///Is the secure crate opened or closed?
|
||||
var/privacy_lock = TRUE
|
||||
///Is the crate being bought by a person, or a budget card?
|
||||
var/department_purchase = FALSE
|
||||
|
||||
/obj/structure/closet/crate/secure/owned/examine(mob/user)
|
||||
. = ..()
|
||||
to_chat(user, "<span class='notice'>It's locked with a privacy lock, and can only be unlocked by the buyer's ID.</span>")
|
||||
. += "<span class='notice'>It's locked with a privacy lock, and can only be unlocked by the buyer's ID.</span>"
|
||||
|
||||
/obj/structure/closet/crate/secure/owned/Initialize(mapload, datum/bank_account/_buyer_account)
|
||||
. = ..()
|
||||
buyer_account = _buyer_account
|
||||
if(istype(buyer_account, /datum/bank_account/department))
|
||||
department_purchase = TRUE
|
||||
department_account = buyer_account
|
||||
|
||||
/obj/structure/closet/crate/secure/owned/togglelock(mob/living/user, silent)
|
||||
if(privacy_lock)
|
||||
@@ -97,7 +106,7 @@
|
||||
var/obj/item/card/id/id_card = user.get_idcard(TRUE)
|
||||
if(id_card)
|
||||
if(id_card.registered_account)
|
||||
if(id_card.registered_account == buyer_account)
|
||||
if(id_card.registered_account == buyer_account || (department_purchase && (id_card.registered_account?.account_job?.paycheck_department) == (department_account.department_id)))
|
||||
if(iscarbon(user))
|
||||
add_fingerprint(user)
|
||||
locked = !locked
|
||||
|
||||
@@ -676,7 +676,6 @@
|
||||
ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT)
|
||||
ADD_TRAIT(new_spawn, TRAIT_EXEMPT_HEALTH_EVENTS, GHOSTROLE_TRAIT)
|
||||
ADD_TRAIT(new_spawn, TRAIT_NO_MIDROUND_ANTAG, GHOSTROLE_TRAIT) //The mob can't be made into a random antag, they are still eligible for ghost roles popups.
|
||||
ADD_TRAIT(new_spawn, TRAIT_PACIFISM, GHOSTROLE_TRAIT)
|
||||
to_chat(new_spawn,"<span class='boldwarning'>Ghosting is free!</span>")
|
||||
var/datum/action/toggle_dead_chat_mob/D = new(new_spawn)
|
||||
D.Grant(new_spawn)
|
||||
|
||||
@@ -125,6 +125,8 @@
|
||||
/datum/antagonist/changeling/proc/remove_changeling_powers()
|
||||
if(ishuman(owner.current) || ismonkey(owner.current))
|
||||
reset_properties()
|
||||
QDEL_NULL(cellular_emporium)
|
||||
QDEL_NULL(emporium_action)
|
||||
for(var/obj/effect/proc_holder/changeling/p in purchasedpowers)
|
||||
if(p.always_keep)
|
||||
continue
|
||||
@@ -139,6 +141,7 @@
|
||||
/datum/antagonist/changeling/proc/reset_powers()
|
||||
if(purchasedpowers)
|
||||
remove_changeling_powers()
|
||||
create_actions()
|
||||
//Repurchase free powers.
|
||||
for(var/path in all_powers)
|
||||
var/obj/effect/proc_holder/changeling/S = new path()
|
||||
@@ -225,7 +228,8 @@
|
||||
/datum/antagonist/changeling/proc/regenerate()
|
||||
var/mob/living/carbon/the_ling = owner.current
|
||||
if(istype(the_ling))
|
||||
emporium_action.Grant(the_ling)
|
||||
if(emporium_action)
|
||||
emporium_action.Grant(the_ling)
|
||||
if(the_ling.stat == DEAD)
|
||||
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), (chem_storage*0.5))
|
||||
geneticdamage = max(LING_DEAD_GENETICDAMAGE_HEAL_CAP,geneticdamage-1)
|
||||
|
||||
@@ -11,6 +11,14 @@
|
||||
|
||||
//Revive from revival stasis
|
||||
/obj/effect/proc_holder/changeling/revive/sting_action(mob/living/carbon/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!changeling)
|
||||
return
|
||||
if(changeling.hostile_absorbed)
|
||||
to_chat(user, "<span class='notice'>We cannot muster up the strength to revive ourselves!</span>")
|
||||
changeling.purchasedpowers -= src
|
||||
src.action.Remove(user)
|
||||
return
|
||||
user.cure_fakedeath("changeling")
|
||||
user.revive(full_heal = 1)
|
||||
var/list/missing = user.get_missing_limbs()
|
||||
@@ -27,7 +35,6 @@
|
||||
user.regenerate_limbs(0, list(BODY_ZONE_HEAD))
|
||||
user.regenerate_organs()
|
||||
to_chat(user, "<span class='notice'>We have revived ourselves.</span>")
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
changeling.purchasedpowers -= src
|
||||
src.action.Remove(user)
|
||||
return TRUE
|
||||
|
||||
@@ -202,8 +202,9 @@
|
||||
filled = 1
|
||||
release_pressure = ONE_ATMOSPHERE*2
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/Initialize(mapload, datum/gas_mixture/existing_mixture)
|
||||
. = ..()
|
||||
/obj/machinery/portable_atmospherics/canister/New(loc, datum/gas_mixture/existing_mixture)
|
||||
..()
|
||||
|
||||
if(existing_mixture)
|
||||
air_contents.copy_from(existing_mixture)
|
||||
else
|
||||
@@ -221,10 +222,8 @@
|
||||
air_contents.set_temperature(starter_temp)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/air/create_gas()
|
||||
var/oh_two = /datum/gas/oxygen
|
||||
var/dihydrogen = /datum/gas/nitrogen //how to piss of chemists
|
||||
air_contents.set_moles(oh_two, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
air_contents.set_moles(dihydrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
air_contents.set_moles(/datum/gas/oxygen, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
air_contents.set_moles(/datum/gas/nitrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/update_icon_state()
|
||||
if(stat & BROKEN)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/datum/blackmarket_item
|
||||
var/name // Name for the item entry used in the uplink.
|
||||
var/desc // Description for the item entry used in the uplink.
|
||||
var/category // The category this item belongs to, should be already declared in the market that this item is accessible in.
|
||||
var/list/markets = list(/datum/blackmarket_market/blackmarket) // "/datum/blackmarket_market"s that this item should be in, used by SSblackmarket on init.
|
||||
|
||||
var/price // Price for the item, if not set creates a price according to the *_min and *_max vars.
|
||||
var/stock // How many of this type of item is available, if not set creates a price according to the *_min and *_max vars.
|
||||
|
||||
var/item // Path to or the item itself what this entry is for, this should be set even if you override spawn_item to spawn your item.
|
||||
|
||||
var/price_min = 0 // Minimum price for the item if generated randomly.
|
||||
var/price_max = 0 // Maximum price for the item if generated randomly.
|
||||
var/stock_min = 1 // Minimum amount that there should be of this item in the market if generated randomly. This defaults to 1 as most items will have it as 1.
|
||||
var/stock_max = 0 // Maximum amount that there should be of this item in the market if generated randomly.
|
||||
var/availability_prob = 0 // Probability for this item to be available. Used by SSblackmarket on init.
|
||||
|
||||
/datum/blackmarket_item/New()
|
||||
if(isnull(price))
|
||||
price = rand(price_min, price_max)
|
||||
if(isnull(stock))
|
||||
stock = rand(stock_min, stock_max)
|
||||
|
||||
/datum/blackmarket_item/proc/spawn_item(loc) // Used for spawning the wanted item, override if you need to do something special with the item.
|
||||
return new item(loc)
|
||||
|
||||
/datum/blackmarket_item/proc/buy(obj/item/blackmarket_uplink/uplink, mob/buyer, shipping_method) // Buys the item and makes SSblackmarket handle it.
|
||||
// Sanity
|
||||
if(!istype(uplink) || !istype(buyer))
|
||||
return FALSE
|
||||
if(!item || stock <= 0) // This shouldn't be able to happen unless there was some manipulation or admin fuckery.
|
||||
return FALSE
|
||||
var/datum/blackmarket_purchase/purchase = new(src, uplink, shipping_method) // Alright, the item has been purchased.
|
||||
if(SSblackmarket.queue_item(purchase)) // SSblackmarket takes care of the shipping.
|
||||
stock--
|
||||
log_game("[key_name(buyer)] has succesfully purchased [name] using [shipping_method] for shipping.")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/blackmarket_purchase // This exists because it is easier to keep track of all the vars this way.
|
||||
var/datum/blackmarket_item/entry // The entry being purchased.
|
||||
var/item // Instance of the item being sent.
|
||||
var/obj/item/blackmarket_uplink/uplink // The uplink where this purchase was done from.
|
||||
var/method // Shipping method used to buy this item.
|
||||
|
||||
/datum/blackmarket_purchase/New(_entry, _uplink, _method)
|
||||
entry = _entry
|
||||
if(!ispath(entry.item))
|
||||
item = entry.item
|
||||
uplink = _uplink
|
||||
method = _method
|
||||
@@ -0,0 +1,55 @@
|
||||
/datum/blackmarket_item/clothing
|
||||
category = "Clothing"
|
||||
|
||||
/datum/blackmarket_item/clothing/ninja_mask
|
||||
name = "Space Ninja Mask"
|
||||
desc = "Apart from being acid, lava, fireproof and being hard to take off someone it does nothing special on it's own."
|
||||
item = /obj/item/clothing/mask/gas/space_ninja
|
||||
price_min = 200
|
||||
price_max = 500
|
||||
stock_max = 3
|
||||
availability_prob = 40
|
||||
|
||||
/datum/blackmarket_item/clothing/durathread_vest
|
||||
name = "Durathread Vest"
|
||||
desc = "Dont let them tell you this stuff is \"Like asbestos\" or \"Pulled from the market for safety concerns\". It could be the difference between a robusting and a retaliation."
|
||||
item = /obj/item/clothing/suit/armor/vest/durathread
|
||||
price_min = 200
|
||||
price_max = 400
|
||||
stock_max = 4
|
||||
availability_prob = 50
|
||||
|
||||
/datum/blackmarket_item/clothing/durathread_helmet
|
||||
name = "Durathread Helmet"
|
||||
desc = "Customers ask why it's called a helmet when it's just made from armoured fabric and I always say the same thing: No refunds."
|
||||
item = /obj/item/clothing/head/helmet/durathread
|
||||
price_min = 100
|
||||
price_max = 200
|
||||
stock_max = 4
|
||||
availability_prob = 50
|
||||
|
||||
/datum/blackmarket_item/clothing/full_spacesuit_set
|
||||
name = "Nanotrasen Branded Spacesuit Box"
|
||||
desc = "A few boxes of \"Old Style\" space suits fell off the back of a space truck."
|
||||
item = /obj/item/storage/box
|
||||
price_min = 1500
|
||||
price_max = 4000
|
||||
stock_max = 3
|
||||
availability_prob = 30
|
||||
|
||||
/datum/blackmarket_item/clothing/full_spacesuit_set/spawn_item(loc)
|
||||
var/obj/item/storage/box/B = ..()
|
||||
B.name = "Spacesuit Box"
|
||||
B.desc = "It has a NT logo on it."
|
||||
new /obj/item/clothing/suit/space(B)
|
||||
new /obj/item/clothing/head/helmet/space(B)
|
||||
return B
|
||||
|
||||
/datum/blackmarket_item/clothing/chameleon_hat
|
||||
name = "Chameleon Hat"
|
||||
desc = "Pick any hat you want with this Handy device. Not Quality Tested."
|
||||
item = /obj/item/clothing/head/chameleon/broken
|
||||
price_min = 100
|
||||
price_max = 200
|
||||
stock_max = 2
|
||||
availability_prob = 70
|
||||
@@ -0,0 +1,58 @@
|
||||
/datum/blackmarket_item/consumable
|
||||
category = "Consumables"
|
||||
|
||||
/datum/blackmarket_item/consumable/clown_tears
|
||||
name = "Bowl of Clown's Tears"
|
||||
desc = "Guaranteed fresh from Weepy Boggins Tragic Kitchen"
|
||||
item = /obj/item/reagent_containers/food/snacks/soup/clownstears
|
||||
stock = 1
|
||||
price_min = 520
|
||||
price_max = 600
|
||||
availability_prob = 10
|
||||
|
||||
/datum/blackmarket_item/consumable/donk_pocket_box
|
||||
name = "Box of Donk Pockets"
|
||||
desc = "A well packaged box containing the favourite snack of every spacefarer."
|
||||
item = /obj/item/storage/box/donkpockets
|
||||
stock_min = 2
|
||||
stock_max = 5
|
||||
price_min = 325
|
||||
price_max = 400
|
||||
availability_prob = 80
|
||||
|
||||
/datum/blackmarket_item/consumable/suspicious_pills
|
||||
name = "Bottle of Suspicious Pills"
|
||||
desc = "A random cocktail of luxury drugs that are sure to put a smile on your face!"
|
||||
item = /obj/item/storage/pill_bottle
|
||||
stock_min = 2
|
||||
stock_max = 3
|
||||
price_min = 400
|
||||
price_max = 700
|
||||
availability_prob = 50
|
||||
|
||||
/datum/blackmarket_item/consumable/suspicious_pills/spawn_item(loc)
|
||||
var/pillbottle = pick(list(/obj/item/storage/pill_bottle/zoom,
|
||||
/obj/item/storage/pill_bottle/happy,
|
||||
/obj/item/storage/pill_bottle/lsd,
|
||||
/obj/item/storage/pill_bottle/aranesp,
|
||||
/obj/item/storage/pill_bottle/stimulant))
|
||||
return new pillbottle(loc)
|
||||
|
||||
/datum/blackmarket_item/consumable/floor_pill
|
||||
name = "Strange Pill"
|
||||
desc = "The Russian Roulette of the Maintenance Tunnels."
|
||||
item = /obj/item/reagent_containers/pill/floorpill
|
||||
stock_min = 5
|
||||
stock_max = 35
|
||||
price_min = 10
|
||||
price_max = 60
|
||||
availability_prob = 50
|
||||
|
||||
/datum/blackmarket_item/consumable/pumpup
|
||||
name = "Shoddy Stimulants"
|
||||
desc = "Feel the energy inside each needle!"
|
||||
item = /obj/item/reagent_containers/hypospray/medipen/stimpack
|
||||
stock_max = 5
|
||||
price_min = 50
|
||||
price_max = 150
|
||||
availability_prob = 90
|
||||
@@ -0,0 +1,53 @@
|
||||
/datum/blackmarket_item/misc
|
||||
category = "Miscellaneous"
|
||||
|
||||
/datum/blackmarket_item/misc/cap_gun
|
||||
name = "Cap Gun"
|
||||
desc = "Prank your friends with this harmless gun! Harmlessness guranteed."
|
||||
item = /obj/item/toy/gun
|
||||
price_min = 50
|
||||
price_max = 200
|
||||
stock_max = 6
|
||||
availability_prob = 80
|
||||
|
||||
/datum/blackmarket_item/misc/shoulder_holster
|
||||
name = "Shoulder holster"
|
||||
desc = "Yeehaw, hardboiled friends! This holster is the first step in your dream of becoming a detective and being allowed to shoot real guns!"
|
||||
item = /obj/item/storage/belt/holster
|
||||
price_min = 400
|
||||
price_max = 800
|
||||
stock_max = 8
|
||||
availability_prob = 60
|
||||
|
||||
/datum/blackmarket_item/misc/holywater
|
||||
name = "Flask of holy water"
|
||||
desc = "Father Lootius' own brand of ready-made holy water."
|
||||
item = /obj/item/reagent_containers/food/drinks/bottle/holywater
|
||||
price_min = 400
|
||||
price_max = 600
|
||||
stock_max = 3
|
||||
availability_prob = 40
|
||||
|
||||
/datum/blackmarket_item/misc/holywater/spawn_item(loc)
|
||||
if (prob(6.66))
|
||||
return new /obj/item/reagent_containers/glass/beaker/unholywater(loc)
|
||||
return ..()
|
||||
|
||||
/datum/blackmarket_item/misc/strange_seed
|
||||
name = "Strange Seeds"
|
||||
desc = "An Exotic Variety of seed that can contain anything from glow to acid."
|
||||
item = /obj/item/seeds/random
|
||||
price_min = 320
|
||||
price_max = 360
|
||||
stock_min = 2
|
||||
stock_max = 5
|
||||
availability_prob = 50
|
||||
|
||||
/datum/blackmarket_item/misc/smugglers_satchel
|
||||
name = "Smuggler's Satchel"
|
||||
desc = "This easily hidden satchel can become a versatile tool to anybody with the desire to keep certain items out of sight and out of mind."
|
||||
item = /obj/item/storage/backpack/satchel/flat
|
||||
price_min = 750
|
||||
price_max = 1000
|
||||
stock_max = 2
|
||||
availability_prob = 30
|
||||
@@ -0,0 +1,74 @@
|
||||
/datum/blackmarket_item/tool
|
||||
category = "Tools"
|
||||
|
||||
/datum/blackmarket_item/tool/caravan_wrench
|
||||
name = "Experimental Wrench"
|
||||
desc = "The extra fast and handy wrench you always wanted!"
|
||||
item = /obj/item/wrench/caravan
|
||||
stock = 1
|
||||
price_min = 400
|
||||
price_max = 800
|
||||
availability_prob = 20
|
||||
|
||||
/datum/blackmarket_item/tool/caravan_wirecutters
|
||||
name = "Experimental Wirecutters"
|
||||
desc = "The extra fast and handy wirecutters you always wanted!"
|
||||
item = /obj/item/wirecutters/caravan
|
||||
stock = 1
|
||||
price_min = 400
|
||||
price_max = 800
|
||||
availability_prob = 20
|
||||
|
||||
/datum/blackmarket_item/tool/caravan_screwdriver
|
||||
name = "Experimental Screwdriver"
|
||||
desc = "The extra fast and handy screwdriver you always wanted!"
|
||||
item = /obj/item/screwdriver/caravan
|
||||
stock = 1
|
||||
price_min = 400
|
||||
price_max = 800
|
||||
availability_prob = 20
|
||||
|
||||
/datum/blackmarket_item/tool/caravan_crowbar
|
||||
name = "Experimental Crowbar"
|
||||
desc = "The extra fast and handy crowbar you always wanted!"
|
||||
item = /obj/item/crowbar/red/caravan
|
||||
stock = 1
|
||||
price_min = 400
|
||||
price_max = 800
|
||||
availability_prob = 20
|
||||
|
||||
/datum/blackmarket_item/tool/binoculars
|
||||
name = "Binoculars"
|
||||
desc = "Increase your sight by 150% with this handy tool!"
|
||||
item = /obj/item/binoculars
|
||||
stock = 1
|
||||
price_min = 400
|
||||
price_max = 960
|
||||
availability_prob = 30
|
||||
|
||||
/datum/blackmarket_item/tool/riot_shield
|
||||
name = "Riot Shield"
|
||||
desc = "Protect yourself from an unexpected riot at your local police department!"
|
||||
item = /obj/item/shield/riot
|
||||
price_min = 450
|
||||
price_max = 650
|
||||
stock_max = 2
|
||||
availability_prob = 50
|
||||
|
||||
/datum/blackmarket_item/tool/thermite_bottle
|
||||
name = "Thermite Bottle"
|
||||
desc = "30 units of Thermite to assist in creating a quick access point or get away!"
|
||||
item = /obj/item/reagent_containers/glass/bottle/thermite
|
||||
price_min = 500
|
||||
price_max = 1500
|
||||
stock_max = 3
|
||||
availability_prob = 30
|
||||
|
||||
/datum/blackmarket_item/tool/science_goggles
|
||||
name = "Science Goggles"
|
||||
desc = "These glasses scan the contents of containers and projects their contents to the user in an easy-to-read format."
|
||||
item = /obj/item/clothing/glasses/science
|
||||
price_min = 150
|
||||
price_max = 200
|
||||
stock_max = 3
|
||||
availability_prob = 50
|
||||
@@ -0,0 +1,41 @@
|
||||
/datum/blackmarket_item/weapon
|
||||
category = "Weapons"
|
||||
|
||||
/datum/blackmarket_item/weapon/bear_trap
|
||||
name = "Bear Trap"
|
||||
desc = "Get the janitor back at his own game with this affordable prank kit."
|
||||
item = /obj/item/restraints/legcuffs/beartrap
|
||||
price_min = 300
|
||||
price_max = 550
|
||||
stock_max = 3
|
||||
availability_prob = 40
|
||||
|
||||
/datum/blackmarket_item/weapon/shotgun_dart
|
||||
name = "Shotgun Dart"
|
||||
desc = "These handy darts can be filled up with any chemical and be shot with a shotgun! \
|
||||
Prank your friends by shooting them with laughter! \
|
||||
Not recommended for commercial use."
|
||||
item = /obj/item/ammo_casing/shotgun/dart
|
||||
price_min = 10
|
||||
price_max = 50
|
||||
stock_min = 5
|
||||
stock_max = 30
|
||||
availability_prob = 40
|
||||
|
||||
/datum/blackmarket_item/weapon/bone_spear
|
||||
name = "Bone Spear"
|
||||
desc = "Authentic tribal spear, made from real bones! A steal at any price, especially if you're a caveman."
|
||||
item = /obj/item/spear/bonespear
|
||||
price_min = 200
|
||||
price_max = 300
|
||||
stock_max = 3
|
||||
availability_prob = 60
|
||||
|
||||
/datum/blackmarket_item/weapon/emp_grenade
|
||||
name = "EMP Grenade"
|
||||
desc = "Use this grenade for SHOCKING results!"
|
||||
item = /obj/item/grenade/empgrenade
|
||||
price_min = 100
|
||||
price_max = 400
|
||||
stock_max = 2
|
||||
availability_prob = 50
|
||||
@@ -0,0 +1,40 @@
|
||||
/datum/blackmarket_market
|
||||
var/name = "huh?" // Name for the market.
|
||||
|
||||
var/list/shipping // Available shipping methods and prices, just leave the shipping method out that you don't want to have.
|
||||
|
||||
// Automatic vars, do not touch these.
|
||||
var/list/available_items = list() // Items available from this market, populated by SSblackmarket on initialization.
|
||||
var/list/categories = list() // Item categories available from this market, only items which are in these categories can be gotten from this market.
|
||||
|
||||
/datum/blackmarket_market/proc/add_item(datum/blackmarket_item/item) // Adds item to the available items and add it's category if it is not in categories yet.
|
||||
if(!prob(initial(item.availability_prob)))
|
||||
return FALSE
|
||||
if(ispath(item))
|
||||
item = new item()
|
||||
if(!(item.category in categories))
|
||||
categories += item.category
|
||||
available_items[item.category] = list()
|
||||
available_items[item.category] += item
|
||||
return TRUE
|
||||
|
||||
/datum/blackmarket_market/proc/purchase(item, category, method, obj/item/blackmarket_uplink/uplink, user) // Handles buying the item, this is mainly for future use and moving the code away from the uplink.
|
||||
if(!istype(uplink) || !(method in shipping))
|
||||
return FALSE
|
||||
for(var/datum/blackmarket_item/I in available_items[category])
|
||||
if(I.type != item)
|
||||
continue
|
||||
var/price = I.price + shipping[method]
|
||||
if(uplink.money < price) // I can't get the price of the item and shipping in a clean way to the UI, so I have to do this.
|
||||
to_chat("<span class='warning'>You don't have enough credits in [uplink] for [I] with [method] shipping.</span>")
|
||||
return FALSE
|
||||
if(I.buy(uplink, user, method))
|
||||
uplink.money -= price
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/blackmarket_market/blackmarket
|
||||
name = "Black Market"
|
||||
shipping = list(SHIPPING_METHOD_LTSRBT =50,
|
||||
SHIPPING_METHOD_LAUNCH =10,
|
||||
SHIPPING_METHOD_TELEPORT=75)
|
||||
@@ -0,0 +1,92 @@
|
||||
/obj/item/circuitboard/machine/ltsrbt
|
||||
name = "LTSRBT (Machine Board)"
|
||||
icon_state = "bluespacearray"
|
||||
build_path = /obj/machinery/ltsrbt
|
||||
req_components = list(
|
||||
/obj/item/stack/ore/bluespace_crystal = 2,
|
||||
/obj/item/stock_parts/subspace/ansible = 1,
|
||||
/obj/item/stock_parts/micro_laser = 1,
|
||||
/obj/item/stock_parts/scanning_module = 2)
|
||||
def_components = list(/obj/item/stack/ore/bluespace_crystal = /obj/item/stack/ore/bluespace_crystal/artificial)
|
||||
|
||||
/obj/machinery/ltsrbt
|
||||
name = "Long-To-Short-Range-Bluespace-Transciever"
|
||||
desc = "The LTSRBT is a compact teleportation machine for recieving and sending items outside the station and inside the station.\nUsing teleportation frequencies stolen from NT it is near undetectable.\nEssential for any illegal market operations on NT stations.\n"
|
||||
icon_state = "exonet_node"
|
||||
circuit = /obj/item/circuitboard/machine/ltsrbt
|
||||
density = TRUE
|
||||
idle_power_usage = 200
|
||||
var/power_efficiency = 1 // Divider for power_usage_per_teleport.
|
||||
var/power_usage_per_teleport = 10000 // Power used per teleported which gets divided by power_efficiency.
|
||||
var/recharge_time = 0 // The time it takes for the machine to recharge before being able to send or recieve items.
|
||||
var/recharge_cooldown = 0 // Current recharge progress.
|
||||
var/base_recharge_time = 100 // Base recharge time which is used to get recharge_time.
|
||||
var/recieving // Current /datum/blackmarket_purchase being recieved.
|
||||
var/transmitting // Current /datum/blackmarket_purchase being sent to the target uplink.
|
||||
var/list/datum/blackmarket_purchase/queue = list() // Queue for purchases that the machine should recieve and send.
|
||||
|
||||
/obj/machinery/ltsrbt/Initialize()
|
||||
. = ..()
|
||||
SSblackmarket.telepads += src
|
||||
|
||||
/obj/machinery/ltsrbt/Destroy()
|
||||
SSblackmarket.telepads -= src
|
||||
if(SSblackmarket.telepads.len) // Bye bye orders.
|
||||
for(var/datum/blackmarket_purchase/P in queue)
|
||||
SSblackmarket.queue_item(P)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/ltsrbt/RefreshParts()
|
||||
recharge_time = base_recharge_time
|
||||
for(var/obj/item/stock_parts/scanning_module/scan in component_parts) // On tier 4 recharge_time should be 20 and by default it is 80 as scanning modules should be tier 1.
|
||||
recharge_time -= scan.rating * 10
|
||||
recharge_cooldown = recharge_time
|
||||
power_efficiency = 0
|
||||
for(var/obj/item/stock_parts/micro_laser/laser in component_parts)
|
||||
power_efficiency += laser.rating
|
||||
if(!power_efficiency) // Shouldn't happen but you never know.
|
||||
power_efficiency = 1
|
||||
|
||||
/obj/machinery/ltsrbt/proc/add_to_queue(datum/blackmarket_purchase/purchase) // Adds /datum/blackmarket_purchase to queue unless the machine is free, then it sets the purchase to be instantly recieved
|
||||
if(!recharge_cooldown && !recieving && !transmitting)
|
||||
recieving = purchase
|
||||
return
|
||||
queue += purchase
|
||||
|
||||
/obj/machinery/ltsrbt/process()
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
if(recharge_cooldown)
|
||||
recharge_cooldown--
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
if(recieving)
|
||||
var/datum/blackmarket_purchase/P = recieving
|
||||
if(!P.item || ispath(P.item))
|
||||
P.item = P.entry.spawn_item(T)
|
||||
else
|
||||
var/atom/movable/M = P.item
|
||||
M.forceMove(T)
|
||||
use_power(power_usage_per_teleport / power_efficiency)
|
||||
var/datum/effect_system/spark_spread/sparks = new
|
||||
sparks.set_up(5, 1, get_turf(src))
|
||||
sparks.attach(P.item)
|
||||
sparks.start()
|
||||
recieving = null
|
||||
transmitting = P
|
||||
recharge_cooldown = recharge_time
|
||||
return
|
||||
else if(transmitting)
|
||||
var/datum/blackmarket_purchase/P = transmitting
|
||||
if(!P.item)
|
||||
QDEL_NULL(transmitting)
|
||||
if(!(P.item in T.contents))
|
||||
QDEL_NULL(transmitting)
|
||||
return
|
||||
do_teleport(P.item, get_turf(P.uplink))
|
||||
use_power(power_usage_per_teleport / power_efficiency)
|
||||
QDEL_NULL(transmitting)
|
||||
recharge_cooldown = recharge_time
|
||||
return
|
||||
if(queue.len)
|
||||
recieving = pick_n_take(queue)
|
||||
@@ -0,0 +1,141 @@
|
||||
/obj/item/blackmarket_uplink
|
||||
name = "Black Market Uplink"
|
||||
icon = 'icons/obj/blackmarket.dmi'
|
||||
icon_state = "uplink"
|
||||
// UI variables.
|
||||
var/ui_x = 720
|
||||
var/ui_y = 480
|
||||
var/viewing_category
|
||||
var/viewing_market
|
||||
var/selected_item
|
||||
var/buying
|
||||
var/money = 0 // How much money is inserted into the uplink.
|
||||
var/list/accessible_markets = list(/datum/blackmarket_market/blackmarket) // List of typepaths for "/datum/blackmarket_market"s that this uplink can access.
|
||||
|
||||
/obj/item/blackmarket_uplink/Initialize()
|
||||
. = ..()
|
||||
if(accessible_markets.len)
|
||||
viewing_market = accessible_markets[1]
|
||||
var/list/categories = SSblackmarket.markets[viewing_market].categories
|
||||
if(categories && categories.len)
|
||||
viewing_category = categories[1]
|
||||
|
||||
/obj/item/blackmarket_uplink/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/holochip) || istype(I, /obj/item/stack/spacecash) || istype(I, /obj/item/coin))
|
||||
var/worth = I.get_item_credit_value()
|
||||
if(!worth)
|
||||
to_chat(user, "<span class='warning'>[I] doesn't seem to be worth anything!</span>")
|
||||
money += worth
|
||||
to_chat(user, "<span class='notice'>You slot [I] into [src] and it reports a total of [money] credits inserted.</span>")
|
||||
qdel(I)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/item/blackmarket_uplink/AltClick(mob/user)
|
||||
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
var/amount_to_remove = FLOOR(input(user, "How much do you want to withdraw? Current Amount: [money]", "Withdraw Funds", 5) as num|null, 1)
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
if(!amount_to_remove || amount_to_remove < 0)
|
||||
return
|
||||
if(amount_to_remove > money)
|
||||
to_chat(user, "<span class='warning'>There is only [money] credits in [src]</span>")
|
||||
return
|
||||
var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove)
|
||||
money -= amount_to_remove
|
||||
holochip.name = "washed " + holochip.name
|
||||
user.put_in_hands(holochip)
|
||||
to_chat(user, "<span class='notice'>You withdraw [amount_to_remove] credits into a holochip.</span>")
|
||||
|
||||
/obj/item/blackmarket_uplink/ui_interact(mob/user, ui_key = "BlackMarketUplink", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/blackmarket_uplink/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/datum/blackmarket_market/market = viewing_market ? SSblackmarket.markets[viewing_market] : null
|
||||
data["categories"] = market ? market.categories : null
|
||||
data["delivery_methods"] = list()
|
||||
if(market)
|
||||
for(var/delivery in market.shipping)
|
||||
data["delivery_methods"] += list(list("name" = delivery, "price" = market.shipping[delivery]))
|
||||
data["money"] = money
|
||||
data["buying"] = buying
|
||||
data["items"] = list()
|
||||
data["viewing_category"] = viewing_category
|
||||
data["viewing_market"] = viewing_market
|
||||
if(viewing_category && market)
|
||||
if(market.available_items[viewing_category])
|
||||
for(var/datum/blackmarket_item/I in market.available_items[viewing_category])
|
||||
data["items"] += list(list(
|
||||
"id" = I.type,
|
||||
"name" = I.name,
|
||||
"cost" = I.price,
|
||||
"amount" = I.stock,
|
||||
"desc" = I.desc || I.name
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/item/blackmarket_uplink/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["delivery_method_description"] = SSblackmarket.shipping_method_descriptions
|
||||
data["ltsrbt_built"] = SSblackmarket.telepads.len
|
||||
data["markets"] = list()
|
||||
for(var/M in accessible_markets)
|
||||
var/datum/blackmarket_market/BM = SSblackmarket.markets[M]
|
||||
data["markets"] += list(list(
|
||||
"id" = M,
|
||||
"name" = BM.name
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/item/blackmarket_uplink/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("set_category")
|
||||
if(isnull(params["category"]))
|
||||
return
|
||||
if(isnull(viewing_market))
|
||||
return
|
||||
if(!(params["category"] in SSblackmarket.markets[viewing_market].categories))
|
||||
return
|
||||
viewing_category = params["category"]
|
||||
. = TRUE
|
||||
if("set_market")
|
||||
if(isnull(params["market"]))
|
||||
return
|
||||
var/market = text2path(params["market"])
|
||||
if(!(market in accessible_markets))
|
||||
return
|
||||
viewing_market = market
|
||||
var/list/categories = SSblackmarket.markets[viewing_market].categories
|
||||
if(categories && categories.len)
|
||||
viewing_category = categories[1]
|
||||
else
|
||||
viewing_category = null
|
||||
. = TRUE
|
||||
if("select")
|
||||
if(isnull(params["item"]))
|
||||
return
|
||||
var/item = text2path(params["item"])
|
||||
selected_item = item
|
||||
buying = TRUE
|
||||
. = TRUE
|
||||
if("cancel")
|
||||
selected_item = null
|
||||
buying = FALSE
|
||||
. = TRUE
|
||||
if("buy")
|
||||
if(isnull(params["method"]))
|
||||
return
|
||||
if(isnull(selected_item))
|
||||
buying = FALSE
|
||||
return
|
||||
var/datum/blackmarket_market/market = SSblackmarket.markets[viewing_market]
|
||||
market.purchase(selected_item, viewing_category, params["method"], src, usr)
|
||||
buying = FALSE
|
||||
selected_item = null
|
||||
@@ -16,7 +16,7 @@
|
||||
errors |= MANIFEST_ERROR_ITEM
|
||||
|
||||
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_approved()
|
||||
return stamped && stamped.len && !is_denied()
|
||||
return stamped?.len && !is_denied()
|
||||
|
||||
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_denied()
|
||||
return stamped && ("stamp-deny" in stamped)
|
||||
@@ -49,6 +49,7 @@
|
||||
P.info += "<h2>[station_name()] Supply Requisition</h2>"
|
||||
P.info += "<hr/>"
|
||||
P.info += "Order #[id]<br/>"
|
||||
P.info += "Time of Order: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]<br/>"
|
||||
P.info += "Item: [pack.name]<br/>"
|
||||
P.info += "Access Restrictions: [get_access_desc(pack.access)]<br/>"
|
||||
P.info += "Requested by: [orderer]<br/>"
|
||||
@@ -68,10 +69,10 @@
|
||||
P.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]"
|
||||
P.info += "<h2>[command_name()] Shipping Manifest</h2>"
|
||||
P.info += "<hr/>"
|
||||
if(id && !(id == "Cargo"))
|
||||
if(owner && !(owner == "Cargo"))
|
||||
P.info += "Direct purchase from [owner]<br/>"
|
||||
P.name += " - Purchased by [owner]"
|
||||
P.info += "Order #[id]<br/>"
|
||||
P.info += "Order[packname?"":"s"]: [id]<br/>"
|
||||
P.info += "Destination: [station_name]<br/>"
|
||||
if(packname)
|
||||
P.info += "Item: [packname]<br/>"
|
||||
@@ -82,8 +83,11 @@
|
||||
var/obj/structure/closet/C = container
|
||||
ignore_this += C.lockerelectronics
|
||||
for(var/atom/movable/AM in container.contents - ignore_this)
|
||||
if((P.errors & MANIFEST_ERROR_CONTENTS) && prob(50))
|
||||
continue
|
||||
if((P.errors & MANIFEST_ERROR_CONTENTS))
|
||||
if(prob(50))
|
||||
P.info += "<li>[AM.name]</li>"
|
||||
else
|
||||
continue
|
||||
P.info += "<li>[AM.name]</li>"
|
||||
P.info += "</ul>"
|
||||
P.info += "<h4>Stamp below to confirm receipt of goods:</h4>"
|
||||
@@ -94,7 +98,7 @@
|
||||
/obj/structure/closet/crate/large,
|
||||
/obj/structure/closet/secure_closet/goodies
|
||||
))
|
||||
if(blacklisted_error[container.type])
|
||||
if(is_type_in_list(container, blacklisted_error))
|
||||
P.errors &= ~MANIFEST_ERROR_ITEM
|
||||
else
|
||||
var/lost = max(round(container.contents.len / 10), 1)
|
||||
@@ -108,15 +112,23 @@
|
||||
var/obj/structure/closet/crate/C = container
|
||||
C.manifest = P
|
||||
C.update_icon()
|
||||
else
|
||||
// manifest goes in if it's not a crate
|
||||
container.contents += P
|
||||
|
||||
return P
|
||||
|
||||
/datum/supply_order/proc/generate(atom/A)
|
||||
var/account_holder
|
||||
if(paying_account)
|
||||
account_holder = paying_account.account_holder
|
||||
else
|
||||
account_holder = "Cargo"
|
||||
var/obj/structure/closet/crate/C = pack.generate(A, paying_account)
|
||||
generateManifest(C, paying_account, pack)
|
||||
generateManifest(C, account_holder, pack)
|
||||
return C
|
||||
|
||||
/datum/supply_order/proc/generateCombo(var/miscbox, var/misc_own, var/misc_contents)
|
||||
/datum/supply_order/proc/generateCombo(miscbox, misc_own, misc_contents)
|
||||
for (var/I in misc_contents)
|
||||
new I(miscbox)
|
||||
generateManifest(miscbox, misc_own, "")
|
||||
|
||||
@@ -434,6 +434,17 @@
|
||||
/obj/item/stack/tile/noslip/thirty)
|
||||
crate_name = "high-traction floor tiles crate"
|
||||
|
||||
/datum/supply_pack/misc/blackmarket_telepad
|
||||
name = "Black Market LTSRBT"
|
||||
desc = "Need a faster and better way of transporting your illegal goods from and to the station? Fear not, the Long-To-Short-Range-Bluespace-Transceiver (LTSRBT for short) is here to help. Contains a LTSRBT circuit, two bluespace crystals, and one ansible."
|
||||
cost = 8000
|
||||
contraband = TRUE
|
||||
contains = list(/obj/item/circuitboard/machine/ltsrbt,
|
||||
/obj/item/stack/ore/bluespace_crystal/artificial,
|
||||
/obj/item/stack/ore/bluespace_crystal/artificial,
|
||||
/obj/item/stock_parts/subspace/ansible)
|
||||
crate_name = "crate"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// Lewd Supplies ///////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
/datum/supply_pack/vending/hydro
|
||||
name = "Hydroponics Supply Crate"
|
||||
desc = "Arnt you glad you dont have to do it the natural way? Contains a megaseed and nutrimax vending machine refill."
|
||||
desc = "Aren't you glad you dont have to do it the natural way? Contains a megaseed and nutrimax vending machine refill."
|
||||
cost = 5000
|
||||
contains = list(/obj/item/vending_refill/hydroseeds,
|
||||
/obj/item/vending_refill/hydronutrients)
|
||||
@@ -82,6 +82,14 @@
|
||||
contains = list(/obj/item/vending_refill/kink)
|
||||
crate_name = "Kinkmate construction kit"
|
||||
|
||||
/datum/supply_pack/vending/barkbox
|
||||
name = "Bark Box Supply Crate"
|
||||
desc = "Running of out things to keep your pets happy?"
|
||||
cost = 2000
|
||||
contraband = TRUE
|
||||
contains = list(/obj/item/vending_refill/barkbox)
|
||||
crate_name = "bark box supply crate"
|
||||
|
||||
/datum/supply_pack/vending/medical
|
||||
name = "Medical Vending Crate"
|
||||
desc = "Contains refills for medical vending machines."
|
||||
|
||||
@@ -130,26 +130,28 @@
|
||||
|
||||
/obj/structure/closet/supplypod/update_overlays()
|
||||
. = ..()
|
||||
if (style == STYLE_INVISIBLE)
|
||||
if(style == STYLE_INVISIBLE)
|
||||
return
|
||||
if (rubble)
|
||||
|
||||
if(rubble)
|
||||
. += rubble.getForeground(src)
|
||||
if (style == STYLE_SEETHROUGH)
|
||||
for (var/atom/A in contents)
|
||||
|
||||
if(style == STYLE_SEETHROUGH)
|
||||
for(var/atom/A in contents)
|
||||
var/mutable_appearance/itemIcon = new(A)
|
||||
itemIcon.transform = matrix().Translate(-1 * SUPPLYPOD_X_OFFSET, 0)
|
||||
. += itemIcon
|
||||
for (var/t in turfs_in_cargo)//T is just a turf's type
|
||||
for(var/t in turfs_in_cargo)//T is just a turf's type
|
||||
var/turf/turf_type = t
|
||||
var/mutable_appearance/itemIcon = mutable_appearance(initial(turf_type.icon), initial(turf_type.icon_state))
|
||||
itemIcon.transform = matrix().Translate(-1 * SUPPLYPOD_X_OFFSET, 0)
|
||||
. += itemIcon
|
||||
return
|
||||
|
||||
if (opened) //We're opened means all we have to worry about is masking a decal if we have one
|
||||
if (!decal) //We don't have a decal to mask
|
||||
if(opened) //We're opened means all we have to worry about is masking a decal if we have one
|
||||
if(!decal) //We don't have a decal to mask
|
||||
return
|
||||
if (!door) //We have a decal but no door, so let's just add the decal
|
||||
if(!door) //We have a decal but no door, so let's just add the decal
|
||||
. += decal
|
||||
return
|
||||
var/icon/masked_decal = new(icon, decal) //The decal we want to apply
|
||||
@@ -159,23 +161,25 @@
|
||||
door_masker.Blend("#000000", ICON_SUBTRACT)
|
||||
masked_decal.Blend(door_masker, ICON_ADD)
|
||||
. += masked_decal
|
||||
else //If we're closed
|
||||
if (!door) //We have no door, lets see if we have a decal. If not, theres nothing we need to do
|
||||
if (decal)
|
||||
. += decal
|
||||
return
|
||||
else if (GLOB.podstyles[style][POD_SHAPE] != POD_SHAPE_NORML) //If we're not a normal pod shape (aka, if we don't have fins), just add the door without masking
|
||||
. += door
|
||||
else
|
||||
var/icon/masked_door = new(icon, door) //The door we want to apply
|
||||
var/icon/fin_masker = new(icon, "mask_[fin_mask]") //The fin shape we want to 'cut out' of the door
|
||||
fin_masker.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 1,1,1,0, 0,0,0,1)
|
||||
fin_masker.SwapColor("#ffffffff", null)
|
||||
fin_masker.Blend("#000000", ICON_SUBTRACT)
|
||||
masked_door.Blend(fin_masker, ICON_ADD)
|
||||
. += masked_door
|
||||
if (decal)
|
||||
return
|
||||
|
||||
//If we're closed
|
||||
if(!door) //We have no door, lets see if we have a decal. If not, theres nothing we need to do
|
||||
if(decal)
|
||||
. += decal
|
||||
return
|
||||
else if (GLOB.podstyles[style][POD_SHAPE] != POD_SHAPE_NORML) //If we're not a normal pod shape (aka, if we don't have fins), just add the door without masking
|
||||
. += door
|
||||
else
|
||||
var/icon/masked_door = new(icon, door) //The door we want to apply
|
||||
var/icon/fin_masker = new(icon, "mask_[fin_mask]") //The fin shape we want to 'cut out' of the door
|
||||
fin_masker.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 1,1,1,0, 0,0,0,1)
|
||||
fin_masker.SwapColor("#ffffffff", null)
|
||||
fin_masker.Blend("#000000", ICON_SUBTRACT)
|
||||
masked_door.Blend(fin_masker, ICON_ADD)
|
||||
. += masked_door
|
||||
if(decal)
|
||||
. += decal
|
||||
|
||||
/obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user)
|
||||
if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
|
||||
@@ -192,7 +196,7 @@
|
||||
/obj/structure/closet/supplypod/toggle(mob/living/user)
|
||||
return
|
||||
|
||||
/obj/structure/closet/supplypod/open(mob/living/user, force = TRUE)
|
||||
/obj/structure/closet/supplypod/open(mob/living/user, force = FALSE)
|
||||
return
|
||||
|
||||
/obj/structure/closet/supplypod/proc/handleReturnAfterDeparting(atom/movable/holder = src)
|
||||
@@ -550,9 +554,6 @@
|
||||
var/obj/effect/pod_landingzone_effect/helper
|
||||
var/list/smoke_effects = new /list(13)
|
||||
|
||||
/obj/effect/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/pod_landingzone/Initialize(mapload, podParam, single_order = null, clientman)
|
||||
. = ..()
|
||||
if (ispath(podParam)) //We can pass either a path for a pod (as expressconsoles do), or a reference to an instantiated pod (as the centcom_podlauncher does)
|
||||
@@ -647,4 +648,12 @@
|
||||
desc = "This disk provides a firmware update to the Express Supply Console, granting the use of Nanotrasen's Bluespace Drop Pods to the supply department."
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "cargodisk"
|
||||
// inhand_icon_state = "card-id"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
// let's not.
|
||||
/obj/structure/closet/supplypod/handle_lock_addition()
|
||||
return
|
||||
|
||||
/obj/structure/closet/supplypod/handle_lock_removal()
|
||||
return
|
||||
|
||||
@@ -190,6 +190,12 @@
|
||||
tagname = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot", MAX_NAME_LEN)
|
||||
name = "[initial(name)] - [tagname]"
|
||||
|
||||
/obj/item/clothing/neck/petcollar/ribbon
|
||||
name = "ribbon pet collar"
|
||||
icon_state = "ribboncollar"
|
||||
poly_states = 2
|
||||
poly_colors = list("#454545", "#292929")
|
||||
|
||||
/obj/item/clothing/neck/petcollar/leather
|
||||
name = "leather pet collar"
|
||||
icon_state = "leathercollar"
|
||||
@@ -225,6 +231,12 @@
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/ribbon
|
||||
name = "ribbon pet collar"
|
||||
icon_state = "ribboncollar"
|
||||
poly_states = 2
|
||||
poly_colors = list("#454545", "#292929")
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/leather
|
||||
name = "leather pet collar"
|
||||
icon_state = "leathercollar"
|
||||
|
||||
@@ -567,6 +567,26 @@
|
||||
attack_verb = list("warned", "cautioned", "smashed")
|
||||
armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
|
||||
/obj/item/clothing/suit/petharness
|
||||
name = "pet harness"
|
||||
desc = "For your pet! Or not! Has a little clip on the back."
|
||||
icon_state = "petharness"
|
||||
item_state = "petharness"
|
||||
body_parts_covered = NONE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
allowed = /obj/item/toy/fluff
|
||||
|
||||
/obj/item/clothing/suit/petharness/mesh
|
||||
name = "mesh pet harness"
|
||||
desc = "For your pet! Or not! Has some mesh to cover up your more sensitive bits and a little clip on the back."
|
||||
icon_state = "petharness_mesh"
|
||||
item_state = "petharness_mesh"
|
||||
body_parts_covered = CHEST
|
||||
|
||||
/obj/item/clothing/suit/petharness/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/polychromic, list("#0056D9", "#959595"), 2, _flags = POLYCHROMIC_ACTION)
|
||||
|
||||
// WINTER COATS
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat
|
||||
|
||||
@@ -13,11 +13,27 @@
|
||||
var/power = 2000
|
||||
|
||||
/datum/round_event/supermatter_surge/setup()
|
||||
power = rand(200,4000)
|
||||
if(prob(70))
|
||||
power = rand(200,100000)
|
||||
else
|
||||
power = rand(200,200000)
|
||||
|
||||
/datum/round_event/supermatter_surge/announce()
|
||||
if(power > 800 || prob(round(power/8)))
|
||||
priority_announce("Class [round(power/500) + 1] supermatter surge detected. Intervention may be required.", "Anomaly Alert")
|
||||
var/severity = ""
|
||||
switch(power)
|
||||
if(-INFINITY to 100000)
|
||||
var/low_threat_perc = 100-round(100*((power-200)/(100000-200)))
|
||||
if(prob(low_threat_perc))
|
||||
if(prob(low_threat_perc))
|
||||
severity = "low; the supermatter should return to normal operation shortly."
|
||||
else
|
||||
severity = "medium; the supermatter should return to normal operation, but check NT CIMS to ensure this."
|
||||
else
|
||||
severity = "high; if the supermatter's cooling is not fortified, coolant may need to be added."
|
||||
if(100000 to INFINITY)
|
||||
severity = "extreme; emergency action is likely to be required even if coolant loop is fine."
|
||||
if(power > 20000 || prob(round(power/200)))
|
||||
priority_announce("Supermatter surge detected. Estimated severity is [severity]", "Anomaly Alert")
|
||||
|
||||
/datum/round_event/supermatter_surge/start()
|
||||
GLOB.main_supermatter_engine.matter_power += power
|
||||
|
||||
@@ -466,6 +466,17 @@
|
||||
foodtype = GRAIN | SUGAR
|
||||
dunkable = TRUE
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/dogtreat
|
||||
name = "dog treat"
|
||||
desc = "It's a scooby-snack. Right?"
|
||||
icon_state = "dogtreat"
|
||||
bitesize = 1
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 1)
|
||||
filling_color = "#635444"
|
||||
tastes = list("meat" = 1, "dough" = 1)
|
||||
foodtype = GRAIN | MEAT
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/donkpocket
|
||||
name = "\improper Donk-pocket"
|
||||
desc = "The food of choice for the seasoned traitor."
|
||||
|
||||
@@ -214,6 +214,17 @@
|
||||
result = /obj/item/reagent_containers/food/snacks/cracker
|
||||
subcategory = CAT_PASTRY
|
||||
|
||||
/datum/crafting_recipe/food/dogtreat
|
||||
time = 15
|
||||
name = "Dog Treat"
|
||||
reqs = list(
|
||||
/datum/reagent/consumable/sodiumchloride = 1,
|
||||
/obj/item/reagent_containers/food/snacks/meat/cutlet = 1,
|
||||
/obj/item/reagent_containers/food/snacks/pastrybase = 1,
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/dogtreat
|
||||
subcategory = CAT_PASTRY
|
||||
|
||||
/datum/crafting_recipe/food/fortunecookie
|
||||
time = 15
|
||||
name = "Fortune cookie"
|
||||
|
||||
@@ -1285,8 +1285,8 @@
|
||||
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
|
||||
chaser_timer = world.time + chaser_cooldown
|
||||
var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(user), user, target, chaser_speed, friendly_fire_check)
|
||||
C.damage = 30
|
||||
C.monster_damage_boost = FALSE
|
||||
C.damage = 15
|
||||
C.monster_damage_boost = TRUE
|
||||
log_combat(user, target, "fired a chaser at", src)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast
|
||||
@@ -1402,10 +1402,10 @@
|
||||
new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, user)
|
||||
for(var/t in RANGE_TURFS(1, T))
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new /obj/effect/temp_visual/hierophant/blast(t, user, TRUE) //blasts produced will not hurt allies
|
||||
B.damage = 30
|
||||
B.damage = 15
|
||||
for(var/t in RANGE_TURFS(1, source))
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new /obj/effect/temp_visual/hierophant/blast(t, user, TRUE) //but absolutely will hurt enemies
|
||||
B.damage = 30
|
||||
B.damage = 15
|
||||
for(var/mob/living/L in range(1, source))
|
||||
INVOKE_ASYNC(src, .proc/teleport_mob, source, L, T, user) //regardless, take all mobs near us along
|
||||
sleep(6) //at this point the blasts detonate
|
||||
@@ -1466,8 +1466,8 @@
|
||||
if(!J)
|
||||
return
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new(J, user, friendly_fire_check)
|
||||
B.damage = 30
|
||||
B.monster_damage_boost = FALSE
|
||||
B.damage = 15
|
||||
B.monster_damage_boost = TRUE
|
||||
previousturf = J
|
||||
J = get_step(previousturf, dir)
|
||||
|
||||
@@ -1479,7 +1479,7 @@
|
||||
sleep(2)
|
||||
for(var/t in RANGE_TURFS(1, T))
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new(t, user, friendly_fire_check)
|
||||
B.damage = 15 //keeps monster damage boost due to lower damage
|
||||
B.damage = 15 //keeps monster damage boost due to lower damage (now added to all damage due to reduction to 15, 30dmg 50AP isn't cool)
|
||||
|
||||
|
||||
//Just some minor stuff
|
||||
|
||||
@@ -115,13 +115,13 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(HAS_TRAIT(src, TRAIT_NOGUNS))
|
||||
to_chat(src, "<span class='warning'>You can't bring yourself to use a ranged weapon!</span>")
|
||||
return FALSE
|
||||
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
|
||||
if(HAS_TRAIT(src, TRAIT_CHUNKYFINGERS))
|
||||
to_chat(src, "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>")
|
||||
return FALSE
|
||||
if(HAS_TRAIT(src, TRAIT_NOGUNS))
|
||||
to_chat(src, "<span class='warning'>Your fingers don't fit in the trigger guard!</span>")
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/get_bank_account()
|
||||
RETURN_TYPE(/datum/bank_account)
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
to_chat(owner, "There's something stuck to your hand, stopping you from transforming!")
|
||||
return
|
||||
if(IsAvailable())
|
||||
transforming = TRUE
|
||||
UpdateButtonIcon()
|
||||
var/mutcolor = owner.get_ability_property(INNATE_ABILITY_SLIME_BLOBFORM, PROPERTY_BLOBFORM_COLOR) || ("#" + H.dna.features["mcolor"])
|
||||
if(!is_puddle)
|
||||
if(CHECK_MOBILITY(H, MOBILITY_USE)) //if we can use items, we can turn into a puddle
|
||||
transforming = TRUE
|
||||
is_puddle = TRUE //so we know which transformation to use when its used
|
||||
ADD_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
|
||||
owner.cut_overlays() //we dont show our normal sprite, we show a puddle sprite
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
id = SPECIES_VAMPIRE
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD,HAS_FLESH,HAS_BONE)
|
||||
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
|
||||
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH,TRAIT_NOMARROW)
|
||||
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
|
||||
exotic_bloodtype = "U"
|
||||
@@ -53,10 +53,11 @@
|
||||
C.adjustOxyLoss(-4)
|
||||
C.adjustCloneLoss(-4)
|
||||
return
|
||||
C.blood_volume -= 0.75 //Will take roughly 19.5 minutes to die from standard blood volume, roughly 83 minutes to die from max blood volume.
|
||||
if(C.blood_volume <= (BLOOD_VOLUME_SURVIVE*C.blood_ratio))
|
||||
to_chat(C, "<span class='danger'>You ran out of blood!</span>")
|
||||
C.dust()
|
||||
if(C.blood_volume > 0.5)
|
||||
C.blood_volume -= 0.5 //Will take roughly 19.5 minutes to die from standard blood volume, roughly 83 minutes to die from max blood volume.
|
||||
else
|
||||
C.dust(FALSE, TRUE)
|
||||
|
||||
var/area/A = get_area(C)
|
||||
if(istype(A, /area/chapel) && C.mind?.assigned_role != "Chaplain")
|
||||
to_chat(C, "<span class='danger'>You don't belong here!</span>")
|
||||
@@ -125,7 +126,7 @@
|
||||
. = ..()
|
||||
var/obj/item/organ/heart/vampire/darkheart = getorgan(/obj/item/organ/heart/vampire)
|
||||
if(darkheart)
|
||||
. += "<span class='notice'>Current blood level: [blood_volume]/[BLOOD_VOLUME_MAXIMUM].</span>"
|
||||
. += "Current blood level: [blood_volume]/[BLOOD_VOLUME_MAXIMUM]."
|
||||
|
||||
|
||||
/obj/item/organ/heart/vampire
|
||||
|
||||
@@ -90,11 +90,11 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
|
||||
|
||||
var/ic_blocked = FALSE
|
||||
/*
|
||||
if(client && !forced && config.ic_filter_regex && findtext(message, config.ic_filter_regex))
|
||||
|
||||
if(client && !forced && CHAT_FILTER_CHECK(message))
|
||||
//The filter doesn't act on the sanitized message, but the raw message.
|
||||
ic_blocked = TRUE
|
||||
*/
|
||||
|
||||
if(sanitize)
|
||||
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
if(!message || message == "")
|
||||
@@ -103,6 +103,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
if(ic_blocked)
|
||||
//The filter warning message shows the sanitized message though.
|
||||
to_chat(src, "<span class='warning'>That message contained a word prohibited in IC chat! Consider reviewing the server rules.\n<span replaceRegex='show_filtered_ic_chat'>\"[message]\"</span></span>")
|
||||
SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match))
|
||||
return
|
||||
|
||||
var/datum/saymode/saymode = SSradio.saymodes[talk_key]
|
||||
@@ -333,7 +334,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
var/obj/item/bodypart/rightarm = get_bodypart(BODY_ZONE_R_ARM)
|
||||
if(HAS_TRAIT(src, TRAIT_MUTE) && get_selected_language() != /datum/language/signlanguage)
|
||||
return 0
|
||||
|
||||
|
||||
if (get_selected_language() == /datum/language/signlanguage)
|
||||
var/left_disabled = FALSE
|
||||
var/right_disabled = FALSE
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
/obj/item/modular_computer/laptop/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Drag it in your hand to pick it up.</span>"
|
||||
if(screen_on)
|
||||
. += "<span class='notice'>Alt-click to close it.</span>"
|
||||
|
||||
@@ -76,6 +77,9 @@
|
||||
M.put_in_hand(src, H.held_index)
|
||||
|
||||
/obj/item/modular_computer/laptop/on_attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(screen_on && isturf(loc))
|
||||
return attack_self(user)
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/datum/computer_file/program/budgetorders
|
||||
filename = "orderapp"
|
||||
filedesc = "Nanotrasen Internal Requisition Network (NIRN)"
|
||||
filedesc = "NT IRN"
|
||||
// category = PROGRAM_CATEGORY_SUPL
|
||||
program_icon_state = "request"
|
||||
extended_desc = "A request network that utilizes the Nanotrasen Ordering network to purchase supplies using a department budget account."
|
||||
extended_desc = "Nanotrasen Internal Requisition Network interface for supply purchasing using a department budget account."
|
||||
requires_ntnet = TRUE
|
||||
transfer_access = ACCESS_HEADS
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET
|
||||
@@ -79,7 +80,6 @@
|
||||
data["supplies"] = list()
|
||||
for(var/pack in SSshuttle.supply_packs)
|
||||
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
|
||||
// todo: replace to P.access_view
|
||||
if(!is_visible_pack(usr, P.access , null, P.contraband) || P.hidden)
|
||||
continue
|
||||
if(!data["supplies"][P.group])
|
||||
@@ -105,7 +105,7 @@
|
||||
data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE
|
||||
data["loan"] = !!SSshuttle.shuttle_loan
|
||||
data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched
|
||||
data["can_send"] = FALSE //There is no situation where I want the app to be able to send the shuttle AWAY from the station, but conversely is fine.
|
||||
data["can_send"] = FALSE //There is no situation where I want the app to be able to send the shuttle AWAY from the station, but conversely is fine.
|
||||
data["can_approve_requests"] = can_approve_requests
|
||||
data["app_cost"] = TRUE
|
||||
var/message = "Remember to stamp and send back the supply manifests."
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
"Head of Security",
|
||||
"Chief Engineer",
|
||||
"Research Director",
|
||||
"Chief Medical Officer")
|
||||
"Chief Medical Officer",
|
||||
"Quartermaster")
|
||||
|
||||
//The scaling factor of max total positions in relation to the total amount of people on board the station in %
|
||||
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players
|
||||
@@ -43,7 +44,7 @@
|
||||
|
||||
/datum/computer_file/program/job_management/proc/can_close_job(datum/job/job)
|
||||
if(!(job?.title in blacklisted))
|
||||
if(job.total_positions > length(GLOB.player_list) * (max_relative_positions / 100))
|
||||
if(job.total_positions > job.current_positions)
|
||||
var/delta = (world.time / 10) - GLOB.time_last_changed_position
|
||||
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
|
||||
return TRUE
|
||||
@@ -67,7 +68,7 @@
|
||||
if(!j || !can_open_job(j))
|
||||
return
|
||||
if(opened_positions[edit_job_target] >= 0)
|
||||
GLOB.time_last_changed_position = world.time / 10
|
||||
GLOB.time_last_changed_position = world.time / 10 // global cd
|
||||
j.total_positions++
|
||||
opened_positions[edit_job_target]++
|
||||
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
|
||||
@@ -453,3 +453,8 @@
|
||||
/obj/item/reagent_containers/glass/bottle/ichor/green
|
||||
name = "green potion"
|
||||
list_reagents = list(/datum/reagent/green_ichor = 1)
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/thermite
|
||||
name = "thermite bottle"
|
||||
list_reagents = list(/datum/reagent/thermite = 30)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
build_type = IMPRINTER
|
||||
materials = list(/datum/material/glass = 1000)
|
||||
build_path = /obj/item/circuitboard/computer/cargo/express
|
||||
category = list("Mining Designs")
|
||||
category = list("Computer Boards")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_CARGO
|
||||
|
||||
/datum/design/bluespace_pod
|
||||
@@ -19,7 +19,7 @@
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/glass = 1000)
|
||||
build_path = /obj/item/disk/cargo/bluespace_pod
|
||||
category = list("Mining Designs")
|
||||
category = list("Electronics")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_CARGO
|
||||
|
||||
/datum/design/drill
|
||||
|
||||
@@ -25,7 +25,14 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
|
||||
/obj/item/shared_storage,
|
||||
/obj/structure/extraction_point,
|
||||
/obj/machinery/syndicatebomb,
|
||||
/obj/item/hilbertshotel
|
||||
/obj/item/hilbertshotel,
|
||||
/obj/machinery/launchpad,
|
||||
/obj/machinery/disposal,
|
||||
/obj/structure/disposalpipe,
|
||||
/obj/item/hilbertshotel,
|
||||
/obj/machinery/camera,
|
||||
/obj/item/gps,
|
||||
/obj/structure/checkoutmachine
|
||||
)))
|
||||
|
||||
GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
@@ -33,6 +40,11 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
/mob/living/simple_animal/slaughter
|
||||
)))
|
||||
|
||||
/// How many goody orders we can fit in a lockbox before we upgrade to a crate
|
||||
#define GOODY_FREE_SHIPPING_MAX 5
|
||||
/// How much to charge oversized goody orders
|
||||
#define CRATE_TAX 700
|
||||
|
||||
/obj/docking_port/mobile/supply
|
||||
name = "supply shuttle"
|
||||
id = "supply"
|
||||
@@ -58,6 +70,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
return check_blacklist(shuttle_areas, GLOB.blacklisted_cargo_types - GLOB.cargo_shuttle_leave_behind_typecache)
|
||||
return ..()
|
||||
|
||||
// fuc off
|
||||
/obj/docking_port/mobile/supply/enterTransit()
|
||||
var/list/leave_behind = list()
|
||||
for(var/i in check_blacklist(shuttle_areas, GLOB.cargo_shuttle_leave_behind_typecache))
|
||||
@@ -98,12 +111,11 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
sell()
|
||||
|
||||
/obj/docking_port/mobile/supply/proc/buy()
|
||||
if(!SSshuttle.shoppinglist.len)
|
||||
return
|
||||
|
||||
var/list/obj/miscboxes = list() //miscboxes are combo boxes that contain all goody orders grouped
|
||||
var/list/misc_order_num = list() //list of strings of order numbers, so that the manifest can show all orders in a box
|
||||
var/list/misc_contents = list() //list of lists of items that each box will contain
|
||||
if(!SSshuttle.shoppinglist.len)
|
||||
return
|
||||
|
||||
var/list/empty_turfs = list()
|
||||
for(var/place in shuttle_areas)
|
||||
@@ -113,30 +125,39 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
continue
|
||||
empty_turfs += T
|
||||
|
||||
var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
var/value = 0
|
||||
var/purchases = 0
|
||||
var/list/goodies_by_buyer = list() // if someone orders more than GOODY_FREE_SHIPPING_MAX goodies, we upcharge to a normal crate so they can't carry around 20 combat shotties
|
||||
|
||||
for(var/datum/supply_order/SO in SSshuttle.shoppinglist)
|
||||
if(!empty_turfs.len)
|
||||
break
|
||||
|
||||
var/price = SO.pack.cost
|
||||
if(SO.applied_coupon)
|
||||
price *= (1 - SO.applied_coupon.discount_pct_off)
|
||||
|
||||
var/datum/bank_account/D
|
||||
if(SO.paying_account) //Someone paid out of pocket
|
||||
D = SO.paying_account
|
||||
var/list/current_buyer_orders = goodies_by_buyer[SO.paying_account] // so we can access the length a few lines down
|
||||
if(!SO.pack.goody)
|
||||
price *= 1.1 //TODO make this customizable by the quartermaster
|
||||
|
||||
// note this is before we increment, so this is the GOODY_FREE_SHIPPING_MAX + 1th goody to ship. also note we only increment off this step if they successfully pay the fee, so there's no way around it
|
||||
else if(LAZYLEN(current_buyer_orders) == GOODY_FREE_SHIPPING_MAX)
|
||||
price += CRATE_TAX
|
||||
D.bank_card_talk("Goody order size exceeds free shipping limit: Assessing [CRATE_TAX] credit S&H fee.")
|
||||
else
|
||||
D = cargo_budget
|
||||
D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
if(D)
|
||||
if(!D.adjust_money(-SO.pack.cost))
|
||||
if(!D.adjust_money(-price))
|
||||
if(SO.paying_account)
|
||||
D.bank_card_talk("Cargo order #[SO.id] rejected due to lack of funds. Credits required: [price]")
|
||||
continue
|
||||
|
||||
if(SO.paying_account)
|
||||
if(SO.pack.goody)
|
||||
LAZYADD(goodies_by_buyer[SO.paying_account], SO)
|
||||
D.bank_card_talk("Cargo order #[SO.id] has shipped. [price] credits have been charged to your bank account.")
|
||||
var/datum/bank_account/department/cargo = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
cargo.adjust_money(price - SO.pack.cost) //Cargo gets the handling fee
|
||||
@@ -145,30 +166,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
SSshuttle.orderhistory += SO
|
||||
QDEL_NULL(SO.applied_coupon)
|
||||
|
||||
if(SO.pack.goody) //goody means it gets piled in the miscbox
|
||||
if(SO.paying_account)
|
||||
if(!miscboxes.len || !miscboxes[D.account_holder]) //if there's no miscbox for this person
|
||||
miscboxes[D.account_holder] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs))
|
||||
var/obj/item/storage/lockbox/order/our_box = miscboxes[D.account_holder]
|
||||
our_box.buyer_account = SO.paying_account
|
||||
miscboxes[D.account_holder].name = "small items case - purchased by [D.account_holder]"
|
||||
misc_contents[D.account_holder] = list()
|
||||
for (var/item in SO.pack.contains)
|
||||
misc_contents[D.account_holder] += item
|
||||
misc_order_num[D.account_holder] = "[misc_order_num[D.account_holder]]#[SO.id] "
|
||||
else //No private payment, so we just stuff it all into a generic crate
|
||||
if(!miscboxes.len || !miscboxes["Cargo"])
|
||||
miscboxes["Cargo"] = new /obj/structure/closet/secure_closet/goodies(pick_n_take(empty_turfs))
|
||||
miscboxes["Cargo"].name = "small items closet"
|
||||
misc_contents["Cargo"] = list()
|
||||
miscboxes["Cargo"].req_access = list()
|
||||
for (var/item in SO.pack.contains)
|
||||
misc_contents["Cargo"] += item
|
||||
//new item(miscboxes["Cargo"])
|
||||
if(SO.pack.access)
|
||||
miscboxes["Cargo"].req_access += SO.pack.access
|
||||
misc_order_num["Cargo"] = "[misc_order_num["Cargo"]]#[SO.id] "
|
||||
else
|
||||
if(!SO.pack.goody) //we handle goody crates below
|
||||
SO.generate(pick_n_take(empty_turfs))
|
||||
|
||||
SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[SO.pack.cost]", "[SO.pack.name]"))
|
||||
@@ -177,16 +175,43 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
message_admins("\A [SO.pack.name] ordered by [ADMIN_LOOKUPFLW(SO.orderer_ckey)], paid by [D.account_holder] has shipped.")
|
||||
purchases++
|
||||
|
||||
// we handle packing all the goodies last, since the type of crate we use depends on how many goodies they ordered. If it's more than GOODY_FREE_SHIPPING_MAX
|
||||
// then we send it in a crate (including the CRATE_TAX cost), otherwise send it in a free shipping case
|
||||
for(var/D in goodies_by_buyer)
|
||||
var/list/buying_account_orders = goodies_by_buyer[D]
|
||||
var/datum/bank_account/buying_account = D
|
||||
var/buyer = buying_account.account_holder
|
||||
|
||||
if(buying_account_orders.len > GOODY_FREE_SHIPPING_MAX) // no free shipping, send a crate
|
||||
var/obj/structure/closet/crate/secure/owned/our_crate = new /obj/structure/closet/crate/secure/owned(pick_n_take(empty_turfs))
|
||||
our_crate.buyer_account = buying_account
|
||||
our_crate.name = "goody crate - purchased by [buyer]"
|
||||
miscboxes[buyer] = our_crate
|
||||
else //free shipping in a case
|
||||
miscboxes[buyer] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs))
|
||||
var/obj/item/storage/lockbox/order/our_case = miscboxes[buyer]
|
||||
our_case.buyer_account = buying_account
|
||||
miscboxes[buyer].name = "goody case - purchased by [buyer]"
|
||||
misc_contents[buyer] = list()
|
||||
|
||||
for(var/O in buying_account_orders)
|
||||
var/datum/supply_order/our_order = O
|
||||
for (var/item in our_order.pack.contains)
|
||||
misc_contents[buyer] += item
|
||||
misc_order_num[buyer] = "[misc_order_num[buyer]]#[our_order.id] "
|
||||
|
||||
for(var/I in miscboxes)
|
||||
var/datum/supply_order/SO = new/datum/supply_order()
|
||||
SO.id = misc_order_num[I]
|
||||
SO.generateCombo(miscboxes[I], I, misc_contents[I])
|
||||
qdel(SO)
|
||||
|
||||
var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
investigate_log("[purchases] orders in this shipment, worth [value] credits. [cargo_budget.account_balance] credits left.", INVESTIGATE_CARGO)
|
||||
|
||||
/obj/docking_port/mobile/supply/proc/sell()
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
var/presale_points = D.account_balance
|
||||
var/gain = 0
|
||||
|
||||
if(!GLOB.exports_list.len) // No exports list? Generate it!
|
||||
@@ -204,6 +229,8 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
continue
|
||||
if(bounty_ship_item_and_contents(AM, dry_run = FALSE))
|
||||
matched_bounty = TRUE
|
||||
// ignore mech checks because the mech is ONLY for bounty
|
||||
continue
|
||||
if(!AM.anchored || istype(AM, /obj/mecha))
|
||||
export_item_and_contents(AM, export_categories , dry_run = FALSE, external_report = ex)
|
||||
|
||||
@@ -230,4 +257,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
|
||||
msg = copytext_char(msg, 1, MAX_MESSAGE_LEN)
|
||||
|
||||
SSshuttle.centcom_message = msg
|
||||
investigate_log("Shuttle contents sold for [gain] credits. Contents: [ex.exported_atoms || "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO)
|
||||
investigate_log("Shuttle contents sold for [D.account_balance - presale_points] credits. Contents: [ex.exported_atoms ? ex.exported_atoms.Join(",") + "." : "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO)
|
||||
|
||||
#undef GOODY_FREE_SHIPPING_MAX
|
||||
#undef CRATE_TAX
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/obj/machinery/vending/barkbox
|
||||
name = "Bark Box"
|
||||
desc = "For all your pet needs!"
|
||||
icon_state = "barkbox"
|
||||
product_slogans = "Whuff!;Bark!;Give me a treat!"
|
||||
products = list(
|
||||
/obj/item/storage/fancy/treat_box = 8,
|
||||
/obj/item/clothing/neck/petcollar = 5,
|
||||
/obj/item/clothing/neck/petcollar/ribbon = 5,
|
||||
/obj/item/clothing/neck/petcollar/leather = 5,
|
||||
/obj/item/clothing/suit/petharness = 4,
|
||||
/obj/item/clothing/suit/petharness/mesh = 4,
|
||||
/obj/item/toy/fluff/tennis_poly = 4,
|
||||
/obj/item/toy/fluff/tennis_poly/tri = 2,
|
||||
/obj/item/toy/fluff/bone_poly = 4,
|
||||
/obj/item/toy/fluff/frisbee_poly = 4
|
||||
)
|
||||
contraband = list(
|
||||
/obj/item/clothing/neck/petcollar/locked = 2,
|
||||
/obj/item/clothing/neck/petcollar/locked/ribbon = 2,
|
||||
/obj/item/clothing/neck/petcollar/locked/leather = 2,
|
||||
/obj/item/key/collar = 2,
|
||||
/obj/item/dildo/knotted = 3
|
||||
)
|
||||
premium = list(
|
||||
/obj/item/toy/fluff/tennis_poly/tri/squeak = 1,
|
||||
/obj/item/toy/fluff/bone_poly/squeak = 1
|
||||
)
|
||||
refill_canister = /obj/item/vending_refill/barkbox
|
||||
default_price = PRICE_CHEAP
|
||||
extra_price = PRICE_BELOW_NORMAL
|
||||
payment_department = NO_FREEBIES
|
||||
|
||||
/obj/item/vending_refill/barkbox
|
||||
machine_name = "Bark Box"
|
||||
icon_state = "refill_barkbox"
|
||||
Reference in New Issue
Block a user