diff --git a/code/WorkInProgress/Railgun.dm b/code/WorkInProgress/Railgun.dm index 4b35ff0a..f8b4e9bf 100644 --- a/code/WorkInProgress/Railgun.dm +++ b/code/WorkInProgress/Railgun.dm @@ -404,8 +404,6 @@ proc/line_ReturnEfficDir(Angle) ReturnedDir = WEST return ReturnedDir - - //This returns the tangent reciprocal of x, for use with East and West straights. proc/tanR(x) return (cos(x)/sin(x)) diff --git a/code/datums/mining/cloud_storage.dm b/code/datums/mining/cloud_storage.dm new file mode 100644 index 00000000..f85ba2dd --- /dev/null +++ b/code/datums/mining/cloud_storage.dm @@ -0,0 +1,245 @@ +#define ROCKBOX_STANDARD_FEE 5 +var/global/rockbox_client_fee_min = 1 +var/global/rockbox_client_fee_pct = 10 +var/global/rockbox_premium_purchased = 0 + +/obj/machinery/ore_cloud_storage_container + name = "Rockbox™ Ore Cloud Storage Container" + desc = "This thing stores ore in \"the cloud\" for the station to use. Best not to think about it too hard." + icon = 'icons/obj/mining.dmi' + icon_state = "ore_storage_unit" + density = 1 + anchored = 1 + var/base_material_class = /obj/item/raw_material/ + var/list/sell_price = list() + var/list/for_sale = list() + var/list/ores = list() + var/list/sellable_ores = list() + var/health = 100 + var/broken = 0 + + MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + + if (!O || !user) + return + + if(!istype(user,/mob/living/)) + boutput(user, "Only living mobs are able to use the storage container's quick-load feature.") + return + + if (!istype(O,/obj/)) + boutput(user, "You can't quick-load that.") + return + + if(get_dist(O,user) > 1) + boutput(user, "You are too far away!") + return + + else if (istype(O, /obj/storage/crate/) && src.accept_loading(user,1)) + if (O:welded || O:locked) + boutput(user, "You cannot load from a crate that cannot open!") + return + + user.visible_message("[user] uses [src]'s automatic loader on [O]!", "You use [src]'s automatic loader on [O].") + var/amtload = 0 + for (var/obj/item/M in O.contents) + if (!istype(M,src.base_material_class)) + continue + src.load_item(M) + amtload++ + if (amtload) boutput(user, "[amtload] materials loaded from [O]!") + else boutput(user, "No material loaded!") + + else if (istype(O, /obj/item/) && src.accept_loading(user,1)) + user.visible_message("[user] begins quickly stuffing materials into [src]!") + var/staystill = user.loc + for(var/obj/item/M in view(1,user)) + if (!O) + continue + if (!istype(M,O.type)) + continue + if (!istype(M,src.base_material_class)) + continue + if (O.loc == user) + continue + if (O in user.contents) + continue + src.load_item(M) + sleep(0.5) + if (user.loc != staystill) break + boutput(user, "You finish stuffing materials into [src]!") + src.update_ores() + + else ..() + + src.updateUsrDialog() + + attackby(obj/item/W as obj, mob/user as mob) + if (istype(W, src.base_material_class) && src.accept_loading(user)) + user.visible_message("[user] loads [W] into the [src].", "You load [W] into the [src].") + src.load_item(W,user) + src.update_ores() + + else + src.health = max(src.health-W.force,0) + src.check_health() + ..() + + proc/check_health() + if(!src.health) + src.broken = 1 + src.icon_state = "ore_storage_unit-broken" + src.update_sellable() + + proc/load_item(var/obj/item/O,var/mob/living/user) + if (!O) + return + if(O.amount == 1) + O.set_loc(src) + if (user && O) + user.u_equip(O) + O.dropped() + else if(O.amount>1) + O.set_loc(src) + for(O.amount,O.amount > 0, O.amount--) + new O.type(src) + if (user && O) + user.u_equip(O) + O.dropped() + qdel(O) + else + return // uhhhhhh + + + proc/accept_loading(var/mob/user,var/allow_silicon = 0) + if (!user) + return 0 + if (src.stat & BROKEN || src.stat & NOPOWER) + return 0 + if (!istype(user, /mob/living/)) + return 0 + if (istype(user, /mob/living/silicon) && !allow_silicon) + return 0 + var/mob/living/L = user + if (L.stat || L.transforming) + return 0 + return 1 + + proc/update_ores() + src.ores.len = 0 + for(var/obj/item/raw_material/R in src.contents) + if(!(R.material_name in ores)) + ores += R.material_name + ores[R.material_name] = 1 + + else + ores[R.material_name]++ + src.update_sellable() + return + + proc/update_sellable() + src.sellable_ores.len = 0 + if(src.broken) + return + for(var/ore in src.ores) + if(ore in src.for_sale) + if(for_sale[ore]) + if(!(ore in sellable_ores)) + sellable_ores += ore + sellable_ores[ore] = ores[ore] + else + continue + else + continue + + attack_hand(var/mob/user as mob) + + var/list/ores = src.ores + + user.machine = src + var/dat = "[src.name]" + + dat += "

" + + if (stat & BROKEN || stat & NOPOWER) + dat = "The screen is blank." + user << browse(dat, "window=mining_dropbox;size=400x500") + onclose(user, "mining_dropbox") + return + + if(ores.len) + for(var/ore in ores) + var/sellable = 0 + var/price = 0 + if(src.sell_price[ore] != null) + price = sell_price[ore] + if(src.for_sale[ore] != null) + sellable = src.for_sale[ore] + dat += "[ore]: [ores[ore]] ([sellable ? "For Sale" : "Not For Sale"]) ($[price] per ore) (Eject)
" + else + dat += "No ores currently loaded.
" + + user << browse(dat, "window=mining_dropbox;size=450x500") + onclose(user, "mining_dropbox") + + + + Topic(href, href_list) + + if(stat & BROKEN || stat & NOPOWER) + return + + if(usr.stat || usr.restrained()) + return + + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf)))) + usr.machine = src + + if (href_list["eject"]) + var/ore = href_list["eject"] + var/turf/ejectturf = get_turf(usr) + + src.eject_ores(ore,ejectturf,0,0,usr) + + if (href_list["price"]) + var/ore = href_list["price"] + var/new_price = null + new_price = input(usr,"What price would you like to set? (Min 0)","Set Sale Price",null) as num + new_price = max(0,new_price) + if(src.sell_price[ore]) + sell_price[ore] = new_price + else + sell_price += ore + sell_price[ore] = new_price + + if (href_list["sellable"]) + var/ore = href_list["sellable"] + if(src.for_sale[ore]) + for_sale[ore] = !for_sale[ore] + else + for_sale += ore + for_sale[ore] = 1 + update_sellable() + + src.updateUsrDialog() + return + + proc/eject_ores(var/ore, var/turf/ejectturf, var/ejectamt, var/transmit = 0, var/user as mob) + for(var/obj/item/raw_material/R in src.contents) + if (R.material_name == ore) + if (!ejectamt) + ejectamt = input(usr,"How many ores do you want to eject?","Eject Ores") as num + if ((ejectamt <= 0 || get_dist(src, user) > 1) && !transmit) + break + if (!ejectturf) + break + R.set_loc(ejectturf) + ejectamt-- + if (ejectamt <= 0) + break + if(transmit) + flick("ore_storage_unit-transmit",src) + showswirl(ejectturf) + leaveresidual(ejectturf) + + src.update_ores() \ No newline at end of file diff --git a/code/obj/machinery/computer/QM_order.dm b/code/obj/machinery/computer/QM_order.dm index f3b8ee95..29f4ca02 100644 --- a/code/obj/machinery/computer/QM_order.dm +++ b/code/obj/machinery/computer/QM_order.dm @@ -35,6 +35,12 @@ account = FindBankAccountByName(src.scan.registered) if(account) dat += "Credits on Account: [account.fields["current_money"]] Credits

" + + dat += "Rockbox™ Ore Cloud Storage Service Settings:
" + dat += "Rockbox™ Fees: $[!rockbox_premium_purchased ? ROCKBOX_STANDARD_FEE : 0] per ore [!rockbox_premium_purchased ? "(Purchase our Premium Service to remove this fee!)" : ""]
" + dat += "Client Quartermaster Transaction Fee: [rockbox_client_fee_pct]%
" + dat += "Client Quartermaster Transaction Fee Per Ore Minimum: $[rockbox_client_fee_min]
" + dat += "

" dat += {"View Requests
Request Items
Purchase Supply Points
@@ -212,6 +218,28 @@ else if (href_list["mainmenu"]) src.temp = null - src.add_fingerprint(usr) + + else if (href_list["fee_pct"]) + var/fee_pct = null + fee_pct = input(usr,"What fee percent would you like to set? (Min 0)","Fee Percent per Transaction:",null) as num + fee_pct = max(0,fee_pct) + rockbox_client_fee_pct = fee_pct + + else if (href_list["fee_min"]) + var/fee_min = null + fee_min = input(usr,"What fee min would you like to set? (Min 0)","Minimum Fee per Transaction in Credits:",) as num + fee_min = max(0,fee_min) + rockbox_client_fee_min = fee_min + + else if (href_list["premium_service"]) + var/response = "" + response = alert(usr,"Would you like to purchase the Rockbox™ Premium Service for 10000 Credits?",,"Yes","No") + if(response == "Yes") + if(wagesystem.shipping_budget >= 10000) + wagesystem.shipping_budget -= 10000 + rockbox_premium_purchased = 1 + else + boutput(usr,"Not enough money in the budget!") + src.updateUsrDialog() return \ No newline at end of file diff --git a/code/obj/machinery/manufacturer.dm b/code/obj/machinery/manufacturer.dm index 4f895a61..31886c5a 100644 --- a/code/obj/machinery/manufacturer.dm +++ b/code/obj/machinery/manufacturer.dm @@ -61,6 +61,8 @@ var/static/list/text_flipout_adjective = list("an awful","a terrible","a loud","a horrible","a nasty","a horrendous") var/static/list/text_flipout_noun = list("noise","racket","ruckus","clatter","commotion","din") var/list/text_bad_output_adjective = list("janky","crooked","warped","shoddy","shabby","lousy","crappy","shitty") + var/obj/item/card/id/scan = null + var/temp = null #define WIRE_EXTEND 1 #define WIRE_POWER 2 @@ -276,6 +278,34 @@ dat += "
" dat += build_material_list() + dat += "
" + + dat +="Scanned Card: ([src.scan])
" + if(scan) + var/datum/data/record/account = null + account = FindBankAccountByName(src.scan.registered) + if (account) + dat+="Current Funds: [account.fields["current_money"]] Credits
" + dat+= src.temp + dat+="
" + else + dat+= src.temp + dat+="
" + else + dat+= src.temp + dat+="
" + + + + dat += "Ores Available for Purchase:
" + for(var/obj/machinery/ore_cloud_storage_container/S in world) + var/list/ores = S.sellable_ores + if(ores.len) + dat += "[S.name] at [get_turf(S).loc.name]:
" + for(var/ore in ores) + var/taxes = round(max(rockbox_client_fee_min,abs(S.sell_price[ore]*rockbox_client_fee_pct/100)),0.01) //transaction taxes for the station budget + dat += "[ore]: [ores[ore]] ($[S.sell_price[ore]+taxes+(!rockbox_premium_purchased ? ROCKBOX_STANDARD_FEE : 0)]/ore) (Purchase)
" + dat += "

" if (!page) @@ -589,6 +619,91 @@ src.pulse(twire) src.build_icon() + if (href_list["card"]) + if (src.scan) src.scan = null + else + var/obj/item/I = usr.equipped() + if (istype(I, /obj/item/card/id)) + boutput(usr, "You swipe the ID card in the card reader.") + var/datum/data/record/account = null + account = FindBankAccountByName(I:registered) + if(account) + var/enterpin = input(usr, "Please enter your PIN number.", "Card Reader", 0) as null|num + if (enterpin == I:pin) + boutput(usr, "Card authorized.") + src.scan = I + else + boutput(usr, "Pin number incorrect.") + src.scan = null + else + boutput(usr, "No bank account associated with this ID found.") + src.scan = null + + if (href_list["purchase"]) + var/obj/machinery/ore_cloud_storage_container/storage = locate(href_list["storage"]) + var/ore = href_list["ore"] + var/list/ores = storage.sellable_ores + var/price = storage.sell_price[ore] + var/taxes = round(max(rockbox_client_fee_min,abs(price*rockbox_client_fee_pct/100)),0.01) //transaction taxes for the station budget + + if(!scan) + src.temp = {"You have to scan a card in first.
"} + src.updateUsrDialog() + return + else + src.temp = null + if (src.scan.registered in FrozenAccounts) + boutput(usr, "Your account cannot currently be liquidated due to active borrows.") + return + var/datum/data/record/account = null + account = FindBankAccountByName(src.scan.registered) + if (account) + var/quantity = 1 + quantity = input("How many units do you want to purchase?", "Ore Purchase", null, null) as num + + //////////// + + if(ores[ore] >= quantity) + var/subtotal = round(price * quantity) + var/sum_taxes = round(taxes * quantity) + var/rockbox_fees = (!rockbox_premium_purchased ? ROCKBOX_STANDARD_FEE : 0) * quantity + var/total = subtotal + sum_taxes + rockbox_fees + if(account.fields["current_money"] >= total) + account.fields["current_money"] -= total + storage.eject_ores(ore, get_turf(usr), quantity, transmit=1, user=usr) + + // This next bit is stolen from PTL Code + var/list/accounts = list() + for(var/datum/data/record/t in data_core.bank) + if(t.fields["job"] == "Chief Engineer") + accounts += t + accounts += t //fuck it x2 + else if(t.fields["job"] == "Miner") + accounts += t + + + //any non-divisible amounts go to the shipping budget + var/leftovers = 0 + if(accounts.len) + leftovers = subtotal%accounts.len + var/divisible_amount = subtotal - leftovers + if(divisible_amount) + for(var/datum/data/record/t in accounts) + t.fields["current_money"] += divisible_amount/accounts.len + else + leftovers = subtotal + wagesystem.shipping_budget += (leftovers + sum_taxes) + + + + src.temp = {"Enjoy your purchase!
"} + else + src.temp = {"You don't have enough dosh, bucko.
"} + else + src.temp = {"I don't have that many for sale, champ.
"} + else + src.temp = {"That card doesn't have an account anymore, you might wanna get that checked out.
"} + src.updateUsrDialog() return @@ -831,6 +946,7 @@ return MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + if (!O || !user) return diff --git a/goonstation.dme b/goonstation.dme index c49da5f1..3ef2236c 100644 --- a/goonstation.dme +++ b/goonstation.dme @@ -464,6 +464,7 @@ var/datum/preMapLoad/preMapLoad = new #include "code\datums\hydroponics\plants_herb.dm" #include "code\datums\hydroponics\plants_veg.dm" #include "code\datums\hydroponics\plants_weed.dm" +#include "code\datums\mining\cloud_storage.dm" #include "code\datums\mining\mining_encounters.dm" #include "code\datums\mining\ore.dm" #include "code\datums\mining\tile_events.dm" @@ -1199,7 +1200,6 @@ var/datum/preMapLoad/preMapLoad = new #include "libs\Base64\hexadecimal.dm" #include "libs\Base64\text.dm" #include "maps\_disposaltester.dm" -#include "maps\adv_test.dmm" #include "maps\config\map.dm" #include "maps\placeholders\map_placeholders.dm" // END_INCLUDE diff --git a/goonstation.int b/goonstation.int index 1930186e..42ce1519 100644 --- a/goonstation.int +++ b/goonstation.int @@ -1,9 +1,12 @@ // BEGIN_INTERNALS /* -LAST_COMPILE_TIME: 1457219709 -DIR: code code\chui\example code\datums\buildmodes code\datums\buildmodes\adventure code\datums\buildmodes\adventure\elements code\datums\chemistry code\datums\chemistry\tools code\datums\critter_mobs\health code\datums\gamemodes code\datums\genetics +MAP_ZOOM: 1.000 +LAST_COMPILE_TIME: 1576914694 +DIR: browserassets browserassets\images browserassets\images\genetics browserassets\images\traders code code\chui\example code\datums code\datums\buildmodes code\datums\buildmodes\adventure code\datums\buildmodes\adventure\elements code\datums\chemistry code\datums\genetics code\datums\mining code\obj code\obj\item code\obj\machinery code\WorkInProgress code\WorkInProgress\griffening code\WorkInProgress\Materials_Crafting icons icons\obj libs maps maps\config sound sound\vox AUTO_FILE_DIR: OFF MAP_ICON_TYPE: 0 -LAST_COMPILE_VERSION: 510.1327 +LAST_COMPILE_VERSION: 513.1501 +WINDOW: code\datums\mining\ore.dm;code\datums\mining\cloud_storage.dm;icons\obj\mining.dmi;maps\config\standard.dm;code\obj\machinery\manufacturer.dm;code\obj\item\material.dm;maps\oretest.dmm;code\WorkInProgress\Materials_Crafting\Mat_RawMaterials.dm;code\WorkInProgress\Materials_Crafting\Mat_ProcsDefines.dm;code\WorkInProgress\Materials_Crafting\Mat_Materials.dm +FILE: code\datums\mining\cloud_storage.dm */ // END_INTERNALS diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index cc3c3b65..3c935174 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ