mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
[MIRROR] You can sell stuff on the blackmarket now. (#29401)
* You can sell stuff on the blackmarket now. (#85464) ## About The Pull Request The idea came up during the last blackmarket-related PR (#85066), when the original creator @ TheChosenEvilOne came and said the LTSRBT was originally supposed to allow players to sell stuff on the blackmarket. I replied saying the idea has some potential, and then other github users followed, also saying it's a good idea. So, here we are, adding another feature to the LTSRBT, to let you provide other players with potentially knock-offs and fraudulent (or genuinely honest) items on the blackmarket. How you do it is fairly simple: left click the machine to open it, place the item inside, then right-click to open the UI. From there you can adjust the name, description and price of the market item. Finally, click on the "Place on Market" button twice, pay a 30 credits fee, and it's done. You have an item on the market, and once it's sold, 85% or the earnings (the price) will be deposited on your account. By the by, the icon of the item you're trying to sell will also show up on the market. You should get a picture of what you're getting before falling for an obvious scam.  By the by, it's a cardboard cutout. ## Why It's Good For The Game This fits the design of the LTSRBT and blackmarket in general. ## Changelog 🆑 add: You can sell items on the blackmarket with the LTSRBT now. fix: Added some checks to prevent the swapper device and bluespace anomalies from theorically being able to send things and people to nullspace. /🆑 --------- Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@ users.noreply.github.com> * You can sell stuff on the blackmarket now. --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@ users.noreply.github.com>
This commit is contained in:
@@ -10,3 +10,5 @@
|
||||
// Sends a supply pod to the buyer's location, showy.
|
||||
#define SHIPPING_METHOD_SUPPLYPOD "Supply Pod"
|
||||
|
||||
/// The percentage on gains that's removed when selling an item through the blackmarket with the LTSRBT
|
||||
#define MARKET_WITHHOLDING_TAX 0.15
|
||||
|
||||
@@ -31,8 +31,16 @@
|
||||
// Calculate new position (searches through beacons in world)
|
||||
var/obj/item/beacon/chosen
|
||||
var/list/possible = list()
|
||||
for(var/obj/item/beacon/W in GLOB.teleportbeacons)
|
||||
possible += W
|
||||
for(var/obj/item/beacon/beacon in GLOB.teleportbeacons)
|
||||
var/turf/turf = get_turf(beacon)
|
||||
if(!turf)
|
||||
continue
|
||||
if(is_centcom_level(turf.z) || is_away_level(turf.z))
|
||||
continue
|
||||
var/area/area = get_area(turf)
|
||||
if(!area || (area.area_flags & NOTELEPORT))
|
||||
continue
|
||||
possible += beacon
|
||||
|
||||
if(possible.len > 0)
|
||||
chosen = pick(possible)
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
return teleportable
|
||||
|
||||
/obj/item/swapper/proc/swap(mob/user)
|
||||
if(QDELETED(linked_swapper) || world.time < linked_swapper.cooldown)
|
||||
if(QDELETED(linked_swapper) || isnull(linked_swapper.loc) || world.time < linked_swapper.cooldown)
|
||||
return
|
||||
|
||||
var/atom/movable/A = get_teleportable_container()
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
/// Probability for this item to be available. Used by SSmarket on init.
|
||||
var/availability_prob
|
||||
|
||||
/// If set, this icon will be shown in the UI.
|
||||
var/html_icon
|
||||
|
||||
///The identifier for the market item, generated on runtime and used to access them in the market categories.
|
||||
var/identifier
|
||||
|
||||
@@ -51,9 +54,11 @@
|
||||
//we're replacing the item to sell, and the old item is an instance!
|
||||
if(ismovable(item))
|
||||
UnregisterSignal(item, COMSIG_QDELETING)
|
||||
html_icon = null
|
||||
item = path_or_ref
|
||||
identifier = "[path_or_ref]"
|
||||
if(ismovable(path_or_ref))
|
||||
html_icon = icon2base64(getFlatIcon(item, no_anim=TRUE))
|
||||
RegisterSignal(item, COMSIG_QDELETING, PROC_REF(on_item_del))
|
||||
identifier = "[REF(src)]"
|
||||
|
||||
|
||||
25
code/modules/cargo/markets/market_items/local_goods.dm
Normal file
25
code/modules/cargo/markets/market_items/local_goods.dm
Normal file
@@ -0,0 +1,25 @@
|
||||
///A special category for goods placed on the market by station by someone with the LTSRBT.
|
||||
/datum/market_item/local_good
|
||||
category = "Local Goods"
|
||||
abstract_path = /datum/market_item/local_good
|
||||
stock = 1
|
||||
availability_prob = 100
|
||||
restockable = FALSE
|
||||
var/datum/bank_account/seller
|
||||
|
||||
/datum/market_item/local_good/New(atom/movable/thing, datum/bank_account/seller)
|
||||
..()
|
||||
set_item(thing)
|
||||
src.seller = seller
|
||||
if(seller)
|
||||
RegisterSignal(seller, COMSIG_QDELETING, PROC_REF(delete_reference))
|
||||
|
||||
/datum/market_item/local_good/buy(obj/item/market_uplink/uplink, mob/buyer, shipping_method, legal_status)
|
||||
. = ..()
|
||||
if(. && seller)
|
||||
seller.adjust_money(round(price * (1 - MARKET_WITHHOLDING_TAX)), "Market: Item Sold")
|
||||
QDEL_IN(src, 10 MINUTES) //This category cannot hold more than 40 items at a time, so we need to clear sold items.
|
||||
|
||||
/datum/market_item/local_good/proc/delete_reference(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
seller = null
|
||||
@@ -1,4 +1,5 @@
|
||||
#define DEFAULT_RESTOCK_COST 675
|
||||
#define DEFAULT_RESTOCK_COST CARGO_CRATE_VALUE * 3.375
|
||||
#define PLACE_ON_MARKET_COST PAYCHECK_LOWER * 1.2
|
||||
|
||||
/obj/item/circuitboard/machine/ltsrbt
|
||||
name = "LTSRBT (Machine Board)"
|
||||
@@ -14,13 +15,14 @@
|
||||
/obj/machinery/ltsrbt
|
||||
name = "Long-To-Short-Range-Bluespace-Transceiver"
|
||||
desc = "The LTSRBT is a compact teleportation machine for receiving 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 = 'icons/obj/machines/telecomms.dmi'
|
||||
icon_state = "exonet_node_idle"
|
||||
base_icon_state = "exonet_node"
|
||||
icon = 'icons/obj/machines/ltsrbt.dmi'
|
||||
icon_state = "ltsrbt_idle"
|
||||
base_icon_state = "ltsrbt"
|
||||
circuit = /obj/item/circuitboard/machine/ltsrbt
|
||||
density = TRUE
|
||||
|
||||
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 2
|
||||
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND
|
||||
|
||||
/// Divider for energy_usage_per_teleport.
|
||||
var/power_efficiency = 1
|
||||
@@ -38,6 +40,12 @@
|
||||
var/datum/market_purchase/transmitting
|
||||
/// Queue for purchases that the machine should receive and send.
|
||||
var/list/datum/market_purchase/queue = list()
|
||||
/// The name of the market item that we've set on the UI
|
||||
var/current_name = ""
|
||||
/// The desc of the market item that we've set on the UI
|
||||
var/current_desc = ""
|
||||
/// The price of the market item that we've set on the UI
|
||||
var/current_price = CARGO_CRATE_VALUE
|
||||
/**
|
||||
* Attacking the machinery with enough credits will restock the markets, allowing for more/better items.
|
||||
* The cost doubles each time this is done.
|
||||
@@ -48,32 +56,267 @@
|
||||
. = ..()
|
||||
register_context()
|
||||
SSmarket.telepads += src
|
||||
ADD_TRAIT(src, TRAIT_SECLUDED_LOCATION, INNATE_TRAIT) //you cannot sell disky, boss.
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/ltsrbt/Destroy()
|
||||
SSmarket.telepads -= src
|
||||
// Bye bye orders.
|
||||
if(length(SSmarket.telepads))
|
||||
for(var/datum/market_purchase/P in queue)
|
||||
SSmarket.queue_item(P)
|
||||
. = ..()
|
||||
for(var/datum/market_purchase/purchase in queue)
|
||||
SSmarket.queue_item(purchase)
|
||||
if(receiving)
|
||||
SSmarket.queue_item(receiving)
|
||||
queue = null
|
||||
receiving = null
|
||||
transmitting = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/ltsrbt/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
if(held_item && held_item.get_item_credit_value())
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Restock"
|
||||
if(held_item)
|
||||
if(state_open)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Insert"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
if(held_item.get_item_credit_value() && !(machine_stat & NOPOWER))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Restock"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
return NONE
|
||||
if(state_open)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Close"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
return NONE
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Open"
|
||||
if(occupant && !(machine_stat & NOPOWER))
|
||||
context[SCREENTIP_CONTEXT_RMB] = "Place on market"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/machinery/ltsrbt/examine(mob/user)
|
||||
. = ..()
|
||||
if(machine_stat & NOPOWER)
|
||||
. += span_info("A display reads: \"Current market restock price: [EXAMINE_HINT("[restock_cost] cr")]\".")
|
||||
if(!(machine_stat & NOPOWER))
|
||||
. += span_info("A small display reads:")
|
||||
. += span_tinynoticeital("Current market restock price: [EXAMINE_HINT("[restock_cost] cr")].")
|
||||
. += span_tinynoticeital("Market placement fee: [EXAMINE_HINT("[PLACE_ON_MARKET_COST] cr")].")
|
||||
. += span_tinynoticeital("Withholding tax on local items: [EXAMINE_HINT("[MARKET_WITHHOLDING_TAX * 100]%")].")
|
||||
|
||||
/obj/machinery/ltsrbt/update_icon_state()
|
||||
. = ..()
|
||||
if(machine_stat & NOPOWER)
|
||||
icon_state = "[base_icon_state]_off"
|
||||
else
|
||||
icon_state = "[base_icon_state][(receiving || length(queue)) ? "" : "_idle"]"
|
||||
icon_state = "[base_icon_state][(receiving || length(queue) || occupant) ? "" : "_idle"]"
|
||||
|
||||
/obj/machinery/ltsrbt/update_overlays()
|
||||
. = ..()
|
||||
if(!state_open)
|
||||
. += "[base_icon_state]_closed"
|
||||
else
|
||||
var/mutable_appearance/overlay = mutable_appearance(icon, "[base_icon_state]_open")
|
||||
overlay.pixel_w -= 2
|
||||
overlay.pixel_z -= 1
|
||||
. += overlay
|
||||
|
||||
/obj/machinery/ltsrbt/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!state_open)
|
||||
open_machine(density_to_set = TRUE)
|
||||
else
|
||||
close_machine()
|
||||
|
||||
/obj/machinery/ltsrbt/open_machine(drop = TRUE, density_to_set = FALSE)
|
||||
. = ..()
|
||||
playsound(src, 'sound/machines/oven/oven_open.ogg', 75, TRUE)
|
||||
|
||||
/obj/machinery/ltsrbt/close_machine(atom/movable/target, density_to_set = TRUE)
|
||||
. = ..()
|
||||
playsound(src, 'sound/machines/oven/oven_close.ogg', 75, TRUE)
|
||||
|
||||
/obj/machinery/ltsrbt/set_occupant(obj/item/new_occupant)
|
||||
. = ..()
|
||||
if(new_occupant)
|
||||
current_name = new_occupant.name
|
||||
current_desc = new_occupant.desc
|
||||
|
||||
/obj/machinery/ltsrbt/can_be_occupant(atom/movable/atom)
|
||||
return isitem(atom) && !atom.anchored
|
||||
|
||||
/obj/machinery/ltsrbt/Exited(atom/movable/gone)
|
||||
if(gone == occupant)
|
||||
current_price = initial(current_price)
|
||||
current_name = ""
|
||||
current_desc = ""
|
||||
update_appearance(UPDATE_ICON_STATE)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/ltsrbt/attack_hand_secondary(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
|
||||
return
|
||||
if(state_open)
|
||||
balloon_alert(user, "close it first!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(!occupant)
|
||||
balloon_alert(user, "nothing loaded!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(machine_stat & NOPOWER)
|
||||
balloon_alert(user, "machine unpowered!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(!COOLDOWN_FINISHED(src, recharge_cooldown))
|
||||
balloon_alert(user, "on cooldown!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
ui_interact(user)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/obj/machinery/ltsrbt/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(user.combat_mode)
|
||||
return NONE
|
||||
|
||||
var/creds_value = tool.get_item_credit_value()
|
||||
|
||||
if(state_open)
|
||||
if(locate(/mob/living) in tool.get_all_contents())
|
||||
say("Living being detected, cannot sell!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!user.transferItemToLoc(tool, src))
|
||||
balloon_alert(user, "stuck to your hands!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
balloon_alert(user, "item loaded")
|
||||
close_machine(tool)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
else if(!creds_value)
|
||||
balloon_alert(user, "open the machine!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(machine_stat & NOPOWER)
|
||||
return
|
||||
|
||||
if(creds_value < restock_cost)
|
||||
say("Insufficient credits!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(istype(tool, /obj/item/holochip))
|
||||
var/obj/item/holochip/chip = tool
|
||||
chip.spend(restock_cost)
|
||||
else
|
||||
qdel(tool)
|
||||
if(creds_value != restock_cost)
|
||||
var/obj/item/holochip/change = new(loc, creds_value - restock_cost)
|
||||
user.put_in_hands(change)
|
||||
|
||||
SSmarket.restock()
|
||||
restock_cost *= 2
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/ltsrbt/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "LTSRBT", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/ltsrbt/ui_state()
|
||||
if(!occupant || !COOLDOWN_FINISHED(src, recharge_cooldown))
|
||||
return GLOB.never_state //close it.
|
||||
else
|
||||
return GLOB.default_state
|
||||
|
||||
#define LTSRBT_MIN_PRICE PAYCHECK_LOWER
|
||||
#define LTSRBT_MAX_PRICE CARGO_CRATE_VALUE * 50
|
||||
|
||||
/obj/machinery/ltsrbt/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["loaded_icon"] = icon2base64(getFlatIcon(occupant, no_anim=TRUE))
|
||||
data["min_price"] = LTSRBT_MIN_PRICE
|
||||
data["max_price"] = LTSRBT_MAX_PRICE
|
||||
return data
|
||||
|
||||
/obj/machinery/ltsrbt/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["name"] = current_name
|
||||
data["price"] = current_price
|
||||
data["desc"] = current_desc
|
||||
return data
|
||||
|
||||
/obj/machinery/ltsrbt/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("change_name")
|
||||
var/value = params["value"]
|
||||
if(!CAN_BYPASS_FILTER(usr) && is_ic_filtered_for_pdas(value))
|
||||
return TRUE
|
||||
current_name = trim(value, MAX_NAME_LEN)
|
||||
return TRUE
|
||||
if("change_desc")
|
||||
var/value = params["value"]
|
||||
if(!CAN_BYPASS_FILTER(usr) && is_ic_filtered_for_pdas(value))
|
||||
return TRUE
|
||||
current_desc = trim(value, MAX_DESC_LEN)
|
||||
return TRUE
|
||||
if("change_price")
|
||||
current_price = clamp(params["value"], LTSRBT_MIN_PRICE, LTSRBT_MAX_PRICE)
|
||||
return TRUE
|
||||
if("place_on_market")
|
||||
place_on_market(usr)
|
||||
return TRUE
|
||||
|
||||
#undef LTSRBT_MIN_PRICE
|
||||
#undef LTSRBT_MAX_PRICE
|
||||
|
||||
#define LTSRBT_MAX_MARKET_ITEMS 40
|
||||
/obj/machinery/ltsrbt/proc/place_on_market(mob/user)
|
||||
if(QDELETED(occupant))
|
||||
return
|
||||
if(locate(/mob/living) in occupant.get_all_contents())
|
||||
say("Living being detected, cannot sell!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
|
||||
return
|
||||
var/datum/bank_account/account
|
||||
var/datum/market/our_market = SSmarket.markets[/datum/market/blackmarket]
|
||||
if(!isAdminGhostAI(user))
|
||||
if(!isliving(user))
|
||||
return
|
||||
if(length(our_market.available_items[/datum/market_item/local_good::category]) >= LTSRBT_MAX_MARKET_ITEMS)
|
||||
say("Local market saturated, buy some goods first!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
|
||||
return
|
||||
var/mob/living/living_user = user
|
||||
var/obj/item/card/id/card = living_user.get_idcard(TRUE)
|
||||
if(!(card?.registered_account))
|
||||
say("No bank account to charge market fees detected!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
|
||||
return
|
||||
if(!card.registered_account.adjust_money(-PLACE_ON_MARKET_COST, "Market: Placement Fee"))
|
||||
say("Insufficient credits!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
|
||||
return
|
||||
account = card.registered_account
|
||||
|
||||
var/obj/item/item = occupant //occupant, name, price and desc will be null'd once it exits the machine so we need this.
|
||||
var/name_to_use = current_name || item.name
|
||||
var/desc_to_use = current_desc
|
||||
if(account)
|
||||
desc_to_use += "[current_desc ? " - " : ""]Seller: [account.account_holder]"
|
||||
var/price_to_use = current_price
|
||||
item.moveToNullspace()
|
||||
//Something happened and the item was deleted or relocated as soon as it was moved to nullspace.
|
||||
if(QDELETED(item) || item.loc != null)
|
||||
say("Runtime at market_placement.dm, line 153: item gone!") //metajoke
|
||||
return
|
||||
var/datum/market_item/local_good/new_item = new(item, account)
|
||||
new_item.name = name_to_use
|
||||
new_item.desc = desc_to_use
|
||||
new_item.price = price_to_use
|
||||
|
||||
our_market.add_item(new_item)
|
||||
|
||||
say("Item placed on the market!")
|
||||
playsound(src, 'sound/effects/cashregister.ogg', 40, FALSE)
|
||||
COOLDOWN_START(src, recharge_cooldown, recharge_time * 3)
|
||||
|
||||
#undef LTSRBT_MAX_MARKET_ITEMS
|
||||
|
||||
/obj/machinery/ltsrbt/RefreshParts()
|
||||
. = ..()
|
||||
@@ -81,7 +324,6 @@
|
||||
// On tier 4 recharge_time should be 20 and by default it is 80 as scanning modules should be tier 1.
|
||||
for(var/datum/stock_part/scanning_module/scanning_module in component_parts)
|
||||
recharge_time -= scanning_module.tier * 1 SECONDS
|
||||
recharge_cooldown = recharge_time
|
||||
|
||||
power_efficiency = 0
|
||||
for(var/datum/stock_part/micro_laser/laser in component_parts)
|
||||
@@ -132,43 +374,17 @@
|
||||
transmitting = receiving
|
||||
receiving = null
|
||||
|
||||
COOLDOWN_START(src, recharge_cooldown, recharge_time)
|
||||
return
|
||||
if(transmitting)
|
||||
if(transmitting.item.loc == turf)
|
||||
do_teleport(transmitting.item, get_turf(transmitting.uplink))
|
||||
use_energy(energy_usage_per_teleport / power_efficiency)
|
||||
QDEL_NULL(transmitting)
|
||||
COOLDOWN_START(src, recharge_cooldown, recharge_time)
|
||||
return
|
||||
|
||||
if(length(queue))
|
||||
receiving = pick_n_take(queue)
|
||||
|
||||
/obj/machinery/ltsrbt/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
var/creds_value = tool.get_item_credit_value()
|
||||
if(!creds_value)
|
||||
return NONE
|
||||
|
||||
. = ITEM_INTERACT_SUCCESS
|
||||
|
||||
if(machine_stat & NOPOWER)
|
||||
return
|
||||
|
||||
if(creds_value < restock_cost)
|
||||
say("Insufficient credits!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
|
||||
return
|
||||
|
||||
if(istype(tool, /obj/item/holochip))
|
||||
var/obj/item/holochip/chip = tool
|
||||
chip.spend(restock_cost)
|
||||
else
|
||||
qdel(tool)
|
||||
if(creds_value != restock_cost)
|
||||
var/obj/item/holochip/change = new(creds_value - restock_cost)
|
||||
user.put_in_hands(change)
|
||||
|
||||
SSmarket.restock()
|
||||
restock_cost *= 2
|
||||
|
||||
#undef DEFAULT_RESTOCK_COST
|
||||
#undef PLACE_ON_MARKET_COST
|
||||
|
||||
@@ -80,7 +80,8 @@
|
||||
"name" = item.name,
|
||||
"cost" = item.price,
|
||||
"amount" = item.stock,
|
||||
"desc" = item.desc || item.name
|
||||
"desc" = item.desc || item.name,
|
||||
"html_icon" = item.html_icon,
|
||||
))
|
||||
return data
|
||||
|
||||
|
||||
BIN
icons/obj/machines/ltsrbt.dmi
Normal file
BIN
icons/obj/machines/ltsrbt.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
@@ -3790,6 +3790,7 @@
|
||||
#include "code\modules\cargo\markets\market_items\clothing.dm"
|
||||
#include "code\modules\cargo\markets\market_items\consumables.dm"
|
||||
#include "code\modules\cargo\markets\market_items\hostages.dm"
|
||||
#include "code\modules\cargo\markets\market_items\local_goods.dm"
|
||||
#include "code\modules\cargo\markets\market_items\misc.dm"
|
||||
#include "code\modules\cargo\markets\market_items\stolen_goods.dm"
|
||||
#include "code\modules\cargo\markets\market_items\tools.dm"
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
AnimatedNumber,
|
||||
Box,
|
||||
Button,
|
||||
Image,
|
||||
Modal,
|
||||
Section,
|
||||
Stack,
|
||||
@@ -36,6 +37,7 @@ type Item = {
|
||||
desc: string;
|
||||
amount: number;
|
||||
cost: number;
|
||||
html_icon: string;
|
||||
};
|
||||
|
||||
type DeliveryMethod = {
|
||||
@@ -106,8 +108,22 @@ export const BlackMarketUplink = (props) => {
|
||||
{items.map((item) => (
|
||||
<Box key={item.name} className="candystripe" p={1} pb={2}>
|
||||
<Stack align="baseline">
|
||||
<Stack.Item grow bold>
|
||||
{item.name}
|
||||
<Stack.Item grow>
|
||||
<Stack align="horizontal">
|
||||
{!!item.html_icon && (
|
||||
<Stack.Item>
|
||||
<Image
|
||||
m={1}
|
||||
src={`data:image/jpeg;base64,${item.html_icon}`}
|
||||
height="64px"
|
||||
width="64px"
|
||||
/>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item grow bold>
|
||||
{item.name}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item color="label">
|
||||
{item.amount ? item.amount + ' in stock' : 'Out of stock'}
|
||||
|
||||
94
tgui/packages/tgui/interfaces/LTSRBT.tsx
Normal file
94
tgui/packages/tgui/interfaces/LTSRBT.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import { useBackend } from '../backend';
|
||||
import {
|
||||
Button,
|
||||
Image,
|
||||
Input,
|
||||
NumberInput,
|
||||
Section,
|
||||
Stack,
|
||||
TextArea,
|
||||
} from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
type Data = {
|
||||
name: string;
|
||||
price: number;
|
||||
min_price: number;
|
||||
max_price: number;
|
||||
loaded_icon: string;
|
||||
desc: string;
|
||||
};
|
||||
|
||||
export const LTSRBT = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
const { name, price, min_price, max_price, loaded_icon, desc } = data;
|
||||
|
||||
return (
|
||||
<Window width={300} height={380} theme="hackerman">
|
||||
<Window.Content>
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<Input
|
||||
width="80%"
|
||||
value={name}
|
||||
placeholder="Insert a name"
|
||||
onChange={(e, value) =>
|
||||
act('change_name', {
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<NumberInput
|
||||
step={1}
|
||||
width="20%"
|
||||
value={price}
|
||||
minValue={min_price}
|
||||
maxValue={max_price}
|
||||
unit="cr"
|
||||
onChange={(value) =>
|
||||
act('change_price', {
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Divider />
|
||||
{!!loaded_icon && (
|
||||
<Stack.Item>
|
||||
<Section align="center">
|
||||
<Image
|
||||
m={1}
|
||||
src={`data:image/jpeg;base64,${loaded_icon}`}
|
||||
height="96px"
|
||||
width="96px"
|
||||
/>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Divider />
|
||||
<Stack.Item grow>
|
||||
<TextArea
|
||||
height="90%"
|
||||
value={desc}
|
||||
placeholder="Insert a description (or don't)"
|
||||
onChange={(e, value) =>
|
||||
act('change_desc', {
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Divider />
|
||||
<Stack.Item>
|
||||
<Button.Confirm
|
||||
fluid
|
||||
icon="truck-arrow-right"
|
||||
content="Place on Market"
|
||||
onClick={() => act('place_on_market')}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user