mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-01-06 15:32:52 +00:00
Merge remote-tracking branch 'polaris/master' into pixel_projectiles
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
var/datum/map_template/template
|
||||
|
||||
|
||||
var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in map_templates
|
||||
var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in SSmapping.map_templates
|
||||
if(!map)
|
||||
return
|
||||
template = map_templates[map]
|
||||
template = SSmapping.map_templates[map]
|
||||
|
||||
var/orientation = text2dir(input(usr, "Choose an orientation for this Map Template.", "Orientation") as null|anything in list("North", "South", "East", "West"))
|
||||
if(!orientation)
|
||||
@@ -41,10 +41,10 @@
|
||||
|
||||
var/datum/map_template/template
|
||||
|
||||
var/map = input(usr, "Choose a Map Template to place on a new Z-level.","Place Map Template") as null|anything in map_templates
|
||||
var/map = input(usr, "Choose a Map Template to place on a new Z-level.","Place Map Template") as null|anything in SSmapping.map_templates
|
||||
if(!map)
|
||||
return
|
||||
template = map_templates[map]
|
||||
template = SSmapping.map_templates[map]
|
||||
|
||||
var/orientation = text2dir(input(usr, "Choose an orientation for this Map Template.", "Orientation") as null|anything in list("North", "South", "East", "West"))
|
||||
if(!orientation)
|
||||
@@ -76,7 +76,7 @@
|
||||
var/datum/map_template/M = new(map, "[map]")
|
||||
if(M.preload_size(map))
|
||||
to_chat(usr, "Map template '[map]' ready to place ([M.width]x[M.height])")
|
||||
map_templates[M.name] = M
|
||||
SSmapping.map_templates[M.name] = M
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has uploaded a map template ([map])</span>")
|
||||
else
|
||||
to_chat(usr, "Map template '[map]' failed to load properly")
|
||||
|
||||
@@ -244,42 +244,34 @@ datum/gear/suit/duster
|
||||
/datum/gear/suit/roles/poncho/cloak/cargo
|
||||
display_name = "cloak, cargo"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/cargo
|
||||
allowed_roles = list("Cargo Technician","Quartermaster")
|
||||
|
||||
/datum/gear/suit/roles/poncho/cloak/mining
|
||||
display_name = "cloak, mining"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/mining
|
||||
allowed_roles = list("Quartermaster","Shaft Miner")
|
||||
|
||||
/datum/gear/suit/roles/poncho/cloak/security
|
||||
display_name = "cloak, security"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/security
|
||||
allowed_roles = list("Head of Security","Detective","Warden","Security Officer")
|
||||
|
||||
/datum/gear/suit/roles/poncho/cloak/service
|
||||
display_name = "cloak, service"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/service
|
||||
allowed_roles = list("Head of Personnel","Bartender","Botanist","Janitor","Chef","Librarian")
|
||||
|
||||
/datum/gear/suit/roles/poncho/cloak/engineer
|
||||
display_name = "cloak, engineer"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/engineer
|
||||
allowed_roles = list("Chief Engineer","Station Engineer")
|
||||
|
||||
/datum/gear/suit/roles/poncho/cloak/atmos
|
||||
display_name = "cloak, atmos"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/atmos
|
||||
allowed_roles = list("Chief Engineer","Atmospheric Technician")
|
||||
|
||||
/datum/gear/suit/roles/poncho/cloak/research
|
||||
display_name = "cloak, science"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/research
|
||||
allowed_roles = list("Research Director","Scientist", "Roboticist", "Xenobiologist")
|
||||
|
||||
/datum/gear/suit/roles/poncho/cloak/medical
|
||||
display_name = "cloak, medical"
|
||||
path = /obj/item/clothing/accessory/poncho/roles/cloak/medical
|
||||
allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist")
|
||||
|
||||
/datum/gear/suit/unathi_robe
|
||||
display_name = "roughspun robe"
|
||||
@@ -499,4 +491,4 @@ datum/gear/suit/duster
|
||||
/datum/gear/suit/snowsuit/cargo
|
||||
display_name = "snowsuit, supply"
|
||||
path = /obj/item/clothing/suit/storage/snowsuit/cargo
|
||||
allowed_roles = list("Quartermaster","Shaft Miner","Cargo Technician","Head of Personnel")
|
||||
allowed_roles = list("Quartermaster","Shaft Miner","Cargo Technician","Head of Personnel")
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
var/list/error_last_seen = list()
|
||||
// error_cooldown items will either be positive (cooldown time) or negative (silenced error)
|
||||
// If negative, starts at -1, and goes down by 1 each time that error gets skipped
|
||||
var/list/error_cooldown = list()
|
||||
var/total_runtimes = 0
|
||||
var/total_runtimes_skipped = 0
|
||||
// The ifdef needs to be down here, since the error viewer references total_runtimes
|
||||
@@ -10,18 +8,18 @@ var/total_runtimes_skipped = 0
|
||||
if(!istype(e)) // Something threw an unusual exception
|
||||
log_error("\[[time_stamp()]] Uncaught exception: [e]")
|
||||
return ..()
|
||||
if(!error_last_seen) // A runtime is occurring too early in start-up initialization
|
||||
if(!GLOB.error_last_seen) // A runtime is occurring too early in start-up initialization
|
||||
return ..()
|
||||
total_runtimes++
|
||||
|
||||
var/erroruid = "[e.file][e.line]"
|
||||
var/last_seen = error_last_seen[erroruid]
|
||||
var/cooldown = error_cooldown[erroruid] || 0
|
||||
var/last_seen = GLOB.error_last_seen[erroruid]
|
||||
var/cooldown = GLOB.error_cooldown[erroruid] || 0
|
||||
if(last_seen == null) // A new error!
|
||||
error_last_seen[erroruid] = world.time
|
||||
GLOB.error_last_seen[erroruid] = world.time
|
||||
last_seen = world.time
|
||||
if(cooldown < 0)
|
||||
error_cooldown[erroruid]-- // Used to keep track of skip count for this error
|
||||
GLOB.error_cooldown[erroruid]-- // Used to keep track of skip count for this error
|
||||
total_runtimes_skipped++
|
||||
return // Error is currently silenced, skip handling it
|
||||
|
||||
@@ -36,13 +34,13 @@ var/total_runtimes_skipped = 0
|
||||
spawn(0)
|
||||
usr = null
|
||||
sleep(ERROR_SILENCE_TIME)
|
||||
var/skipcount = abs(error_cooldown[erroruid]) - 1
|
||||
error_cooldown[erroruid] = 0
|
||||
var/skipcount = abs(GLOB.error_cooldown[erroruid]) - 1
|
||||
GLOB.error_cooldown[erroruid] = 0
|
||||
if(skipcount > 0)
|
||||
log_error("\[[time_stamp()]] Skipped [skipcount] runtimes in [e.file],[e.line].")
|
||||
error_cache.logError(e, skipCount = skipcount)
|
||||
error_last_seen[erroruid] = world.time
|
||||
error_cooldown[erroruid] = cooldown
|
||||
GLOB.error_last_seen[erroruid] = world.time
|
||||
GLOB.error_cooldown[erroruid] = cooldown
|
||||
|
||||
// The detailed error info needs some tweaking to make it look nice
|
||||
var/list/srcinfo = null
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
watching_mob = user
|
||||
GLOB.moved_event.register(watching_mob, src, /obj/machinery/station_map/proc/checkPosition)
|
||||
GLOB.dir_set_event.register(watching_mob, src, /obj/machinery/station_map/proc/checkPosition)
|
||||
destroyed_event.register(watching_mob, src, /obj/machinery/station_map/proc/stopWatching)
|
||||
GLOB.destroyed_event.register(watching_mob, src, /obj/machinery/station_map/proc/stopWatching)
|
||||
update_use_power(2)
|
||||
|
||||
if(bogus)
|
||||
@@ -154,7 +154,7 @@
|
||||
M.client.images -= holomap_datum.station_map
|
||||
GLOB.moved_event.unregister(watching_mob, src)
|
||||
GLOB.dir_set_event.unregister(watching_mob, src)
|
||||
destroyed_event.unregister(watching_mob, src)
|
||||
GLOB.destroyed_event.unregister(watching_mob, src)
|
||||
watching_mob = null
|
||||
update_use_power(1)
|
||||
|
||||
|
||||
127
code/modules/identification/identification.dm
Normal file
127
code/modules/identification/identification.dm
Normal file
@@ -0,0 +1,127 @@
|
||||
// This is a datum attached to objects to make their 'identity' be unknown initially.
|
||||
// The identitiy and properties of an unidentified object can be determined in-game through a specialized process or by potentially risky trial-and-error.
|
||||
// This is very similar to a traditional roguelike's identification system, and as such will use certain terms from those to describe them.
|
||||
// Despite this, unlike a roguelike, objects that do the same thing DO NOT have the same name/appearance/etc.
|
||||
|
||||
/datum/identification
|
||||
var/obj/holder = null // The thing the datum is 'attached' to.
|
||||
// Holds the true information.
|
||||
var/true_name = null // The real name of the object. It is copied automatically from holder, on the datum being instantiated.
|
||||
var/true_desc = null // Ditto, for desc.
|
||||
var/true_description_info = null // Ditto, for helpful examine panel entries.
|
||||
var/true_description_fluff = null // Ditto, for lore.
|
||||
var/true_description_antag = null // Ditto, for antag info (this probably won't get used).
|
||||
var/identified = IDENTITY_UNKNOWN // Can be IDENTITY_UNKNOWN, IDENTITY_PROPERTIES, IDENTITY_QUALITY, or IDENTITY_FULL.
|
||||
|
||||
// Holds what is displayed when not identified sufficently.
|
||||
var/unidentified_name = null // The name given to the object when not identified. Generated by generate_unidentified_name()
|
||||
var/unidentified_desc = "You're not too sure what this is."
|
||||
var/unidentified_description_info = "This object is unidentified, and as such its properties are unknown. Using this object may be dangerous."
|
||||
|
||||
// Lists of lists for generating names by combining one from each.
|
||||
var/list/naming_lists = list()
|
||||
|
||||
// What 'identification type' is needed to identify this.
|
||||
var/identification_type = IDENTITY_TYPE_NONE
|
||||
|
||||
/datum/identification/New(obj/new_holder)
|
||||
ASSERT(new_holder)
|
||||
holder = new_holder
|
||||
record_true_identity() // Get all the identifying features from the holder.
|
||||
update_name() // Then hide them for awhile if needed.
|
||||
|
||||
/datum/identification/Destroy()
|
||||
holder = null
|
||||
return ..()
|
||||
|
||||
// Records the object's inital identifiying features to the datum for future safekeeping.
|
||||
/datum/identification/proc/record_true_identity()
|
||||
true_name = holder.name
|
||||
true_desc = holder.desc
|
||||
true_description_info = holder.description_info
|
||||
true_description_fluff = holder.description_fluff
|
||||
true_description_antag = holder.description_antag
|
||||
|
||||
// Formally identifies the holder.
|
||||
/datum/identification/proc/identify(new_identity = IDENTITY_FULL, mob/user)
|
||||
if(new_identity & identified) // Already done.
|
||||
return
|
||||
identified |= new_identity // Set the bitflag.
|
||||
if(user)
|
||||
switch(identified)
|
||||
if(IDENTITY_QUALITY)
|
||||
to_chat(user, "<span class='notice'>You've identified \the [holder]'s quality.</span>")
|
||||
if(IDENTITY_PROPERTIES)
|
||||
to_chat(user, "<span class='notice'>You've identified \the [holder]'s functionality as a [true_name].</span>")
|
||||
if(IDENTITY_FULL)
|
||||
to_chat(user, "<span class='notice'>You've identified \the [holder] as a [true_name], and its quality.</span>")
|
||||
update_name()
|
||||
holder.update_icon()
|
||||
|
||||
// Reverses identification for whatever reason.
|
||||
/datum/identification/proc/unidentify(new_identity = IDENTITY_UNKNOWN, mob/user)
|
||||
identified &= ~new_identity // Unset the bitflag.
|
||||
update_name()
|
||||
holder.update_icon()
|
||||
if(user)
|
||||
switch(identified) // Give a message based on what's left.
|
||||
if(IDENTITY_QUALITY)
|
||||
to_chat(user, span("warning", "You forgot what \the [holder] actually did..."))
|
||||
if(IDENTITY_PROPERTIES)
|
||||
to_chat(user, span("warning", "You forgot \the [holder]'s quality..."))
|
||||
if(IDENTITY_UNKNOWN)
|
||||
to_chat(user, span("warning", "You forgot everything about \the [holder]."))
|
||||
|
||||
// Sets the holder's name to the real name if its properties are identified, or obscures it otherwise.
|
||||
/datum/identification/proc/update_name()
|
||||
if(identified & IDENTITY_PROPERTIES)
|
||||
holder.name = true_name
|
||||
holder.desc = true_desc
|
||||
holder.description_info = true_description_info
|
||||
holder.description_fluff = true_description_fluff
|
||||
holder.description_antag = true_description_antag
|
||||
return
|
||||
|
||||
if(!unidentified_name)
|
||||
unidentified_name = generate_unidentified_name()
|
||||
|
||||
holder.name = unidentified_name
|
||||
holder.desc = unidentified_desc
|
||||
holder.description_info = unidentified_description_info
|
||||
holder.description_fluff = null
|
||||
holder.description_antag = null
|
||||
|
||||
// Makes a name for an object that is not identified. It picks one string out of each list inside naming_list.
|
||||
/datum/identification/proc/generate_unidentified_name()
|
||||
if(!LAZYLEN(naming_lists))
|
||||
return "unidentified object"
|
||||
|
||||
var/list/new_name = list()
|
||||
for(var/i in naming_lists)
|
||||
var/list/current_list = i
|
||||
new_name += pick(current_list)
|
||||
return new_name.Join(" ")
|
||||
|
||||
// Used for tech-based objects.
|
||||
// Unused for now pending Future Stuff(tm).
|
||||
/datum/identification/mechanical
|
||||
naming_lists = list(
|
||||
list("unidentified", "unknown", "strange", "weird", "unfamiliar", "peculiar", "mysterious", "bizarre", "odd"),
|
||||
list("device", "apparatus", "gadget", "mechanism", "appliance", "machine", "equipment", "invention", "contraption")
|
||||
)
|
||||
identification_type = IDENTITY_TYPE_TECH
|
||||
|
||||
// Used for unidentified hypos.
|
||||
// Their contents can range from genuine medication, expired medicine, illicit drugs, toxins and poisons, and more.
|
||||
// They are the analog for potions in a traditional roguelike.
|
||||
/datum/identification/hypo
|
||||
naming_lists = list(
|
||||
list("unidentified", "unknown", "unmarked", "blank", "refilled", "custom", "modified", "questionable", "suspicious"),
|
||||
list("hypospray", "autoinjector")
|
||||
)
|
||||
unidentified_desc = "An autoinjector that does not give any indication towards what is inside. \
|
||||
The case is also sealed tight and the liquids contained cannot be removed except by injecting it into someone. \
|
||||
Do you feel lucky?"
|
||||
unidentified_description_info = "A skilled chemist with a specialized machine can identify this autoinjector. \
|
||||
Blindly using the autoinjector is risky and can be dangerous."
|
||||
identification_type = IDENTITY_TYPE_CHEMICAL
|
||||
30
code/modules/identification/item_procs.dm
Normal file
30
code/modules/identification/item_procs.dm
Normal file
@@ -0,0 +1,30 @@
|
||||
// This is on the base /item so badmins can play with it by calling hide_identity().
|
||||
/obj/item
|
||||
var/datum/identification/identity = null
|
||||
var/identity_type = /datum/identification
|
||||
var/init_hide_identity = FALSE // Set to true to automatically obscure the object on initialization.
|
||||
|
||||
/obj/item/Initialize()
|
||||
if(init_hide_identity)
|
||||
identity = new identity_type(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/Destroy()
|
||||
if(identity)
|
||||
QDEL_NULL(identity)
|
||||
return ..()
|
||||
|
||||
/obj/item/proc/hide_identity() // Mostly for admins to make things secret.
|
||||
if(!identity)
|
||||
identity = new identity_type(src)
|
||||
else
|
||||
identity.unidentify()
|
||||
|
||||
/obj/item/proc/identify(identity_type = IDENTITY_FULL, mob/user)
|
||||
if(identity)
|
||||
identity.identify(identity_type, user)
|
||||
|
||||
/obj/item/proc/is_identified(identity_type = IDENTITY_FULL)
|
||||
if(!identity) // No identification datum means nothing to hide.
|
||||
return TRUE
|
||||
return identity_type & identity.identified
|
||||
@@ -188,14 +188,14 @@
|
||||
// These procs do not relocate the grenade, that's the callers responsibility
|
||||
/obj/item/integrated_circuit/manipulation/grenade/proc/attach_grenade(var/obj/item/weapon/grenade/G)
|
||||
attached_grenade = G
|
||||
destroyed_event.register(attached_grenade, src, /obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade)
|
||||
GLOB.destroyed_event.register(attached_grenade, src, /obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade)
|
||||
size += G.w_class
|
||||
desc += " \An [attached_grenade] is attached to it!"
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade()
|
||||
if(!attached_grenade)
|
||||
return
|
||||
destroyed_event.unregister(attached_grenade, src, /obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade)
|
||||
GLOB.destroyed_event.unregister(attached_grenade, src, /obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade)
|
||||
attached_grenade = null
|
||||
size = initial(size)
|
||||
desc = initial(desc)
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
text_output += "\an [name]"
|
||||
else
|
||||
text_output += "\an ["\improper[initial_name]"] labeled '[name]'"
|
||||
text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit <font color=[led_color]><EFBFBD></font>" : "unlit."]"
|
||||
text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit <font color=[led_color]>¤</font>" : "unlit."]"
|
||||
to_chat(user,jointext(text_output,null))
|
||||
|
||||
/obj/item/integrated_circuit/output/led/red
|
||||
@@ -462,8 +462,7 @@
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/output/holographic_projector/proc/destroy_hologram()
|
||||
hologram.forceMove(src)
|
||||
qdel(hologram)
|
||||
QDEL_NULL(hologram)
|
||||
|
||||
// holo_beam.End()
|
||||
// qdel_null(holo_beam)
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
var/list/global/map_templates = list()
|
||||
|
||||
// Called when the world starts, in world.dm
|
||||
/proc/load_map_templates()
|
||||
for(var/T in subtypesof(/datum/map_template))
|
||||
var/datum/map_template/template = T
|
||||
if(!(initial(template.mappath))) // If it's missing the actual path its probably a base type or being used for inheritence.
|
||||
continue
|
||||
template = new T()
|
||||
map_templates[template.name] = template
|
||||
return TRUE
|
||||
|
||||
/datum/map_template
|
||||
var/name = "Default Template Name"
|
||||
var/desc = "Some text should go here. Maybe."
|
||||
@@ -27,8 +15,6 @@ var/list/global/map_templates = list()
|
||||
var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually.
|
||||
var/discard_prob = 0 // If non-zero, there is a chance that the map seeding algorithm will skip this template when selecting potential templates to use.
|
||||
|
||||
var/static/dmm_suite/maploader = new
|
||||
|
||||
/datum/map_template/New(path = null, rename = null)
|
||||
if(path)
|
||||
mappath = path
|
||||
@@ -39,7 +25,7 @@ var/list/global/map_templates = list()
|
||||
name = rename
|
||||
|
||||
/datum/map_template/proc/preload_size(path, orientation = SOUTH)
|
||||
var/bounds = maploader.load_map(file(path), 1, 1, 1, cropMap=FALSE, measureOnly=TRUE, orientation=orientation)
|
||||
var/bounds = SSmapping.maploader.load_map(file(path), 1, 1, 1, cropMap=FALSE, measureOnly=TRUE, orientation=orientation)
|
||||
if(bounds)
|
||||
width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1
|
||||
height = bounds[MAP_MAXY]
|
||||
@@ -91,7 +77,7 @@ var/list/global/map_templates = list()
|
||||
x = round((world.maxx - width)/2)
|
||||
y = round((world.maxy - height)/2)
|
||||
|
||||
var/list/bounds = maploader.load_map(file(mappath), x, y, no_changeturf = TRUE, orientation=orientation)
|
||||
var/list/bounds = SSmapping.maploader.load_map(file(mappath), x, y, no_changeturf = TRUE, orientation=orientation)
|
||||
if(!bounds)
|
||||
return FALSE
|
||||
|
||||
@@ -116,7 +102,7 @@ var/list/global/map_templates = list()
|
||||
if(annihilate)
|
||||
annihilate_bounds(old_T, centered, orientation)
|
||||
|
||||
var/list/bounds = maploader.load_map(file(mappath), T.x, T.y, T.z, cropMap=TRUE, orientation = orientation)
|
||||
var/list/bounds = SSmapping.maploader.load_map(file(mappath), T.x, T.y, T.z, cropMap=TRUE, orientation = orientation)
|
||||
if(!bounds)
|
||||
return
|
||||
|
||||
@@ -175,8 +161,8 @@ var/list/global/map_templates = list()
|
||||
var/list/priority_submaps = list() // Submaps that will always be placed.
|
||||
|
||||
// Lets go find some submaps to make.
|
||||
for(var/map in map_templates)
|
||||
var/datum/map_template/MT = map_templates[map]
|
||||
for(var/map in SSmapping.map_templates)
|
||||
var/datum/map_template/MT = SSmapping.map_templates[map]
|
||||
if(!MT.allow_duplicates && MT.loaded > 0) // This probably won't be an issue but we might as well.
|
||||
continue
|
||||
if(!istype(MT, desired_map_template_type)) // Not the type wanted.
|
||||
|
||||
@@ -181,6 +181,23 @@ the artifact triggers the rage.
|
||||
accuracy_dispersion = 3 // Ditto.
|
||||
evasion = -45 // Too angry to dodge.
|
||||
|
||||
// Non-cult version of deep wounds.
|
||||
// Surprisingly, more dangerous.
|
||||
/datum/modifier/grievous_wounds
|
||||
name = "grievous wounds"
|
||||
desc = "Your wounds are not easily mended."
|
||||
|
||||
on_created_text = "<span class='critical'>Your wounds pain you greatly.</span>"
|
||||
on_expired_text = "<span class='notice'>The pain lulls.</span>"
|
||||
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
incoming_healing_percent = 0.50 // 50% less healing.
|
||||
disable_duration_percent = 1.22 // 22% longer disables.
|
||||
bleeding_rate_percent = 1.20 // 20% more bleeding.
|
||||
|
||||
accuracy_dispersion = 2 // A combination of fear and immense pain or damage reults in a twitching firing arm. Flee.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
|
||||
var/charge_cost = 240 //How much energy is needed to fire.
|
||||
|
||||
var/accept_cell_type = /obj/item/weapon/cell/device
|
||||
var/cell_type = /obj/item/weapon/cell/device/weapon
|
||||
projectile_type = /obj/item/projectile/beam/practice
|
||||
|
||||
@@ -89,13 +90,13 @@
|
||||
if(self_recharge || battery_lock)
|
||||
user << "<span class='notice'>[src] does not have a battery port.</span>"
|
||||
return
|
||||
if(istype(C, /obj/item/weapon/cell/device))
|
||||
var/obj/item/weapon/cell/device/P = C
|
||||
if(istype(C, accept_cell_type))
|
||||
var/obj/item/weapon/cell/P = C
|
||||
if(power_supply)
|
||||
user << "<span class='notice'>[src] already has a power cell.</span>"
|
||||
else
|
||||
user.visible_message("[user] is reloading [src].", "<span class='notice'>You start to insert [P] into [src].</span>")
|
||||
if(do_after(user, 10))
|
||||
if(do_after(user, 5 * P.w_class))
|
||||
user.remove_from_mob(P)
|
||||
power_supply = P
|
||||
P.loc = src
|
||||
@@ -175,6 +176,13 @@
|
||||
icon_state = "[modifystate][ratio]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)][ratio]"
|
||||
|
||||
else if(power_supply)
|
||||
if(modifystate)
|
||||
icon_state = "[modifystate]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
if(!ignore_inhands) update_held_icon()
|
||||
|
||||
/obj/item/weapon/gun/energy/proc/start_recharge()
|
||||
|
||||
40
code/modules/projectiles/guns/energy/hooklauncher.dm
Normal file
40
code/modules/projectiles/guns/energy/hooklauncher.dm
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Contains weapons primarily using the 'grappling hook' projectiles.
|
||||
*/
|
||||
|
||||
/obj/item/weapon/gun/energy/hooklauncher
|
||||
name = "gravity whip"
|
||||
desc = "A large, strange gauntlet."
|
||||
icon_state = "gravwhip"
|
||||
item_state = "gravwhip"
|
||||
fire_sound = 'sound/effects/zzzt.ogg'
|
||||
fire_sound_text = "laser blast"
|
||||
|
||||
fire_delay = 15
|
||||
charge_cost = 300
|
||||
|
||||
cell_type = /obj/item/weapon/cell/device/weapon
|
||||
projectile_type = /obj/item/projectile/energy/hook
|
||||
|
||||
// An easily concealable not-ripoff version. It would be silenced, if it didn't make it blatant you're the one using it.
|
||||
|
||||
/obj/item/weapon/gun/energy/hooklauncher/ring
|
||||
name = "ominous ring"
|
||||
desc = "A small ring with strange symbols engraved upon it."
|
||||
icon = 'icons/obj/clothing/rings.dmi'
|
||||
icon_state = "seal-signet"
|
||||
item_state = "concealed"
|
||||
|
||||
w_class = ITEMSIZE_TINY
|
||||
|
||||
cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien
|
||||
battery_lock = TRUE
|
||||
charge_cost = 400
|
||||
charge_meter = FALSE
|
||||
|
||||
projectile_type = /obj/item/projectile/energy/hook/ring
|
||||
|
||||
firemodes = list(
|
||||
list(mode_name="manipulate", fire_delay=15, projectile_type=/obj/item/projectile/energy/hook/ring, charge_cost = 400),
|
||||
list(mode_name="battle", fire_delay=8, projectile_type=/obj/item/projectile/beam/xray, charge_cost = 260),
|
||||
)
|
||||
@@ -151,6 +151,42 @@
|
||||
|
||||
toggle_scope(2.0)
|
||||
|
||||
/obj/item/weapon/gun/energy/monorifle
|
||||
name = "antique mono-rifle"
|
||||
desc = "An old laser rifle. This one can only fire once before requiring recharging."
|
||||
description_fluff = "Modeled after ancient hunting rifles, this rifle was dubbed the 'Rainy Day Special' by some, due to its use as some barmens' fight-stopper of choice. One shot is all it takes, or so they say."
|
||||
icon_state = "eshotgun"
|
||||
item_state = "shotgun"
|
||||
fire_sound = 'sound/weapons/gauss_shoot.ogg'
|
||||
origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_POWER = 3)
|
||||
projectile_type = /obj/item/projectile/beam/sniper
|
||||
slot_flags = SLOT_BACK
|
||||
charge_cost = 1300
|
||||
fire_delay = 20
|
||||
force = 8
|
||||
w_class = ITEMSIZE_LARGE
|
||||
accuracy = 10
|
||||
scoped_accuracy = 15
|
||||
var/scope_multiplier = 1.5
|
||||
|
||||
/obj/item/weapon/gun/energy/monorifle/verb/sights()
|
||||
set category = "Object"
|
||||
set name = "Aim Down Sights"
|
||||
set popup_menu = 1
|
||||
|
||||
toggle_scope(scope_multiplier)
|
||||
|
||||
/obj/item/weapon/gun/energy/monorifle/combat
|
||||
name = "combat mono-rifle"
|
||||
desc = "A modernized version of the mono-rifle. This one can fire twice before requiring recharging."
|
||||
description_fluff = "A modern design produced by a company once working from Saint Columbia, based on the antique mono-rifle 'Rainy Day Special' design."
|
||||
icon_state = "ecshotgun"
|
||||
item_state = "cshotgun"
|
||||
charge_cost = 1000
|
||||
force = 12
|
||||
accuracy = 0
|
||||
scoped_accuracy = 20
|
||||
|
||||
////////Laser Tag////////////////////
|
||||
|
||||
/obj/item/weapon/gun/energy/lasertag
|
||||
|
||||
@@ -186,6 +186,7 @@ obj/item/weapon/gun/energy/staff/focus
|
||||
desc = "A massive weapon designed to pressure the opposition by raining down a torrent of energy pellets."
|
||||
icon_state = "dakkalaser"
|
||||
item_state = "dakkalaser"
|
||||
wielded_item_state = "dakkalaser-wielded"
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
w_class = ITEMSIZE_HUGE
|
||||
charge_cost = 24 // 100 shots, it's a spray and pray (to RNGesus) weapon.
|
||||
@@ -200,4 +201,94 @@ obj/item/weapon/gun/energy/staff/focus
|
||||
list(mode_name="single shot", burst = 1, burst_accuracy = list(75), dispersion = list(0), charge_cost = 24),
|
||||
list(mode_name="five shot burst", burst = 5, burst_accuracy = list(75,75,75,75,75), dispersion = list(1,1,1,1,1)),
|
||||
list(mode_name="ten shot burst", burst = 10, burst_accuracy = list(75,75,75,75,75,75,75,75,75,75), dispersion = list(2,2,2,2,2,2,2,2,2,2)),
|
||||
)
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/energy/maghowitzer
|
||||
name = "portable MHD howitzer"
|
||||
desc = "A massive weapon designed to destroy fortifications with a stream of molten tungsten."
|
||||
description_fluff = "A weapon designed by joint cooperation of NanoTrasen, Hephaestus, and SCG scientists. Everything else is red tape and black highlighters."
|
||||
description_info = "This weapon requires a wind-up period before being able to fire. Clicking on a target will create a beam between you and its turf, starting the timer. Upon completion, it will fire at the designated location."
|
||||
icon_state = "mhdhowitzer"
|
||||
item_state = "mhdhowitzer"
|
||||
wielded_item_state = "mhdhowitzer-wielded"
|
||||
fire_sound = 'sound/weapons/emitter2.ogg'
|
||||
w_class = ITEMSIZE_HUGE
|
||||
|
||||
charge_cost = 10000 // Uses large cells, can at max have 3 shots.
|
||||
projectile_type = /obj/item/projectile/beam/tungsten
|
||||
cell_type = /obj/item/weapon/cell/high
|
||||
accept_cell_type = /obj/item/weapon/cell
|
||||
|
||||
accuracy = 75
|
||||
charge_meter = 0
|
||||
one_handed_penalty = 30
|
||||
|
||||
var/power_cycle = FALSE
|
||||
|
||||
/obj/item/weapon/gun/energy/maghowitzer/proc/pick_random_target(var/turf/T)
|
||||
var/foundmob = FALSE
|
||||
var/foundmobs = list()
|
||||
for(var/mob/living/L in T.contents)
|
||||
foundmob = TRUE
|
||||
foundmobs += L
|
||||
if(foundmob)
|
||||
var/return_target = pick(foundmobs)
|
||||
return return_target
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/gun/energy/maghowitzer/attack(atom/A, mob/living/user, def_zone)
|
||||
if(power_cycle)
|
||||
to_chat(user, "<span class='notice'>\The [src] is already powering up!</span>")
|
||||
return 0
|
||||
var/turf/target_turf = get_turf(A)
|
||||
var/beameffect = user.Beam(target_turf,icon_state="sat_beam",icon='icons/effects/beam.dmi',time=31, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3)
|
||||
if(beameffect)
|
||||
user.visible_message("<span class='cult'>[user] aims \the [src] at \the [A].</span>")
|
||||
if(power_supply && power_supply.charge >= charge_cost) //Do a delay for pointblanking too.
|
||||
power_cycle = TRUE
|
||||
if(do_after(user, 30))
|
||||
if(A.loc == target_turf)
|
||||
..(A, user, def_zone)
|
||||
else
|
||||
var/rand_target = pick_random_target(target_turf)
|
||||
if(rand_target)
|
||||
..(rand_target, user, def_zone)
|
||||
else
|
||||
..(target_turf, user, def_zone)
|
||||
else
|
||||
if(beameffect)
|
||||
qdel(beameffect)
|
||||
power_cycle = FALSE
|
||||
else
|
||||
..(A, user, def_zone) //If it can't fire, just bash with no delay.
|
||||
|
||||
/obj/item/weapon/gun/energy/maghowitzer/afterattack(atom/A, mob/living/user, adjacent, params)
|
||||
if(power_cycle)
|
||||
to_chat(user, "<span class='notice'>\The [src] is already powering up!</span>")
|
||||
return 0
|
||||
|
||||
var/turf/target_turf = get_turf(A)
|
||||
|
||||
var/beameffect = user.Beam(target_turf,icon_state="sat_beam",icon='icons/effects/beam.dmi',time=31, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3)
|
||||
|
||||
if(beameffect)
|
||||
user.visible_message("<span class='cult'>[user] aims \the [src] at \the [A].</span>")
|
||||
|
||||
if(!power_cycle)
|
||||
power_cycle = TRUE
|
||||
if(do_after(user, 30))
|
||||
if(A.loc == target_turf)
|
||||
..(A, user, adjacent, params)
|
||||
else
|
||||
var/rand_target = pick_random_target(target_turf)
|
||||
if(rand_target)
|
||||
..(rand_target, user, adjacent, params)
|
||||
else
|
||||
..(target_turf, user, adjacent, params)
|
||||
else
|
||||
if(beameffect)
|
||||
qdel(beameffect)
|
||||
handle_click_empty(user)
|
||||
power_cycle = FALSE
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] is already powering up!</span>")
|
||||
|
||||
141
code/modules/projectiles/guns/magnetic/bore.dm
Normal file
141
code/modules/projectiles/guns/magnetic/bore.dm
Normal file
@@ -0,0 +1,141 @@
|
||||
/obj/item/weapon/gun/magnetic/matfed
|
||||
name = "portable phoron bore"
|
||||
desc = "A large man-portable tunnel bore, using phorogenic plasma blasts. Point away from user."
|
||||
description_fluff = "An aging Grayson Manufactories mining tool used for rapidly digging through rock. Mass production was discontinued when many of the devices were stolen and used to break into a high security facility by Boiling Point drones."
|
||||
description_antag = "This device is exceptional at breaking down walls, though it is incredibly loud when doing so."
|
||||
description_info = "The projectile of this tool will travel six tiles before dissipating, excavating mineral walls as it does so. It can be reloaded with phoron sheets."
|
||||
|
||||
icon_state = "bore"
|
||||
item_state = "bore"
|
||||
wielded_item_state = "bore-wielded"
|
||||
one_handed_penalty = 5
|
||||
|
||||
projectile_type = /obj/item/projectile/bullet/magnetic/bore
|
||||
|
||||
gun_unreliable = 0
|
||||
|
||||
power_cost = 750
|
||||
load_type = /obj/item/stack/material
|
||||
var/mat_storage = 0 // How much material is stored inside? Input in multiples of 2000 as per auto/protolathe.
|
||||
var/max_mat_storage = 8000 // How much material can be stored inside?
|
||||
var/mat_cost = 500 // How much material is used per-shot?
|
||||
var/ammo_material = MAT_PHORON
|
||||
var/loading = FALSE
|
||||
|
||||
/obj/item/weapon/gun/magnetic/matfed/examine(mob/user)
|
||||
. = ..()
|
||||
show_ammo(user)
|
||||
|
||||
/obj/item/weapon/gun/magnetic/matfed/update_icon()
|
||||
var/list/overlays_to_add = list()
|
||||
if(removable_components)
|
||||
if(cell)
|
||||
overlays_to_add += image(icon, "[icon_state]_cell")
|
||||
if(capacitor)
|
||||
overlays_to_add += image(icon, "[icon_state]_capacitor")
|
||||
if(!cell || !capacitor)
|
||||
overlays_to_add += image(icon, "[icon_state]_red")
|
||||
else if(capacitor.charge < power_cost)
|
||||
overlays_to_add += image(icon, "[icon_state]_amber")
|
||||
else
|
||||
overlays_to_add += image(icon, "[icon_state]_green")
|
||||
if(mat_storage)
|
||||
overlays_to_add += image(icon, "[icon_state]_loaded")
|
||||
|
||||
overlays = overlays_to_add
|
||||
..()
|
||||
/obj/item/weapon/gun/magnetic/matfed/attack_hand(var/mob/user) // It doesn't keep a loaded item inside.
|
||||
if(user.get_inactive_hand() == src)
|
||||
var/obj/item/removing
|
||||
|
||||
if(cell && removable_components)
|
||||
removing = cell
|
||||
cell = null
|
||||
|
||||
if(removing)
|
||||
removing.forceMove(get_turf(src))
|
||||
user.put_in_hands(removing)
|
||||
user.visible_message("<span class='notice'>\The [user] removes \the [removing] from \the [src].</span>")
|
||||
playsound(loc, 'sound/machines/click.ogg', 10, 1)
|
||||
update_icon()
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/gun/magnetic/matfed/check_ammo()
|
||||
if(mat_storage - mat_cost >= 0)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/gun/magnetic/matfed/use_ammo()
|
||||
mat_storage -= mat_cost
|
||||
|
||||
/obj/item/weapon/gun/magnetic/matfed/show_ammo(var/mob/user)
|
||||
if(mat_storage)
|
||||
to_chat(user, "<span class='notice'>It has [mat_storage] out of [max_mat_storage] units of [ammo_material] loaded.</span>")
|
||||
|
||||
/obj/item/weapon/gun/magnetic/matfed/attackby(var/obj/item/thing, var/mob/user)
|
||||
if(removable_components)
|
||||
if(istype(thing, /obj/item/weapon/cell))
|
||||
if(cell)
|
||||
to_chat(user, "<span class='warning'>\The [src] already has \a [cell] installed.</span>")
|
||||
return
|
||||
cell = thing
|
||||
user.drop_from_inventory(cell)
|
||||
cell.forceMove(src)
|
||||
playsound(loc, 'sound/machines/click.ogg', 10, 1)
|
||||
user.visible_message("<span class='notice'>\The [user] slots \the [cell] into \the [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(thing.is_screwdriver())
|
||||
if(!capacitor)
|
||||
to_chat(user, "<span class='warning'>\The [src] has no capacitor installed.</span>")
|
||||
return
|
||||
capacitor.forceMove(get_turf(src))
|
||||
user.put_in_hands(capacitor)
|
||||
user.visible_message("<span class='notice'>\The [user] unscrews \the [capacitor] from \the [src].</span>")
|
||||
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
capacitor = null
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(thing, /obj/item/weapon/stock_parts/capacitor))
|
||||
if(capacitor)
|
||||
to_chat(user, "<span class='warning'>\The [src] already has \a [capacitor] installed.</span>")
|
||||
return
|
||||
capacitor = thing
|
||||
user.drop_from_inventory(capacitor)
|
||||
capacitor.forceMove(src)
|
||||
playsound(loc, 'sound/machines/click.ogg', 10, 1)
|
||||
power_per_tick = (power_cost*0.15) * capacitor.rating
|
||||
user.visible_message("<span class='notice'>\The [user] slots \the [capacitor] into \the [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(thing, load_type))
|
||||
loading = TRUE
|
||||
var/obj/item/stack/material/M = thing
|
||||
|
||||
if(!M.material || M.material.name != ammo_material)
|
||||
return
|
||||
|
||||
if(mat_storage + 2000 > max_mat_storage)
|
||||
to_chat(user, "<span class='warning'>\The [src] cannot hold more [ammo_material].</span>")
|
||||
return
|
||||
|
||||
var/can_hold_val = 0
|
||||
while(can_hold_val < round(max_mat_storage / 2000))
|
||||
if(mat_storage + 2000 <= max_mat_storage && do_after(user,1.5 SECONDS))
|
||||
can_hold_val ++
|
||||
mat_storage += 2000
|
||||
playsound(loc, 'sound/effects/phasein.ogg', 15, 1)
|
||||
else
|
||||
loading = FALSE
|
||||
break
|
||||
M.use(can_hold_val)
|
||||
|
||||
user.visible_message("<span class='notice'>\The [user] loads \the [src] with \the [M].</span>")
|
||||
playsound(loc, 'sound/weapons/flipblade.ogg', 50, 1)
|
||||
update_icon()
|
||||
return
|
||||
. = ..()
|
||||
192
code/modules/projectiles/projectile/hook.dm
Normal file
192
code/modules/projectiles/projectile/hook.dm
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* File containing special 'hook' projectiles. Function is dictated by the launcher's intent.
|
||||
*/
|
||||
|
||||
/obj/item/projectile/energy/hook
|
||||
name = "graviton sphere"
|
||||
icon_state = "bluespace"
|
||||
|
||||
var/beam_state = "b_beam"
|
||||
|
||||
damage = 5
|
||||
step_delay = 2
|
||||
damage_type = BURN
|
||||
check_armour = "energy"
|
||||
armor_penetration = 15
|
||||
|
||||
var/impact_sound = 'sound/effects/uncloak.ogg'
|
||||
var/crack_sound = 'sound/effects/teleport.ogg'
|
||||
|
||||
var/target_distance = null // Shamelessly stolen from arcing projectiles.
|
||||
var/my_tracking_beam = null // Beam made by the launcher. Tracked here to destroy it in time with the impact.
|
||||
var/launcher_intent = null // Stores the launcher's intent.
|
||||
|
||||
var/disarm_chance = 60 // Chance for a successful disarm hit. The inverse is a throw away from the firer.
|
||||
|
||||
var/list/help_messages = list("slaps", "pokes", "nudges", "bumps", "pinches")
|
||||
var/done_mob_unique = FALSE // Has the projectile already done something to a mob?
|
||||
|
||||
/obj/item/projectile/energy/hook/launch(atom/target, target_zone, x_offset=0, y_offset=0, angle_offset=0)
|
||||
var/expected_distance = get_dist(target, loc)
|
||||
kill_count = expected_distance // So the hook hits the ground if no mob is hit.
|
||||
target_distance = expected_distance
|
||||
if(firer) // Needed to ensure later checks in impact and on hit function.
|
||||
launcher_intent = firer.a_intent
|
||||
firer.Beam(src,icon_state=beam_state,icon='icons/effects/beam.dmi',time=60, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=1)
|
||||
|
||||
if(launcher_intent)
|
||||
switch(launcher_intent)
|
||||
if(I_HURT)
|
||||
check_armour = "bullet"
|
||||
damage *= 3
|
||||
sharp = 1
|
||||
agony = 20
|
||||
if(I_GRAB)
|
||||
check_armour = "melee"
|
||||
damage_type = HALLOSS
|
||||
if(I_DISARM)
|
||||
check_armour = "melee"
|
||||
if(prob(30)) // A chance for a successful hit to either knock someone down, or cause minor disorientation.
|
||||
weaken = 1
|
||||
else
|
||||
stun = 2
|
||||
eyeblur = 3
|
||||
if(I_HELP)
|
||||
silenced = 1
|
||||
damage_type = HALLOSS
|
||||
|
||||
..() // Does the regular launching stuff.
|
||||
|
||||
/obj/item/projectile/energy/hook/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
|
||||
if(..())
|
||||
perform_intent_unique(target)
|
||||
|
||||
/obj/item/projectile/energy/hook/on_impact(var/atom/A)
|
||||
perform_intent_unique(get_turf(A))
|
||||
|
||||
/obj/item/projectile/energy/hook/proc/ranged_disarm(var/mob/living/carbon/human/H)
|
||||
if(istype(H))
|
||||
var/list/holding = list(H.get_active_hand() = 60, H.get_inactive_hand() = 40)
|
||||
|
||||
for(var/obj/item/weapon/gun/W in holding) // Guns are complex devices, both of a mechanical and electronic nature. A weird gravity ball or other type of object trying to pull or grab it is likely not safe.
|
||||
if(W && prob(holding[W]))
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in view())
|
||||
turfs += T
|
||||
if(turfs.len)
|
||||
var/turf/target = pick(turfs)
|
||||
visible_message("<span class='danger'>[H]'s [W] goes off due to \the [src]!</span>")
|
||||
return W.afterattack(target,H)
|
||||
|
||||
if(!(H.species.flags & NO_SLIP) && prob(50))
|
||||
var/armor_check = H.run_armor_check(def_zone, "melee")
|
||||
H.apply_effect(3, WEAKEN, armor_check)
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
if(armor_check < 60)
|
||||
visible_message("<span class='danger'>\The [src] has pushed [H]!</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>\The [src] attempted to push [H]!</span>")
|
||||
return
|
||||
|
||||
else
|
||||
if(H.break_all_grabs(firer))
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
return
|
||||
|
||||
for(var/obj/item/I in holding)
|
||||
if(I)
|
||||
H.drop_from_inventory(I)
|
||||
visible_message("<span class='danger'>\The [src] has disarmed [H]!</span>")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/projectile/energy/hook/proc/perform_intent_unique(atom/target)
|
||||
playsound(src.loc, impact_sound, 40, 1)
|
||||
var/success = FALSE
|
||||
if(istype(target,/turf))
|
||||
if(launcher_intent)
|
||||
if(launcher_intent != I_HELP && !done_mob_unique)
|
||||
var/target_mob = pick(/mob/living in target.contents)
|
||||
|
||||
if(!target_mob)
|
||||
return
|
||||
|
||||
if(Bump(target_mob, forced=1)) //If we hit a turf, try to force an interaction with a mob on the turf.
|
||||
done_mob_unique = TRUE
|
||||
success = TRUE
|
||||
else if(firer)
|
||||
var/obj/T
|
||||
|
||||
if(original in target.contents && istype(original, /obj))
|
||||
T = original
|
||||
|
||||
var/list/possible_targets = list()
|
||||
for(var/obj/item/I in target.contents)
|
||||
if(!I.anchored)
|
||||
possible_targets += I
|
||||
for(var/obj/structure/S in target.contents)
|
||||
if(!S.anchored)
|
||||
possible_targets += S
|
||||
|
||||
if(!T)
|
||||
if(!possible_targets || !possible_targets.len)
|
||||
return
|
||||
T = pick(possible_targets)
|
||||
|
||||
spawn(2)
|
||||
playsound(target, crack_sound, 40, 1)
|
||||
visible_message("<span class='notice'>\The [T] is snatched by \the [src]!</span>")
|
||||
T.throw_at(get_turf(firer), 7, 1, src)
|
||||
success = TRUE
|
||||
else if(isliving(target) && !done_mob_unique)
|
||||
var/mob/living/L = target
|
||||
if(launcher_intent)
|
||||
switch(launcher_intent)
|
||||
if(I_HELP)
|
||||
var/message = pick(help_messages)
|
||||
if(message == "slaps")
|
||||
spawn(1)
|
||||
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
|
||||
visible_message("<span class='notice'>\The [src] [message] [target].</span>")
|
||||
done_mob_unique = TRUE
|
||||
success = TRUE
|
||||
if(I_HURT)
|
||||
if(prob(10) && istype(L, /mob/living/carbon/human))
|
||||
to_chat(L, "<span class='warning'>\The [src] rips at your hands!</span>")
|
||||
ranged_disarm(L)
|
||||
success = TRUE
|
||||
done_mob_unique = TRUE
|
||||
if(I_DISARM)
|
||||
if(prob(disarm_chance) && istype(L, /mob/living/carbon/human))
|
||||
ranged_disarm(L)
|
||||
else
|
||||
L.visible_message("<span class='danger'>\The [src] sends \the [L] stumbling backwards.</span>")
|
||||
L.throw_at(get_turf(get_step(L,get_dir(firer,L))), 1, 1, src)
|
||||
done_mob_unique = TRUE
|
||||
success = TRUE
|
||||
if(I_GRAB)
|
||||
var/turf/STurf = get_turf(L)
|
||||
spawn(2)
|
||||
playsound(STurf, crack_sound, 60, 1)
|
||||
L.visible_message("<span class='critical'>\The [src] rips [L] towards \the [firer]!</span>")
|
||||
L.throw_at(get_turf(get_step(firer,get_dir(firer,L))), 6, 1, src)
|
||||
done_mob_unique = TRUE
|
||||
success = TRUE
|
||||
else if(istype(target, /obj/structure))
|
||||
var/obj/structure/S = target
|
||||
if(!S.anchored)
|
||||
S.throw_at(get_turf(get_step(firer,get_dir(firer,S))), 4, 1, src)
|
||||
success = TRUE
|
||||
qdel(my_tracking_beam)
|
||||
return success
|
||||
|
||||
/*
|
||||
* Hook subtypes.
|
||||
*/
|
||||
|
||||
/obj/item/projectile/energy/hook/ring
|
||||
name = "green orb"
|
||||
icon_state = "green_laser"
|
||||
beam_state = "n_beam"
|
||||
damage = 3
|
||||
@@ -116,4 +116,29 @@
|
||||
return ..(target, blocked, def_zone)
|
||||
|
||||
/obj/item/projectile/bullet/magnetic/fuelrod/supermatter/check_penetrate()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/bullet/magnetic/bore
|
||||
name = "phorogenic blast"
|
||||
icon_state = "purpleemitter"
|
||||
damage = 20
|
||||
incendiary = 1
|
||||
armor_penetration = 20
|
||||
penetrating = 0
|
||||
check_armour = "melee"
|
||||
irradiate = 20
|
||||
kill_count = 6
|
||||
|
||||
/obj/item/projectile/bullet/magnetic/bore/Bump(atom/A, forced=0)
|
||||
if(istype(A, /turf/simulated/mineral))
|
||||
var/turf/simulated/mineral/MI = A
|
||||
loc = get_turf(A) // Careful.
|
||||
permutated.Add(A)
|
||||
MI.GetDrilled(TRUE)
|
||||
return 0
|
||||
else if(istype(A, /turf/simulated/wall) || istype(A, /turf/simulated/shuttle/wall)) // Cause a loud, but relatively minor explosion on the wall it hits.
|
||||
explosion(A, -1, -1, 1, 3)
|
||||
qdel(src)
|
||||
return 1
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -257,3 +257,82 @@
|
||||
visible_message("<span class='danger'>\The [src] splatters a layer of web on \the [target]!</span>")
|
||||
new /obj/effect/spider/stickyweb(target.loc)
|
||||
..()
|
||||
|
||||
/obj/item/projectile/beam/tungsten
|
||||
name = "core of molten tungsten"
|
||||
icon_state = "energy"
|
||||
fire_sound = 'sound/weapons/emitter2.ogg'
|
||||
pass_flags = PASSTABLE | PASSGRILLE
|
||||
damage = 70
|
||||
damage_type = BURN
|
||||
check_armour = "laser"
|
||||
light_range = 4
|
||||
light_power = 3
|
||||
light_color = "#3300ff"
|
||||
|
||||
muzzle_type = /obj/effect/projectile/tungsten/muzzle
|
||||
tracer_type = /obj/effect/projectile/tungsten/tracer
|
||||
impact_type = /obj/effect/projectile/tungsten/impact
|
||||
|
||||
/obj/item/projectile/beam/tungsten/on_hit(var/atom/target, var/blocked = 0)
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.add_modifier(/datum/modifier/grievous_wounds, 30 SECONDS)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
|
||||
var/target_armor = H.getarmor(def_zone, check_armour)
|
||||
var/obj/item/organ/external/target_limb = H.get_organ(def_zone)
|
||||
|
||||
var/armor_special = 0
|
||||
|
||||
if(target_armor >= 60)
|
||||
var/turf/T = get_step(H, pick(alldirs - src.dir))
|
||||
H.throw_at(T, 1, 1, src)
|
||||
H.apply_damage(20, BURN, def_zone)
|
||||
if(target_limb)
|
||||
armor_special = 2
|
||||
target_limb.fracture()
|
||||
|
||||
else if(target_armor >= 45)
|
||||
H.apply_damage(15, BURN, def_zone)
|
||||
if(target_limb)
|
||||
armor_special = 1
|
||||
target_limb.dislocate()
|
||||
|
||||
else if(target_armor >= 30)
|
||||
H.apply_damage(10, BURN, def_zone)
|
||||
if(prob(30) && target_limb)
|
||||
armor_special = 1
|
||||
target_limb.dislocate()
|
||||
|
||||
else if(target_armor >= 15)
|
||||
H.apply_damage(5, BURN, def_zone)
|
||||
if(prob(15) && target_limb)
|
||||
armor_special = 1
|
||||
target_limb.dislocate()
|
||||
|
||||
if(armor_special > 1)
|
||||
target.visible_message("<span class='cult'>\The [src] slams into \the [target]'s [target_limb], reverberating loudly!</span>")
|
||||
|
||||
else if(armor_special)
|
||||
target.visible_message("<span class='cult'>\The [src] slams into \the [target]'s [target_limb] with a low rumble!</span>")
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/projectile/beam/tungsten/on_impact(var/atom/A)
|
||||
if(istype(A,/turf/simulated/shuttle/wall) || istype(A,/turf/simulated/wall) || (istype(A,/turf/simulated/mineral) && A.density) || istype(A,/obj/mecha) || istype(A,/obj/machinery/door))
|
||||
var/blast_dir = src.dir
|
||||
A.visible_message("<span class='danger'>\The [A] begins to glow!</span>")
|
||||
spawn(2 SECONDS)
|
||||
var/blastloc = get_step(A, blast_dir)
|
||||
if(blastloc)
|
||||
explosion(blastloc, -1, -1, 2, 3)
|
||||
..()
|
||||
|
||||
/obj/item/projectile/beam/tungsten/Bump(atom/A, forced=0)
|
||||
if(istype(A, /obj/structure/window)) //It does not pass through windows. It pulverizes them.
|
||||
var/obj/structure/window/W = A
|
||||
W.shatter()
|
||||
return 0
|
||||
..()
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
/obj/machinery/chem_master/New()
|
||||
..()
|
||||
var/datum/reagents/R = new/datum/reagents(900) //Just a huge random number so the buffer should (probably) never dump your reagents.
|
||||
var/datum/reagents/R = new/datum/reagents(900) //Just a huge random number so the buffer should (probably) never dump your reagents.
|
||||
reagents = R //There should be a nano ui thingy to warn of this.
|
||||
R.my_atom = src
|
||||
|
||||
@@ -544,3 +544,65 @@
|
||||
qdel(O)
|
||||
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
||||
break
|
||||
|
||||
|
||||
///////////////
|
||||
///////////////
|
||||
// Detects reagents inside most containers, and acts as an infinite identification system for reagent-based unidentified objects.
|
||||
|
||||
/obj/machinery/chemical_analyzer
|
||||
name = "chem analyzer"
|
||||
desc = "Used to precisely scan chemicals and other liquids inside various containers. \
|
||||
It may also identify the liquid contents of unknown objects."
|
||||
description_info = "This machine will try to tell you what reagents are inside of something capable of holding reagents. \
|
||||
It is also used to 'identify' specific reagent-based objects with their properties obscured from inspection by normal means."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "chem_analyzer"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
use_power = TRUE
|
||||
idle_power_usage = 20
|
||||
clicksound = "button"
|
||||
var/analyzing = FALSE
|
||||
|
||||
/obj/machinery/chemical_analyzer/update_icon()
|
||||
icon_state = "chem_analyzer[analyzing ? "-working":""]"
|
||||
|
||||
/obj/machinery/chemical_analyzer/attackby(obj/item/I, mob/living/user)
|
||||
if(!istype(I))
|
||||
return ..()
|
||||
|
||||
if(default_deconstruction_screwdriver(user, I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(user, I))
|
||||
return
|
||||
|
||||
if(istype(I,/obj/item/weapon/reagent_containers))
|
||||
analyzing = TRUE
|
||||
update_icon()
|
||||
to_chat(user, span("notice", "Analyzing \the [I], please stand by..."))
|
||||
|
||||
if(!do_after(user, 2 SECONDS, src))
|
||||
to_chat(user, span("warning", "Sample moved outside of scan range, please try again and remain still."))
|
||||
analyzing = FALSE
|
||||
update_icon()
|
||||
return
|
||||
|
||||
// First, identify it if it isn't already.
|
||||
if(!I.is_identified(IDENTITY_FULL))
|
||||
var/datum/identification/ID = I.identity
|
||||
if(ID.identification_type == IDENTITY_TYPE_CHEMICAL) // This only solves chemical-based mysteries.
|
||||
I.identify(IDENTITY_FULL, user)
|
||||
|
||||
// Now tell us everything that is inside.
|
||||
if(I.reagents && I.reagents.reagent_list.len)
|
||||
to_chat(user, "<br>") // To add padding between regular chat and the output.
|
||||
for(var/datum/reagent/R in I.reagents.reagent_list)
|
||||
if(!R.name)
|
||||
continue
|
||||
to_chat(user, span("notice", "Contains [R.volume]u of <b>[R.name]</b>.<br>[R.description]<br>"))
|
||||
|
||||
to_chat(user, span("notice", "Scanning of \the [I] complete."))
|
||||
analyzing = FALSE
|
||||
update_icon()
|
||||
return
|
||||
@@ -489,4 +489,21 @@
|
||||
description = "A slurry of compounds that contains the basic requirements for life."
|
||||
taste_description = "salty meat"
|
||||
reagent_state = LIQUID
|
||||
color = "#DF9FBF"
|
||||
color = "#DF9FBF"
|
||||
|
||||
// The opposite to healing nanites, exists to make unidentified hypos implied to have nanites not be 100% safe.
|
||||
/datum/reagent/defective_nanites
|
||||
name = "Defective Nanites"
|
||||
id = "defective_nanites"
|
||||
description = "Miniature medical robots that are malfunctioning and cause bodily harm. Fortunately, they cannot self-replicate."
|
||||
taste_description = "metal"
|
||||
reagent_state = SOLID
|
||||
color = "#333333"
|
||||
metabolism = REM * 3 // Broken nanomachines go a bit slower.
|
||||
scannable = 1
|
||||
|
||||
/datum/reagent/defective_nanites/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
|
||||
M.take_organ_damage(2 * removed, 2 * removed)
|
||||
M.adjustOxyLoss(4 * removed)
|
||||
M.adjustToxLoss(2 * removed)
|
||||
M.adjustCloneLoss(2 * removed)
|
||||
@@ -155,10 +155,26 @@
|
||||
|
||||
/datum/reagent/toxin/mold/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
|
||||
..()
|
||||
M.adjustToxLoss(strength * removed)
|
||||
if(prob(5))
|
||||
M.vomit()
|
||||
|
||||
/datum/reagent/toxin/expired_medicine
|
||||
name = "Expired Medicine"
|
||||
id = "expired_medicine"
|
||||
description = "Some form of liquid medicine that is well beyond its shelf date. Administering it now would cause illness."
|
||||
taste_description = "bitterness"
|
||||
reagent_state = LIQUID
|
||||
strength = 5
|
||||
|
||||
/datum/reagent/toxin/expired_medicine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
|
||||
..()
|
||||
if(prob(5))
|
||||
M.vomit()
|
||||
|
||||
/datum/reagent/toxin/expired_medicine/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
|
||||
affect_blood(M, alien, removed * 0.66)
|
||||
|
||||
|
||||
/datum/reagent/toxin/stimm //Homemade Hyperzine
|
||||
name = "Stimm"
|
||||
id = "stimm"
|
||||
|
||||
@@ -53,20 +53,29 @@
|
||||
if(!do_after(user, 30, H))
|
||||
return
|
||||
|
||||
do_injection(H, user)
|
||||
return
|
||||
|
||||
// This does the actual injection and transfer.
|
||||
/obj/item/weapon/reagent_containers/hypospray/proc/do_injection(mob/living/carbon/human/H, mob/living/user)
|
||||
if(!istype(H) || !istype(user))
|
||||
return FALSE
|
||||
|
||||
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
|
||||
to_chat(user, "<span class='notice'>You inject [M] with \the [src].</span>")
|
||||
to_chat(M, "<span class='notice'>You feel a tiny prick!</span>")
|
||||
to_chat(user, span("notice", "You inject \the [H] with \the [src]."))
|
||||
to_chat(H, span("warning", "You feel a tiny prick!"))
|
||||
|
||||
if(hyposound)
|
||||
playsound(src, hyposound,25)
|
||||
playsound(src, hyposound, 25)
|
||||
|
||||
if(M.reagents)
|
||||
if(H.reagents)
|
||||
var/contained = reagentlist()
|
||||
var/trans = reagents.trans_to_mob(M, amount_per_transfer_from_this, CHEM_BLOOD)
|
||||
add_attack_logs(user,M,"Injected with [src.name] containing [contained], trasferred [trans] units")
|
||||
to_chat(user, "<span class='notice'>[trans] units injected. [reagents.total_volume] units remaining in \the [src].</span>")
|
||||
var/trans = reagents.trans_to_mob(H, amount_per_transfer_from_this, CHEM_BLOOD)
|
||||
add_attack_logs(user,H,"Injected with [src.name] containing [contained], trasferred [trans] units")
|
||||
to_chat(user, span("notice", "[trans] units injected. [reagents.total_volume] units remaining in \the [src]."))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
return
|
||||
//A vial-loaded hypospray. Cartridge-based!
|
||||
/obj/item/weapon/reagent_containers/hypospray/vial
|
||||
name = "hypospray mkII"
|
||||
@@ -143,12 +152,11 @@
|
||||
flags &= ~OPENCONTAINER
|
||||
icon_state = "[initial(icon_state)]0"
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/attack(mob/M as mob, mob/user as mob)
|
||||
..()
|
||||
if(reagents.total_volume <= 0) //Prevents autoinjectors to be refilled.
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/do_injection(mob/living/carbon/human/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.) // Will occur if successfully injected.
|
||||
flags &= ~OPENCONTAINER
|
||||
update_icon()
|
||||
return
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/update_icon()
|
||||
if(reagents.total_volume > 0)
|
||||
@@ -168,6 +176,63 @@
|
||||
icon_state = "green"
|
||||
filled_reagents = list("anti_toxin" = 5)
|
||||
|
||||
// These have a 15u capacity, somewhat higher tech level, and generally more useful chems, but are otherwise the same as the regular autoinjectors.
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector
|
||||
name = "empty hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity."
|
||||
icon_state = "autoinjector"
|
||||
amount_per_transfer_from_this = 15
|
||||
volume = 15
|
||||
origin_tech = list(TECH_BIO = 4)
|
||||
filled_reagents = list("inaprovaline" = 15)
|
||||
flags = 0 // Removed OPENCONTAINER so you can't extract things to cheese the identification system in unidentified versions.
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute
|
||||
name = "trauma hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to be used on victims of \
|
||||
moderate blunt trauma."
|
||||
filled_reagents = list("bicaridine" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn
|
||||
name = "burn hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to be used on burn victims, \
|
||||
featuring an optimized chemical mixture to allow for rapid healing."
|
||||
filled_reagents = list("kelotane" = 7.5, "dermaline" = 7.5)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin
|
||||
name = "toxin hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract toxins."
|
||||
filled_reagents = list("anti_toxin" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy
|
||||
name = "oxy hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract oxygen \
|
||||
deprivation."
|
||||
filled_reagents = list("dexalinp" = 10, "tricordrazine" = 5)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity
|
||||
name = "purity hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This variant excels at \
|
||||
resolving viruses, infections, radiation, and genetic maladies."
|
||||
filled_reagents = list("spaceacillin" = 9, "arithrazine" = 5, "ryetalyn" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain
|
||||
name = "pain hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one contains potent painkillers."
|
||||
filled_reagents = list("tramadol" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ
|
||||
name = "organ hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. Organ damage is resolved by this variant."
|
||||
filled_reagents = list("alkysine" = 3, "imidazoline" = 2, "peridaxon" = 10)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat
|
||||
name = "combat hypo"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This is a more dangerous and potentially \
|
||||
addictive hypo compared to others, as it contains a potent cocktail of various chemicals to optimize the recipient's combat \
|
||||
ability."
|
||||
filled_reagents = list("bicaridine" = 3, "kelotane" = 1.5, "dermaline" = 1.5, "oxycodone" = 3, "hyperzine" = 3, "tricordrazine" = 3)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting
|
||||
name = "clotting agent"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This variant excels at treating bleeding wounds and internal bleeding."
|
||||
@@ -177,3 +242,109 @@
|
||||
name = "bone repair injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one excels at treating damage to bones."
|
||||
filled_reagents = list("inaprovaline" = 5, "osteodaxon" = 10)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm
|
||||
name = "stimm injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one is filled with a home-made stimulant, with some serious side-effects."
|
||||
filled_reagents = list("stimm" = 10) // More than 10u will OD.
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired
|
||||
name = "expired injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one has had its contents expire a long time ago, using it now will probably make someone sick, or worse."
|
||||
filled_reagents = list("expired_medicine" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific
|
||||
name = "soporific injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one is sometimes used by orderlies, as it has soporifics, which make someone tired and fall asleep."
|
||||
filled_reagents = list("stoxin" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide
|
||||
name = "cyanide injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one contains cyanide, a lethal poison. It being inside a medical autoinjector has certain unsettling implications."
|
||||
filled_reagents = list("cyanide" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium
|
||||
name = "serotrotium injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one is filled with serotrotium, which causes concentrated production of the serotonin neurotransmitter in humans."
|
||||
filled_reagents = list("serotrotium" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs
|
||||
name = "illicit injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one contains various illicit drugs, held inside a hypospray to make smuggling easier."
|
||||
filled_reagents = list("space_drugs" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin
|
||||
name = "cryptobiolin injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one contains cryptobiolin, which causes confusion."
|
||||
filled_reagents = list("cryptobiolin" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/impedrezene
|
||||
name = "impedrezene injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one has impedrezene inside, a narcotic that impairs higher brain functioning. \
|
||||
This autoinjector is almost certainly created illegitimately."
|
||||
filled_reagents = list("impedrezene" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mindbreaker
|
||||
name = "mindbreaker injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This one stores the dangerous hallucinogen called 'Mindbreaker', likely put in place \
|
||||
by illicit groups hoping to hide their product."
|
||||
filled_reagents = list("mindbreaker" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/psilocybin
|
||||
name = "psilocybin injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This has psilocybin inside, which is a strong psychotropic derived from certain species of mushroom. \
|
||||
This autoinjector likely was made by criminal elements to avoid detection from casual inspection."
|
||||
filled_reagents = list("psilocybin" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen
|
||||
name = "unstable mutagen injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This contains unstable mutagen, which makes using this a very bad idea. It will either \
|
||||
ruin your genetic health, turn you into a Five Points violation, or both!"
|
||||
filled_reagents = list("mutagen" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/lexorin
|
||||
name = "lexorin injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
This contains lexorin, a dangerous toxin that stops respiration, and has been \
|
||||
implicated in several high-profile assassinations in the past."
|
||||
filled_reagents = list("lexorin" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites
|
||||
name = "medical nanite injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
The injector stores a slurry of highly advanced and specialized nanomachines designed \
|
||||
to restore bodily health from within. The nanomachines are short-lived but degrade \
|
||||
harmlessly, and cannot self-replicate in order to remain Five Points compliant."
|
||||
filled_reagents = list("healing_nanites" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites
|
||||
name = "defective nanite injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
The injector stores a slurry of highly advanced and specialized nanomachines that \
|
||||
are unfortunately malfunctioning, making them unsafe to use inside of a living body. \
|
||||
Because of the Five Points, these nanites cannot self-replicate."
|
||||
filled_reagents = list("defective_nanites" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated
|
||||
name = "contaminated injector"
|
||||
desc = "A refined version of the standard autoinjector, allowing greater capacity. \
|
||||
The hypospray contains a viral agent inside, as well as a liquid substance that encourages \
|
||||
the growth of the virus inside."
|
||||
filled_reagents = list("virusfood" = 15)
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/do_injection(mob/living/carbon/human/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.) // Will occur if successfully injected.
|
||||
infect_mob_random_lesser(H)
|
||||
add_attack_logs(user, H, "Infected \the [H] with \the [src], by \the [user].")
|
||||
@@ -0,0 +1,80 @@
|
||||
// Here are the paths for all hypos that start unidentified.
|
||||
// Usually you want to use a random spawner instead of using them directly, unless you're spawning these live for adminbus purposes.
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector
|
||||
identity_type = /datum/identification/hypo
|
||||
|
||||
// The good.
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
// The somewhat bad.
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mindbreaker/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/psilocybin/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/soporific/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
// The very bad.
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cyanide/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/impedrezene/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mutagen/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/defective_nanites/unidentified
|
||||
init_hide_identity = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/contaminated/unidentified
|
||||
init_hide_identity = TRUE
|
||||
Reference in New Issue
Block a user