Skip to content

Commit

Permalink
Used pressure crystals: credit value scaling with explosion power (#1…
Browse files Browse the repository at this point in the history
…5933)

Co-authored-by: kbsmilk <kbsmilk@gmail.com>
Co-authored-by: TobleroneSwordfish <20713227+TobleroneSwordfish@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 27, 2023
1 parent 3269e8e commit a45e689
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 15 deletions.
47 changes: 47 additions & 0 deletions code/modules/economy/shippingmarket.dm
@@ -1,6 +1,11 @@
#define SUPPLY_OPEN_TIME 1 SECOND //Time it takes to open supply door in seconds.
#define SUPPLY_CLOSE_TIME 15 SECONDS //Time it takes to close supply door in seconds.

/// The full explosion-power-to-credits conversion formula. Also used in smallprogs.dm
#define PRESSURE_CRYSTAL_VALUATION(power) power ** 1.1 * 100
/// The number of peak points on the pressure crystal graph offering bonus credits
#define PRESSURE_CRYSTAL_PEAK_COUNT 3

//Codes for requisition post-transaction returns handling
///Requisition was not used, conduct a standard QM sale
#define RET_IGNORE 0
Expand Down Expand Up @@ -35,6 +40,12 @@
var/list/supply_requests = list() // Pending requests, of type /datum/supply_order
var/list/supply_history = list() // History of all approved requests, of type string

// Both of these are string indexed because byond will whine and complain and explode otherwise
/// Previously sold pressure crystal values, will negatively affect future sales (associative list of pressure to credit value)
var/list/pressure_crystal_sales = list()
/// Pressure crystal market peaks, will positively affect future sales (associative list of pressure to multipliers)
var/list/pressure_crystal_peaks = list()

var/points_per_crate = 10

var/list/datum/req_contract/complete_orders = list()
Expand Down Expand Up @@ -96,6 +107,11 @@

src.launch_distance = get_dist(spawnpoint, target)

//set up pressure crystal market peaks
for (var/i in 1 to PRESSURE_CRYSTAL_PEAK_COUNT)
var/value = rand(1, 230)
src.pressure_crystal_peaks["[value]"] = (rand() * 2) + 1 //random number between 2 and 3

proc/add_commodity(var/datum/commodity/new_c)
src.commodities["[new_c.comtype]"] = new_c

Expand Down Expand Up @@ -433,6 +449,11 @@
if (sell)
qdel(O)
break
else if (istype(O, /obj/item/pressure_crystal))
duckets += src.appraise_pressure_crystal(O, sell)
if (sell)
qdel(O)
break
else if (O.artifact && sell)
src.sell_artifact(O, O.artifact)
else // Please excuse this duplicate code, I'm gonna change trader commodity lists into associative ones later I swear
Expand All @@ -459,6 +480,32 @@

return duckets

proc/appraise_pressure_crystal(var/obj/item/pressure_crystal/pc, var/sell = 0)
if (pc.pressure <= 0)
return
//calculate the base value
var/value = PRESSURE_CRYSTAL_VALUATION(pc.pressure)
//for each previously sold pressure crystal
for (var/sale in src.pressure_crystal_sales)
var/sale_value = text2num(sale)
//calculate a modifier based on the proximity of our current pressure to the previous one
//scales by a simple x^2 curve, stretched by the magnitude of the sale pressure (ie bigger bombs affect larger ranges)
//obligatory desmos: https://www.desmos.com/calculator/mumuykqlju
var/modifier = 1/(sale_value * 3) * ((pc.pressure - sale_value) ** 2)
if (modifier < 1) //a range cutoff to ensure we never add credit value
value *= modifier
for (var/peak in src.pressure_crystal_peaks)
var/peak_value = text2num(peak) //I hate byond lists
//very similar to above except inverted and bounded by the multiplier of the peak
//another desmos: https://www.desmos.com/calculator/ahhoxuwho8
var/modifier = -1/(peak_value * 3) * ((pc.pressure - peak_value) ** 2) + src.pressure_crystal_peaks[peak]
if (modifier > 1)
value *= modifier
value = round(value)
if (sell && value > 0)
src.pressure_crystal_sales["[pc.pressure]"] = value
return value

proc/handle_returns(obj/storage/crate/sold_crate,var/return_code)
if(return_code == RET_INSUFFICIENT) //clarifies purpose for crate return
sold_crate.name = "Returned Requisitions Crate"
Expand Down
9 changes: 9 additions & 0 deletions code/modules/economy/supply_packs.dm
Expand Up @@ -1455,6 +1455,15 @@ ABSTRACT_TYPE(/datum/supply_packs)
containername = "AI Law Rack ManuDrive Crate (Cardlocked \[Heads])"
access = access_heads

/datum/supply_packs/pressure_crystals_qt5
name = "Pressure Crystal Resupply"
desc = "Five (5) pressure crystals used in high-energy research."
category = "Research Department"
contains = list(/obj/item/pressure_crystal = 5)
cost = 2500
containertype = /obj/storage/crate
containername = "Pressure Crystal Crate"

/* ================================================= */
/* -------------------- Complex -------------------- */
/* ================================================= */
Expand Down
1 change: 1 addition & 0 deletions code/obj/item/device/pda2/cartridges.dm
Expand Up @@ -237,6 +237,7 @@ TYPEINFO(/obj/item/disk/data/cartridge/syndicate)
..()
src.root.add_file( new /datum/computer/file/pda_program/scan/reagent_scan(src))
src.root.add_file( new /datum/computer/file/pda_program/signaler(src))
src.root.add_file( new /datum/computer/file/pda_program/pressure_crystal_shopper(src))
src.read_only = 1

bartender
Expand Down
27 changes: 27 additions & 0 deletions code/obj/item/device/pda2/smallprogs.dm
Expand Up @@ -1691,3 +1691,30 @@ Using electronic "Detomatix" SELF-DESTRUCT program is perhaps less simple!<br>
if(product.desc)
. += product.desc
. += "<br>"

/datum/computer/file/pda_program/pressure_crystal_shopper
name = "Crystal Bazaar"
size = 2

return_text()
if(..())
return

. = src.return_text_header()

. += "<h4>The Pressure Crystal Market</h4> \
A few well-funded organizations will pay handsomely for crystals exposed to different pressure values. \
The bigger the boom, the higher the payout, although duplicate or similar data will be worth less.\
<br><br>\
<b>Certain pressure values are of particular interest and will reward bonuses:</b>\
<br>"
for (var/peak in shippingmarket.pressure_crystal_peaks)
var/peak_value = text2num(peak)
var/mult = shippingmarket.pressure_crystal_peaks[peak]
. += "[peak] kiloblast: \
[mult > 1 ? "<B>" : ""]worth [round(mult * 100, 0.01)]% of normal. \
[mult > 1 ? "Maximum estimated value: [round(mult * PRESSURE_CRYSTAL_VALUATION(peak_value))]</B> credits." : ""]<br>"
. += "<br><b>Pressure crystal values already sold:</b>\
<br>"
for (var/value in shippingmarket.pressure_crystal_sales)
. += "[value] kiloblast for [shippingmarket.pressure_crystal_sales[value]] credits.<br>"
51 changes: 36 additions & 15 deletions code/obj/item/device/transfer_valve.dm
Expand Up @@ -516,17 +516,41 @@ TYPEINFO(/obj/item/device/transfer_valve/briefcase)
/obj/item/pressure_crystal
icon = 'icons/obj/items/assemblies.dmi'
icon_state = "pressure_3"
var/pressure = 0
var/total_pressure = 0
desc = "A pressure crystal. We're not really sure how it works, but it does. Place this near where the epicenter of a bomb would be, then detonate the bomb. Afterwards, place the crystal in a tester to determine the strength."
name = "Pressure Crystal"
w_class = W_CLASS_SMALL
var/pressure = 0 // used to calculate credit value, in shippingmarket.dm proc/appraise_value
var/last_explode_time = 0
var/static/explosion_id = 0
name = "pressure crystal"
desc = "A mysterious gadget that measures the power of bombs detonated over it. \
High measurements within the crystal can be very valuable on the shipping market."
HELP_MESSAGE_OVERRIDE("Place this where the epicenter of a bomb would be, then detonate the bomb. \
Afterwards, place the crystal in a pressure sensor to determine the explosion power.<br>\
Spent pressure crystals can be sold to researchers on the shipping market, for a credit sum depending on the measured power.")

examine()
. = ..()
if (src.pressure)
. += "<br><span class='notice'>This crystal has already measured something. Another explosion will overwrite the previous results.</span>"

ex_act(var/ex, var/inf, var/factor)
pressure = factor || (4-clamp(ex, 1, 3))*2
total_pressure += pressure
pressure += (rand()-0.5) * (pressure/1000)//its not extremely accurate.
icon_state = "pressure_[clamp(ex, 1, 3)]"
var/exp_power = (factor / 2) ** 2 || (4-clamp(ex, 1, 3))*2 // we made it extremely accurate

if (src.explosion_id == exp_power * world.time)
return // we don't want peeps stacking 50 crystals on 1 explosion
// this only stops stacking, or making rings of crystals - you can still make a line of valuable crystals from the epicenter

if (src.last_explode_time < world.time)
src.pressure = exp_power
else // sum the power of multiple explosions at roughly the same instant, but diminishingly
// preferring stronger explosions, too
src.pressure = max(src.pressure, exp_power) + sqrt(min(src.pressure, exp_power))

src.icon_state = "pressure_[clamp(ex, 1, 3)]"
src.last_explode_time = world.time
src.explosion_id = exp_power * world.time

/obj/item/device/pressure_sensor
name = "Pressure Sensor"
name = "pressure sensor"
icon = 'icons/obj/items/assemblies.dmi'
icon_state = "pressure_tester"
desc = "Put in a pressure crystal to determine the strength of the explosion."
Expand All @@ -536,9 +560,10 @@ TYPEINFO(/obj/item/device/transfer_valve/briefcase)
boutput( user, "<b>There's no crystal in this here device!</b>")
else
if(crystal.pressure)
boutput( user, "The reader reads <b>[crystal.pressure/25]</b> kilojoules." )
boutput( user, "The reader reads <b>[crystal.pressure]</b> kiloblast." )
else
boutput( user, "The reader reads a firm 0. It guilts you into trying to read an unexploded pressure crystal, and seems to have succeeded. You feel ashamed for being so compelled by a device that has nothing more than a slot and a number display.")
boutput( user, "The reader reads a firm 0. It guilts you into trying to read an unexploded pressure crystal, and seems to have \
succeeded. You feel ashamed for being so compelled by a device that has nothing more than a slot and a number display.")
ex_act()
qdel(src)
attackby(obj/item/thing, mob/user)
Expand All @@ -559,10 +584,6 @@ TYPEINFO(/obj/item/device/transfer_valve/briefcase)
overlays = list()
wear_image.overlays = list()
boutput( user, "You pry out the crystal." )
if(prob(src.crystal.total_pressure / 45))
boutput( user, "<b class='alert'>It shatters!</b>" )
qdel(src.crystal)
return
src.crystal.set_loc(user.loc)
src.crystal = null
return
Expand Down

0 comments on commit a45e689

Please sign in to comment.