mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-20 03:26:37 +01:00
Adds New PoI Features + Bonus PoI
This commit is contained in:
@@ -1,78 +1,78 @@
|
||||
// Creates effects like smoke clouds every so often.
|
||||
/obj/effect/map_effect/interval/effect_emitter
|
||||
var/datum/effect/effect/system/effect_system = null
|
||||
var/effect_system_type = null // Which effect system to attach.
|
||||
|
||||
var/effect_amount = 10 // How many effect objects to create on each interval. Note that there's a hard cap on certain effect_systems.
|
||||
var/effect_cardinals_only = FALSE // If true, effects only move in cardinal directions.
|
||||
var/effect_forced_dir = null // If set, effects emitted will always move in this direction.
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/Initialize()
|
||||
effect_system = new effect_system_type()
|
||||
effect_system.attach(src)
|
||||
configure_effects()
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/interval/Destroy()
|
||||
QDEL_NULL(effect_system)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/proc/configure_effects()
|
||||
effect_system.set_up(effect_amount, effect_cardinals_only, usr.loc, effect_forced_dir)
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/trigger()
|
||||
configure_effects() // We do this every interval in case it changes.
|
||||
effect_system.start()
|
||||
..()
|
||||
|
||||
|
||||
// Creates smoke clouds every so often.
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke
|
||||
name = "smoke emitter"
|
||||
icon_state = "smoke_emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread
|
||||
|
||||
interval_lower_bound = 1 SECOND
|
||||
interval_upper_bound = 1 SECOND
|
||||
effect_amount = 2
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/bad
|
||||
name = "bad smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/bad
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/fire
|
||||
name = "fire smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/fire
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/frost
|
||||
name = "frost smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/frost
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/shock
|
||||
name = "shock smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/shock
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/mist
|
||||
name = "mist smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/mist
|
||||
|
||||
|
||||
// Makes sparks.
|
||||
/obj/effect/map_effect/interval/effect_emitter/sparks
|
||||
name = "spark emitter"
|
||||
icon_state = "spark_emitter"
|
||||
effect_system_type = /datum/effect/effect/system/spark_spread
|
||||
|
||||
interval_lower_bound = 3 SECONDS
|
||||
interval_upper_bound = 7 SECONDS
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/sparks/frequent
|
||||
effect_amount = 4 // Otherwise it caps out fast.
|
||||
interval_lower_bound = 1
|
||||
interval_upper_bound = 3 SECONDS
|
||||
|
||||
// Makes ""steam"" that looks like fire extinguisher water except it does nothing.
|
||||
/obj/effect/map_effect/interval/effect_emitter/steam
|
||||
name = "steam emitter"
|
||||
icon_state = "smoke_emitter"
|
||||
effect_system_type = /datum/effect/effect/system/steam_spread
|
||||
// Creates effects like smoke clouds every so often.
|
||||
/obj/effect/map_effect/interval/effect_emitter
|
||||
var/datum/effect/effect/system/effect_system = null
|
||||
var/effect_system_type = null // Which effect system to attach.
|
||||
|
||||
var/effect_amount = 10 // How many effect objects to create on each interval. Note that there's a hard cap on certain effect_systems.
|
||||
var/effect_cardinals_only = FALSE // If true, effects only move in cardinal directions.
|
||||
var/effect_forced_dir = null // If set, effects emitted will always move in this direction.
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/Initialize()
|
||||
effect_system = new effect_system_type()
|
||||
effect_system.attach(src)
|
||||
configure_effects()
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/interval/Destroy()
|
||||
QDEL_NULL(effect_system)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/proc/configure_effects()
|
||||
effect_system.set_up(effect_amount, effect_cardinals_only, src.loc, effect_forced_dir)
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/trigger()
|
||||
configure_effects() // We do this every interval in case it changes.
|
||||
effect_system.start()
|
||||
..()
|
||||
|
||||
|
||||
// Creates smoke clouds every so often.
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke
|
||||
name = "smoke emitter"
|
||||
icon_state = "smoke_emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread
|
||||
|
||||
interval_lower_bound = 1 SECOND
|
||||
interval_upper_bound = 1 SECOND
|
||||
effect_amount = 2
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/bad
|
||||
name = "bad smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/bad
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/fire
|
||||
name = "fire smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/fire
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/frost
|
||||
name = "frost smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/frost
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/shock
|
||||
name = "shock smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/shock
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/smoke/mist
|
||||
name = "mist smoke emitter"
|
||||
effect_system_type = /datum/effect/effect/system/smoke_spread/mist
|
||||
|
||||
|
||||
// Makes sparks.
|
||||
/obj/effect/map_effect/interval/effect_emitter/sparks
|
||||
name = "spark emitter"
|
||||
icon_state = "spark_emitter"
|
||||
effect_system_type = /datum/effect/effect/system/spark_spread
|
||||
|
||||
interval_lower_bound = 3 SECONDS
|
||||
interval_upper_bound = 7 SECONDS
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/sparks/frequent
|
||||
effect_amount = 4 // Otherwise it caps out fast.
|
||||
interval_lower_bound = 1
|
||||
interval_upper_bound = 3 SECONDS
|
||||
|
||||
// Makes ""steam"" that looks like fire extinguisher water except it does nothing.
|
||||
/obj/effect/map_effect/interval/effect_emitter/steam
|
||||
name = "steam emitter"
|
||||
icon_state = "smoke_emitter"
|
||||
effect_system_type = /datum/effect/effect/system/steam_spread
|
||||
|
||||
@@ -1,71 +1,72 @@
|
||||
// These are objects you can use inside special maps (like PoIs), or for adminbuse.
|
||||
// Players cannot see or interact with these.
|
||||
/obj/effect/map_effect
|
||||
anchored = TRUE
|
||||
invisibility = 99 // So a badmin can go view these by changing their see_invisible.
|
||||
icon = 'icons/effects/map_effects.dmi'
|
||||
|
||||
// Below vars concern check_for_player_proximity() and is used to not waste effort if nobody is around to appreciate the effects.
|
||||
var/always_run = FALSE // If true, the game will not try to suppress this from firing if nobody is around to see it.
|
||||
var/proximity_needed = 12 // How many tiles a mob with a client must be for this to run.
|
||||
var/ignore_ghosts = FALSE // If true, ghosts won't satisfy the above requirement.
|
||||
var/ignore_afk = TRUE // If true, AFK people (5 minutes) won't satisfy it as well.
|
||||
var/retry_delay = 3 SECONDS // How long until we check for players again.
|
||||
|
||||
/obj/effect/map_effect/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_act()
|
||||
return
|
||||
|
||||
// Base type for effects that run on variable intervals.
|
||||
/obj/effect/map_effect/interval
|
||||
var/interval_lower_bound = 5 SECONDS // Lower number for how often the map_effect will trigger.
|
||||
var/interval_upper_bound = 5 SECONDS // Higher number for above.
|
||||
var/halt = FALSE // Set to true to stop the loop when it reaches the next iteration.
|
||||
|
||||
/obj/effect/map_effect/interval/Initialize()
|
||||
handle_interval_delay()
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/interval/Destroy()
|
||||
halt = TRUE // Shouldn't need it to GC but just in case.
|
||||
return ..()
|
||||
|
||||
// Override this for the specific thing to do. Be sure to call parent to keep looping.
|
||||
/obj/effect/map_effect/interval/proc/trigger()
|
||||
handle_interval_delay()
|
||||
|
||||
// Handles the delay and making sure it doesn't run when it would be bad.
|
||||
/obj/effect/map_effect/interval/proc/handle_interval_delay()
|
||||
// Check to see if we're useful first.
|
||||
if(halt)
|
||||
return // Do not pass .(), do not recursively collect 200 thaler.
|
||||
|
||||
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
|
||||
spawn(retry_delay) // Maybe someday we'll have fancy TG timers/schedulers.
|
||||
if(!QDELETED(src))
|
||||
.()
|
||||
|
||||
var/next_interval = rand(interval_lower_bound, interval_upper_bound)
|
||||
spawn(next_interval)
|
||||
if(!QDELETED(src))
|
||||
trigger()
|
||||
|
||||
// Helper proc to optimize the use of effects by making sure they do not run if nobody is around to perceive it.
|
||||
/proc/check_for_player_proximity(var/atom/proximity_to, var/radius = 12, var/ignore_ghosts = FALSE, var/ignore_afk = TRUE)
|
||||
if(!proximity_to)
|
||||
return FALSE
|
||||
|
||||
for(var/thing in player_list)
|
||||
var/mob/M = thing // Avoiding typechecks for more speed, player_list will only contain mobs anyways.
|
||||
if(ignore_ghosts && isobserver(M))
|
||||
continue
|
||||
if(ignore_afk && M.client && M.client.is_afk(5 MINUTES))
|
||||
continue
|
||||
if(M.z == proximity_to.z && get_dist(M, proximity_to) <= radius)
|
||||
return TRUE
|
||||
// These are objects you can use inside special maps (like PoIs), or for adminbuse.
|
||||
// Players cannot see or interact with these.
|
||||
/obj/effect/map_effect
|
||||
anchored = TRUE
|
||||
invisibility = 99 // So a badmin can go view these by changing their see_invisible.
|
||||
icon = 'icons/effects/map_effects.dmi'
|
||||
|
||||
// Below vars concern check_for_player_proximity() and is used to not waste effort if nobody is around to appreciate the effects.
|
||||
var/always_run = FALSE // If true, the game will not try to suppress this from firing if nobody is around to see it.
|
||||
var/proximity_needed = 12 // How many tiles a mob with a client must be for this to run.
|
||||
var/ignore_ghosts = FALSE // If true, ghosts won't satisfy the above requirement.
|
||||
var/ignore_afk = TRUE // If true, AFK people (5 minutes) won't satisfy it as well.
|
||||
var/retry_delay = 3 SECONDS // How long until we check for players again.
|
||||
|
||||
/obj/effect/map_effect/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_act()
|
||||
return
|
||||
|
||||
// Base type for effects that run on variable intervals.
|
||||
/obj/effect/map_effect/interval
|
||||
var/interval_lower_bound = 5 SECONDS // Lower number for how often the map_effect will trigger.
|
||||
var/interval_upper_bound = 5 SECONDS // Higher number for above.
|
||||
var/halt = FALSE // Set to true to stop the loop when it reaches the next iteration.
|
||||
|
||||
/obj/effect/map_effect/interval/Initialize()
|
||||
handle_interval_delay()
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/interval/Destroy()
|
||||
halt = TRUE // Shouldn't need it to GC but just in case.
|
||||
return ..()
|
||||
|
||||
// Override this for the specific thing to do. Be sure to call parent to keep looping.
|
||||
/obj/effect/map_effect/interval/proc/trigger()
|
||||
handle_interval_delay()
|
||||
|
||||
// Handles the delay and making sure it doesn't run when it would be bad.
|
||||
/obj/effect/map_effect/interval/proc/handle_interval_delay()
|
||||
// Check to see if we're useful first.
|
||||
if(halt)
|
||||
return // Do not pass .(), do not recursively collect 200 thaler.
|
||||
|
||||
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
|
||||
spawn(retry_delay) // Maybe someday we'll have fancy TG timers/schedulers.
|
||||
if(!QDELETED(src))
|
||||
.()
|
||||
return
|
||||
|
||||
var/next_interval = rand(interval_lower_bound, interval_upper_bound)
|
||||
spawn(next_interval)
|
||||
if(!QDELETED(src))
|
||||
trigger()
|
||||
|
||||
// Helper proc to optimize the use of effects by making sure they do not run if nobody is around to perceive it.
|
||||
/proc/check_for_player_proximity(var/atom/proximity_to, var/radius = 12, var/ignore_ghosts = FALSE, var/ignore_afk = TRUE)
|
||||
if(!proximity_to)
|
||||
return FALSE
|
||||
|
||||
for(var/thing in player_list)
|
||||
var/mob/M = thing // Avoiding typechecks for more speed, player_list will only contain mobs anyways.
|
||||
if(ignore_ghosts && isobserver(M))
|
||||
continue
|
||||
if(ignore_afk && M.client && M.client.is_afk(5 MINUTES))
|
||||
continue
|
||||
if(M.z == proximity_to.z && get_dist(M, proximity_to) <= radius)
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -10,6 +10,7 @@
|
||||
var/mineitemtype = /obj/item/weapon/mine
|
||||
var/panel_open = 0
|
||||
var/datum/wires/mines/wires = null
|
||||
register_as_dangerous_object = TRUE
|
||||
|
||||
/obj/effect/mine/New()
|
||||
icon_state = "uglyminearmed"
|
||||
@@ -271,4 +272,10 @@
|
||||
/obj/item/weapon/mine/incendiary
|
||||
name = "incendiary mine"
|
||||
desc = "A small explosive mine with a fire symbol on the side."
|
||||
minetype = /obj/effect/mine/incendiary
|
||||
minetype = /obj/effect/mine/incendiary
|
||||
|
||||
// This tells AI mobs to not be dumb and step on mines willingly.
|
||||
/obj/item/weapon/mine/is_safe_to_step(mob/living/L)
|
||||
if(!L.hovering)
|
||||
return FALSE
|
||||
return ..()
|
||||
@@ -3,7 +3,8 @@
|
||||
/obj/effect/step_trigger
|
||||
var/affect_ghosts = 0
|
||||
var/stopper = 1 // stops throwers
|
||||
invisibility = 101 // nope cant see this shit
|
||||
invisibility = 99 // nope cant see this shit
|
||||
plane = ABOVE_PLANE
|
||||
anchored = 1
|
||||
|
||||
/obj/effect/step_trigger/proc/Trigger(var/atom/movable/A)
|
||||
@@ -93,21 +94,56 @@
|
||||
var/teleport_y = 0
|
||||
var/teleport_z = 0
|
||||
|
||||
Trigger(var/atom/movable/A)
|
||||
if(teleport_x && teleport_y && teleport_z)
|
||||
var/turf/T = locate(teleport_x, teleport_y, teleport_z)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(L.pulling)
|
||||
var/atom/movable/P = L.pulling
|
||||
L.stop_pulling()
|
||||
P.forceMove(T)
|
||||
L.forceMove(T)
|
||||
L.start_pulling(P)
|
||||
else
|
||||
A.forceMove(T)
|
||||
else
|
||||
A.forceMove(T)
|
||||
/obj/effect/step_trigger/teleporter/Trigger(atom/movable/AM)
|
||||
if(teleport_x && teleport_y && teleport_z)
|
||||
var/turf/T = locate(teleport_x, teleport_y, teleport_z)
|
||||
move_object(AM, T)
|
||||
|
||||
|
||||
/obj/effect/step_trigger/teleporter/proc/move_object(atom/movable/AM, turf/T)
|
||||
if(AM.anchored)
|
||||
return
|
||||
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.pulling)
|
||||
var/atom/movable/P = L.pulling
|
||||
L.stop_pulling()
|
||||
P.forceMove(T)
|
||||
L.forceMove(T)
|
||||
L.start_pulling(P)
|
||||
else
|
||||
L.forceMove(T)
|
||||
else
|
||||
AM.forceMove(T)
|
||||
|
||||
/* Moves things by an offset, useful for 'Bridges'. Uses dir and a distance var to work with maploader direction changes. */
|
||||
/obj/effect/step_trigger/teleporter/offset
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "arrow"
|
||||
var/distance = 3
|
||||
|
||||
/obj/effect/step_trigger/teleporter/offset/north
|
||||
dir = NORTH
|
||||
|
||||
/obj/effect/step_trigger/teleporter/offset/south
|
||||
dir = SOUTH
|
||||
|
||||
/obj/effect/step_trigger/teleporter/offset/east
|
||||
dir = EAST
|
||||
|
||||
/obj/effect/step_trigger/teleporter/offset/west
|
||||
dir = WEST
|
||||
|
||||
/obj/effect/step_trigger/teleporter/offset/Trigger(atom/movable/AM)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/i = 1 to distance)
|
||||
T = get_step(T, dir)
|
||||
if(!istype(T))
|
||||
return
|
||||
move_object(AM, T)
|
||||
|
||||
|
||||
|
||||
/* Random teleporter, teleports atoms to locations ranging from teleport_x - teleport_x_offset, etc */
|
||||
|
||||
|
||||
@@ -18,11 +18,29 @@
|
||||
var/can_speak = 0 //For MMIs and admin trickery. If an object has a brainmob in its contents, set this to 1 to allow it to speak.
|
||||
|
||||
var/show_examine = TRUE // Does this pop up on a mob when the mob is examined?
|
||||
var/register_as_dangerous_object = FALSE // Should this tell its turf that it is dangerous automatically?
|
||||
|
||||
/obj/Initialize()
|
||||
if(register_as_dangerous_object)
|
||||
register_dangerous_to_step()
|
||||
return ..()
|
||||
|
||||
/obj/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(register_as_dangerous_object)
|
||||
unregister_dangerous_to_step()
|
||||
return ..()
|
||||
|
||||
/obj/Moved(atom/oldloc)
|
||||
. = ..()
|
||||
if(register_as_dangerous_object)
|
||||
var/turf/old_turf = get_turf(oldloc)
|
||||
var/turf/new_turf = get_turf(src)
|
||||
|
||||
if(old_turf != new_turf)
|
||||
old_turf.unregister_dangerous_object(src)
|
||||
new_turf.register_dangerous_object(src)
|
||||
|
||||
/obj/Topic(href, href_list, var/datum/topic_state/state = default_state)
|
||||
if(usr && ..())
|
||||
return 1
|
||||
@@ -161,4 +179,19 @@
|
||||
return
|
||||
|
||||
/obj/proc/get_cell()
|
||||
return
|
||||
return
|
||||
|
||||
// Used to mark a turf as containing objects that are dangerous to step onto.
|
||||
/obj/proc/register_dangerous_to_step()
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
T.register_dangerous_object(src)
|
||||
|
||||
/obj/proc/unregister_dangerous_to_step()
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
T.unregister_dangerous_object(src)
|
||||
|
||||
// Test for if stepping on a tile containing this obj is safe to do, used for things like landmines and cliffs.
|
||||
/obj/proc/is_safe_to_step(mob/living/L)
|
||||
return TRUE
|
||||
@@ -1,149 +1,149 @@
|
||||
/*
|
||||
Semi-randomized loot for PoIs involving medicine.
|
||||
Note that most of these include both 'good' and 'bad' results, with the bad results often being
|
||||
much more likely to show up. This is done for several purposes;
|
||||
|
||||
* A large influx of valuable medicine makes medical/SAR less needed for explorers, which is something we want to avoid.
|
||||
* Blindly using autoinjectors should be risky, and to accomplish that, it needs to be more likely to get a bad effect.
|
||||
* A large amount of bad loot helps make the good loot feel better to acquire.
|
||||
|
||||
*/
|
||||
|
||||
// This one makes a purely random hypo. Not recommended for PoIs since it will produce nonsensical results for a PoI's theme.
|
||||
// It's more of a thing to help pick specific hypos for the other lists.
|
||||
/obj/random/unidentified_medicine
|
||||
name = "unidentified medicine"
|
||||
desc = "This will make a random hypo."
|
||||
icon = 'icons/obj/syringe.dmi'
|
||||
item_state = "hypo"
|
||||
|
||||
/obj/random/unidentified_medicine/item_to_spawn()
|
||||
return pick(
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mindbreaker/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/psilocybin/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/impedrezene/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified)
|
||||
|
||||
// Produces things you might find in an old medicine cabinet in a PoI.
|
||||
// Old cabinets are typical of ruins and abandoned buildings in the plains, meaning they're usually easier to reach, and as such, inferior loot.
|
||||
/obj/random/unidentified_medicine/old_medicine/item_to_spawn()
|
||||
// 30 Good, 70 Bad. 30% to get something good.
|
||||
// Poor odds, but these are fairly easy to reach as they're in abandoned areas.
|
||||
return pick(
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(65);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified)
|
||||
|
||||
// Medicine belonging to a place still being occupied (or was recently), meaning the goods might still be fresh, and better.
|
||||
/obj/random/unidentified_medicine/fresh_medicine/item_to_spawn()
|
||||
// More likely to get something good, and a chance to get rare medicines.
|
||||
// 75 Good, 25 Bad. 75% chance of getting something good.
|
||||
// Good odds, but the contents aren't super great unless someone gets lucky.
|
||||
return pick(
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(25);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified)
|
||||
|
||||
// For military PoIs like BSD. High odds of good loot since those PoIs are really hard.
|
||||
/obj/random/unidentified_medicine/combat_medicine/item_to_spawn()
|
||||
// More likely to get something good, and a chance to get rare medicines.
|
||||
// 75 Good, 30 Bad, roughly 71.4% chance to get something good.
|
||||
// Very high but very hard to reach and still has a chance of ending poorly if injecting blind.
|
||||
return pick(
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific/unidentified,
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified)
|
||||
|
||||
// Hyposprays found inside various illicit places.
|
||||
/obj/random/unidentified_medicine/drug_den/item_to_spawn()
|
||||
// Combat stims are common, but so are nasty drugs.
|
||||
// 65 Good, 160 Bad, roughly 28.8% to get something good.
|
||||
// Poor odds, but there are a lot of these scattered in the drug dens and illegal chem labs.
|
||||
return pick(
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(40);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mindbreaker/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/psilocybin/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/impedrezene/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified)
|
||||
|
||||
// Medicine made FOR SCIENCE.
|
||||
/obj/random/unidentified_medicine/scientific/item_to_spawn()
|
||||
// Potential for amazing loot, also potential for very nasty consequences if injecting blind.
|
||||
// 45 Good, 45 Bad, 50% chance to get something good.
|
||||
// Do you feel lucky?
|
||||
return pick(
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites/unidentified)
|
||||
|
||||
// Nanomachines, son. Found in very advanced places such as the Crashed UFO.
|
||||
/obj/random/unidentified_medicine/nanites/item_to_spawn()
|
||||
// You better identify this if you value your life.
|
||||
// 30 Good, 70 Bad. 30% of getting a good outcome.
|
||||
return pick(
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified,
|
||||
prob(70);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites/unidentified)
|
||||
|
||||
// Found in virus-related areas like the Quarantined Shuttle.
|
||||
/obj/random/unidentified_medicine/viral/item_to_spawn()
|
||||
// Another one where's its important to identify the hypo.
|
||||
// 30 Good, 70 Bad. 30% of getting a good outcome.
|
||||
return pick(
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
prob(40);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen/unidentified,
|
||||
/*
|
||||
Semi-randomized loot for PoIs involving medicine.
|
||||
Note that most of these include both 'good' and 'bad' results, with the bad results often being
|
||||
much more likely to show up. This is done for several purposes;
|
||||
|
||||
* A large influx of valuable medicine makes medical/SAR less needed for explorers, which is something we want to avoid.
|
||||
* Blindly using autoinjectors should be risky, and to accomplish that, it needs to be more likely to get a bad effect.
|
||||
* A large amount of bad loot helps make the good loot feel better to acquire.
|
||||
|
||||
*/
|
||||
|
||||
// This one makes a purely random hypo. Not recommended for PoIs since it will produce nonsensical results for a PoI's theme.
|
||||
// It's more of a thing to help pick specific hypos for the other lists.
|
||||
/obj/random/unidentified_medicine
|
||||
name = "unidentified medicine"
|
||||
desc = "This will make a random hypo."
|
||||
icon = 'icons/obj/syringe.dmi'
|
||||
icon_state = "autoinjector1"
|
||||
|
||||
/obj/random/unidentified_medicine/item_to_spawn()
|
||||
return pick(
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mindbreaker/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/psilocybin/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/impedrezene/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites/unidentified,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified)
|
||||
|
||||
// Produces things you might find in an old medicine cabinet in a PoI.
|
||||
// Old cabinets are typical of ruins and abandoned buildings in the plains, meaning they're usually easier to reach, and as such, inferior loot.
|
||||
/obj/random/unidentified_medicine/old_medicine/item_to_spawn()
|
||||
// 30 Good, 70 Bad. 30% to get something good.
|
||||
// Poor odds, but these are fairly easy to reach as they're in abandoned areas.
|
||||
return pick(
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(65);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified)
|
||||
|
||||
// Medicine belonging to a place still being occupied (or was recently), meaning the goods might still be fresh, and better.
|
||||
/obj/random/unidentified_medicine/fresh_medicine/item_to_spawn()
|
||||
// More likely to get something good, and a chance to get rare medicines.
|
||||
// 75 Good, 25 Bad. 75% chance of getting something good.
|
||||
// Good odds, but the contents aren't super great unless someone gets lucky.
|
||||
return pick(
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(25);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified)
|
||||
|
||||
// For military PoIs like BSD. High odds of good loot since those PoIs are really hard.
|
||||
/obj/random/unidentified_medicine/combat_medicine/item_to_spawn()
|
||||
// More likely to get something good, and a chance to get rare medicines.
|
||||
// 75 Good, 30 Bad, roughly 71.4% chance to get something good.
|
||||
// Very high but very hard to reach and still has a chance of ending poorly if injecting blind.
|
||||
return pick(
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific/unidentified,
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified)
|
||||
|
||||
// Hyposprays found inside various illicit places.
|
||||
/obj/random/unidentified_medicine/drug_den/item_to_spawn()
|
||||
// Combat stims are common, but so are nasty drugs.
|
||||
// 65 Good, 160 Bad, roughly 28.8% to get something good.
|
||||
// Poor odds, but there are a lot of these scattered in the drug dens and illegal chem labs.
|
||||
return pick(
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(40);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mindbreaker/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/psilocybin/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/impedrezene/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified)
|
||||
|
||||
// Medicine made FOR SCIENCE.
|
||||
/obj/random/unidentified_medicine/scientific/item_to_spawn()
|
||||
// Potential for amazing loot, also potential for very nasty consequences if injecting blind.
|
||||
// 45 Good, 45 Bad, 50% chance to get something good.
|
||||
// Do you feel lucky?
|
||||
return pick(
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen/unidentified,
|
||||
prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites/unidentified)
|
||||
|
||||
// Nanomachines, son. Found in very advanced places such as the Crashed UFO.
|
||||
/obj/random/unidentified_medicine/nanites/item_to_spawn()
|
||||
// You better identify this if you value your life.
|
||||
// 30 Good, 70 Bad. 30% of getting a good outcome.
|
||||
return pick(
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified,
|
||||
prob(70);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites/unidentified)
|
||||
|
||||
// Found in virus-related areas like the Quarantined Shuttle.
|
||||
/obj/random/unidentified_medicine/viral/item_to_spawn()
|
||||
// Another one where's its important to identify the hypo.
|
||||
// 30 Good, 70 Bad. 30% of getting a good outcome.
|
||||
return pick(
|
||||
prob(30);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified,
|
||||
prob(40);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified,
|
||||
prob(10);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen/unidentified,
|
||||
prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified)
|
||||
@@ -3,9 +3,11 @@
|
||||
w_class = ITEMSIZE_NO_CONTAINER
|
||||
|
||||
var/climbable
|
||||
var/climb_delay = 3.5 SECONDS
|
||||
var/breakable
|
||||
var/parts
|
||||
var/list/climbers = list()
|
||||
var/block_turf_edges = FALSE // If true, turf edge icons will not be made on the turf this occupies.
|
||||
|
||||
/obj/structure/Destroy()
|
||||
if(parts)
|
||||
@@ -99,7 +101,7 @@
|
||||
usr.visible_message("<span class='warning'>[user] starts climbing onto \the [src]!</span>")
|
||||
climbers |= user
|
||||
|
||||
if(!do_after(user,(issmall(user) ? 20 : 34)))
|
||||
if(!do_after(user,(issmall(user) ? climb_delay * 0.6 : climb_delay)))
|
||||
climbers -= user
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
GLOBAL_LIST_EMPTY(cliff_icon_cache)
|
||||
|
||||
/*
|
||||
Cliffs give a visual illusion of depth by seperating two places while presenting a 'top' and 'bottom' side.
|
||||
|
||||
Mobs moving into a cliff from the bottom side will simply bump into it and be denied moving into the tile,
|
||||
where as mobs moving into a cliff from the top side will 'fall' off the cliff, forcing them to the bottom, causing significant damage and stunning them.
|
||||
|
||||
Mobs can climb this while wearing climbing equipment by clickdragging themselves onto a cliff, as if it were a table.
|
||||
|
||||
Flying mobs can pass over all cliffs with no risk of falling.
|
||||
|
||||
Projectiles and thrown objects can pass, however if moving upwards, there is a chance for it to be stopped by the cliff.
|
||||
This makes fighting something that is on top of a cliff more challenging.
|
||||
|
||||
As a note, dir points upwards, e.g. pointing WEST means the left side is 'up', and the right side is 'down'.
|
||||
|
||||
When mapping these in, be sure to give at least a one tile clearance, as NORTH facing cliffs expand to
|
||||
two tiles on initialization, and which way a cliff is facing may change during maploading.
|
||||
*/
|
||||
|
||||
/obj/structure/cliff
|
||||
name = "cliff"
|
||||
desc = "A steep rock ledge. You might be able to climb it if you feel bold enough."
|
||||
description_info = "Walking off the edge of a cliff while on top will cause you to fall off, causing severe injury.<br>\
|
||||
You can climb this cliff if wearing special climbing equipment, by click-dragging yourself onto the cliff.<br>\
|
||||
Projectiles traveling up a cliff may hit the cliff instead, making it more difficult to fight something \
|
||||
on top."
|
||||
icon = 'icons/obj/flora/rocks.dmi'
|
||||
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
opacity = FALSE
|
||||
climbable = TRUE
|
||||
climb_delay = 10 SECONDS
|
||||
block_turf_edges = TRUE // Don't want turf edges popping up from the cliff edge.
|
||||
register_as_dangerous_object = TRUE
|
||||
|
||||
var/icon_variant = null // Used to make cliffs less repeative by having a selection of sprites to display.
|
||||
var/corner = FALSE // Used for icon things.
|
||||
var/ramp = FALSE // Ditto.
|
||||
var/bottom = FALSE // Used for 'bottom' typed cliffs, to avoid infinite cliffs, and for icons.
|
||||
|
||||
var/is_double_cliff = FALSE // Set to true when making the two-tile cliffs, used for projectile checks.
|
||||
var/uphill_penalty = 30 // Odds of a projectile not making it up the cliff.
|
||||
|
||||
// These arrange their sprites at runtime, as opposed to being statically placed in the map file.
|
||||
/obj/structure/cliff/automatic
|
||||
icon_state = "cliffbuilder"
|
||||
dir = NORTH
|
||||
|
||||
/obj/structure/cliff/automatic/corner
|
||||
icon_state = "cliffbuilder-corner"
|
||||
dir = NORTHEAST
|
||||
corner = TRUE
|
||||
|
||||
// Tiny part that doesn't block, used for making 'ramps'.
|
||||
/obj/structure/cliff/automatic/ramp
|
||||
icon_state = "cliffbuilder-ramp"
|
||||
dir = NORTHEAST
|
||||
density = FALSE
|
||||
ramp = TRUE
|
||||
|
||||
// Made automatically as needed by automatic cliffs.
|
||||
/obj/structure/cliff/bottom
|
||||
bottom = TRUE
|
||||
|
||||
/obj/structure/cliff/automatic/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
// Paranoid about the maploader, direction is very important to cliffs, since they may get bigger if initialized while facing NORTH.
|
||||
/obj/structure/cliff/automatic/LateInitialize()
|
||||
if(dir in GLOB.cardinal)
|
||||
icon_variant = pick("a", "b", "c")
|
||||
|
||||
if(dir & NORTH && !bottom) // North-facing cliffs require more cliffs to be made.
|
||||
make_bottom()
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/structure/cliff/proc/make_bottom()
|
||||
// First, make sure there's room to put the bottom side.
|
||||
var/turf/T = locate(x, y - 1, z)
|
||||
if(!istype(T))
|
||||
return FALSE
|
||||
|
||||
// Now make the bottom cliff have mostly the same variables.
|
||||
var/obj/structure/cliff/bottom/bottom = new(T)
|
||||
is_double_cliff = TRUE
|
||||
climb_delay /= 2 // Since there are two cliffs to climb when going north, both take half the time.
|
||||
|
||||
bottom.dir = dir
|
||||
bottom.is_double_cliff = TRUE
|
||||
bottom.climb_delay = climb_delay
|
||||
bottom.icon_variant = icon_variant
|
||||
bottom.corner = corner
|
||||
bottom.ramp = ramp
|
||||
bottom.layer = layer - 0.1
|
||||
bottom.density = density
|
||||
bottom.update_icon()
|
||||
|
||||
/obj/structure/cliff/set_dir(new_dir)
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/structure/cliff/update_icon()
|
||||
icon_state = "cliff-[dir][icon_variant][bottom ? "-bottom" : ""][corner ? "-corner" : ""][ramp ? "-ramp" : ""]"
|
||||
|
||||
// Now for making the top-side look like a different turf.
|
||||
var/turf/T = get_step(src, dir)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
var/subtraction_icon_state = "[icon_state]-subtract"
|
||||
var/cache_string = "[icon_state]_[T.icon]_[T.icon_state]"
|
||||
if(T && subtraction_icon_state in icon_states(icon))
|
||||
cut_overlays()
|
||||
// If we've made the same icon before, just recycle it.
|
||||
if(cache_string in GLOB.cliff_icon_cache)
|
||||
add_overlay(GLOB.cliff_icon_cache[cache_string])
|
||||
|
||||
else // Otherwise make a new one, but only once.
|
||||
var/icon/underlying_ground = icon(T.icon, T.icon_state, T.dir)
|
||||
var/icon/subtract = icon(icon, subtraction_icon_state)
|
||||
underlying_ground.Blend(subtract, ICON_SUBTRACT)
|
||||
var/image/final = image(underlying_ground)
|
||||
final.layer = src.layer - 0.2
|
||||
GLOB.cliff_icon_cache[cache_string] = final
|
||||
add_overlay(final)
|
||||
|
||||
|
||||
// Movement-related code.
|
||||
|
||||
/obj/structure/cliff/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0)
|
||||
if(air_group || height == 0)
|
||||
return TRUE // Airflow can always pass.
|
||||
|
||||
else if(isliving(mover))
|
||||
var/mob/living/L = mover
|
||||
if(L.hovering) // Flying mobs can always pass.
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
// Projectiles and objects flying 'upward' have a chance to hit the cliff instead, wasting the shot.
|
||||
else if(istype(mover, /obj))
|
||||
var/obj/O = mover
|
||||
if(check_shield_arc(src, dir, O)) // This is actually for mobs but it will work for our purposes as well.
|
||||
if(prob(uphill_penalty / (1 + is_double_cliff) )) // Firing upwards facing NORTH means it will likely have to pass through two cliffs, so the chance is halved.
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/cliff/Bumped(atom/A)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(should_fall(L))
|
||||
fall_off_cliff(L)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/structure/cliff/proc/should_fall(mob/living/L)
|
||||
if(L.hovering)
|
||||
return FALSE
|
||||
|
||||
var/turf/T = get_turf(L)
|
||||
if(T && get_dir(T, loc) & reverse_dir[dir]) // dir points 'up' the cliff, e.g. cliff pointing NORTH will cause someone to fall if moving SOUTH into it.
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/cliff/proc/fall_off_cliff(mob/living/L)
|
||||
if(!istype(L))
|
||||
return FALSE
|
||||
var/turf/T = get_step(src, reverse_dir[dir])
|
||||
var/displaced = FALSE
|
||||
|
||||
if(dir in list(EAST, WEST)) // Apply an offset if flying sideways, to help maintain the illusion of depth.
|
||||
for(var/i = 1 to 2)
|
||||
var/turf/new_T = locate(T.x, T.y - i, T.z)
|
||||
if(!new_T || locate(/obj/structure/cliff) in new_T)
|
||||
break
|
||||
T = new_T
|
||||
displaced = TRUE
|
||||
|
||||
if(istype(T))
|
||||
visible_message(span("danger", "\The [L] falls off \the [src]!"))
|
||||
L.forceMove(T)
|
||||
|
||||
// Do the actual hurting. Double cliffs do halved damage due to them most likely hitting twice.
|
||||
var/harm = !is_double_cliff ? 1 : 0.5
|
||||
if(istype(L.buckled, /obj/vehicle)) // People falling off in vehicles will take less damage, but will damage the vehicle severely.
|
||||
var/obj/vehicle/vehicle = L.buckled
|
||||
vehicle.adjust_health(40 * harm)
|
||||
to_chat(L, span("warning", "\The [vehicle] absorbs some of the impact, damaging it."))
|
||||
harm /= 2
|
||||
|
||||
playsound(L, 'sound/effects/break_stone.ogg', 70, 1)
|
||||
L.Weaken(5 * harm)
|
||||
var/fall_time = 3
|
||||
if(displaced) // Make the fall look more natural when falling sideways.
|
||||
L.pixel_z = 32 * 2
|
||||
animate(L, pixel_z = 0, time = fall_time)
|
||||
sleep(fall_time) // A brief delay inbetween the two sounds helps sell the 'ouch' effect.
|
||||
playsound(L, "punch", 70, 1)
|
||||
shake_camera(L, 1, 1)
|
||||
visible_message(span("danger", "\The [L] hits the ground!"))
|
||||
|
||||
// The bigger they are, the harder they fall.
|
||||
// They will take at least 20 damage at the minimum, and tries to scale up to 40% of their max health.
|
||||
// This scaling is capped at 100 total damage, which occurs if the thing that fell has more than 250 health.
|
||||
var/damage = between(20, L.getMaxHealth() * 0.4, 100)
|
||||
var/target_zone = ran_zone()
|
||||
var/blocked = L.run_armor_check(target_zone, "melee") * harm
|
||||
var/soaked = L.get_armor_soak(target_zone, "melee") * harm
|
||||
|
||||
L.apply_damage(damage * harm, BRUTE, target_zone, blocked, soaked, used_weapon=src)
|
||||
|
||||
// Now fall off more cliffs below this one if they exist.
|
||||
var/obj/structure/cliff/bottom_cliff = locate() in T
|
||||
if(bottom_cliff)
|
||||
visible_message(span("danger", "\The [L] rolls down towards \the [bottom_cliff]!"))
|
||||
sleep(5)
|
||||
bottom_cliff.fall_off_cliff(L)
|
||||
|
||||
/obj/structure/cliff/can_climb(mob/living/user, post_climb_check = FALSE)
|
||||
// Cliff climbing requires climbing gear.
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/clothing/shoes/shoes = H.shoes
|
||||
if(shoes && shoes.rock_climbing)
|
||||
return ..() // Do the other checks too.
|
||||
|
||||
to_chat(user, span("warning", "\The [src] is too steep to climb unassisted."))
|
||||
return FALSE
|
||||
|
||||
// This tells AI mobs to not be dumb and step off cliffs willingly.
|
||||
/obj/structure/cliff/is_safe_to_step(mob/living/L)
|
||||
if(should_fall(L))
|
||||
return FALSE
|
||||
return ..()
|
||||
@@ -0,0 +1,179 @@
|
||||
//Chain link fences
|
||||
//Sprites ported from /VG/
|
||||
|
||||
#define CUT_TIME 10 SECONDS
|
||||
#define CLIMB_TIME 5 SECONDS
|
||||
|
||||
#define NO_HOLE 0 //section is intact
|
||||
#define MEDIUM_HOLE 1 //medium hole in the section - can climb through
|
||||
#define LARGE_HOLE 2 //large hole in the section - can walk through
|
||||
#define MAX_HOLE_SIZE LARGE_HOLE
|
||||
|
||||
/obj/structure/fence
|
||||
name = "fence"
|
||||
desc = "A chain link fence. Not as effective as a wall, but generally it keeps people out."
|
||||
description_info = "Projectiles can freely pass fences."
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
|
||||
icon = 'icons/obj/fence.dmi'
|
||||
icon_state = "straight"
|
||||
|
||||
var/cuttable = TRUE
|
||||
var/hole_size= NO_HOLE
|
||||
var/invulnerable = FALSE
|
||||
|
||||
/obj/structure/fence/Initialize()
|
||||
update_cut_status()
|
||||
return ..()
|
||||
|
||||
/obj/structure/fence/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
switch(hole_size)
|
||||
if(MEDIUM_HOLE)
|
||||
user.show_message("There is a large hole in \the [src].")
|
||||
if(LARGE_HOLE)
|
||||
user.show_message("\The [src] has been completely cut through.")
|
||||
|
||||
/obj/structure/fence/get_description_interaction()
|
||||
var/list/results = list()
|
||||
if(cuttable && !invulnerable && hole_size < MAX_HOLE_SIZE)
|
||||
results += "[desc_panel_image("wirecutters")]to [hole_size > NO_HOLE ? "expand the":"cut a"] hole into the fence, allowing passage."
|
||||
return results
|
||||
|
||||
/obj/structure/fence/end
|
||||
icon_state = "end"
|
||||
cuttable = FALSE
|
||||
|
||||
/obj/structure/fence/corner
|
||||
icon_state = "corner"
|
||||
cuttable = FALSE
|
||||
|
||||
/obj/structure/fence/post
|
||||
icon_state = "post"
|
||||
cuttable = FALSE
|
||||
|
||||
/obj/structure/fence/cut/medium
|
||||
icon_state = "straight_cut2"
|
||||
hole_size = MEDIUM_HOLE
|
||||
|
||||
/obj/structure/fence/cut/large
|
||||
icon_state = "straight_cut3"
|
||||
hole_size = LARGE_HOLE
|
||||
|
||||
// Projectiles can pass through fences.
|
||||
/obj/structure/fence/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0)
|
||||
if(istype(mover, /obj/item/projectile))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/fence/attackby(obj/item/W, mob/user)
|
||||
if(W.is_wirecutter())
|
||||
if(!cuttable)
|
||||
to_chat(user, span("warning", "This section of the fence can't be cut."))
|
||||
return
|
||||
if(invulnerable)
|
||||
to_chat(user, span("warning", "This fence is too strong to cut through."))
|
||||
return
|
||||
var/current_stage = hole_size
|
||||
if(current_stage >= MAX_HOLE_SIZE)
|
||||
to_chat(user, span("notice", "This fence has too much cut out of it already."))
|
||||
return
|
||||
|
||||
user.visible_message(span("danger", "\The [user] starts cutting through \the [src] with \the [W]."),\
|
||||
span("danger", "You start cutting through \the [src] with \the [W]."))
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
|
||||
if(do_after(user, CUT_TIME * W.toolspeed, target = src))
|
||||
if(current_stage == hole_size)
|
||||
switch(++hole_size)
|
||||
if(MEDIUM_HOLE)
|
||||
visible_message(span("notice", "\The [user] cuts into \the [src] some more."))
|
||||
to_chat(user, span("notice", "You could probably fit yourself through that hole now. Although climbing through would be much faster if you made it even bigger."))
|
||||
climbable = TRUE
|
||||
if(LARGE_HOLE)
|
||||
visible_message(span("notice", "\The [user] completely cuts through \the [src]."))
|
||||
to_chat(user, span("notice", "The hole in \the [src] is now big enough to walk through."))
|
||||
climbable = FALSE
|
||||
update_cut_status()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/fence/proc/update_cut_status()
|
||||
if(!cuttable)
|
||||
return
|
||||
density = TRUE
|
||||
|
||||
switch(hole_size)
|
||||
if(NO_HOLE)
|
||||
icon_state = initial(icon_state)
|
||||
if(MEDIUM_HOLE)
|
||||
icon_state = "straight_cut2"
|
||||
if(LARGE_HOLE)
|
||||
icon_state = "straight_cut3"
|
||||
density = FALSE
|
||||
|
||||
//FENCE DOORS
|
||||
|
||||
/obj/structure/fence/door
|
||||
name = "fence door"
|
||||
desc = "Not very useful without a real lock."
|
||||
icon_state = "door_closed"
|
||||
cuttable = FALSE
|
||||
var/open = FALSE
|
||||
var/locked = FALSE
|
||||
|
||||
/obj/structure/fence/door/Initialize()
|
||||
update_door_status()
|
||||
return ..()
|
||||
|
||||
/obj/structure/fence/door/opened
|
||||
icon_state = "door_opened"
|
||||
open = TRUE
|
||||
density = TRUE
|
||||
|
||||
/obj/structure/fence/door/locked
|
||||
desc = "It looks like it has a strong padlock attached."
|
||||
locked = TRUE
|
||||
|
||||
/obj/structure/fence/door/attack_hand(mob/user)
|
||||
if(can_open(user))
|
||||
toggle(user)
|
||||
else
|
||||
to_chat(user, span("warning", "\The [src] is [!open ? "locked" : "stuck open"]."))
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/structure/fence/door/proc/toggle(mob/user)
|
||||
switch(open)
|
||||
if(FALSE)
|
||||
visible_message(span("notice", "\The [user] opens \the [src]."))
|
||||
open = TRUE
|
||||
if(TRUE)
|
||||
visible_message(span("notice", "\The [user] closes \the [src]."))
|
||||
open = FALSE
|
||||
|
||||
update_door_status()
|
||||
playsound(src, 'sound/machines/click.ogg', 100, 1)
|
||||
|
||||
/obj/structure/fence/door/proc/update_door_status()
|
||||
switch(open)
|
||||
if(FALSE)
|
||||
density = TRUE
|
||||
icon_state = "door_closed"
|
||||
if(TRUE)
|
||||
density = FALSE
|
||||
icon_state = "door_opened"
|
||||
|
||||
/obj/structure/fence/door/proc/can_open(mob/user)
|
||||
if(locked)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
#undef CUT_TIME
|
||||
#undef CLIMB_TIME
|
||||
|
||||
#undef NO_HOLE
|
||||
#undef MEDIUM_HOLE
|
||||
#undef LARGE_HOLE
|
||||
#undef MAX_HOLE_SIZE
|
||||
@@ -239,6 +239,18 @@
|
||||
name = "\improper EMERGENT INTELLIGENCE DETAILS"
|
||||
icon_state = "rogueai"
|
||||
|
||||
/obj/structure/sign/warning/falling
|
||||
name = "\improper FALL HAZARD"
|
||||
icon_state = "falling"
|
||||
|
||||
/obj/structure/sign/warning/lava
|
||||
name = "\improper MOLTEN SURFACE"
|
||||
icon_state = "lava"
|
||||
|
||||
/obj/structure/sign/warning/acid
|
||||
name = "\improper ACIDIC SURFACE"
|
||||
icon_state = "acid"
|
||||
|
||||
/obj/structure/sign/redcross
|
||||
name = "medbay"
|
||||
desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here."
|
||||
|
||||
Reference in New Issue
Block a user