mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-19 11:05:50 +01:00
Stasis Cage Exporting (#19612)
* sellable stasis cage * Sellable mobs * crate code cleanup * export fix * clamp * sold mobs should vanish
This commit is contained in:
@@ -32,6 +32,7 @@ SUBSYSTEM_DEF(supply)
|
||||
var/list/order_history = list() // History of orders, showing edits made by users
|
||||
var/list/adm_order_history = list() // Complete history of all orders, for admin use
|
||||
var/list/adm_export_history = list() // Complete history of all crates sent back on the shuttle, for admin use
|
||||
var/list/exported_research_mobs = list()// Number of mob types sold from cargo, used to calculate diminishing returns
|
||||
//shuttle movement
|
||||
var/movetime = 1200
|
||||
var/datum/shuttle/autodock/ferry/supply/shuttle
|
||||
@@ -58,7 +59,10 @@ SUBSYSTEM_DEF(supply)
|
||||
//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types.
|
||||
/datum/controller/subsystem/supply/proc/forbidden_atoms_check(atom/A)
|
||||
if(isliving(A))
|
||||
return 1
|
||||
var/mob/living/check_living = A
|
||||
// Mobs inside stasis cages can be sold. otherwise loose mobs or mobs with clients are forbidden.
|
||||
if(!istype(check_living.loc, /obj/structure/stasis_cage) || check_living.client)
|
||||
return 1
|
||||
if(istype(A,/obj/item/disk/nuclear))
|
||||
return 1
|
||||
if(istype(A,/obj/machinery/nuclearbomb))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/datum/element/sellable
|
||||
var/sale_info = "This can be sold on the cargo shuttle if packed in a crate."
|
||||
var/needs_crate = TRUE
|
||||
var/datum/techweb/research_default_techweb = null
|
||||
var/department = DEPARTMENT_CARGO // Which kind of points does selling this give, by default it gives cargo supply points
|
||||
|
||||
/datum/element/sellable/Attach(datum/target)
|
||||
. = ..()
|
||||
@@ -45,7 +47,15 @@
|
||||
"value" = calculate_sell_value(source),
|
||||
"quantity" = calculate_sell_quantity(source)
|
||||
)
|
||||
EC.value += EC.contents[EC.contents.len]["value"]
|
||||
|
||||
var/point_value = EC.contents[EC.contents.len]["value"]
|
||||
switch(department)
|
||||
if(DEPARTMENT_CARGO)
|
||||
EC.value += point_value
|
||||
if(DEPARTMENT_RESEARCH)
|
||||
if(!research_default_techweb) // Lets do this when we sell a research giving item, instead of fighting subsystem init order
|
||||
research_default_techweb = locate(/datum/techweb/science) in SSresearch.techwebs
|
||||
research_default_techweb.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = point_value))
|
||||
return TRUE
|
||||
|
||||
/datum/element/sellable/proc/on_examine(datum/source, mob/user, list/examine_texts)
|
||||
@@ -398,3 +408,54 @@
|
||||
amount /= 20
|
||||
|
||||
return FLOOR(amount,5)
|
||||
|
||||
|
||||
// Selling xenomobs for science!!
|
||||
/datum/element/sellable/stasis_cage
|
||||
sale_info = "This can be export on the cargo shuttle. Central command will reward the station with research points if the creature within has scientific value."
|
||||
needs_crate = FALSE
|
||||
department = DEPARTMENT_RESEARCH
|
||||
|
||||
/datum/element/sellable/stasis_cage/sell_error(obj/source)
|
||||
var/obj/structure/stasis_cage/cage = source
|
||||
if(!cage.contained)
|
||||
return "Error: [cage] was empty."
|
||||
// Check if this creature can even be sold at all
|
||||
if(!istype(cage.contained, /mob/living/simple_mob))
|
||||
return "Error: This creature has no scientific value."
|
||||
if(cage.contained.client) // Lets not allow player possessed creatures to be sold
|
||||
return "Error: This creature has an undesirable mutation and has no scientific value."
|
||||
var/mob/living/simple_mob/our_mob = cage.contained
|
||||
if(our_mob.stat == DEAD)
|
||||
return "Error: The creature must be alive to study. It has no scientific value."
|
||||
if(!our_mob.export_research_value || !our_mob.export_research_diminished_max)
|
||||
return "Error: This creature has no scientific value."
|
||||
// We know it HAD value, see if it has any value remaining
|
||||
var/check_val = calculate_sell_value(source)
|
||||
if(!check_val)
|
||||
return "Error: This creature no longer has any scientific value."
|
||||
// Increase sold count, now that we've reached successful export
|
||||
var/mob_key = "[cage.contained.type]"
|
||||
if(!(mob_key in SSsupply.exported_research_mobs))
|
||||
SSsupply.exported_research_mobs[mob_key] = 0
|
||||
SSsupply.exported_research_mobs[mob_key] += 1
|
||||
return null
|
||||
|
||||
/datum/element/sellable/stasis_cage/calculate_sell_value(obj/source)
|
||||
var/obj/structure/stasis_cage/cage = source
|
||||
if(!cage.contained)
|
||||
return 0
|
||||
if(!istype(cage.contained, /mob/living/simple_mob))
|
||||
return 0
|
||||
var/mob/living/simple_mob/our_mob = cage.contained
|
||||
if(our_mob.stat == DEAD)
|
||||
return 0
|
||||
if(!our_mob.export_research_value || !our_mob.export_research_diminished_max)
|
||||
return 0
|
||||
// Calculate diminishing returns from number of mobs that have already been sold of this type
|
||||
var/mob_key = "[cage.contained.type]"
|
||||
var/sold_mobs = 0
|
||||
if(mob_key in SSsupply.exported_research_mobs)
|
||||
sold_mobs = SSsupply.exported_research_mobs[mob_key]
|
||||
var/research_val = our_mob.export_research_value // Each mob sold will linearly scale the value of research points recieved, until it hits 25% of it's value.
|
||||
return max(1, FLOOR(lerp(research_val, research_val * 0.25, CLAMP(sold_mobs / our_mob.export_research_diminished_max, 0, 1)), 1))
|
||||
|
||||
@@ -269,19 +269,20 @@
|
||||
|
||||
/obj/structure/closet/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(W.has_tool_quality(TOOL_WRENCH))
|
||||
if(opened)
|
||||
if(anchored)
|
||||
user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
|
||||
else
|
||||
user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
|
||||
if(do_after(user, 2 SECONDS * W.toolspeed, target = src))
|
||||
if(!src) return
|
||||
to_chat(user, span_notice("You [anchored? "un" : ""]secured \the [src]!"))
|
||||
anchored = !anchored
|
||||
return
|
||||
else
|
||||
if(!opened)
|
||||
to_chat(user, span_notice("You can't reach the anchoring bolts when the door is closed!"))
|
||||
else if(opened)
|
||||
return
|
||||
if(anchored)
|
||||
user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
|
||||
else
|
||||
user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
|
||||
if(do_after(user, 2 SECONDS * W.toolspeed, target = src))
|
||||
if(!src) return
|
||||
to_chat(user, span_notice("You [anchored? "un" : ""]secured \the [src]!"))
|
||||
anchored = !anchored
|
||||
return
|
||||
|
||||
if(opened)
|
||||
if(istype(W, /obj/item/grab))
|
||||
var/obj/item/grab/G = W
|
||||
MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
|
||||
@@ -319,9 +320,15 @@
|
||||
if(W)
|
||||
W.do_drop_animation(user)
|
||||
W.forceMove(loc)
|
||||
else if(istype(W, /obj/item/packageWrap))
|
||||
return
|
||||
else if(seal_tool)
|
||||
|
||||
if(istype(W, /obj/item/packageWrap))
|
||||
return
|
||||
|
||||
if(istype(W,/obj/item/cargo_scanner))
|
||||
return
|
||||
|
||||
if(seal_tool)
|
||||
if(istype(W, seal_tool))
|
||||
var/obj/item/S = W
|
||||
if(S.has_tool_quality(TOOL_WELDER))
|
||||
@@ -338,9 +345,9 @@
|
||||
update_icon()
|
||||
for(var/mob/M in viewers(src))
|
||||
M.show_message(span_warning("[src] has been [sealed?"sealed":"unsealed"] by [user.name]."), 3)
|
||||
else
|
||||
attack_hand(user)
|
||||
return
|
||||
return
|
||||
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/closet/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
|
||||
if(istype(O, /atom/movable/screen)) //fix for HUD elements making their way into the world -Pete
|
||||
|
||||
@@ -74,9 +74,11 @@
|
||||
/obj/structure/closet/crate/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(W.has_tool_quality(TOOL_WRENCH) && istype(src,/obj/structure/closet/crate/bin))
|
||||
return ..()
|
||||
else if(W.has_tool_quality(TOOL_WELDER))
|
||||
|
||||
if(W.has_tool_quality(TOOL_WELDER))
|
||||
return ..()
|
||||
else if(opened)
|
||||
|
||||
if(opened)
|
||||
if(isrobot(user))
|
||||
return
|
||||
if(W.loc != user) // This should stop mounted modules ending up outside the module.
|
||||
@@ -86,9 +88,15 @@
|
||||
user.drop_item()
|
||||
if(W)
|
||||
W.forceMove(src.loc)
|
||||
else if(istype(W, /obj/item/packageWrap))
|
||||
return
|
||||
else if(istype(W, /obj/item/stack/cable_coil))
|
||||
|
||||
if(istype(W, /obj/item/packageWrap))
|
||||
return
|
||||
|
||||
if(istype(W,/obj/item/cargo_scanner))
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
if(rigged)
|
||||
to_chat(user, span_notice("[src] is already rigged!"))
|
||||
@@ -97,19 +105,22 @@
|
||||
to_chat(user , span_notice("You rig [src]."))
|
||||
rigged = 1
|
||||
return
|
||||
else if(istype(W, /obj/item/radio/electropack))
|
||||
|
||||
if(istype(W, /obj/item/radio/electropack))
|
||||
if(rigged)
|
||||
to_chat(user , span_notice("You attach [W] to [src]."))
|
||||
user.drop_item()
|
||||
W.forceMove(src)
|
||||
return
|
||||
else if(W.has_tool_quality(TOOL_WIRECUTTER))
|
||||
return
|
||||
|
||||
if(W.has_tool_quality(TOOL_WIRECUTTER))
|
||||
if(rigged)
|
||||
to_chat(user , span_notice("You cut away the wiring."))
|
||||
playsound(src, W.usesound, 100, 1)
|
||||
rigged = 0
|
||||
return
|
||||
else return attack_hand(user)
|
||||
return
|
||||
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/closet/crate/ex_act(severity)
|
||||
switch(severity)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
var/mob/living/simple_mob/A = locate() in loc
|
||||
if(A)
|
||||
contain(A)
|
||||
AddElement(/datum/element/sellable/stasis_cage)
|
||||
|
||||
/obj/structure/stasis_cage/attack_hand(mob/user)
|
||||
release()
|
||||
@@ -48,9 +49,14 @@
|
||||
desc = initial(desc)
|
||||
|
||||
/obj/structure/stasis_cage/Destroy()
|
||||
// If sold by cargo, we need to delete our contents instead of releasing them
|
||||
// Check for admin z instead of shuttle area. Cause destroying it on the station will make the mob qdel.
|
||||
if(z in using_map.admin_levels)
|
||||
for(var/atom/thing in contents)
|
||||
qdel(thing)
|
||||
contained = null
|
||||
release()
|
||||
|
||||
return ..()
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_mob/MouseDrop(obj/structure/stasis_cage/over_object)
|
||||
if(istype(over_object) && Adjacent(over_object) && CanMouseDrop(over_object, usr))
|
||||
|
||||
@@ -27,23 +27,36 @@
|
||||
if(istype(AM,/obj/effect))
|
||||
return 0
|
||||
|
||||
var/final_output = span_boldnotice("\The [src] assesses the supply point value of \the [AM]...\n")
|
||||
var/final_output = span_boldnotice("\The [src] assesses the value of \the [AM]...\n")
|
||||
playsound(src, 'sound/machines/beep.ogg', 50, 1)
|
||||
|
||||
// Some things cannot be sold
|
||||
if(isliving(AM) || isstructure(AM) || isturf(AM))
|
||||
if(isliving(AM) || isturf(AM))
|
||||
final_output += span_danger("-Cannot be sold.")
|
||||
to_chat(user,final_output)
|
||||
return 0
|
||||
|
||||
// Get item value
|
||||
var/value = SEND_SIGNAL(AM,COMSIG_ITEM_SCAN_PROFIT)
|
||||
var/value = 0
|
||||
if(istype(AM,/obj/structure/closet/crate))
|
||||
// Scan all contents in crate
|
||||
for(var/atom/movable/thing in AM.contents)
|
||||
value += SEND_SIGNAL(thing,COMSIG_ITEM_SCAN_PROFIT)
|
||||
else
|
||||
// Get single item value
|
||||
value = SEND_SIGNAL(AM,COMSIG_ITEM_SCAN_PROFIT)
|
||||
|
||||
if(!value)
|
||||
final_output += span_danger("-It's worth nothing.")
|
||||
to_chat(user,final_output)
|
||||
return 0
|
||||
|
||||
// Stasis cages are for RESEARCH!
|
||||
if(istype(AM,/obj/structure/stasis_cage))
|
||||
final_output += span_notice("-Its contents can be studied for [value] research points.")
|
||||
to_chat(user,final_output)
|
||||
return value
|
||||
|
||||
var/price = SSsupply.points_to_cash(value)
|
||||
final_output += span_notice("-It can be sold for [value] points, or [price] [price > 1 ? "thalers" : "thaler"]")
|
||||
final_output += span_notice("-It can be sold for [value] supply points, or [price] [price > 1 ? "thalers" : "thaler"]")
|
||||
to_chat(user,final_output)
|
||||
return value
|
||||
|
||||
@@ -166,12 +166,14 @@
|
||||
var/heal_countdown = 5 //VOREStation Edit - A cooldown ticker for passive healing
|
||||
var/list/myid_access = list() //VOREStation Edit
|
||||
var/ID_provided = FALSE //VOREStation Edit
|
||||
// VOREStation Add: Move/Shoot/Attack delays based on damage
|
||||
var/damage_fatigue_mult = 1 // Our multiplier for how heavily mobs are affected by injury. [UPDATE THIS IF THE FORMULA CHANGES]: Formula = injury_level = round(rand(1,3) * damage_fatigue_mult * clamp(((rand(2,5) * (h / getMaxHealth())) - rand(0,2)), 1, 5))
|
||||
var/injury_level = 0 // What our injury level is. Rather than being the flat damage, this is the amount added to various delays to simulate injuries in a manner as lightweight as possible.
|
||||
var/threshold = 0.6 // When we start slowing down. Configure this setting per-mob. Default is 60%
|
||||
var/injury_enrages = FALSE // Do injuries enrage (aka strengthen) our mob? If yes, we'll interpret how hurt we are differently.
|
||||
// VOREStation Add End
|
||||
|
||||
// Stasis cage cargo export values
|
||||
var/export_research_value // Amount of research points gained when this mob is sold from cargo in a stasis cage
|
||||
var/export_research_diminished_max // Amount of mobs that can be sold before the value reaches its lowest point
|
||||
|
||||
var/has_recoloured = FALSE
|
||||
var/hunting_cooldown = 0
|
||||
|
||||
@@ -129,6 +129,8 @@
|
||||
|
||||
no_pull_when_living = TRUE
|
||||
|
||||
export_research_value = TECHWEB_TIER_1_POINTS
|
||||
export_research_diminished_max = 3
|
||||
|
||||
/mob/living/simple_mob/animal/giant_spider/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
can_be_drop_prey = FALSE
|
||||
|
||||
export_research_value = TECHWEB_TIER_2_POINTS
|
||||
export_research_diminished_max = 4
|
||||
|
||||
/mob/living/simple_mob/animal/space/alien/drone
|
||||
name = "alien drone"
|
||||
icon_state = "aliend_running"
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
can_be_drop_prey = FALSE
|
||||
allow_mind_transfer = TRUE
|
||||
|
||||
export_research_value = TECHWEB_TIER_1_POINTS
|
||||
export_research_diminished_max = 3
|
||||
|
||||
/datum/say_list/bear
|
||||
speak = list("RAWR!","Rawr!","GRR!","Growl!")
|
||||
emote_see = list("stares ferociously", "stomps")
|
||||
|
||||
@@ -67,6 +67,9 @@
|
||||
var/random_color = FALSE
|
||||
var/rarechance = 1
|
||||
|
||||
export_research_value = TECHWEB_TIER_1_POINTS
|
||||
export_research_diminished_max = 4
|
||||
|
||||
var/static/list/carp_colors = list(\
|
||||
"lightpurple" = "#c3b9f1", \
|
||||
"lightpink" = "#da77a8", \
|
||||
|
||||
@@ -110,6 +110,9 @@ I think I covered everything.
|
||||
special_attack_max_range = 10
|
||||
special_attack_cooldown = 80
|
||||
|
||||
export_research_value = TECHWEB_TIER_4_POINTS
|
||||
export_research_diminished_max = 2
|
||||
|
||||
plane = MOB_PLANE
|
||||
|
||||
//Dragon vars
|
||||
|
||||
@@ -78,6 +78,9 @@
|
||||
can_be_drop_prey = FALSE
|
||||
allow_mind_transfer = TRUE
|
||||
|
||||
export_research_value = TECHWEB_TIER_1_POINTS
|
||||
export_research_diminished_max = 3
|
||||
|
||||
/mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi
|
||||
name = "corrupt corrupt hound"
|
||||
desc = "Bad boy machine broke as well. Seems an attempt was made to achieve a less threatening look, and this one is definitely having some conflicting feelings about it."
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
|
||||
can_be_drop_prey = FALSE
|
||||
|
||||
export_research_value = TECHWEB_TIER_2_POINTS
|
||||
export_research_diminished_max = 3
|
||||
|
||||
/mob/living/simple_mob/vore/aggressive/deathclaw/Login()
|
||||
. = ..()
|
||||
if(!riding_datum)
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
pain_emote_1p = list("yelp", "whine", "bark", "growl")
|
||||
pain_emote_3p = list("yelps", "whines", "barks", "growls")
|
||||
|
||||
export_research_value = TECHWEB_TIER_2_POINTS
|
||||
export_research_diminished_max = 3
|
||||
|
||||
/mob/living/simple_mob/vore/greatwolf/black
|
||||
name = "great black wolf"
|
||||
desc = "A massive black wolf with a sandy colored underside, and intimidating amber eyes. Much like a dire wolf, but bigger. Passive, until you give it a reason to not be."
|
||||
|
||||
@@ -53,6 +53,9 @@
|
||||
pain_emote_1p = list("yelp", "whine", "bark", "growl")
|
||||
pain_emote_3p = list("yelps", "whines", "barks", "growls")
|
||||
|
||||
export_research_value = TECHWEB_TIER_2_POINTS
|
||||
export_research_diminished_max = 2
|
||||
|
||||
/datum/category_item/catalogue/fauna/leopardmander
|
||||
name = "Sivian Fauna - Va'aen Drake"
|
||||
desc = "Classification: S Draconis uncia\
|
||||
|
||||
@@ -65,6 +65,9 @@ GLOBAL_VAR_INIT(moth_amount, 0)
|
||||
allow_mind_transfer = TRUE
|
||||
glow_override = TRUE
|
||||
|
||||
export_research_value = TECHWEB_TIER_1_POINTS
|
||||
export_research_diminished_max = 6
|
||||
|
||||
/datum/say_list/solargrub
|
||||
emote_see = list("squelches", "squishes")
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
|
||||
glow_override = TRUE
|
||||
|
||||
export_research_value = TECHWEB_TIER_2_POINTS
|
||||
export_research_diminished_max = 4
|
||||
|
||||
/datum/say_list/solarmoth
|
||||
emote_see = list("flutters")
|
||||
|
||||
|
||||
@@ -120,3 +120,6 @@
|
||||
|
||||
/mob/living/simple_mob/vore/aggressive
|
||||
mob_bump_flag = HEAVY
|
||||
|
||||
export_research_value = TECHWEB_TIER_1_POINTS
|
||||
export_research_diminished_max = 5
|
||||
|
||||
Reference in New Issue
Block a user