diff --git a/SQL/migrate/V009__Cargo.sql b/SQL/migrate/V009__Cargo.sql new file mode 100644 index 00000000000..ed3f6cddd68 --- /dev/null +++ b/SQL/migrate/V009__Cargo.sql @@ -0,0 +1,63 @@ +-- +-- Create the Cargo Database +-- + +CREATE TABLE `ss13_cargo_categories` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(100) NOT NULL COLLATE 'utf8_bin', + `display_name` VARCHAR(100) NOT NULL COLLATE 'utf8_bin', + `description` VARCHAR(300) NOT NULL COLLATE 'utf8_bin', + `icon` VARCHAR(50) NOT NULL COLLATE 'utf8_bin', + `price_modifier` FLOAT UNSIGNED NOT NULL DEFAULT '1', + `order_by` VARCHAR(5) NULL DEFAULT NULL COLLATE 'utf8_bin', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `name` (`name`) +) +COLLATE='utf8_bin' +ENGINE=InnoDB +; + +CREATE TABLE `ss13_cargo_items` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `path` VARCHAR(150) NOT NULL COLLATE 'utf8_bin', + `name` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8_bin', + `description` VARCHAR(300) NULL DEFAULT NULL COLLATE 'utf8_bin', + `categories` VARCHAR(300) NOT NULL COMMENT 'JSON list of categories' COLLATE 'utf8_bin', + `suppliers` TEXT NULL COMMENT 'JSTON list of suppliers' COLLATE 'utf8_bin', + `amount` INT(10) UNSIGNED NOT NULL DEFAULT '1', + `access` INT(10) UNSIGNED NULL DEFAULT NULL, + `container_type` VARCHAR(50) NOT NULL DEFAULT 'crate' COLLATE 'utf8_bin', + `groupable` TINYINT(3) UNSIGNED NOT NULL DEFAULT '1', + `order_by` VARCHAR(5) NULL DEFAULT NULL COLLATE 'utf8_bin', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `path` (`path`) +) +COLLATE='utf8_bin' +ENGINE=InnoDB +; + +CREATE TABLE `ss13_cargo_suppliers` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `short_name` VARCHAR(50) NOT NULL COLLATE 'utf8_bin', + `name` VARCHAR(100) NOT NULL COLLATE 'utf8_bin', + `description` VARCHAR(300) NOT NULL COLLATE 'utf8_bin', + `tag_line` VARCHAR(300) NOT NULL COLLATE 'utf8_bin', + `shuttle_time` INT(11) UNSIGNED NOT NULL, + `shuttle_price` INT(11) UNSIGNED NOT NULL, + `available` TINYINT(4) UNSIGNED NOT NULL DEFAULT '1', + `price_modifier` FLOAT UNSIGNED NOT NULL DEFAULT '1', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `Schlüssel 2` (`short_name`) +) +COLLATE='utf8_bin' +ENGINE=InnoDB +; diff --git a/aurorastation.dme b/aurorastation.dme index 2c62b4eef86..5ff0cd574dc 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -203,6 +203,7 @@ #include "code\datums\beam.dm" #include "code\datums\browser.dm" #include "code\datums\callback.dm" +#include "code\datums\cargo.dm" #include "code\datums\category.dm" #include "code\datums\computerfiles.dm" #include "code\datums\datacore.dm" @@ -215,7 +216,6 @@ #include "code\datums\progressbar.dm" #include "code\datums\server_greeting.dm" #include "code\datums\statistic.dm" -#include "code\datums\supplypacks.dm" #include "code\datums\weakref.dm" #include "code\datums\diseases\appendicitis.dm" #include "code\datums\diseases\beesease.dm" @@ -575,7 +575,6 @@ #include "code\game\machinery\computer\skills.dm" #include "code\game\machinery\computer\specops_shuttle.dm" #include "code\game\machinery\computer\station_alert.dm" -#include "code\game\machinery\computer\supply.dm" #include "code\game\machinery\computer\syndicate_specops_shuttle.dm" #include "code\game\machinery\doors\airlock.dm" #include "code\game\machinery\doors\airlock_control.dm" @@ -803,7 +802,6 @@ #include "code\game\objects\items\weapons\circuitboards\computer\holodeckcontrol.dm" #include "code\game\objects\items\weapons\circuitboards\computer\research.dm" #include "code\game\objects\items\weapons\circuitboards\computer\station_alert.dm" -#include "code\game\objects\items\weapons\circuitboards\computer\supply.dm" #include "code\game\objects\items\weapons\circuitboards\computer\telecomms.dm" #include "code\game\objects\items\weapons\circuitboards\machinery\biogenerator.dm" #include "code\game\objects\items\weapons\circuitboards\machinery\cloning.dm" @@ -1284,7 +1282,6 @@ #include "code\modules\events\radiation_storm.dm" #include "code\modules\events\random_antagonist.dm" #include "code\modules\events\rogue_drones.dm" -#include "code\modules\events\shipping_error.dm" #include "code\modules\events\space_ninja.dm" #include "code\modules\events\spacevine.dm" #include "code\modules\events\spider_infestation.dm" @@ -1744,6 +1741,8 @@ #include "code\modules\modular_computers\file_system\programs\antagonist\dos.dm" #include "code\modules\modular_computers\file_system\programs\antagonist\hacked_camera.dm" #include "code\modules\modular_computers\file_system\programs\antagonist\revelation.dm" +#include "code\modules\modular_computers\file_system\programs\civilian\cargo_control.dm" +#include "code\modules\modular_computers\file_system\programs\civilian\cargo_order.dm" #include "code\modules\modular_computers\file_system\programs\civilian\crusher_control.dm" #include "code\modules\modular_computers\file_system\programs\command\card.dm" #include "code\modules\modular_computers\file_system\programs\command\comm.dm" @@ -1985,7 +1984,6 @@ #include "code\modules\reagents\dispenser\coffeebeans.dm" #include "code\modules\reagents\dispenser\dispenser2.dm" #include "code\modules\reagents\dispenser\dispenser_presets.dm" -#include "code\modules\reagents\dispenser\supply.dm" #include "code\modules\reagents\reagent_containers\blood_pack.dm" #include "code\modules\reagents\reagent_containers\borghydro.dm" #include "code\modules\reagents\reagent_containers\dropper.dm" diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 778918efd3d..1806473e89c 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -383,6 +383,11 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s //Of course, this will affect code that checks for blocked < 100, as blocked will be less likely to actually be 100. #define ARMOR_BLOCK_CHANCE_MULT 1.0 +//Cargo Container Types +#define CARGO_CONTAINER_CRATE "crate" +#define CARGO_CONTAINER_FREEZER "freezer" +#define CARGO_CONTAINER_BOX "box" + // We should start using these. #define ITEMSIZE_TINY 1 #define ITEMSIZE_SMALL 2 diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 2936dce4196..4112756f3cc 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -271,6 +271,7 @@ var/list/gamemode_cache = list() var/sun_accuracy = 8 var/sun_target_z = 7 + var/cargo_load_items_from = "json" var/merchant_chance = 20 //Chance, in percentage, of the merchant job slot being open at round start var/show_game_type_odd = 1 // If the check gamemode probability verb is enabled or not @@ -841,6 +842,9 @@ var/list/gamemode_cache = list() access_deny_vms = text2num(value) if("access_warn_vms") access_warn_vms = text2num(value) + + if("cargo_load_items_from") + cargo_load_items_from = value if("fastboot") fastboot = TRUE diff --git a/code/controllers/subsystems/supply.dm b/code/controllers/subsystems/supply.dm index 4096e36a8af..f55c90d363c 100644 --- a/code/controllers/subsystems/supply.dm +++ b/code/controllers/subsystems/supply.dm @@ -4,43 +4,70 @@ #define SUPPLY_STATION_AREATYPE /area/supply/station //Type of the supply shuttle area for station #define SUPPLY_DOCK_AREATYPE /area/supply/dock //Type of the supply shuttle area for dock +/proc/fetch_supply_account() + SScargo.supply_account = department_accounts["Cargo"] + var/datum/controller/subsystem/cargo/SScargo /datum/controller/subsystem/cargo name = "Cargo" wait = 30 SECONDS - flags = SS_NO_TICK_CHECK + flags = SS_NO_TICK_CHECK | SS_NO_FIRE init_order = SS_INIT_CARGO - //supply points - var/points = 50 - var/points_per_process = 1 - var/points_per_slip = 2 - var/points_per_crate = 5 - var/points_per_platinum = 5 // 5 points per sheet - var/points_per_phoron = 5 - //control + //Shipment stuff + var/shipmentnum + var/list/cargo_shipments = list() //List of the shipments to the station + var/datum/cargo_shipment/current_shipment = null // The current cargo shipment + + //order stuff var/ordernum - var/list/shoppinglist = list() - var/list/requestlist = list() - var/list/supply_packs = list() + var/list/cargo_items = list() //The list of items + var/list/cargo_categories = list() //The list of categories + var/list/cargo_suppliers = list() //The list of suppliers + var/list/all_orders = list() //All orders + + //Fee Stuff + var/credits_per_crate = 100 //Cost / Payment per crate shipped from / to centcom + var/credits_per_platinum = 140 //Per sheet + var/credits_per_phoron = 100 //Per sheet + var/cargo_handlingfee = 50 //The handling fee cargo takes per crate + var/cargo_handlingfee_min = 0 // The minimum handling fee + var/cargo_handlingfee_max = 500 // The maximum handling fee + var/cargo_handlingfee_change = 1 // If the handlingfee can be changed -> For a random event + var/datum/money_account/supply_account + //shuttle movement var/movetime = 1200 var/datum/shuttle/ferry/supply/shuttle /datum/controller/subsystem/cargo/Recover() - src.points = SScargo.points - src.shoppinglist = SScargo.shoppinglist - src.requestlist = SScargo.requestlist - src.supply_packs = SScargo.supply_packs src.shuttle = SScargo.shuttle + src.cargo_items = SScargo.cargo_items + src.cargo_categories = SScargo.cargo_categories + src.cargo_shipments = SScargo.cargo_shipments + src.all_orders = SScargo.all_orders + src.cargo_handlingfee = SScargo.cargo_handlingfee + src.cargo_handlingfee_change = SScargo.cargo_handlingfee_change + src.supply_account = SScargo.supply_account /datum/controller/subsystem/cargo/Initialize(timeofday) - ordernum = rand(1,9000) + //Generate the ordernumber and shipmentnumber to start with + ordernum = rand(1,8000) + shipmentnum = rand(500,700) - for (var/typepath in subtypesof(/datum/supply_packs)) - var/datum/supply_packs/P = new typepath() - supply_packs[P.name] = P + //Fetch the cargo account once the round is started - TODO: Repalce that once economy gets its own subsystem + SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/fetch_supply_account)) + + //Load in the cargo items config + if(config.cargo_load_items_from == "sql") + log_debug("SSCargo: Attempting to Load from SQL") + load_from_sql() + else if(config.cargo_load_items_from == "json") + log_debug("SSCargo: Attempting to Load from JSON") + load_from_json() + else + log_game("SSCargo: invalid load option specified in config") var/datum/cargospawner/spawner = new spawner.start() @@ -50,8 +77,491 @@ var/datum/controller/subsystem/cargo/SScargo /datum/controller/subsystem/cargo/New() NEW_SS_GLOBAL(SScargo) -/datum/controller/subsystem/cargo/fire() - points += points_per_process + +/* + Loading Data +*/ +//Reset cargo to prep for loading in new items +/datum/controller/subsystem/cargo/proc/reset_cargo() + cargo_shipments = list() //List of the shipments to the station + current_shipment = null // The current cargo shipment + cargo_items = list() //The list of items + cargo_categories = list() //The list of categories + cargo_suppliers = list() //The list of suppliers + all_orders = list() //All orders + +//Load the cargo data from SQL +/datum/controller/subsystem/cargo/proc/load_from_sql() + if(!establish_db_connection(dbcon)) + log_debug("SSCargo: SQL ERROR - Failed to connect. - Falling back to JSON") + return load_from_json() + else + //Reset the currently loaded data + reset_cargo() + + //Populate the items missing a name or a description with the missing name / description + var/DBQuery/item_null_query = dbcon.NewQuery("SELECT path, name, description, suppliers, id FROM ss13_cargo_items WHERE (name IS NULL OR description IS NULL OR suppliers IS NULL) AND deleted_at IS NULL" ) + item_null_query.Execute() + while(item_null_query.NextRow()) + //Spawn the item with the path + var/oldpath = item_null_query.item[1] + var/oldname = item_null_query.item[2] + var/olddsec = item_null_query.item[3] + var/oldsuppliers = item_null_query.item[4] + var/item_id = item_null_query.item[5] + var/path = text2path(oldpath) + + log_debug("SSCargo: Got path without name or description - updating: [oldpath]") + if(path) + var/obj/cargoitem = new path + //The following sql queries arnt overly optimized. Its just not worht it, because they are only run once if a item is added without the complete data + if(cargoitem) + //Update the name of the item if its null + if(!oldname) + log_debug("SSCargo: Updating name to [cargoitem.name]") + var/DBQuery/item_update_name_query = dbcon.NewQuery("UPDATE ss13_cargo_items SET name = :name: WHERE id = :item_id:") + item_update_name_query.Execute(list("name" = cargoitem.name, "item_id" = item_id )) + //Update the name of the item if its null + if(!olddsec) + log_debug("SSCargo: Updating desc to [cargoitem.desc]") + var/DBQuery/item_update_desc_query = dbcon.NewQuery("UPDATE ss13_cargo_items SET description = :desc: WHERE id = :item_id:") + item_update_desc_query.Execute(list("desc" = cargoitem.desc, "item_id" = item_id )) + //Set NT as default supplier with a price 1.5 times of the item value + if(!oldsuppliers) + var/price = get_value(cargoitem) * 1.5 + var/list/sups = list() + sups["nt"] = list() + sups["nt"]["base_purchase_price"] = price + sups["nt"]["vars"] = list() + log_debug("SSCargo: Updating suppliers string to [json_encode(sups)]") + var/DBQuery/item_update_supl_query = dbcon.NewQuery("UPDATE ss13_cargo_items SET suppliers = '[json_encode(sups)]' WHERE id = [item_id]") + item_update_supl_query.Execute() + qdel(cargoitem) + + //Load the categories + var/DBQuery/category_query = dbcon.NewQuery("SELECT name, display_name, description, icon, price_modifier FROM ss13_cargo_categories WHERE deleted_at IS NULL ORDER BY order_by ASC") + category_query.Execute() + while(category_query.NextRow()) + log_debug("SSCargo: Loading Category: [category_query.item[1]]") + var/datum/cargo_category/cc = new() + cc.name = category_query.item[1] + cc.display_name = category_query.item[2] + cc.description = category_query.item[3] + cc.icon = category_query.item[4] + cc.price_modifier = text2num(category_query.item[5]) + + //Add the category to the cargo_categories list + cargo_categories[cc.name] = cc + + //Load the suppliers + var/DBQuery/supplier_query = dbcon.NewQuery("SELECT short_name, name, description, tag_line, shuttle_time, shuttle_price, available, price_modifier FROM ss13_cargo_suppliers WHERE deleted_at is NULL") + supplier_query.Execute() + while(supplier_query.NextRow()) + log_debug("SSCargo: Loading Supplier: [supplier_query.item[1]]") + var/datum/cargo_supplier/cs = new() + cs.short_name = supplier_query.item[1] + cs.name = supplier_query.item[2] + cs.description = supplier_query.item[3] + cs.tag_line = supplier_query.item[4] + cs.shuttle_time = text2num(supplier_query.item[5]) + cs.shuttle_price = text2num(supplier_query.item[6]) + cs.available = text2num(supplier_query.item[7]) + cs.price_modifier = text2num(supplier_query.item[8]) + + cargo_suppliers[cs.short_name] = cs + + //Load the items + var/DBQuery/item_query = dbcon.NewQuery("SELECT path, name, description, categories, suppliers, amount, access, container_type, groupable FROM ss13_cargo_items WHERE deleted_at is NULL ORDER BY order_by") + item_query.Execute() + while(item_query.NextRow()) + log_debug("SSCargo: Loading Item: [item_query.item[2]]") + var/itempath = text2path(item_query.item[1]) + if(!ispath(itempath)) + log_debug("SSCargo: Warning - Attempted to add item with invalid path: [item_query.item[2]] - [item_query.item[1]]") + continue + var/datum/cargo_item/ci = new() + try + ci.path = item_query.item[1] + ci.name = item_query.item[2] + ci.description = item_query.item[3] + ci.categories = json_decode(item_query.item[4]) + ci.suppliers = json_decode(item_query.item[5]) + ci.amount = text2num(item_query.item[6]) + ci.access = text2num(item_query.item[7]) //TODO: Maybe add the option to specify access as string instead of number + ci.container_type = item_query.item[8] + ci.groupable = text2num(item_query.item[9]) + catch(var/exception/e) + log_debug("SSCargo: Error when loading item: [e]") + qdel(ci) + continue + + //Check if a valid container is specified + if(!(ci.container_type == CARGO_CONTAINER_CRATE || ci.container_type == CARGO_CONTAINER_FREEZER || ci.container_type == CARGO_CONTAINER_BOX)) + log_debug("SScargo: Invalid container type specified for item - Aborting") + qdel(ci) + continue + + //Verify the suppliers exist + for(var/sup in ci.suppliers) + log_debug("SSCargo: Checking [sup]") + var/datum/cargo_supplier/cs = get_supplier_by_name(sup) + if(!cs) + log_debug("SSCargo: [sup] is not a valid supplier") + + //Setting the supplier + ci.suppliers[sup]["supplier_datum"] = cs + + //Add the item to the cargo_items list + cargo_items[ci.path] = ci + + //Log a message if no categories are specified + if(ci.categories.len == 0) + log_debug("SSCargo: No categories speicfied for item") + + //Add the item to the categories + for(var/category in ci.categories) + var/datum/cargo_category/cc = cargo_categories[category] + if(cc) //Check if the category exists + cc.items.Add(ci) + else + log_debug("SSCargo: Warning - Attempted to add item to category [category] that does not exist") + + log_debug("SSCargo: Loaded Item: [ci.name]") + return 1 + +//Loads the cargo data from JSON +/datum/controller/subsystem/cargo/proc/load_from_json() + var/list/cargoconfig = list() + try + cargoconfig = json_decode(return_file_text("config/cargo.json")) + catch(var/exception/e) + log_debug("SSCargo: Warning: Could not load config, as cargo.json is missing - [e]") + return + + //Reset the currently loaded data + reset_cargo() + + //Load the cargo categories + for (var/category in cargoconfig["categories"]) + log_debug("SSCargo: Loading Category: [category]") + var/datum/cargo_category/cc = new() + cc.name = cargoconfig["categories"][category]["name"] + cc.display_name = cargoconfig["categories"][category]["display_name"] + cc.description = cargoconfig["categories"][category]["description"] + cc.icon = cargoconfig["categories"][category]["icon"] + cc.price_modifier = cargoconfig["categories"][category]["price_modifier"] + + //Add the category to the cargo_categories list + cargo_categories[cc.name] = cc + + //Load the suppliers + for (var/supplier in cargoconfig["suppliers"]) + log_debug("SSCargo: Loading Supplier: [supplier]") + var/datum/cargo_supplier/cs = new() + cs.short_name = supplier + cs.name = cargoconfig["suppliers"][supplier]["name"] + cs.description = cargoconfig["suppliers"][supplier]["description"] + cs.tag_line = cargoconfig["suppliers"][supplier]["tag_line"] + cs.shuttle_time = cargoconfig["suppliers"][supplier]["shuttle_time"] + cs.shuttle_price = cargoconfig["suppliers"][supplier]["shuttle_price"] + cs.available = cargoconfig["suppliers"][supplier]["available"] + cs.price_modifier = cargoconfig["suppliers"][supplier]["price_modifier"] + + cargo_suppliers[cs.short_name] = cs + + //Load the cargoitems + for (var/item in cargoconfig["items"]) + log_debug("SSCargo: Loading Item: [item]") + var/itempath = text2path(item) + if(!ispath(itempath)) + log_debug("SSCargo: Warning - Attempted to add item with invalid path: [item]") + continue + var/datum/cargo_item/ci = new() + ci.path = item + ci.name = cargoconfig["items"][item]["name"] + ci.description = cargoconfig["items"][item]["description"] + ci.categories = cargoconfig["items"][item]["categories"] + ci.suppliers = cargoconfig["items"][item]["suppliers"] + ci.amount = cargoconfig["items"][item]["amount"] + ci.access = cargoconfig["items"][item]["access"] + ci.container_type = cargoconfig["items"][item]["container_type"] + ci.groupable = cargoconfig["items"][item]["groupable"] + log_debug("SSCargo: Loaded Item: [ci.name]") + + //Verify the suppliers exist + for(var/sup in ci.suppliers) + log_debug("SSCargo: Checking [sup]") + var/datum/cargo_supplier/cs = get_supplier_by_name(sup) + if(!cs) + log_debug("SSCargo: [sup] is not a valid supplier") + + //Setting the supplier + ci.suppliers[sup]["supplier_datum"] = cs + + //Add the item to the cargo_items list + cargo_items[ci.path] = ci + + //Add the item to the categories + for(var/category in ci.categories) + var/datum/cargo_category/cc = cargo_categories[category] + if(cc) //Check if the category exists + cc.items.Add(ci) + else + log_debug("SSCargo: Warning - Attempted to add item to category that does not exist") + return 1 + + +/* + Getting items, categories, suppliers and shipments +*/ +//Increments the orderid and returns it +/datum/controller/subsystem/cargo/proc/get_next_order_id() + . = ordernum + ordernum++ + return . + +//Gets the items from a category +/datum/controller/subsystem/cargo/proc/get_items_for_category(var/category) + var/datum/cargo_category/cc = cargo_categories[category] + if(cc) + return cc.get_item_list() + else + return list() + +//Gets the categories +/datum/controller/subsystem/cargo/proc/get_category_list() + var/list/category_list = list() + for (var/cat_name in cargo_categories) + var/datum/cargo_category/cc = cargo_categories[cat_name] + category_list.Add(list(cc.get_list())) + return category_list +//Get a category by name +/datum/controller/subsystem/cargo/proc/get_category_by_name(var/name) + return cargo_categories[name] + +//Gets a order by order id +/datum/controller/subsystem/cargo/proc/get_order_by_id(var/id) + for (var/datum/cargo_order/co in all_orders) + if(co.order_id == id) + return co + return null + +//Gets a supplier by name +/datum/controller/subsystem/cargo/proc/get_supplier_by_name(var/name) + return cargo_suppliers[name] + +//Gets all the shipments sent to / from the station +/datum/controller/subsystem/cargo/proc/get_shipment_list() + var/list/shipment_list = list() + for(var/datum/cargo_shipment/cs in cargo_shipments) + if(cs.get_list() != null) + shipment_list.Add(list(cs.get_list())) + return shipment_list + +//Get a shipment by shipment id +/datum/controller/subsystem/cargo/proc/get_shipment_by_id(var/id) + for(var/datum/cargo_shipment/cs in cargo_shipments) + if(cs.shipment_num == id) + return cs + return null + +/* + Submitting, Approving, Rejecting and Shipping Orders +*/ +//Gets the orders based on their status (submitted, approved, shipped) +/datum/controller/subsystem/cargo/proc/get_orders_by_status(var/status, var/data_list=0) + if(!status) + log_debug("SSCargo - get_orders_by_status has been called with a invalud status") + return list() + var/list/orders = list() + for (var/datum/cargo_order/co in all_orders) + if(co.status == status) + if(data_list) + orders.Add(list(co.get_list())) + else + orders.Add(co) + return orders +//Gets the value of orders based on their status, type is passed on to co.get_value +/datum/controller/subsystem/cargo/proc/get_orders_value_by_status(var/status, var/type=0) + if(!status) + log_debug("SSCargo - get_orders_value_by_status has been called with a invalud status") + return 0 + var/value = 0 + for (var/datum/cargo_order/co in all_orders) + if(co.status == status) + value += co.get_value(type) + return value +//Gets the suppliers of the orders of a specific type +/datum/controller/subsystem/cargo/proc/get_order_suppliers_by_status(var/status, var/pretty_names=0) + if(!status) + log_debug("SSCargo - get_order_suppliers_by_status has been called with a invalud status") + return list() + var/list/suppliers = list() + for(var/datum/cargo_order/co in all_orders) + if(co.status == status) + //Get the list of supplirs and add it to the suppliers list + for(var/supplier in co.get_supplier_list()) + if(pretty_names) + var/datum/cargo_supplier/cs = SScargo.cargo_suppliers[supplier] + suppliers[cs.short_name] = cs.name + else + suppliers[supplier] = supplier + return suppliers + +//Submits an order to cargo +/datum/controller/subsystem/cargo/proc/submit_order(var/datum/cargo_order/co) + co.status = "submitted" + co.time_submitted = worldtime2text() + co.order_id = get_next_order_id() + all_orders.Add(co) + return 1 + +//Approve a order - Returns a status message +/datum/controller/subsystem/cargo/proc/approve_order(var/datum/cargo_order/co, var/approved_by) + if(co.status == "submitted") + co.status = "approved" + co.time_approved = worldtime2text() + co.authorized_by = approved_by + return "The order has been approved" + else + return "The order could not be approved - Invalid Status" + +//Reject a order - Returns a status message +/datum/controller/subsystem/cargo/proc/reject_order(var/datum/cargo_order/co) + if(co.status == "submitted") + co.status = "rejected" + co.time_approved = worldtime2text() + return "The order has been rejected" + else + return "The order could not be rejected - Invalid Status" + + + + +//Checks if theorder can be shipped and marks it as shipped if possible +/datum/controller/subsystem/cargo/proc/ship_order(var/datum/cargo_order/co) + //Get the price cargo has to pay for the order + var/item_price = co.get_value(1) + + //Get the maximum shipment costs for the order + var/max_shipment_cost = co.get_max_shipment_cost() + + //Check if cargo has enough money to pay for the shipment of the item and the maximum shipment cost + if(item_price + max_shipment_cost > get_cargo_money()) + log_debug("SSCargo - Order could not be shipped. Insufficient money. [item_price] + [max_shipment_cost] > [get_cargo_money()]") + return 0 + + co.status = "shipped" + co.time_shipped = worldtime2text() + current_shipment.shipment_cost_purchase += item_price //Increase the price of the shipment + current_shipment.orders.Add(co) //Add the order to the order list + return 1 +//Generate a new cargo shipment +/datum/controller/subsystem/cargo/proc/new_shipment() + current_shipment = new() + shipmentnum ++ + cargo_shipments.Add(current_shipment) + current_shipment.shipment_num = shipmentnum +/* + Changing Settings +*/ +//Gets the current handlingfee +/datum/controller/subsystem/cargo/proc/get_handlingfee() + return cargo_handlingfee +// Sets the handling fee - Returns a status message +/datum/controller/subsystem/cargo/proc/set_handlingfee(var/fee) + if(!fee) + return "Unable to set handlingfee - Can not be NULL" + if(fee < cargo_handlingfee_min) + return "Unable to set handlingfee - Smaller than minimum: [cargo_handlingfee_min]" + if(fee > cargo_handlingfee_max) + return "Unable to set handlingfee - Higher than maximum: [cargo_handlingfee_max]" + if(cargo_handlingfee_change != 1) + return "Unable to set handlingfee - Changing the handlingfee is currently not possible" + cargo_handlingfee = fee + return + +//Gets the current crate fee +/datum/controller/subsystem/cargo/proc/get_cratefee() + return credits_per_crate +/* + Money Stuff +*/ +//Gets the current money on the cargo account +/datum/controller/subsystem/cargo/proc/get_cargo_money() + return supply_account.money +//Charges cargo. Accepts a text that should appear as charge and the numer of credits to charge +/datum/controller/subsystem/cargo/proc/charge_cargo(var/charge_text, var/charge_credits) + if(!supply_account) + log_debug("SSCargo - Warning Tried to charge supply account but supply acount doesnt exist") + return 0 + return charge_to_account(supply_account.account_number, "[commstation_name()] - Supply", "[charge_text]", "[commstation_name()] - Banking System", -charge_credits) +//Gets the pending shipment costs for the items that are about to be shipped to the station +/datum/controller/subsystem/cargo/proc/get_pending_shipment_cost(var/status="approved") + //Loop through all the orders marked as shipped and get the suppliers into a list of involved suppliers + var/list/suppliers = get_order_suppliers_by_status(status) + var/price = 0 + for(var/supplier in suppliers) + var/datum/cargo_supplier/cs = SScargo.cargo_suppliers[supplier] + if(cs) + price += cs.shuttle_price + return price +//Gets the pending shipment time for the items that are about to be shipped to the station +/datum/controller/subsystem/cargo/proc/get_pending_shipment_time(var/status="approved") + //Loop through all the orders marked as shipped and get the suppliers into a list of involved suppliers + var/list/suppliers = get_order_suppliers_by_status(status) + var/time = 0 + for(var/supplier in suppliers) + var/datum/cargo_supplier/cs = SScargo.cargo_suppliers[supplier] + if(cs) + time += cs.shuttle_time + return time + +/* + Shuttle Operations - Calling, Forcing, Canceling, Buying / Selling +*/ +//Calls the shuttle. Returns a status message +/datum/controller/subsystem/cargo/proc/shuttle_call(var/caller_name) + if(shuttle.at_station()) + if (shuttle.forbidden_atoms_check()) + . = "For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons." + else + movetime = 1200 //It always takes two minutes to get to centcom + shuttle.launch(src) + . = "Initiating launch sequence" + current_shipment.shuttle_recalled_by = caller_name + else + //Check if there is enough money in the cargo account for the current shipment + var/shipment_cost = get_pending_shipment_cost() + if( shipment_cost > get_cargo_money()) + . = "The supply shuttle could not be called. Insufficient Funds. [shipment_cost] Credits required" + else + //Create a new shipment if one does not exist already + if(!current_shipment) + new_shipment() + + //Set the shuttle movement time + current_shipment.shuttle_time = get_pending_shipment_time() + current_shipment.shuttle_fee = shipment_cost + + if(current_shipment.shuttle_time < 1200) + log_debug("SSCargo: Shuttle Time less than 1200: [current_shipment.shuttle_time] - Setting to 1200") + current_shipment.shuttle_time = 1200 + + movetime = current_shipment.shuttle_time + //Launch it + shuttle.launch(src) + . = "The supply shuttle has been called and will arrive in approximately [round(SScargo.movetime/600,1)] minutes." + current_shipment.shuttle_called_by = caller_name + return . + +//Cancels the shuttle. Can return a status message +/datum/controller/subsystem/cargo/proc/shuttle_cancel() + shuttle.cancel_launch(src) + +//Forces the shuttle. Can return a status message +/datum/controller/subsystem/cargo/proc/shuttle_force() + shuttle.force_launch(src) //To stop things being sent to centcomm which should not be sent to centcomm. Recursively checks for these types. /datum/controller/subsystem/cargo/proc/forbidden_atoms_check(atom/A) @@ -69,8 +579,9 @@ var/datum/controller/subsystem/cargo/SScargo if(.(B)) return 1 - //Sellin +//Sells stuff on the shuttle to centcom /datum/controller/subsystem/cargo/proc/sell() + //TODO: Only pay for specific stuff on the shuttle and not for everything else - Charge a cleanup fee for the rest var/area/area_shuttle = shuttle.get_location_area() if(!area_shuttle) return @@ -84,19 +595,10 @@ var/datum/controller/subsystem/cargo/SScargo if(istype(MA,/obj/structure/closet/crate)) callHook("sell_crate", list(MA, area_shuttle)) - points += points_per_crate - var/find_slip = 1 + current_shipment.shipment_cost_sell += credits_per_crate for(var/atom in MA) - // Sell manifests var/atom/A = atom - if(find_slip && istype(A,/obj/item/weapon/paper/manifest)) - var/obj/item/weapon/paper/manifest/slip = A - if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense - points += points_per_slip - find_slip = 0 - continue - // Sell phoron and platinum if(istype(A, /obj/item/stack)) var/obj/item/stack/P = A @@ -106,17 +608,26 @@ var/datum/controller/subsystem/cargo/SScargo qdel(MA) if(phoron_count) - points += phoron_count * points_per_phoron + current_shipment.shipment_cost_sell += phoron_count * credits_per_phoron if(plat_count) - points += plat_count * points_per_platinum + current_shipment.shipment_cost_sell += plat_count * credits_per_platinum -//Buyin + charge_cargo("Shipment #[current_shipment.shipment_num] - Income", -current_shipment.shipment_cost_sell) + current_shipment.generate_invoice() + current_shipment = null //Null the current shipment because its completed + +//Buys the item and places them on the shuttle +//Returns 0 if unsuccessful returns 1 if the shuttle can be sent /datum/controller/subsystem/cargo/proc/buy() - if(!shoppinglist.len) return + if(!current_shipment) + new_shipment() + + var/list/approved_orders = get_orders_by_status("approved",0) var/area/area_shuttle = shuttle.get_location_area() - if(!area_shuttle) return + if(!area_shuttle) + return 0 var/list/clear_turfs = list() @@ -131,60 +642,68 @@ var/datum/controller/subsystem/cargo/SScargo continue clear_turfs += T - for(var/S in shoppinglist) - if(!clear_turfs.len) break + for(var/datum/cargo_order/co in approved_orders) + if(!co) + break + + //Check if theres space to place the order + if(!clear_turfs.len) + log_debug("SSCargo - Order [co.order_id] could not be placed on the shuttle because the shuttle is full") + break + + //Check if the supplier is still active + for(var/datum/cargo_order_item/coi in co.items) + var/datum/cargo_supplier/csu = get_supplier_by_name(coi.supplier) + if(!csu) + log_debug("SSCargo - Order [co.order_id] could not be placed on the shuttle because supplier [coi.supplier] for item [coi.ci.name] is invalid") + break + if(!csu.available) + log_debug("SSCargo - Order [co.order_id] could not be placed on the shuttle because supplier [coi.supplier] for item [coi.ci.name] is unavailable") + break + + //Check if there is enough money to ship the order + if(!ship_order(co)) + break + var/i = rand(1,clear_turfs.len) var/turf/pickedloc = clear_turfs[i] clear_turfs.Cut(i,i+1) - var/datum/supply_order/SO = S - var/datum/supply_packs/SP = SO.object + //Spawn the crate + var/containertype = co.get_container_type() + var/obj/A = new containertype(pickedloc) - var/obj/A = new SP.containertype(pickedloc) - A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]" + //Label the crate + //TODO: Look into wrapping it in a NT paper + A.name = "[co.order_id] - [co.customer]" - //supply manifest generation begin + //Set the access requirement + if(co.required_access.len > 0) + A.req_access = co.required_access.Copy() - var/obj/item/weapon/paper/manifest/slip - if(!SP.contraband) - slip = new /obj/item/weapon/paper/manifest(A) - slip.is_copy = 0 - slip.info = "

[command_name()] Shipping Manifest



" - slip.info +="Order #[SO.ordernum]
" - slip.info +="Destination: [station_name]
" - slip.info +="[shoppinglist.len] PACKAGES IN THIS SHIPMENT
" - slip.info +="CONTENTS:

" - slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
" + //Now calculate the aliquot shipment cost for the orders and add it to each order + var/aliquot_shipment_cost = current_shipment.shuttle_fee / current_shipment.orders.len + for(var/datum/cargo_order/co in current_shipment.orders) + co.partial_shipment_fee = aliquot_shipment_cost - shoppinglist.Cut() - return + return 1 diff --git a/code/datums/cargo.dm b/code/datums/cargo.dm new file mode 100644 index 00000000000..f133b3df893 --- /dev/null +++ b/code/datums/cargo.dm @@ -0,0 +1,446 @@ +/* + A item orderable via cargo +*/ +/datum/cargo_item + var/path = null //Path of the item + var/name = "Cargo Item" //Name of the item + var/description = "You should not see this" //Description of the item + var/list/categories = list() //List of categories this item appears in + var/list/suppliers = list() //List of supliers and their prices + var/amount = 1 //Amount of items in the crate + var/access = null //What access requirement should be added to the container + var/container_type = "crate" //crate or box + var/groupable = 1 //If the item can be thrown into the same container as other items + +//Gets a list of the cargo item - To be json encoded +/datum/cargo_item/proc/get_list() + var/list/data = list() + data["name"] = name + data["path"] = path + data["description"] = description + data["categories"] = categories + data["amount"] = amount + var/suppliers_list = list() + for(var/supplier in suppliers) + var/list/sd = list() + var/datum/cargo_supplier/cs = suppliers[supplier]["supplier_datum"] + if(!cs) + log_debug("Cargo - Invalid supplier [supplier] encountered when loading item [name] with path [path]") + continue + sd["short_name"] = cs.short_name + sd["name"] = cs.name + sd["available"] = cs.available + sd["price_modifier"] = cs.price_modifier + sd["base_purchase_price"] = suppliers[supplier]["base_purchase_price"] + sd["vars"] = suppliers[supplier]["vars"] + sd["adjusted_price"] = sd["base_purchase_price"] * sd["price_modifier"] + //Add category adjustments + for(var/category in categories) + var/datum/cargo_category/cc = SScargo.get_category_by_name(category) + if(cc) + sd["adjusted_price"] *= cc.price_modifier + suppliers_list[supplier] = sd + data["suppliers"] = suppliers_list + return data + + +/* + A supplier of items +*/ +/datum/cargo_supplier + var/short_name = "" //Short name of the cargo supplier + var/name = "" //Long name of the cargo supplier + var/description = "" //Description of the supplier + var/tag_line = "" //Tag line of the supplier + var/shuttle_time = 0 //Time the shuttle takes to get to the supplier + var/shuttle_price = 0 //Price to call the shuttle + var/available = 1 //If the supplier is available + var/price_modifier = 1 //Price modifier for the supplier +//Gets a list of supplier - to be json encoded +/datum/cargo_supplier/proc/get_list() + var/list/data = list() + data["short_name"] = short_name + data["name"] = name + data["description"] = description + data["tag_line"] = tag_line + data["shuttle_time"] = shuttle_time + data["shuttle_price"] = shuttle_price + data["available"] = available + data["price_modifier"] = price_modifier + return data + + +/* + A category displayed in the cargo order app +*/ +/datum/cargo_category + var/name = "cargo_category" //Name of the category + var/display_name = "Cargo Category" + var/description = "You should not see this" //Description of the Category + var/icon = "gear" //NanoUI Icon for the category + var/price_modifier = 1 //Price Modifier for the category + var/list/items = list() //List of items in the category + +// Gets a list of the cargo category - to be json encoded +/datum/cargo_category/proc/get_list() + var/list/data = list() + data["name"] = name + data["display_name"] = display_name + data["description"] = description + data["icon"] = icon + data["price_modifier"] = price_modifier + return data + +// Gets a list of the items in the cargo category - to be json encoded +/datum/cargo_category/proc/get_item_list() + var/list/item_list = list() + for(var/datum/cargo_item/ci in items) + item_list.Add(list(ci.get_list())) + return item_list + +/* + A order placed in the cargo order app. + Contains multiple order items +*/ +/datum/cargo_order + var/list/items = list() //List of cargo_order_items in the order + var/order_id = 0 //ID of the order + var/price = 0 //Total price of the order + var/item_id = 1 //Current id of the item in the order + var/item_num = 0 //Numer of items in the container - Used to limit the items in the crate + var/status = "basket" //Status of the order: basket - Adding items, submitted - Submitted to cargo, approved - Order sent to suppliers, rejected - Order has been denied, shipped - Has been shipped to the station, delivered - Order has been delivered + var/container_type = "" //Type of the container for the order - cate, box + var/list/required_access = list() //Access required to unlock the crate + var/can_add_items = 1 //If new items can be added to the order + var/customer = null //Person that ordered the items + var/authorized_by = null //Person that authorized the order + var/received_by = null //Person the order has been delivered to by cargo + var/time_submitted = null //Time the order has been sent to cargo + var/time_approved = null //Time the order has been approved by cargo + var/time_shipped = null //Time the order has been shipped to the station + var/time_delivered = null //Time the order has been delivered + var/tracking_code = null //Use this code with the order ID to get details about the order + var/partial_shipment_fee = 0 //Partial Shipment Fee for the order + var/reason = null //Reason for the order + +//Gets the tracking code for the order. Generates one if it does not exist already +/datum/cargo_order/proc/get_tracking_code() + if(!tracking_code) + tracking_code = rand(1000,9999) + return tracking_code + +// Returns a list of the items in the order - Formated as list to be json_encoded +/datum/cargo_order/proc/get_item_list() + var/list/item_list = list() + for (var/datum/cargo_order_item/coi in items) + item_list.Add(list(coi.get_list())) + return item_list + +// Gets a list of the order data - Formated as list to be json_encoded +/datum/cargo_order/proc/get_list() + var/list/data = list() + data["order_id"] = order_id + data["tracking_code"] = get_tracking_code() + data["price"] = get_value(2) + data["price_customer"] = get_value(0) + data["price_cargo"] = get_value(1) + data["status"] = get_order_status(0) + data["status_pretty"] = get_order_status(1) + data["customer"] = customer + data["authorized_by"] = authorized_by + data["received_by"] = received_by + data["time_submitted"] = time_submitted + data["time_approved"] = time_approved + data["time_shipped"] = time_shipped + data["time_delivered"] = time_delivered + data["items"] = get_item_list() + data["shipment_cost"] = partial_shipment_fee + data["shipment_cost_max"] = get_max_shipment_cost() + return data + +//Adds a item to a order. Returns a status message +/datum/cargo_order/proc/add_item(var/datum/cargo_order_item/coi) + if(!coi) + return "Unable to add item - Internal Error" + + //Check if the container type of the added item matches the one of the current order + if(container_type == "") + container_type = coi.ci.container_type + else if (container_type != coi.ci.container_type) + return "Unable to add item - Different container required" //You can only add items with the same container type to the order + + //Check if more items can be added to the order + if(!can_add_items) + return "Unable to add item - Order can not contain more items" + + if(!coi.ci.groupable) //The item is not groupable with other items and needs to be ordered on its own + if(get_item_count() > 0) // There are already other items in the order. -> Reject it + return "Unable to add item - Item can not be grouped and must be ordered separately" + else //No item in the order. Add it and set can_add_items to 0 + can_add_items = 0 + + //Check if there is space in the container + if(item_num + coi.ci.amount > get_container_storage()) + return "Unable to add item - Container full" + + //Set item id of coi and increment item_id of co + coi.item_id = item_id + item_id += 1 + + //Increment the item number + item_num += coi.ci.amount + + //Add coi to ordered item + items.Add(coi) + price += coi.price + + //Update the access requirement of the order + if(coi.ci.access) + required_access.Add(coi.ci.access) + + return "Item successfully added" + +//Removes a item from a order - Returns a status message +/datum/cargo_order/proc/remove_item(var/remove_item_id) + //Find the item with the specified id in the items list + for (var/datum/cargo_order_item/coi in items) + if(coi) + if(coi.item_id == remove_item_id) + items.Remove(coi) + price -= coi.price + item_num -= coi.ci.amount + qdel(coi) + return "Item removed successfully" + return "Unable to remove item - Internal Error 608" + +// Returns the value of the order +/datum/cargo_order/proc/get_value(var/type=0) + //Type specifies if the price cargo has to pay or the price the customer has to be should be returned + // 0 - Price the customer has to pay + // 1 - Price cargo has to pay + // 2 - Just the value of the items in the crate + switch(type) + if(0) + //The price of the contents of the crate + the price for the crate + the handling fee + the partial shipment fee + return price + SScargo.get_cratefee() + SScargo.get_handlingfee() + partial_shipment_fee + if(1) + //The price of the contents of the crate + the price of the crate + return price + SScargo.get_cratefee() + if(2) + //Just the value of the items in the crate + return price + else + //As a fallback, return the value of the items + return price + +// Returns the number of items in the order +/datum/cargo_order/proc/get_item_count() + return items.len + +// Returns the type of the required container for the order +/datum/cargo_order/proc/get_container_type() + switch(container_type) + if(CARGO_CONTAINER_CRATE) + if(required_access.len > 0) + return /obj/structure/closet/crate/secure + else + return /obj/structure/closet/crate + if(CARGO_CONTAINER_BOX) + if(required_access.len > 0) + return /obj/structure/closet/crate/secure/large + else + return /obj/structure/largecrate + if(CARGO_CONTAINER_FREEZER) + return /obj/structure/closet/crate/freezer + else + log_debug("Cargo: Tried to get container type for invalid container [container_type]") + return /obj/structure/largecrate +// Returns the numer of items that can be stored in the container +/datum/cargo_order/proc/get_container_storage() + switch(container_type) + if(CARGO_CONTAINER_CRATE) + return 40 //Thats the default storage capacity of a crate + if(CARGO_CONTAINER_FREEZER) + return 40 + if(CARGO_CONTAINER_BOX) + return 5 //You can fit 5 larger items into a box + else + log_debug("Cargo: Tried to get storage size for invalid container [container_type]") + return 0 //Something went wrong + +// Gets the list of the suppliers involved in the order +/datum/cargo_order/proc/get_supplier_list() + var/list/supplier_list = list() + for(var/datum/cargo_order_item/coi in items) + supplier_list[coi.supplier] = coi.supplier + return supplier_list + +// Gets the maximal shipment cost for the item +/datum/cargo_order/proc/get_max_shipment_cost() + var/list/supplier_list = get_supplier_list() + var/cost = 0 + for(var/supplier in supplier_list) + var/datum/cargo_supplier/cs = SScargo.cargo_suppliers[supplier] + if(cs) + cost += cs.shuttle_price + return cost + +// Gets the order status +/datum/cargo_order/proc/get_order_status(var/pretty=1) + if(pretty) + switch(status) + if("submitted") + return "Submitted to Cargo" + if("approved") + return "Approved" + if("rejected") + return "Rejected" + if("shipped") + return "Shipped to the Station" + if("delivered") + return "Delivered" + else + return "Unknown Status" + + else + return status + +// Returns a HTML to be printed for the order +/datum/cargo_order/proc/get_report() + var/list/order_data = list() + order_data += "

Order [order_id]

" + order_data += "
" + //List the personell involved in the order + order_data += "Ordered by: [customer]
" + order_data += "Submitted at: [time_submitted]
" + if(authorized_by) + order_data += "Authorized by: [authorized_by]
" + order_data += "Approved at: [time_approved]
" + if(time_shipped) + order_data += "Shipped at: [time_shipped]
" + if(received_by) + order_data += "Received by:
" + order_data += "Delivered at: [time_delivered]
" + order_data += "
" + order_data += "Order ID: [order_id]
" + order_data += "Tracking Code: [get_tracking_code()]
" + order_data += "Order Status: [get_order_status(1)]
" + order_data += "
" + if(required_access.len) + order_data += "Required Access:
" + order_data += "" + order_data += "
" + order_data += "Order Fees:
" + order_data += "" + + return order_data.Join("") + + +/* + A cargo order item. Part of a category. + specifies the item, the supplier and the price of the item +*/ +/datum/cargo_order_item + var/datum/cargo_item/ci //Item that has been ordered + var/datum/cargo_supplier/cs //Supplier the item has been ordered from + var/supplier //Supplier the item has been ordered from + var/price //Price of the item with the given supplier + var/item_id //Item id in the order + //TODO: Maybe add the option to set a fake item for traitors here -> So that cargo cant see what they are really ordering + +//Calculate Price +/datum/cargo_order_item/proc/calculate_price() + price = ci.suppliers[supplier]["base_purchase_price"] + //Add suppler modifier + price *= cs.price_modifier + for(var/category in ci.categories) + var/datum/cargo_category/cc = SScargo.get_category_by_name(category) + if(cc) + price *= cc.price_modifier + return price + +// Gets a list of the cargo order item - to be json encoded +/datum/cargo_order_item/proc/get_list() + var/list/data = list() + data["name"] = ci.name + data["supplier"] = supplier + data["supplier_name"] = cs.name + data["price"] = price + data["item_id"] = item_id + return data + +/datum/cargo_order_item/Destroy() + ci = null + cs = null + return ..() + + +/* + A shipment sent to the station. Contains multiple orders +*/ +/datum/cargo_shipment + var/list/orders = list() //List of orders in that shipment + var/shipment_num //Number of the shipment + var/shipment_cost_sell = 0//The amount of money cargo got for the shipment + var/shipment_cost_purchase = 0//The amount of money cargo paid for the shipment + var/shipment_invoice = null//The invoice for the shipment (detailing the expenses ,credits received and charges) + var/shuttle_fee//The shuttle fee at the time of calling it + var/shuttle_time //The time the shuttle took to get to the station + var/shuttle_called_by //The person that called the shuttle + var/shuttle_recalled_by //The person that recalled the shuttle + var/completed = 0 + +/datum/cargo_shipment/proc/get_list(var/shipment_completion = 1) + if(shipment_completion != completed) + return null + else + var/list/data = list() + data["shipment_num"] = shipment_num + data["shipment_cost_sell"] = shipment_cost_sell + data["shipment_cost_purchase"] = shipment_cost_purchase + data["shipment_invoice"] = shipment_invoice + data["shuttle_fee"] = shuttle_fee + data["shuttle_time"] = shuttle_time + data["shuttle_called_by"] = shuttle_called_by + data["shuttle_recalled_by"] = shuttle_recalled_by + data["invoice"] = get_invoice() + return data + +// Generates the invoice at the time of shipping +/datum/cargo_shipment/proc/generate_invoice() + var/list/invoice_data = list() + invoice_data += "One day
" + invoice_data += "This will contain the invoice
" + invoice_data += "Right now its just a placeholder
" + invoice_data += "Shipment num: [shipment_num]
" + invoice_data += "shipment cost sell: [shipment_cost_sell]
" + invoice_data += "shipment cost purchse: [shipment_cost_purchase]
" + invoice_data += "shuttle fee: [shuttle_fee]
" + invoice_data += "shuttle time: [shuttle_time]
" + invoice_data += "shuttle called by: [shuttle_called_by]
" + invoice_data += "shuttle recalled by: [shuttle_recalled_by]
" + + shipment_invoice = invoice_data.Join("") + completed = 1 + return shipment_invoice + +// Returns the invoice. Generates it if it does not exist +/datum/cargo_shipment/proc/get_invoice() + if(!shipment_invoice) + if(completed == 1) + generate_invoice() + else + return "Invoice Unavailable. Shipment not completed." + return shipment_invoice \ No newline at end of file diff --git a/code/game/machinery/computer/supply.dm b/code/game/machinery/computer/supply.dm deleted file mode 100644 index f73aea65a5c..00000000000 --- a/code/game/machinery/computer/supply.dm +++ /dev/null @@ -1,416 +0,0 @@ -/obj/machinery/computer/supplycomp - name = "supply control console" - icon = 'icons/obj/computer.dmi' - - icon_screen = "supply" - light_color = LIGHT_COLOR_ORANGE - req_access = list(access_cargo) - circuit = /obj/item/weapon/circuitboard/supplycomp - var/temp = null - var/reqtime = 0 //Cooldown for requisitions - Quarxink - var/hacked = 0 - var/can_order_contraband = 0 - var/last_viewed_group = "categories" - -/obj/machinery/computer/ordercomp - name = "supply ordering console" - icon = 'icons/obj/computer.dmi' - icon_screen = "request" - light_color = LIGHT_COLOR_ORANGE - circuit = /obj/item/weapon/circuitboard/ordercomp - var/temp = null - var/reqtime = 0 //Cooldown for requisitions - Quarxink - var/last_viewed_group = "categories" - -/obj/machinery/computer/ordercomp/attack_ai(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/supplycomp/attack_ai(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/ordercomp/attack_hand(var/mob/user as mob) - if(..()) - return - user.set_machine(src) - var/dat - if(temp) - dat = temp - else - var/datum/shuttle/ferry/supply/shuttle = SScargo.shuttle - if (shuttle) - dat += {"
Supply shuttle
- Location: [shuttle.has_arrive_time() ? "Moving to station ([shuttle.eta_minutes()] Mins.)":shuttle.at_station() ? "Docked":"Away"]
-
Supply points: [SScargo.points]
-
\nRequest items

- View approved orders

- View requests

- Close"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/ordercomp/Topic(href, href_list) - if(..()) - return 1 - - if( isturf(loc) && (in_range(src, usr) || istype(usr, /mob/living/silicon)) ) - usr.set_machine(src) - - if(href_list["order"]) - if(href_list["order"] == "categories") - //all_supply_groups - //Request what? - last_viewed_group = "categories" - temp = "Supply points: [SScargo.points]
" - temp += "Main Menu


" - temp += "Select a category

" - for(var/supply_group_name in all_supply_groups ) - temp += "[supply_group_name]
" - else - last_viewed_group = href_list["order"] - temp = "Supply points: [SScargo.points]
" - temp += "Back to all categories


" - temp += "Request from: [last_viewed_group]

" - for(var/supply_name in SScargo.supply_packs ) - var/datum/supply_packs/N = SScargo.supply_packs[supply_name] - if(N.hidden || N.contraband || N.group != last_viewed_group) continue //Have to send the type instead of a reference to - temp += "[supply_name] Cost: [N.cost]
" //the obj because it would get caught by the garbage - - else if (href_list["doorder"]) - if(world.time < reqtime) - for(var/mob/V in hearers(src)) - V.show_message("[src]'s monitor flashes, \"[world.time - reqtime] seconds remaining until another requisition form may be printed.\"") - return - - //Find the correct supply_pack datum - var/datum/supply_packs/P = SScargo.supply_packs[href_list["doorder"]] - if(!istype(P)) return - - var/timeout = world.time + 600 - var/reason = sanitize(input(usr,"Reason:","Why do you require this item?","") as null|text) - if(world.time > timeout) return - if(!reason) return - - var/idname = "*None Provided*" - var/idrank = "*None Provided*" - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - idname = H.get_authentification_name() - idrank = H.get_assignment() - else if(issilicon(usr)) - idname = usr.real_name - - SScargo.ordernum++ - var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc) - reqform.name = "Requisition Form - [P.name]" - reqform.info += "

[station_name] Supply Requisition Form


" - reqform.info += "INDEX: #[SScargo.ordernum]
" - reqform.info += "REQUESTED BY: [idname]
" - reqform.info += "RANK: [idrank]
" - reqform.info += "REASON: [reason]
" - reqform.info += "SUPPLY CRATE TYPE: [P.name]
" - reqform.info += "ACCESS RESTRICTION: [get_access_desc(P.access)]
" - reqform.info += "CONTENTS:
" - reqform.info += P.manifest - reqform.info += "
" - reqform.info += "STAMP BELOW TO APPROVE THIS REQUISITION:
" - - reqform.update_icon() //Fix for appearing blank when printed. - reqtime = (world.time + 5) % 1e5 - - //make our supply_order datum - var/datum/supply_order/O = new /datum/supply_order() - O.ordernum = SScargo.ordernum - O.object = P - O.orderedby = idname - SScargo.requestlist += O - - temp = "Thanks for your request. The cargo team will process it as soon as possible.
" - temp += "
Back Main Menu" - - else if (href_list["vieworders"]) - temp = "Current approved orders:

" - for(var/S in SScargo.shoppinglist) - var/datum/supply_order/SO = S - temp += "[SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
" - temp += "
OK" - - else if (href_list["viewrequests"]) - temp = "Current requests:

" - for(var/S in SScargo.requestlist) - var/datum/supply_order/SO = S - temp += "#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby]
" - temp += "
OK" - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/supplycomp/attack_hand(var/mob/user as mob) - if(!allowed(user)) - user << "Access Denied." - return - - if(..()) - return - user.set_machine(src) - post_signal("supply") - var/dat - if (temp) - dat = temp - else - var/datum/shuttle/ferry/supply/shuttle = SScargo.shuttle - if (shuttle) - dat += "
Supply shuttle
" - dat += "\nLocation: " - if (shuttle.has_arrive_time()) - dat += "In transit ([shuttle.eta_minutes()] Mins.)
" - else - if (shuttle.at_station()) - if (shuttle.docking_controller) - switch(shuttle.docking_controller.get_docking_status()) - if ("docked") dat += "Docked at station
" - if ("undocked") dat += "Undocked from station
" - if ("docking") dat += "Docking with station [shuttle.can_force()? "Force Launch" : ""]
" - if ("undocking") dat += "Undocking from station [shuttle.can_force()? "Force Launch" : ""]
" - else - dat += "Station
" - - if (shuttle.can_launch()) - dat += "Send away" - else if (shuttle.can_cancel()) - dat += "Cancel launch" - else - dat += "*Shuttle is busy*" - dat += "
\n
" - else - dat += "Away
" - if (shuttle.can_launch()) - dat += "Request supply shuttle" - else if (shuttle.can_cancel()) - dat += "Cancel request" - else - dat += "*Shuttle is busy*" - dat += "
\n
" - - - dat += {"
\nSupply points: [SScargo.points]
\n
- \nOrder items
\n
- \nView requests
\n
- \nView orders
\n
- \nClose"} - - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/supplycomp/emag_act(var/remaining_charges, var/mob/user) - if(!hacked) - user << "Special supplies unlocked." - hacked = 1 - return 1 - -/obj/machinery/computer/supplycomp/Topic(href, href_list) - if(!SScargo) - world.log << "## ERROR: Eek. The SScargo controller datum is missing somehow." - return - var/datum/shuttle/ferry/supply/shuttle = SScargo.shuttle - if (!shuttle) - world.log << "## ERROR: Eek. The supply/shuttle datum is missing somehow." - return - if(..()) - return 1 - - if(isturf(loc) && ( in_range(src, usr) || istype(usr, /mob/living/silicon) ) ) - usr.set_machine(src) - - //Calling the shuttle - if(href_list["send"]) - if(shuttle.at_station()) - if (shuttle.forbidden_atoms_check()) - temp = "For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.

OK" - else - shuttle.launch(src) - temp = "Initiating launch sequence. \[Force Launch\]

OK" - else - shuttle.launch(src) - temp = "The supply shuttle has been called and will arrive in approximately [round(SScargo.movetime/600,1)] minutes.

OK" - post_signal("supply") - - if (href_list["force_send"]) - shuttle.force_launch(src) - - if (href_list["cancel_send"]) - shuttle.cancel_launch(src) - - else if (href_list["order"]) - //if(!shuttle.idle()) return //this shouldn't be necessary it seems - if(href_list["order"] == "categories") - //all_supply_groups - //Request what? - last_viewed_group = "categories" - temp = "Supply points: [SScargo.points]
" - temp += "Main Menu


" - temp += "Select a category

" - for(var/supply_group_name in all_supply_groups ) - temp += "[supply_group_name]
" - else - last_viewed_group = href_list["order"] - temp = "Supply points: [SScargo.points]
" - temp += "Back to all categories


" - temp += "Request from: [last_viewed_group]

" - for(var/supply_name in SScargo.supply_packs ) - var/datum/supply_packs/N = SScargo.supply_packs[supply_name] - if((N.hidden && !hacked) || (N.contraband && !can_order_contraband) || N.group != last_viewed_group) continue //Have to send the type instead of a reference to - temp += "[supply_name] Cost: [N.cost]
" //the obj because it would get caught by the garbage - - /*temp = "Supply points: [SScargo.points]


Request what?

" - - for(var/supply_name in SScargo.supply_packs ) - var/datum/supply_packs/N = SScargo.supply_packs[supply_name] - if(N.hidden && !hacked) continue - if(N.contraband && !can_order_contraband) continue - temp += "[supply_name] Cost: [N.cost]
" //the obj because it would get caught by the garbage - temp += "
OK"*/ - - else if (href_list["doorder"]) - if(world.time < reqtime) - for(var/mob/V in hearers(src)) - V.show_message("[src]'s monitor flashes, \"[world.time - reqtime] seconds remaining until another requisition form may be printed.\"") - return - - //Find the correct supply_pack datum - var/datum/supply_packs/P = SScargo.supply_packs[href_list["doorder"]] - if(!istype(P)) return - - var/timeout = world.time + 600 - var/reason = sanitize(input(usr,"Reason:","Why do you require this item?","") as null|text) - if(world.time > timeout) return - if(!reason) return - - var/idname = "*None Provided*" - var/idrank = "*None Provided*" - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - idname = H.get_authentification_name() - idrank = H.get_assignment() - else if(issilicon(usr)) - idname = usr.real_name - - SScargo.ordernum++ - var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc) - reqform.name = "Requisition Form - [P.name]" - reqform.info += "

[station_name] Supply Requisition Form


" - reqform.info += "INDEX: #[SScargo.ordernum]
" - reqform.info += "REQUESTED BY: [idname]
" - reqform.info += "RANK: [idrank]
" - reqform.info += "REASON: [reason]
" - reqform.info += "SUPPLY CRATE TYPE: [P.name]
" - reqform.info += "ACCESS RESTRICTION: [get_access_desc(P.access)]
" - reqform.info += "CONTENTS:
" - reqform.info += P.manifest - reqform.info += "
" - reqform.info += "STAMP BELOW TO APPROVE THIS REQUISITION:
" - - reqform.update_icon() //Fix for appearing blank when printed. - reqtime = (world.time + 5) % 1e5 - - //make our supply_order datum - var/datum/supply_order/O = new /datum/supply_order() - O.ordernum = SScargo.ordernum - O.object = P - O.orderedby = idname - SScargo.requestlist += O - - temp = "Order request placed.
" - temp += "
Back | Main Menu | Authorize Order" - - else if(href_list["confirmorder"]) - //Find the correct supply_order datum - var/ordernum = text2num(href_list["confirmorder"]) - var/datum/supply_order/O - var/datum/supply_packs/P - temp = "Invalid Request" - for(var/i=1, i<=SScargo.requestlist.len, i++) - var/datum/supply_order/SO = SScargo.requestlist[i] - if(SO.ordernum == ordernum) - O = SO - P = O.object - if(SScargo.points >= P.cost) - SScargo.requestlist.Cut(i,i+1) - SScargo.points -= P.cost - SScargo.shoppinglist += O - temp = "Thanks for your order.
" - temp += "
Back Main Menu" - else - temp = "Not enough supply points.
" - temp += "
Back Main Menu" - break - - else if (href_list["vieworders"]) - temp = "Current approved orders:

" - for(var/S in SScargo.shoppinglist) - var/datum/supply_order/SO = S - temp += "#[SO.ordernum] - [SO.object.name] approved by [SO.orderedby][SO.comment ? " ([SO.comment])":""]
"// (Cancel)
" - temp += "
OK" -/* - else if (href_list["cancelorder"]) - var/datum/supply_order/remove_supply = href_list["cancelorder"] - supply_shuttle_shoppinglist -= remove_supply - supply_shuttle_points += remove_supply.object.cost - temp += "Canceled: [remove_supply.object.name]


" - - for(var/S in supply_shuttle_shoppinglist) - var/datum/supply_order/SO = S - temp += "[SO.object.name] approved by [SO.orderedby][SO.comment ? " ([SO.comment])":""] (Cancel)
" - temp += "
OK" -*/ - else if (href_list["viewrequests"]) - temp = "Current requests:

" - for(var/S in SScargo.requestlist) - var/datum/supply_order/SO = S - temp += "#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby] Approve Remove
" - - temp += "
Clear list" - temp += "
OK" - - else if (href_list["rreq"]) - var/ordernum = text2num(href_list["rreq"]) - temp = "Invalid Request.
" - for(var/i=1, i<=SScargo.requestlist.len, i++) - var/datum/supply_order/SO = SScargo.requestlist[i] - if(SO.ordernum == ordernum) - SScargo.requestlist.Cut(i,i+1) - temp = "Request removed.
" - break - temp += "
Back Main Menu" - - else if (href_list["clearreq"]) - SScargo.requestlist.Cut() - temp = "List cleared.
" - temp += "
OK" - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/supplycomp/proc/post_signal(var/command) - - var/datum/radio_frequency/frequency = SSradio.return_frequency(1435) - - if(!frequency) return - - var/datum/signal/status_signal = new - status_signal.source = src - status_signal.transmission_method = 1 - status_signal.data["command"] = command - - frequency.post_signal(src, status_signal) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 32595ebf2bc..34c98d766ac 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -397,30 +397,13 @@ supplyData["shuttle_moving"] = shuttle.has_arrive_time() supplyData["shuttle_eta"] = shuttle.eta_minutes() supplyData["shuttle_loc"] = shuttle.at_station() ? "Station" : "Dock" - var/supplyOrderCount = 0 - var/supplyOrderData[0] - for(var/S in SScargo.shoppinglist) - var/datum/supply_order/SO = S - - supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.orderedby, "Comment" = html_encode(SO.comment)) - if(!supplyOrderData.len) - supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null) - - supplyData["approved"] = supplyOrderData - supplyData["approved_count"] = supplyOrderCount - - var/requestCount = 0 - var/requestData[0] - for(var/S in SScargo.requestlist) - var/datum/supply_order/SO = S - requestCount++ - requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.orderedby, "Comment" = html_encode(SO.comment)) - if(!requestData.len) - requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null) - - supplyData["requests"] = requestData - supplyData["requests_count"] = requestCount + var/list/approved_orders = SScargo.get_orders_by_status("approved",1) + supplyData["approved"] = approved_orders + supplyData["approved_count"] = approved_orders.len + var/list/requested_orders = SScargo.get_orders_by_status("submitted",1) + supplyData["requests"] = requested_orders + supplyData["requests_count"] = requested_orders.len values["supply"] = supplyData diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm index 39ec0ee0dff..6b123490756 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm @@ -142,11 +142,6 @@ name = T_BOARD("disease splicer") build_path = /obj/machinery/computer/diseasesplicer -/obj/item/weapon/circuitboard/ordercomp - name = T_BOARD("supply ordering console") - build_path = /obj/machinery/computer/ordercomp - origin_tech = list(TECH_DATA = 2) - /obj/item/weapon/circuitboard/mining_shuttle name = T_BOARD("mining shuttle console") build_path = /obj/machinery/computer/shuttle_control/mining diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 22cf2e50ac3..3c709c21988 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -137,7 +137,6 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 1, 5, 15), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "PDA Spam", /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), 0, 25, 50), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Shipping Error", /datum/event/shipping_error , 30, list(ASSIGNMENT_ANY = 2), 0), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation", /datum/event/infestation, 60, list(ASSIGNMENT_JANITOR = 20, ASSIGNMENT_SECURITY = 10)), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 75, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_GARDENER = 20)), diff --git a/code/modules/events/shipping_error.dm b/code/modules/events/shipping_error.dm deleted file mode 100644 index 45d6bdcfeaa..00000000000 --- a/code/modules/events/shipping_error.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/event/shipping_error/start() - var/datum/supply_order/O = new /datum/supply_order() - O.ordernum = SScargo.ordernum - O.object = SScargo.supply_packs[pick(SScargo.supply_packs)] - O.orderedby = random_name(pick(MALE,FEMALE), species = "Human") - SScargo.shoppinglist += O diff --git a/code/modules/modular_computers/computers/subtypes/preset_console.dm b/code/modules/modular_computers/computers/subtypes/preset_console.dm index 3808716880e..36bf54a6d17 100644 --- a/code/modules/modular_computers/computers/subtypes/preset_console.dm +++ b/code/modules/modular_computers/computers/subtypes/preset_console.dm @@ -59,7 +59,12 @@ _app_preset_name = "civilian" enrolled = 1 -ERT +// Supply +/obj/item/modular_computer/console/preset/supply/ + _app_preset_name = "supply" + enrolled = 1 + +// ERT /obj/item/modular_computer/console/preset/ert/install_default_hardware() ..() ai_slot = new/obj/item/weapon/computer_hardware/ai_slot(src) diff --git a/code/modules/modular_computers/file_system/programs/app_presets.dm b/code/modules/modular_computers/file_system/programs/app_presets.dm index e2c4d3544ae..9347e80c0eb 100644 --- a/code/modules/modular_computers/file_system/programs/app_presets.dm +++ b/code/modules/modular_computers/file_system/programs/app_presets.dm @@ -1,7 +1,7 @@ /datum/modular_computer_app_presets var/name = "default_preset" var/display_name = "default preset" - var/description = "Description of the preset" + var/description = "Description of the preset." var/available = 0 /datum/modular_computer_app_presets/proc/return_install_programs() return list() @@ -9,7 +9,7 @@ /datum/modular_computer_app_presets/all name = "all" display_name = "All Programs" - description = "Contains all Progams" + description = "Contains all programs." available = 0 /datum/modular_computer_app_presets/all/return_install_programs() var/list/_prg_list = list() @@ -21,7 +21,7 @@ /datum/modular_computer_app_presets/engineering name = "engineering" display_name = "Engineering" - description = "Contains the most common engineering Programs" + description = "Contains the most common engineering programs." available = 1 /datum/modular_computer_app_presets/engineering/return_install_programs() var/list/_prg_list = list( @@ -39,7 +39,7 @@ /datum/modular_computer_app_presets/medical name = "medical" display_name = "Medical" - description = "Contains the most common medical Programs" + description = "Contains the most common medical programs." available = 1 /datum/modular_computer_app_presets/medical/return_install_programs() var/list/_prg_list = list( @@ -52,7 +52,7 @@ /datum/modular_computer_app_presets/research name = "research" display_name = "Research" - description = "Contains the most common research Programs" + description = "Contains the most common research programs." available = 1 /datum/modular_computer_app_presets/research/return_install_programs() var/list/_prg_list = list( @@ -67,7 +67,7 @@ /datum/modular_computer_app_presets/command name = "command" display_name = "Command" - description = "Contains the most common command Programs" + description = "Contains the most common command programs." available = 1 /datum/modular_computer_app_presets/command/return_install_programs() var/list/_prg_list = list( @@ -81,7 +81,7 @@ /datum/modular_computer_app_presets/security name = "security" display_name = "Security" - description = "Contains the most common security Programs" + description = "Contains the most common security programs." available = 1 /datum/modular_computer_app_presets/security/return_install_programs() var/list/_prg_list = list( @@ -96,21 +96,36 @@ /datum/modular_computer_app_presets/civilian name = "civilian" display_name = "Civilian" - description = "Contains the most common civilian Programs" + description = "Contains the most common civilian programs." available = 1 /datum/modular_computer_app_presets/civilian/return_install_programs() var/list/_prg_list = list( new/datum/computer_file/program/filemanager(), new/datum/computer_file/program/chatclient(), new/datum/computer_file/program/game/arcade(), - new/datum/computer_file/program/game/sudoku() + new/datum/computer_file/program/game/sudoku(), + new/datum/computer_file/program/civilian/cargoorder() + ) + return _prg_list + +/datum/modular_computer_app_presets/supply + name = "supply" + display_name = "Supply" + description = "Contains the most common cargo programs." + available = 1 +/datum/modular_computer_app_presets/supply/return_install_programs() + var/list/_prg_list = list( + new/datum/computer_file/program/filemanager(), + new/datum/computer_file/program/chatclient(), + new/datum/computer_file/program/civilian/cargocontrol(), + new/datum/computer_file/program/civilian/cargoorder() ) return _prg_list /datum/modular_computer_app_presets/wall_generic name = "wallgeneric" display_name = "Wall - Generic" - description = "A generic preset for the wall console" + description = "A generic preset for the wall console." available = 0 /datum/modular_computer_app_presets/wall_generic/return_install_programs() var/list/_prg_list = list( @@ -124,7 +139,7 @@ /datum/modular_computer_app_presets/merc name = "merc" display_name = "Mercenary" - description = "Preset for the Merc Console" + description = "Preset for the Merc Console." available = 0 /datum/modular_computer_app_presets/merc/return_install_programs() var/list/_prg_list = list( @@ -137,7 +152,7 @@ /datum/modular_computer_app_presets/ert name = "ert" display_name = "EmergencyResposeTeam" - description = "Preset for the ERT Console" + description = "Preset for the ERT Console." available = 0 /datum/modular_computer_app_presets/ert/return_install_programs() var/list/_prg_list = list( @@ -155,7 +170,7 @@ /datum/modular_computer_app_presets/trashcompactor name = "trashcompactor" display_name = "Trash Compactor" - description = "A preset for the Trash Compactor Wall Console" + description = "A preset for the Trash Compactor Wall Console." available = 0 /datum/modular_computer_app_presets/trashcompactor/return_install_programs() var/list/_prg_list = list( @@ -167,7 +182,7 @@ /datum/modular_computer_app_presets/merchant name = "merchant" display_name = "Merchant" - description = "A preset for the merchant console" + description = "A preset for the merchant console." available = 0 /datum/modular_computer_app_presets/merchant/return_install_programs() var/list/_prg_list = list( diff --git a/code/modules/modular_computers/file_system/programs/civilian/cargo_control.dm b/code/modules/modular_computers/file_system/programs/civilian/cargo_control.dm new file mode 100644 index 00000000000..8972e08674f --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/civilian/cargo_control.dm @@ -0,0 +1,192 @@ +/datum/computer_file/program/civilian/cargocontrol + filename = "cargocontrol" + filedesc = "Cargo Control" + extended_desc = "Application to Control Cargo Orders" + size = 12 + requires_ntnet = 1 + available_on_ntnet = 1 + required_access_download = access_hop + required_access_run = access_cargo + nanomodule_path = /datum/nano_module/program/civilian/cargocontrol/ + +/datum/nano_module/program/civilian/cargocontrol/ + name = "Cargo Control" + var/page = "overview_main" //overview_main - Main Menu, overview_submitted - Submitted Order Overview, overview_approved - Approved Order Overview, settings - Settings, details - order details + var/last_user_name = "" //Name of the User that last used the computer + var/status_message = null //A status message that can be displayed + var/list/order_details = list() //Order Details for the order + var/list/shipment_details = list() //Shipment Details for a selected shipment + +/datum/nano_module/program/civilian/cargocontrol/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) + var/list/data = host.initial_data() + + post_signal("supply") + + //Send the page to display + data["page"] = page + //Send teh status message + data["status_message"] = status_message + + //Pass the ID Data + var/obj/item/weapon/card/id/user_id_card = user.GetIdCard() + last_user_name = GetNameAndAssignmentFromId(user_id_card) + data["username"] = last_user_name + + var/list/submitted_orders = SScargo.get_orders_by_status("submitted",1) + data["order_submitted_number"] = submitted_orders.len + data["order_submitted_value"] = SScargo.get_orders_value_by_status("submitted",1) + data["order_submitted_suppliers"] = SScargo.get_order_suppliers_by_status("submitted",1) + data["order_submitted_shuttle_time"] = SScargo.get_pending_shipment_time("submitted") + data["order_submitted_shuttle_price"] = SScargo.get_pending_shipment_cost("submitted") + if(page == "overview_submitted") + data["order_list"] = submitted_orders + + var/list/approved_orders = SScargo.get_orders_by_status("approved",1) + data["order_approved_number"] = approved_orders.len + data["order_approved_value"] = SScargo.get_orders_value_by_status("approved",1) + data["order_approved_suppliers"] = SScargo.get_order_suppliers_by_status("approved",1) + data["order_approved_shuttle_time"] = SScargo.get_pending_shipment_time("approved") + data["order_approved_shuttle_price"] = SScargo.get_pending_shipment_cost("approved") + if(page == "overview_approved") + data["order_list"] = approved_orders + + var/list/shipped_orders = SScargo.get_orders_by_status("shipped",1) + data["order_shipped_number"] = shipped_orders.len + data["order_shipped_value"] = SScargo.get_orders_value_by_status("shipped",1) + if(page == "overview_shipped") + data["order_list"] = shipped_orders + + if(page == "order_details") + data["order_details"] = order_details + + if(page == "overview_shipments") + data["shipment_list"] = SScargo.get_shipment_list() + + if(page == "shipment_details") + data["shipment_details"] = shipment_details + + data["cargo_money"] = SScargo.get_cargo_money() + data["handling_fee"] = SScargo.get_handlingfee() + + //Shuttle Stuff + var/datum/shuttle/ferry/supply/shuttle = SScargo.shuttle + if(shuttle) + data["shuttle_available"] = 1 + data["shuttle_has_arrive_time"] = shuttle.has_arrive_time() + data["shuttle_eta_minutes"] = shuttle.eta_minutes() + data["shuttle_can_launch"] = shuttle.can_launch() + data["shuttle_can_cancel"] = shuttle.can_cancel() + data["shuttle_can_force"] = shuttle.can_force() + data["shuttle_at_station"] = shuttle.at_station() + if(shuttle.docking_controller) + data["shuttle_docking_status"] = shuttle.docking_controller.get_docking_status() + else + data["shuttle_docking_status"] = "error" + else + data["shuttle_available"] = 0 + + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "cargo_control.tmpl", name, 850, 600, state = state) + ui.auto_update_layout = 1 + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/datum/nano_module/program/civilian/cargocontrol/Topic(href, href_list) + var/datum/shuttle/ferry/supply/shuttle = SScargo.shuttle + if (!shuttle) + world.log << "## ERROR: Eek. The supply/shuttle datum is missing somehow." + return + if(..()) + return 1 + + //Page switch between main, submitted, approved and settings + if(href_list["page"]) + switch(href_list["page"]) + if("overview_main") + page = "overview_main" //Main overview page with links to the different sub overview pages - submitted, approved, shipped + if("overview_submitted") + page = "overview_submitted" //Overview page listing the orders that have been submitted with options to view them, approve them and reject them + if("overview_approved") + page = "overview_approved" //Overview page listing the current shuttle price and time as well as orders that have been approved, with options to view the details + if("overview_shipped") + page = "overview_shipped" //Overview page listing the orders that have been shipped to the station but not delivered, with the option to mark them as delivered as well as to specify a person it has been delivered to + if("order_details") + page = "order_details" //Details page for a specific order - Lists the contents of the orde with the suppliers, prices and required access levels + //Fetch the order details and store it for the order. No need to fetch it again every 2 seconds + var/datum/cargo_order/co = SScargo.get_order_by_id(text2num(href_list["order_details"])) + order_details = co.get_list() + if("overview_shipments") //Overview of the shipments to / from the station + page = "overview_shipments" + if("shipment_details") //Details of a Shipment to / from the station + page = "shipment_details" + if("settings") + page = "settings" //Settings page that allows to tweak various settings such as the cargo handling fee + else + page = "overview_main" //fall back to overview_main if a unknown page has been supplied + return 1 + + //Approve a order + if(href_list["order_approve"]) + var/datum/cargo_order/co = SScargo.get_order_by_id(text2num(href_list["order_approve"])) + if(co) + var/message = SScargo.approve_order(co,last_user_name) + if(message) + status_message = message + return 1 + + //Reject a order + if(href_list["order_reject"]) + var/datum/cargo_order/co = SScargo.get_order_by_id(text2num(href_list["order_reject"])) + if(co) + var/message = SScargo.reject_order(co) + if(message) + status_message = message + return 1 + + //Send shuttle + if(href_list["shuttle_send"]) + var/message = SScargo.shuttle_call(last_user_name) + if(message) + status_message = message + return 1 + + //Cancel shuttle + if(href_list["shuttle_cancel"]) + var/message = SScargo.shuttle_cancel() + if(message) + status_message = message + return 1 + + //Force shuttle + if(href_list["shuttle_force"]) + var/message = SScargo.shuttle_force() + if(message) + status_message = message + return 1 + + //Clear Status Message + if(href_list["clear_message"]) + status_message = null + return 1 + + if(href_list["handling_fee"]) + var/handling_fee = sanitize(input(usr,"Handling Fee:","Set the new handling fee?",SScargo.get_handlingfee()) as null|text) + status_message = SScargo.set_handlingfee(text2num(handling_fee)) + return 1 + + //Change Settings + +/datum/nano_module/program/civilian/cargocontrol/proc/post_signal(var/command) //Old code right here - Used to send a refresh command to the status screens incargo + + var/datum/radio_frequency/frequency = SSradio.return_frequency(1435) + + if(!frequency) return + + var/datum/signal/status_signal = new + status_signal.source = src + status_signal.transmission_method = 1 + status_signal.data["command"] = command + + frequency.post_signal(src, status_signal) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/civilian/cargo_order.dm b/code/modules/modular_computers/file_system/programs/civilian/cargo_order.dm new file mode 100644 index 00000000000..3e8d213581d --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/civilian/cargo_order.dm @@ -0,0 +1,187 @@ +/datum/computer_file/program/civilian/cargoorder + filename = "cargoorder" + filedesc = "Cargo Order" + extended_desc = "Application to Order Items from Cargo" + size = 10 + requires_ntnet = 1 + available_on_ntnet = 1 + nanomodule_path = /datum/nano_module/program/civilian/cargoorder/ + +/datum/nano_module/program/civilian/cargoorder/ + name = "Cargo Order" + var/page = "main" //main - Main Menu, order - Order Page, item_details - Item Details Page, tracking - Tracking Page + var/selected_category = "" // Category that is currently selected + var/selected_item = "" // Path of the currently selected item + var/datum/cargo_order/co + var/last_user_name = "" //Name of the user that used the program + var/status_message = null //Status Message to be displayed to the user + var/user_tracking_id = 0 //Tracking id of the user + var/user_tracking_code = 0 //Tracking Code of the user + +/datum/nano_module/program/civilian/cargoorder/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) + //Check if a cargo order exists. If not create a new one + if(!co) + var/datum/cargo_order/crord = new + co = crord + + var/list/data = host.initial_data() + + //Pass the ID Data + var/obj/item/weapon/card/id/user_id_card = user.GetIdCard() + if(!user_id_card) + last_user_name = "Unknown" + else + last_user_name = user_id_card.registered_name + + + data["username"] = last_user_name + + //Pass the list of all ordered items and the order value + data["order_items"] = co.get_item_list() + data["order_value"] = co.get_value(0) + data["order_item_count"] = co.get_item_count() + data["order_shuttle_fee"] = co.get_max_shipment_cost() + + //Pass Data for Main page + if(page == "main") + //Pass all available categories and the selected category + data["cargo_categories"] = SScargo.get_category_list() + data["selected_category"] = selected_category + + //Pass a list of items in the selected category + data["category_items"] = SScargo.get_items_for_category(selected_category) + + //Pass Data for Item Details Page + else if(page == "item_details") + var/datum/cargo_item/ci = SScargo.cargo_items[selected_item] + if(ci) + data["item_details"] = ci.get_list() + + else if (page == "tracking") + data["tracking_id"] = user_tracking_id + data["tracking_code"] = user_tracking_code + //If no tracking id / code is entered the page the enter them should be displayed + if(!user_tracking_id || !user_tracking_code) + data["tracking_status"] = "Incomplete Input" + //If we have a tracking id / code, then try to find a order with mathing details + else if(user_tracking_id && user_tracking_code) + //Now, lets try to find a order with a matching id + var/datum/cargo_order/co = SScargo.get_order_by_id(user_tracking_id) + if(co) + if(co.tracking_code == user_tracking_code) + data["tracking_status"] = "Success" + data["tracked_order"] = co.get_list() + data["tracked_order_report"] = co.get_report() + else + data["tracking_status"] = "Invalid Tracking Code" + else + data["tracking_status"] = "Invalid Order" + + //Pass the current page + data["page"] = page + + //Pass the status message along + data["status_message"] = status_message + + data["handling_fee"] = SScargo.get_handlingfee() + data["crate_fee"] = SScargo.get_cratefee() + + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "cargo_order.tmpl", name, 500, 600, state = state) + ui.auto_update_layout = 1 + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/datum/nano_module/program/civilian/cargoorder/Topic(href, href_list) + if(..()) + return 1 + + //Send the order to cargo + if(href_list["submit_order"]) + if(co.items.len == 0) + return 1 //Only submit the order if there are items in it + + if(last_user_name == "Unknown") + status_message = "Unable to submit order. ID could not be located" + return 1 + + var/reason = sanitize(input(usr,"Reason:","Why do you require this item?","") as null|text) + if(!reason) + status_message = "Unable to submit order. No reason supplied." + return 1 + + co.customer = last_user_name + co.reason = reason + SScargo.submit_order(co) + status_message = "Order submitted successfully. Order ID: [co.order_id] Tracking code: [co.get_tracking_code()]" + //TODO: Print a list with the order data + co = null + return 1 + + //Add item to the order list + if(href_list["add_item"]) + var/datum/cargo_order_item/coi = new + coi.ci = SScargo.cargo_items[href_list["add_item"]] + coi.supplier = href_list["supplier"] + //Check if the selected supplier exists for the item and get the price for the supplier + var/supplier_details = coi.ci.suppliers[coi.supplier] + if(supplier_details) + coi.cs = SScargo.get_supplier_by_name(coi.supplier) + coi.calculate_price() + if(coi.price > 0) + status_message = co.add_item(coi) + else + status_message = "Unable to add item [coi.ci.name] - Internal Error 602." + log_debug("Cargo Order: Warning - Attempted to order item [coi.ci.name] from supplier [href_list["supplier"]] with invalid purchase price") + qdel(coi) + else + status_message = "Unable to add item [coi.ci.name] - Internal Error 605." + log_debug("Cargo Order: Warning - Attempted to order item [coi.ci.name] from non existant supplier [href_list["supplier"]]") + qdel(coi) + + //Reset page to main page - TODO: Maybe add a way to disable jumping back to the main page + page = "main" + selected_item = "" + return 1 + + //Remove item from the order list + if(href_list["remove_item"]) + status_message = co.remove_item(text2num(href_list["remove_item"])) + return 1 + + //Clear the items in the order list + if(href_list["clear_order"]) + status_message = "Order Cleared" + qdel(co) + co = new + return 1 + + //Change the selected page + if(href_list["item_details"]) + page = "item_details" + selected_item = href_list["item_details"] + return 1 + if(href_list["page"]) + page = href_list["page"] + return 1 + //Tracking Stuff + if(href_list["trackingid"]) + var/trackingid = text2num(sanitize(input(usr,"Order ID:","ID of the Order that you want to track","") as null|text)) + if(trackingid) + user_tracking_id = trackingid + return 1 + if(href_list["trackingcode"]) + var/trackingcode = text2num(sanitize(input(usr,"Tracking Code:","Tracking Code of the Order that you want to track","") as null|text)) + if(trackingcode) + user_tracking_code = trackingcode + return 1 + //Change the displayed item category + if(href_list["select_category"]) + selected_category = href_list["select_category"] + return 1 + + if(href_list["clear_message"]) + status_message = null + return 1 \ No newline at end of file diff --git a/code/modules/research/designs/circuit_designs.dm b/code/modules/research/designs/circuit_designs.dm index 54f08b4c752..22a1fdcc9ed 100644 --- a/code/modules/research/designs/circuit_designs.dm +++ b/code/modules/research/designs/circuit_designs.dm @@ -335,19 +335,6 @@ build_path = /obj/item/weapon/airlock_electronics/secure sort_string = "JDAAA" -/datum/design/circuit/ordercomp - name = "supply ordering console" - id = "ordercomp" - build_path = /obj/item/weapon/circuitboard/ordercomp - sort_string = "KAAAA" - -/datum/design/circuit/supplycomp - name = "supply control console" - id = "supplycomp" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/circuitboard/supplycomp - sort_string = "KAAAB" - /datum/design/circuit/biogenerator name = "biogenerator" id = "biogenerator" diff --git a/code/modules/shuttles/shuttle_supply.dm b/code/modules/shuttles/shuttle_supply.dm index cfcd6c4e6c2..84efb4b4934 100644 --- a/code/modules/shuttles/shuttle_supply.dm +++ b/code/modules/shuttles/shuttle_supply.dm @@ -27,7 +27,8 @@ return if (!at_station()) //at centcom - SScargo.buy() + if(!SScargo.buy()) //Check if the shuttle can be sent + moving_status = SHUTTLE_IDLE //Dont move the shuttle //We pretend it's a long_jump by making the shuttle stay at centcom for the "in-transit" period. var/area/away_area = get_location_area(away_location) diff --git a/config/example/config.txt b/config/example/config.txt index 32da00df2d9..9399d6b1635 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -497,3 +497,6 @@ LOG_GELF_PORT 12201 # Enables fastboot - some features not essential to testing (like sunlight) will be disabled to speed up server boot. Should not be used on production servers. FASTBOOT + +# Where to load the cargo items from. json or sql +CARGO_LOAD_ITEMS_FROM json \ No newline at end of file diff --git a/html/changelogs/arrow768-PR-3221.yml b/html/changelogs/arrow768-PR-3221.yml new file mode 100644 index 00000000000..e9db885e23c --- /dev/null +++ b/html/changelogs/arrow768-PR-3221.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +################################# + +# Your name. +author: Arrow768 + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Cargo is now based on credits instead of points." \ No newline at end of file diff --git a/maps/aurora/aurora-1_centcomm.dmm b/maps/aurora/aurora-1_centcomm.dmm index 6ff3bd67362..720367c46f1 100644 --- a/maps/aurora/aurora-1_centcomm.dmm +++ b/maps/aurora/aurora-1_centcomm.dmm @@ -10007,7 +10007,7 @@ }, /area/centcom/control) "wZ" = ( -/obj/machinery/computer/ordercomp, +/obj/item/modular_computer/console/preset/supply, /turf/unsimulated/floor{ icon_state = "floor" }, diff --git a/maps/aurora/aurora-4_mainlevel.dmm b/maps/aurora/aurora-4_mainlevel.dmm index 909b855be4a..0b0c02b9529 100644 --- a/maps/aurora/aurora-4_mainlevel.dmm +++ b/maps/aurora/aurora-4_mainlevel.dmm @@ -29637,7 +29637,7 @@ /obj/machinery/light_switch{ pixel_x = 32 }, -/obj/machinery/computer/supplycomp, +/obj/item/modular_computer/console/preset/supply, /turf/simulated/floor/wood, /area/crew_quarters/heads/hop) "bao" = ( @@ -55983,7 +55983,7 @@ /turf/simulated/floor/tiled, /area/quartermaster/office) "bTB" = ( -/obj/machinery/computer/ordercomp, +/obj/item/modular_computer/console/preset/civilian, /obj/effect/floor_decal/corner/brown{ icon_state = "corner_white"; dir = 9 @@ -56401,7 +56401,7 @@ /turf/simulated/floor/tiled, /area/quartermaster/office) "bUq" = ( -/obj/machinery/computer/supplycomp, +/obj/item/modular_computer/console/preset/supply/, /turf/simulated/floor/tiled, /area/quartermaster/office) "bUr" = ( diff --git a/maps/aurora/aurora-6_surface.dmm b/maps/aurora/aurora-6_surface.dmm index 3221580a80e..56d662ddb88 100644 --- a/maps/aurora/aurora-6_surface.dmm +++ b/maps/aurora/aurora-6_surface.dmm @@ -16995,7 +16995,7 @@ /turf/simulated/floor/tiled, /area/quartermaster/qm) "Fs" = ( -/obj/machinery/computer/supplycomp, +/obj/item/modular_computer/console/preset/supply, /turf/simulated/floor/tiled, /area/quartermaster/qm) "Ft" = ( diff --git a/nano/templates/cargo_control.tmpl b/nano/templates/cargo_control.tmpl new file mode 100644 index 00000000000..7bd1b9a8c6b --- /dev/null +++ b/nano/templates/cargo_control.tmpl @@ -0,0 +1,311 @@ +
+{{:helper.link('Main', 'cart', {'page' : 'overview_main'}, null)}} +{{:helper.link('Submitted', 'cart', {'page' : 'overview_submitted'}, null)}} +{{:helper.link('Approved', 'cart', {'page' : 'overview_approved'}, null)}} +{{:helper.link('Shipped', 'cart', {'page' : 'overview_shipped'}, null)}} +{{:helper.link('Shipments', 'cart', {'page' : 'overview_shipments'}, null)}} +{{:helper.link('Settings', 'cart', {'page' : 'settings'}, null)}} +
+
+
+{{if data.page == "overview_main"}} +
+
+
+ + + + + + + + + + + + + {{if data.shuttle_has_arrive_time}} + + + + + {{/if}} + + + +
Welcome:{{:data.username}}
Cargo Account Value{{:data.cargo_money}}

Shuttle Operations

ETA:{{:data.shuttle_eta_minutes}} Minutes
+ {{if data.shuttle_can_launch}} + {{:helper.link('Send', 'play', {'shuttle_send' : '1'}, null )}} + {{else}} + {{:helper.link('Send', 'play', null, "disabled" )}} + {{/if}} + {{if data.shuttle_can_cancel}} + {{:helper.link('Cancel', 'stop', {'shuttle_cancel' : '1'}, null )}} + {{else}} + {{:helper.link('Cancel', 'stop', null, "disabled" )}} + {{/if}} + {{if data.shuttle_can_force}} + {{:helper.link('Force', 'seek-end', {'shuttle_force' : '1'}, null )}} + {{else}} + {{:helper.link('Force', 'seek-end', null, "disabled" )}} + {{/if}} +
+
+
+
+{{else data.page == "overview_submitted"}} +
+
+
+ + + + + + + + + + + + + + + + + + + + +

Submitted Orders

Submitted Order Number:{{:data.order_submitted_number}}
Submitted Order Value:{{:data.order_submitted_value}} Credits
Estimated Shuttle Time:{{:data.order_submitted_shuttle_time / 10}}s
Estimated Shuttle Cost:{{:data.order_submitted_shuttle_price}} Credits
+
+
+
+ + + + + + + + {{props data.order_list}} + + + + + + + {{/props}} +
Order IDCustomerPriceActions
{{:value.order_id}}{{:value.customer}}{{:value.price}} + {{:helper.link('Approve', 'close', {'order_approve' : value.order_id}, null)}} + {{:helper.link('Reject', 'close', {'order_reject' : value.order_id}, null)}} + {{:helper.link('Details', 'close', {'order_details' : value.order_id, 'page': 'order_details'}, null)}} +
+{{else data.page == "overview_approved"}} +
+
+
+ + + + + + + + + + + + + + + + + + + + +

Approved Orders

Approved Order Number:{{:data.order_approved_number}}
Approved Order Value:{{:data.order_approved_value}} Credits
Estimated Shuttle Time:{{:data.order_approved_shuttle_time / 10}}s
Estimated Shuttle Cost:{{:data.order_approved_shuttle_price}} Credits
+
+
+
+ + + + + + + + {{props data.order_list}} + + + + + + + {{/props}} +
Order IDCustomerPriceActions
{{:value.order_id}}{{:value.customer}}{{:value.price}} + {{:helper.link('Details', 'close', {'order_details' : value.order_id, 'page': 'order_details'}, null)}} +
+ +{{else data.page == "overview_shipped"}} +
+
+
+ + + + + + + + + + + + +

Shipped Orders

Shipped Order Number:{{:data.order_shipped_number}}
Shipped Order Value:{{:data.order_shipped_value}} Credits
+
+
+
+ + + + + + + + {{props data.order_list}} + + + + + + + {{/props}} +
Order IDCustomerPriceActions
{{:value.order_id}}{{:value.customer}}{{:value.price}} + {{:helper.link('Details', 'close', {'order_details' : value.order_id, 'page': 'order_details'}, null)}} +
+ +{{else data.page == "overview_shipments"}} +

Shipment Overview

+ + + + + + + {{props data.shipment_list}} + + + + + + {{/props}} +
Shipment #ExpenseIncome
{{:value.shipment_num}}{{:value.shipment_cost_purchase}}{{:value.shipment_cost_sell}}
+ +{{else data.page == "settings"}} +
+
+
+ + + + + + + + +

Settings

Cargo Handling Fee:{{:helper.link(data.handling_fee, 'pencil', {'handling_fee' : '1'}, null)}}
+
+
+
+{{else data.page == "order_details"}} +
+
+
+ + + + + + + + + + + + + + + + + + + + + {{if data.order_details.shipment_cost != 0}} + + + + + {{else}} + + + + + {{/if}} + + + + + + + + + {{if data.order_details.authorized_by}} + + + + + {{/if}} + {{if data.order_details.time_submitted}} + + + + + {{/if}} + {{if data.order_details.time_approved}} + + + + + {{/if}} + {{if data.order_details.time_shipped}} + + + + + {{/if}} +

Order No: {{:data.order_details.order_id}}

Tracking Code:{{:data.order_details.tracking_code}}
Price (Customer):{{:data.order_details.price_customer}}
Price (Cargo):{{:data.order_details.price_cargo}}
Item Value:{{:data.order_details.price}}
Shipment Cost: (aliquot){{:data.order_details.shipment_cost}}
Shipment Cost: (max){{:data.order_details.shipment_cost_max}}
Status:{{:data.order_details.status_pretty}}
Customer:{{:data.order_details.customer}}
Authorized By:{{:data.order_details.authorized_by}}
Submitted at:{{:data.order_details.time_submitted}}
Approved at:{{:data.order_details.time_approved}}
Shipped at:{{:data.order_details.time_shipped}}
+
+
+
+ + + + + + + + {{props data.order_details.items}} + + + + + + {{/props}} +
Item NameSupplierPrice
{{:value.name}}{{:value.supplier_name}}{{:value.price}}
+{{else}} + else +{{/if}} \ No newline at end of file diff --git a/nano/templates/cargo_order.tmpl b/nano/templates/cargo_order.tmpl new file mode 100644 index 00000000000..209a55e7101 --- /dev/null +++ b/nano/templates/cargo_order.tmpl @@ -0,0 +1,175 @@ +
+{{:helper.link('Order', 'gear', {'page' : 'main'}, null)}} +{{:helper.link('Tracking', 'gear', {'page' : 'tracking'}, null)}} +
+

+{{if data.page == "main" || data.page == "item_details"}} +
+
+
+ + + + + + {{if data.status_message}} + + + + + {{/if}} + + + + + + + + + + + + + + + + + + + +
Welcome:{{:data.username}}
Status:{{:data.status_message}}

Order

Items:{{:data.order_item_count}}
Price:{{:data.order_value}} Credits
Shuttle Fee:{{:data.order_shuttle_fee}}
{{:helper.link('Details', 'cart', {'page' : 'order'}, null)}}{{:helper.link('Clear', 'cancel', {'clear_order' : 'clear_order'}, null)}} {{:helper.link("Submit Order", 'play', {'submit_order' : 'submit_order'}, null)}}
+
+
+
+{{/if}} +{{if data.page == "main"}} +
+
+ {{props data.cargo_categories}} + {{:helper.link(value.display_name, value.icon, {'select_category' : value.name}, (data.selected_category == value.name) ? 'selected' : null)}} + {{/props}} +
+
+
+
+ + {{for data.category_items}} + + + + + + + + + + + {{/for}} +
{{:value.name}}
{{:value.description}}
{{:helper.link('Item Details', 'gear', {'item_details' : value.path}, null)}}

+
+{{else data.page == "item_details"}} +
+ + + + + + + + + + + + + + + + +
{{:helper.link('Return', 'gear', {'page' : 'main'}, null)}}
Name:{{:data.item_details.name}}
Description:{{:data.item_details.description}}
Items per Order:{{:data.item_details.amount}}
+
+ Suppliers: +
+ {{props data.item_details.suppliers}} + {{if value.available && value.adjusted_price > 0}} + {{:helper.link(value.name + " " + value.adjusted_price, 'gear', {'add_item' : data.item_details.path, 'supplier': key}, null)}} + {{else}} + {{:helper.link(value.name + " /Unavailable/", 'gear', null, "disabled")}} + {{/if}} + {{/for}} +
+{{else data.page == "order"}} +
+ + + + + + + + {{props data.order_items}} + + + + + + + {{/props}} + + + + + + + + + + + + + + + +
NameSupplierPrice
{{:value.name}}{{:value.supplier_name}}{{:value.price}}{{:helper.link('Delete', 'close', {'remove_item' : value.item_id}, null)}}
Crate FeeNT Supply Department{{:data.crate_fee}}
Handling FeeCargo{{:data.handling_fee}}
Additional Shuttle Fees may apply
+ {{:helper.link("Submit Order", 'play', {'submit_order' : 'submit_order'}, null)}} + + {{:helper.link('Return', 'gear', {'page' : 'main'}, null)}} +{{else data.page == "tracking"}} +
+

Tracking Data

+
+
+
+ Order ID: +
+
+ {{:helper.link(data.tracking_id, 'pencil', {'trackingid' : '1'})}} +
+
+
+
+ Tracking Code: +
+
+ {{:helper.link(data.tracking_code, 'pencil', {'trackingcode' : '1'})}} +
+
+
+

Order Data

+
+ {{if data.tracking_status == "Success"}} +
+
+
+ {{:data.tracked_order_report}} +
+
+
+ {{else}} +
+ Tracking Status: +
+
+ {{:data.tracking_status}} +
+ {{/if}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/pda.tmpl b/nano/templates/pda.tmpl index 2befc5b0779..3a5ffeb258e 100644 --- a/nano/templates/pda.tmpl +++ b/nano/templates/pda.tmpl @@ -806,18 +806,18 @@ Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm {{if data.records.supply.approved_count == 0}} No current approved orders

{{else}} - {{for data.records.supply.approved}} - #{{:value.Number}} - {{:value.Name}} approved by {{:value.OrderedBy}}
{{if value.Comment != ""}} {{:value.Comment}}
{{/if}}
- {{/for}} + {{props data.records.supply.approved}} + #{{:value.order_id}} - {{:value.customer}} - {{:value.price_cargo}} Credits + {{/props}} {{/if}}

Current Requested Orders
{{if data.records.supply.requests_count == 0}} No current requested orders

{{else}} - {{for data.records.supply.requests}} - #{{:value.Number}} - {{:value.Name}} requested by {{:value.OrderedBy}}
{{if value.Comment != ""}} {{:value.Comment}}
{{/if}}
- {{/for}} + {{props data.records.supply.requests}} + #{{:value.order_id}} - {{:value.customer}} - {{:value.price_cargo}} Credits + {{/props}} {{/if}}