Files
VOREStation/code/datums/elements/lootable/_lootable.dm
T
Will bf29ca396f Shovel digging refactor (#19345)
* fixes per pile lootable counts

* shovel digging element

* retooled to flag

* take two

* proc that

* sand digging

* collapse that system in too

* allow base loot

* desc

* potat

* fix that

* no making that on rocks

* oops

* var version

* prevent that dupe

* fixes

---------

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2026-03-26 22:10:06 -04:00

159 lines
6.4 KiB
Plaintext

/datum/element/lootable
var/chance_nothing = 0 // Unlucky people might need to loot multiple spots to find things.
var/chance_uncommon = 10 // Probability of pulling from the uncommon_loot list.
var/chance_rare = 1 // Ditto, but for rare_loot list.
var/chance_gamma = 0 // Singledrop global loot table shared with all piles.
var/allow_multiple_looting = TRUE // If true, the same person can loot multiple times. Mostly for debugging.
var/loot_depletion = FALSE // If true, loot piles can be 'depleted' after a certain number of searches by different players, where no more loot can be obtained.
var/loot_left = 0 // Maximum number of times a pile can be looted before no loot will remain for anyone
var/delete_on_depletion = FALSE // If true, and if the loot gets depleted as above, the pile is deleted.
var/list/unlucky_loot = list() // Unlucky is the worst tier. Only people with the unlucky trait can get this stuff. Primed grenades, dangerous syringes, etc.
var/list/common_loot = list() // Common is generally less-than-useful junk and filler, at least for maint loot piles.
var/list/uncommon_loot = list() // Uncommon is actually maybe some useful items, usually the reason someone bothers looking inside.
var/list/rare_loot = list() // Rare is really powerful, or at least unique items.
var/static/list/piles_looted = list() // Keeps track of the number of times a specific pile has been looted if the specific lootable type has loot_depletion on
/datum/element/lootable/Attach(atom/target)
. = ..()
if(!isatom(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_LOOT_REWARD, PROC_REF(loot))
/datum/element/lootable/Detach(atom/target)
. = ..()
if(loot_depletion)
piles_looted -= REF(target)
UnregisterSignal(target, COMSIG_LOOT_REWARD)
/// Calculates and drops loot, the source's turf is where it will be dropped, L is the searching mob, and searched_by is a passed list for storing who has searched a loot pile.
/datum/element/lootable/proc/loot(atom/source,mob/living/L,var/list/searched_by, wake_chance = 0)
SIGNAL_HANDLER
// The loot's all gone.
if(loot_depletion)
var/looted_count = piles_looted[REF(source)]
if(looted_count >= loot_left)
to_chat(L, span_warning("\The [source] has been picked clean."))
return
// You got unlucky.
if(chance_nothing && prob(chance_nothing))
to_chat(L, span_warning("Nothing in \the [source] really catches your eye..."))
return
if(L && islist(searched_by)) // This can handle no mob and no list if you just want to use this as a way to hold drop tables
//You already searched this one
if((L.ckey in searched_by) && !allow_multiple_looting)
to_chat(L, span_warning("You can't find anything else vaguely useful in \the [source]. Another set of eyes might, however."))
return
searched_by |= L.ckey // List is stored in the caller!
// You found something!
var/obj/item/loot = null
var/span = "notice" // Blue
if(HAS_TRAIT(L, TRAIT_UNLUCKY) && unlucky_loot.len) // If you're unlucky, you will always find bad stuff.
loot = produce_unlucky_item(source)
span = "cult" // Purple and bold.
if(prob(1))
to_chat(L, span_danger("You cut your hand on something in the trash!"))
L.apply_damage(2, BRUTE, pick(BP_L_HAND, BP_R_HAND), used_weapon = "sharp object")
var/datum/disease/advance/random/random_disease = new /datum/disease/advance/random()
random_disease.spread_flags |= DISEASE_SPREAD_NON_CONTAGIOUS
L.ForceContractDisease(random_disease)
else if(prob(chance_uncommon) && uncommon_loot.len) // You might still get something good.
loot = produce_uncommon_item(source)
span = "alium" // Green
else if(prob(chance_rare) && rare_loot.len) // You won THE GRAND PRIZE!
loot = produce_rare_item(source)
span = "cult" // Purple and bold.
else if(prob(chance_gamma) && GLOB.unique_gamma_loot.len) // ULTRA GRAND PRIZE
loot = produce_gamma_item(source)
span = "cult" // Purple and bold.
else // Welp.
loot = produce_common_item(source)
// Handle randomized items in our tables.
if(istype(loot,/obj/random))
var/obj/random/randy = loot
var/new_I = randy.spawn_item()
QDEL_SWAP(loot,new_I)
//We either have an item to hand over or we don't, at this point!
if(!loot)
return
loot.forceMove(get_turf(source))
var/final_message = "You found \a [loot]!"
switch(span)
if("notice")
final_message = span_notice(final_message)
if("cult")
final_message = span_cult(final_message)
if("alium")
final_message = span_alium(final_message)
to_chat(L, span_info(final_message))
var/disturbed_sleep = rand(1,100) //spawning of mobs, for now only the trash panda.
if(disturbed_sleep <= wake_chance)
new /mob/living/simple_mob/animal/passive/raccoon(get_turf(source))
source.visible_message("A raccoon jumps out of the trash!.")
// Check if we should delete on depletion
if(!loot_depletion)
return
// Add to looted piles if not already one
if(!(REF(source) in piles_looted))
piles_looted[REF(source)] = 0
// Increase the looted count till we've hit our limit
piles_looted[REF(source)] += 1
if(piles_looted[REF(source)] < loot_left)
return
to_chat(L, span_warning("You seem to have gotten the last of the spoils in \the [source]."))
if(delete_on_depletion)
qdel(source)
/datum/element/lootable/proc/produce_unlucky_item(atom/source)
var/path = pick(unlucky_loot)
return new path(source)
/datum/element/lootable/proc/produce_common_item(atom/source)
var/path = pick(common_loot)
return new path(source)
/datum/element/lootable/proc/produce_uncommon_item(atom/source)
var/path = pick(uncommon_loot)
return new path(source)
/datum/element/lootable/proc/produce_rare_item(atom/source)
var/path = pick(rare_loot)
return new path(source)
/// These are types that can only spawn once, and then will be removed from this list.
/datum/element/lootable/proc/produce_gamma_item(atom/source)
var/path = pick_n_take(GLOB.unique_gamma_loot)
if(!path) //Tapped out, reallocate?
for(var/P in GLOB.allocated_gamma_loot)
var/datum/weakref/WF = GLOB.allocated_gamma_loot[P]
var/obj/item/I = WF?.resolve()
if(QDELETED(I) || istype(I.loc,/obj/machinery/computer/cryopod))
restore_gamma_loot(P)
path = P
break
if(path)
var/obj/item/I = new path(source)
GLOB.allocated_gamma_loot[path] = WEAKREF(I)
return I
return produce_rare_item(source)
/// Restores a removed gamma loot item back to the loot table
/proc/restore_gamma_loot(var/w_type)
GLOB.allocated_gamma_loot -= w_type
GLOB.unique_gamma_loot += w_type