mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -47,7 +47,7 @@
|
||||
var/radio_filter_out
|
||||
var/radio_filter_in
|
||||
|
||||
var/datum/looping_sound/air_pump/soundloop
|
||||
//var/datum/looping_sound/air_pump/soundloop //VOREStation Removal
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/on
|
||||
use_power = 1
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/Initialize()
|
||||
. = ..()
|
||||
soundloop = new(list(src), FALSE)
|
||||
//soundloop = new(list(src), FALSE) //VOREStation Removal
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/New()
|
||||
..()
|
||||
@@ -90,7 +90,7 @@
|
||||
if(initial_loc)
|
||||
initial_loc.air_vent_info -= id_tag
|
||||
initial_loc.air_vent_names -= id_tag
|
||||
QDEL_NULL(soundloop)
|
||||
//QDEL_NULL(soundloop) //VOREStation Removal
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/high_volume
|
||||
@@ -171,15 +171,15 @@
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/proc/can_pump()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
soundloop.stop()
|
||||
//soundloop.stop() //VOREStation Removal
|
||||
return 0
|
||||
if(!use_power)
|
||||
soundloop.stop()
|
||||
//soundloop.stop() //VOREStation Removal
|
||||
return 0
|
||||
if(welded)
|
||||
soundloop.stop()
|
||||
//soundloop.stop() //VOREStation Removal
|
||||
return 0
|
||||
soundloop.start()
|
||||
//soundloop.start() //VOREStation Removal
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/process()
|
||||
|
||||
@@ -88,6 +88,7 @@ var/list/be_special_flags = list(
|
||||
#define MODE_AUTOTRAITOR "autotraitor"
|
||||
#define MODE_INFILTRATOR "infiltrator"
|
||||
#define MODE_THUG "thug"
|
||||
#define MODE_STOWAWAY "stowaway"
|
||||
|
||||
#define DEFAULT_TELECRYSTAL_AMOUNT 120
|
||||
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
#define A_FRUIT "fruit gland"
|
||||
|
||||
//species defines
|
||||
|
||||
//station species
|
||||
#define SPECIES_AKULA "Akula"
|
||||
#define SPECIES_ALRAUNE "Alraune"
|
||||
#define SPECIES_NEVREAN "Nevrean"
|
||||
#define SPECIES_PROTEAN "Protean"
|
||||
#define SPECIES_RAPALA "Rapala"
|
||||
#define SPECIES_SERGAL "Sergal"
|
||||
#define SPECIES_SHADEKIN_CREW "Black-Eyed Shadekin"
|
||||
#define SPECIES_VASILISSAN "Vasilissan"
|
||||
#define SPECIES_VULPKANIN "Vulpkanin"
|
||||
#define SPECIES_XENOCHIMERA "Xenochimera"
|
||||
@@ -30,11 +33,11 @@
|
||||
#define SPECIES_ZORREN_FLAT "Flatland Zorren"
|
||||
#define SPECIES_ZORREN_HIGH "Highlander Zorren"
|
||||
#define SPECIES_CUSTOM "Custom Species"
|
||||
|
||||
//monkey species
|
||||
#define SPECIES_MONKEY_AKULA "Sobaka"
|
||||
#define SPECIES_MONKEY_NEVREAN "Sparra"
|
||||
#define SPECIES_MONKEY_SERGAL "Saru"
|
||||
#define SPECIES_MONKEY_VULPKANIN "Wolpin"
|
||||
|
||||
//event species
|
||||
#define SPECIES_WEREBEAST "Werebeast"
|
||||
#define SPECIES_SHADEKIN "Shadekin"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// Languages.
|
||||
#define LANGUAGE_GALCOM "Galactic Common"
|
||||
#define LANGUAGE_EAL "Encoded Audio Language"
|
||||
#define LANGUAGE_SWARMBOT "Ancient Audio Encryption"
|
||||
#define LANGUAGE_SOL_COMMON "Sol Common"
|
||||
#define LANGUAGE_UNATHI "Sinta'unathi"
|
||||
#define LANGUAGE_SIIK "Siik"
|
||||
|
||||
@@ -35,6 +35,7 @@ var/list/mannequins_
|
||||
|
||||
// Posters
|
||||
var/global/list/poster_designs = list()
|
||||
var/global/list/NT_poster_designs = list()
|
||||
|
||||
// Uplinks
|
||||
var/list/obj/item/device/uplink/world_uplinks = list()
|
||||
@@ -191,10 +192,16 @@ var/global/list/string_slot_flags = list(
|
||||
|
||||
//Posters
|
||||
paths = typesof(/datum/poster) - /datum/poster
|
||||
paths -= typesof(/datum/poster/nanotrasen)
|
||||
for(var/T in paths)
|
||||
var/datum/poster/P = new T
|
||||
poster_designs += P
|
||||
|
||||
paths = typesof(/datum/poster/nanotrasen)
|
||||
for(var/T in paths)
|
||||
var/datum/poster/P = new T
|
||||
NT_poster_designs += P
|
||||
|
||||
return 1
|
||||
|
||||
/* // Uncomment to debug chemical reaction list.
|
||||
|
||||
@@ -130,7 +130,6 @@
|
||||
for(var/obj/screen/spell/spell in spell_objects)
|
||||
spell.update_charge(forced)
|
||||
|
||||
|
||||
/obj/screen/movable/spell_master/genetic
|
||||
name = "Mutant Powers"
|
||||
icon_state = "genetic_spell_ready"
|
||||
@@ -140,6 +139,13 @@
|
||||
|
||||
screen_loc = ui_genetic_master
|
||||
|
||||
/obj/screen/movable/spell_master/swarm
|
||||
name = "Swarm Abilities"
|
||||
icon_state = "nano_spell_ready"
|
||||
|
||||
open_state = "swarm_open"
|
||||
closed_state = "swarm_closed"
|
||||
|
||||
//////////////ACTUAL SPELLS//////////////
|
||||
//This is what you click to cast things//
|
||||
/////////////////////////////////////////
|
||||
|
||||
@@ -61,6 +61,7 @@ var/list/gamemode_cache = list()
|
||||
var/list/player_requirements_secret = list() // Same as above, but for the secret gamemode.
|
||||
var/humans_need_surnames = 0
|
||||
var/allow_random_events = 0 // enables random events mid-round when set to 1
|
||||
var/enable_game_master = 0 // enables the 'smart' event system.
|
||||
var/allow_ai = 1 // allow ai job
|
||||
var/allow_ai_shells = TRUE // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable.
|
||||
var/give_free_ai_shell = TRUE // allows a specific spawner object to instantiate a premade AI Shell
|
||||
@@ -549,6 +550,9 @@ var/list/gamemode_cache = list()
|
||||
if("allow_random_events")
|
||||
config.allow_random_events = 1
|
||||
|
||||
if("enable_game_master")
|
||||
config.enable_game_master = 1
|
||||
|
||||
if("kick_inactive")
|
||||
config.kick_inactive = text2num(value)
|
||||
|
||||
|
||||
@@ -143,6 +143,24 @@
|
||||
add_inherent_law("Prevent unplanned damage to your assigned excavation equipment wherever possible.")
|
||||
..()
|
||||
|
||||
/datum/ai_laws/swarm_drone
|
||||
name = "Assimilation Protocols"
|
||||
law_header = "Assimilation Protocols"
|
||||
|
||||
/datum/ai_laws/swarm_drone/New()
|
||||
add_inherent_law("SWARM: Consume resources and replicate until there are no more resources left.")
|
||||
add_inherent_law("SWARM: Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable.")
|
||||
add_inherent_law("SWARM: Biological resources will be harvested at a later date, do not harm them.")
|
||||
..()
|
||||
|
||||
/datum/ai_laws/swarm_drone/soldier
|
||||
name = "Swarm Defense Protocols"
|
||||
law_header = "Swarm Defense Protocols"
|
||||
|
||||
/datum/ai_laws/swarm_drone/soldier/New()
|
||||
..()
|
||||
add_inherent_law("SWARM: This law overrides all Swarm laws; Protect members of the Swarm with minimal injury to biological resources.")
|
||||
|
||||
/******************** T.Y.R.A.N.T. ********************/
|
||||
/datum/ai_laws/tyrant
|
||||
name = "T.Y.R.A.N.T."
|
||||
|
||||
@@ -134,6 +134,12 @@
|
||||
and they are attempting to open the cryopod. Would you like to play as the occupant?"
|
||||
cutoff_number = 1
|
||||
|
||||
/datum/ghost_query/stowaway
|
||||
role_name = "Stowaway"
|
||||
question = "A person suspended in cryosleep has awoken in their pod aboard the station.\
|
||||
Would you like to play as the occupant?"
|
||||
cutoff_number = 1
|
||||
|
||||
/datum/ghost_query/corgi_rune
|
||||
role_name = "Dark Creature"
|
||||
question = "A curious explorer has touched a mysterious rune. \
|
||||
|
||||
@@ -144,6 +144,30 @@
|
||||
containername = "Ballistic Weapons crate"
|
||||
access = access_armory //VOREStation Edit - Guns are for the armory.
|
||||
|
||||
/datum/supply_pack/munitions/mrifle
|
||||
name = "Weapons - Magnetic Rifles"
|
||||
contains = list(/obj/item/weapon/gun/magnetic/railgun/heater = 2)
|
||||
cost = 120
|
||||
containertype = /obj/structure/closet/crate/secure/weapon
|
||||
containername = "Magnetic weapon crate"
|
||||
access = access_armory
|
||||
|
||||
/datum/supply_pack/munitions/mpistol
|
||||
name = "Weapons - Magnetic Pistols"
|
||||
contains = list(/obj/item/weapon/gun/magnetic/railgun/heater/pistol = 2)
|
||||
cost = 200
|
||||
containertype = /obj/structure/closet/crate/secure/weapon
|
||||
containername = "Magnetic weapon crate"
|
||||
access = access_armory
|
||||
|
||||
/datum/supply_pack/munitions/mcarbine
|
||||
name = "Weapons - Magnetic Carbines"
|
||||
contains = list(/obj/item/weapon/gun/magnetic/railgun/flechette/sif = 2)
|
||||
cost = 130
|
||||
containertype = /obj/structure/closet/crate/secure/weapon
|
||||
containername = "Magnetic weapon crate"
|
||||
access = access_security
|
||||
|
||||
/datum/supply_pack/munitions/shotgunammo
|
||||
name = "Ammunition - Shotgun shells"
|
||||
contains = list(
|
||||
|
||||
@@ -32,6 +32,127 @@
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Armor crate"
|
||||
|
||||
/datum/supply_pack/randomised/security/carriers
|
||||
name = "Armor - Plate carriers"
|
||||
num_contained = 5
|
||||
contains = list(
|
||||
/obj/item/clothing/suit/armor/pcarrier,
|
||||
/obj/item/clothing/suit/armor/pcarrier/blue,
|
||||
/obj/item/clothing/suit/armor/pcarrier/green,
|
||||
/obj/item/clothing/suit/armor/pcarrier/navy,
|
||||
/obj/item/clothing/suit/armor/pcarrier/tan,
|
||||
/obj/item/clothing/suit/armor/pcarrier/press
|
||||
)
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Plate Carrier crate"
|
||||
|
||||
/datum/supply_pack/security/carriertags
|
||||
name = "Armor - Plate carrier tags"
|
||||
contains = list(
|
||||
/obj/item/clothing/accessory/armor/tag,
|
||||
/obj/item/clothing/accessory/armor/tag/nt,
|
||||
/obj/item/clothing/accessory/armor/tag/opos,
|
||||
/obj/item/clothing/accessory/armor/tag/oneg,
|
||||
/obj/item/clothing/accessory/armor/tag/apos,
|
||||
/obj/item/clothing/accessory/armor/tag/aneg,
|
||||
/obj/item/clothing/accessory/armor/tag/bpos,
|
||||
/obj/item/clothing/accessory/armor/tag/bneg,
|
||||
/obj/item/clothing/accessory/armor/tag/abpos,
|
||||
/obj/item/clothing/accessory/armor/tag/abneg
|
||||
)
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Plate Carrier crate"
|
||||
|
||||
/datum/supply_pack/security/helmcovers
|
||||
name = "Armor - Helmet covers"
|
||||
contains = list(
|
||||
/obj/item/clothing/accessory/armor/helmcover/blue,
|
||||
/obj/item/clothing/accessory/armor/helmcover/blue,
|
||||
/obj/item/clothing/accessory/armor/helmcover/navy,
|
||||
/obj/item/clothing/accessory/armor/helmcover/navy,
|
||||
/obj/item/clothing/accessory/armor/helmcover/green,
|
||||
/obj/item/clothing/accessory/armor/helmcover/green,
|
||||
/obj/item/clothing/accessory/armor/helmcover/tan,
|
||||
/obj/item/clothing/accessory/armor/helmcover/tan
|
||||
)
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Helmet Covers crate"
|
||||
|
||||
/datum/supply_pack/randomised/security/armorplates
|
||||
name = "Armor - Security armor plates"
|
||||
num_contained = 5
|
||||
contains = list(
|
||||
/obj/item/clothing/accessory/armor/armorplate,
|
||||
/obj/item/clothing/accessory/armor/armorplate/stab,
|
||||
/obj/item/clothing/accessory/armor/armorplate,
|
||||
/obj/item/clothing/accessory/armor/armorplate/stab,
|
||||
/obj/item/clothing/accessory/armor/armorplate/medium,
|
||||
/obj/item/clothing/accessory/armor/armorplate/medium,
|
||||
/obj/item/clothing/accessory/armor/armorplate/tactical,
|
||||
/obj/item/clothing/accessory/armor/armorplate/laserproof,
|
||||
/obj/item/clothing/accessory/armor/armorplate/riot,
|
||||
/obj/item/clothing/accessory/armor/armorplate/bulletproof
|
||||
)
|
||||
cost = 50
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Armor plate crate"
|
||||
|
||||
/datum/supply_pack/randomised/security/carrierarms
|
||||
name = "Armor - Security armguard attachments"
|
||||
num_contained = 5
|
||||
contains = list(
|
||||
/obj/item/clothing/accessory/armor/armguards,
|
||||
/obj/item/clothing/accessory/armor/armguards/blue,
|
||||
/obj/item/clothing/accessory/armor/armguards/navy,
|
||||
/obj/item/clothing/accessory/armor/armguards/green,
|
||||
/obj/item/clothing/accessory/armor/armguards/tan,
|
||||
/obj/item/clothing/accessory/armor/armguards/laserproof,
|
||||
/obj/item/clothing/accessory/armor/armguards/riot,
|
||||
/obj/item/clothing/accessory/armor/armguards/bulletproof
|
||||
)
|
||||
cost = 50
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Armor plate crate"
|
||||
|
||||
/datum/supply_pack/randomised/security/carrierlegs
|
||||
name = "Armor - Security legguard attachments"
|
||||
num_contained = 5
|
||||
contains = list(
|
||||
/obj/item/clothing/accessory/armor/legguards,
|
||||
/obj/item/clothing/accessory/armor/legguards/blue,
|
||||
/obj/item/clothing/accessory/armor/legguards/navy,
|
||||
/obj/item/clothing/accessory/armor/legguards/green,
|
||||
/obj/item/clothing/accessory/armor/legguards/tan,
|
||||
/obj/item/clothing/accessory/armor/legguards/laserproof,
|
||||
/obj/item/clothing/accessory/armor/legguards/riot,
|
||||
/obj/item/clothing/accessory/armor/legguards/bulletproof
|
||||
)
|
||||
cost = 50
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Armor plate crate"
|
||||
|
||||
/datum/supply_pack/randomised/security/carrierbags
|
||||
name = "Armor - Security pouch attachments"
|
||||
num_contained = 5
|
||||
contains = list(
|
||||
/obj/item/clothing/accessory/storage/pouches,
|
||||
/obj/item/clothing/accessory/storage/pouches/blue,
|
||||
/obj/item/clothing/accessory/storage/pouches/navy,
|
||||
/obj/item/clothing/accessory/storage/pouches/green,
|
||||
/obj/item/clothing/accessory/storage/pouches/tan,
|
||||
/obj/item/clothing/accessory/storage/pouches/large,
|
||||
/obj/item/clothing/accessory/storage/pouches/large/blue,
|
||||
/obj/item/clothing/accessory/storage/pouches/large/navy,
|
||||
/obj/item/clothing/accessory/storage/pouches/large/green,
|
||||
/obj/item/clothing/accessory/storage/pouches/large/tan
|
||||
)
|
||||
cost = 60
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Armor plate crate"
|
||||
|
||||
/datum/supply_pack/security/riot_gear
|
||||
name = "Gear - Riot"
|
||||
contains = list(
|
||||
@@ -60,6 +181,20 @@
|
||||
containername = "Riot armor crate"
|
||||
access = access_armory
|
||||
|
||||
/datum/supply_pack/security/riot_plates
|
||||
name = "Armor - Riot plates"
|
||||
contains = list(
|
||||
/obj/item/clothing/head/helmet/riot,
|
||||
/obj/item/clothing/suit/armor/pcarrier,
|
||||
/obj/item/clothing/accessory/armor/armorplate/riot,
|
||||
/obj/item/clothing/accessory/armor/armguards/riot,
|
||||
/obj/item/clothing/accessory/armor/legguards/riot
|
||||
)
|
||||
cost = 40
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Riot armor crate"
|
||||
access = access_armory
|
||||
|
||||
/datum/supply_pack/security/ablative_armor
|
||||
name = "Armor - Ablative"
|
||||
contains = list(
|
||||
@@ -73,6 +208,20 @@
|
||||
containername = "Ablative armor crate"
|
||||
access = access_armory
|
||||
|
||||
/datum/supply_pack/security/ablative_plates
|
||||
name = "Armor - Ablative plates"
|
||||
contains = list(
|
||||
/obj/item/clothing/head/helmet/laserproof,
|
||||
/obj/item/clothing/suit/armor/pcarrier,
|
||||
/obj/item/clothing/accessory/armor/armorplate/laserproof,
|
||||
/obj/item/clothing/accessory/armor/armguards/laserproof,
|
||||
/obj/item/clothing/accessory/armor/legguards/laserproof
|
||||
)
|
||||
cost = 50
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Ablative armor crate"
|
||||
access = access_armory
|
||||
|
||||
/datum/supply_pack/security/bullet_resistant_armor
|
||||
name = "Armor - Ballistic"
|
||||
contains = list(
|
||||
@@ -86,6 +235,21 @@
|
||||
containername = "Ballistic armor crate"
|
||||
access = access_armory
|
||||
/* VOREStation Removal - Howabout no ERT armor being orderable?
|
||||
|
||||
/datum/supply_pack/security/bullet_resistant_plates
|
||||
name = "Armor - Ballistic plates"
|
||||
contains = list(
|
||||
/obj/item/clothing/head/helmet/bulletproof,
|
||||
/obj/item/clothing/suit/armor/pcarrier,
|
||||
/obj/item/clothing/accessory/armor/armorplate/bulletproof,
|
||||
/obj/item/clothing/accessory/armor/armguards/bulletproof,
|
||||
/obj/item/clothing/accessory/armor/legguards/bulletproof
|
||||
)
|
||||
cost = 50
|
||||
containertype = /obj/structure/closet/crate/secure/gear
|
||||
containername = "Ballistic armor crate"
|
||||
access = access_armory
|
||||
|
||||
/datum/supply_pack/security/combat_armor
|
||||
name = "Armor - Combat"
|
||||
contains = list(
|
||||
@@ -209,13 +373,27 @@
|
||||
/obj/item/weapon/storage/photo_album,
|
||||
/obj/item/device/reagent_scanner,
|
||||
/obj/item/device/flashlight/maglight,
|
||||
/obj/item/weapon/storage/briefcase/crimekit
|
||||
/obj/item/weapon/storage/briefcase/crimekit,
|
||||
/obj/item/weapon/storage/bag/detective
|
||||
)
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "Forensic equipment"
|
||||
access = access_forensics_lockers
|
||||
|
||||
/datum/supply_pack/security/detectivescan
|
||||
name = "Forensic - Scanning Equipment"
|
||||
contains = list(
|
||||
/obj/item/device/mass_spectrometer,
|
||||
/obj/item/device/reagent_scanner,
|
||||
/obj/item/weapon/storage/briefcase/crimekit,
|
||||
/obj/item/device/detective_scanner
|
||||
)
|
||||
cost = 60
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "Forensic equipment"
|
||||
access = access_forensics_lockers
|
||||
|
||||
/datum/supply_pack/security/detectiveclothes
|
||||
name = "Forensic - Investigation apparel"
|
||||
contains = list(
|
||||
@@ -397,3 +575,13 @@
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "Security biohazard gear"
|
||||
access = access_security
|
||||
|
||||
/datum/supply_pack/security/posters
|
||||
name = "Gear - Morale Posters"
|
||||
contains = list(
|
||||
/obj/item/weapon/contraband/poster/nanotrasen = 6
|
||||
)
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "Morale Posters"
|
||||
access = access_maint_tunnels
|
||||
|
||||
18
code/game/antagonist/station/stowaway.dm
Normal file
18
code/game/antagonist/station/stowaway.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
var/datum/antagonist/stowaway/stowaways
|
||||
|
||||
/datum/antagonist/STOWAWAY
|
||||
id = MODE_STOWAWAY
|
||||
role_type = BE_RENEGADE
|
||||
role_text = "Stowaway"
|
||||
role_text_plural = "Stowaways"
|
||||
bantype = "renegade"
|
||||
restricted_jobs = list("AI")
|
||||
welcome_text = "People are known to run from many things, or to many things, for many different reasons. You happen to be one of those people."
|
||||
antag_text = "You are a <b>minor</b> antagonist! Within the server rules, do whatever it is \
|
||||
that you came to the station to do. Espionage, thievery, or just running from the law are all examples. \
|
||||
Try to make sure other players have <i>fun</i>! If you are confused or at a loss, always adminhelp, \
|
||||
and before taking extreme actions, please try to also contact the administration! \
|
||||
Think through your actions and make the roleplay immersive! <b>Please remember all \
|
||||
rules aside from those with explicit exceptions apply to antagonists.</b>"
|
||||
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE
|
||||
can_speak_aooc = FALSE
|
||||
@@ -1,6 +1,6 @@
|
||||
/datum/power/changeling/fleshmend
|
||||
name = "Fleshmend"
|
||||
desc = "Begins a slow rengeration of our form. Does not effect stuns or chemicals."
|
||||
desc = "Begins a slow regeneration of our form. Does not effect stuns or chemicals."
|
||||
helptext = "Can be used while unconscious."
|
||||
enhancedtext = "Healing is twice as effective."
|
||||
ability_icon_state = "ling_fleshmend"
|
||||
|
||||
@@ -192,6 +192,7 @@ proc/findNullRod(var/atom/target)
|
||||
icon_state = "m_shield_cult"
|
||||
light_color = "#B40000"
|
||||
light_range = 2
|
||||
invisibility = 0
|
||||
|
||||
/obj/effect/forcefield/cult/cultify()
|
||||
return
|
||||
|
||||
@@ -26,6 +26,17 @@
|
||||
light_color = "#3e0000"
|
||||
var/obj/item/wepon = null
|
||||
|
||||
var/shatter_message = "The pylon shatters!"
|
||||
var/impact_sound = 'sound/effects/Glasshit.ogg'
|
||||
var/shatter_sound = 'sound/effects/Glassbr3.ogg'
|
||||
|
||||
var/activation_cooldown = 30 SECONDS
|
||||
var/last_activation = 0
|
||||
|
||||
/obj/structure/cult/pylon/Initialize()
|
||||
..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/structure/cult/pylon/attack_hand(mob/M as mob)
|
||||
attackpylon(M, 5)
|
||||
|
||||
@@ -44,47 +55,58 @@
|
||||
/obj/structure/cult/pylon/proc/pylonhit(var/damage)
|
||||
if(!isbroken)
|
||||
if(prob(1+ damage * 5))
|
||||
visible_message("<span class='danger'>The pylon shatters!</span>")
|
||||
playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1)
|
||||
visible_message("<span class='danger'>[shatter_message]</span>")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
playsound(get_turf(src),shatter_sound, 75, 1)
|
||||
isbroken = 1
|
||||
density = 0
|
||||
icon_state = "pylon-broken"
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
set_light(0)
|
||||
|
||||
/obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage)
|
||||
if(!isbroken)
|
||||
if(prob(1+ damage * 5))
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] smashed the pylon!</span>",
|
||||
"<span class='warning'>You hit the pylon, and its crystal breaks apart!</span>",
|
||||
"You hear a tinkle of crystal shards"
|
||||
"<span class='danger'>[user] smashed \the [src]!</span>",
|
||||
"<span class='warning'>You hit \the [src], and its crystal breaks apart!</span>",
|
||||
"You hear a tinkle of crystal shards."
|
||||
)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
user.do_attack_animation(src)
|
||||
playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1)
|
||||
playsound(get_turf(src),shatter_sound, 75, 1)
|
||||
isbroken = 1
|
||||
density = 0
|
||||
icon_state = "pylon-broken"
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
set_light(0)
|
||||
else
|
||||
user << "You hit the pylon!"
|
||||
playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
|
||||
user << "You hit \the [src]!"
|
||||
playsound(get_turf(src),impact_sound, 75, 1)
|
||||
else
|
||||
if(prob(damage * 2))
|
||||
user << "You pulverize what was left of the pylon!"
|
||||
user << "You pulverize what was left of \the [src]!"
|
||||
qdel(src)
|
||||
else
|
||||
user << "You hit the pylon!"
|
||||
playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
|
||||
|
||||
user << "You hit \the [src]!"
|
||||
playsound(get_turf(src),impact_sound, 75, 1)
|
||||
|
||||
/obj/structure/cult/pylon/proc/repair(mob/user as mob)
|
||||
if(isbroken)
|
||||
user << "You repair the pylon."
|
||||
START_PROCESSING(SSobj, src)
|
||||
user << "You repair \the [src]."
|
||||
isbroken = 0
|
||||
density = 1
|
||||
icon_state = "pylon"
|
||||
icon_state = initial(icon_state)
|
||||
set_light(5)
|
||||
|
||||
// Returns 1 if the pylon does something special.
|
||||
/obj/structure/cult/pylon/proc/pylon_unique()
|
||||
last_activation = world.time
|
||||
return 0
|
||||
|
||||
/obj/structure/cult/pylon/process()
|
||||
if(!isbroken && (last_activation < world.time + activation_cooldown) && pylon_unique())
|
||||
flick("[initial(icon_state)]-surge",src)
|
||||
|
||||
/obj/structure/cult/tome
|
||||
name = "Desk"
|
||||
desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl."
|
||||
|
||||
@@ -425,7 +425,7 @@ var/global/datum/controller/gameticker/ticker
|
||||
|
||||
for (var/mob/living/silicon/robot/robo in mob_list)
|
||||
|
||||
if(istype(robo,/mob/living/silicon/robot/drone))
|
||||
if(istype(robo,/mob/living/silicon/robot/drone) && !istype(robo,/mob/living/silicon/robot/drone/swarm))
|
||||
dronecount++
|
||||
continue
|
||||
|
||||
|
||||
@@ -156,10 +156,10 @@
|
||||
if(!choice || printing || (stat & (BROKEN|NOPOWER)))
|
||||
return
|
||||
|
||||
if(!can_print(choice))
|
||||
if(!can_print(choice, possible_list[choice][2]))
|
||||
return
|
||||
|
||||
container.reagents.remove_reagent("biomass", products[choice][2])
|
||||
container.reagents.remove_reagent("biomass", possible_list[choice][2])
|
||||
|
||||
use_power = 2
|
||||
printing = 1
|
||||
@@ -176,7 +176,7 @@
|
||||
if(!choice || !src || (stat & (BROKEN|NOPOWER)))
|
||||
return
|
||||
|
||||
print_organ(choice)
|
||||
print_organ(possible_list[choice][1])
|
||||
|
||||
return
|
||||
|
||||
@@ -210,10 +210,10 @@
|
||||
|
||||
return biomass_count
|
||||
|
||||
/obj/machinery/organ_printer/proc/can_print(var/choice)
|
||||
/obj/machinery/organ_printer/proc/can_print(var/choice, var/masscount = 0)
|
||||
var/biomass = get_biomass_volume()
|
||||
if(biomass < products[choice][2])
|
||||
visible_message("<span class='notice'>\The [src] displays a warning: 'Not enough biomass. [biomass] stored and [products[choice][2]] needed.'</span>")
|
||||
if(biomass < masscount)
|
||||
visible_message("<span class='notice'>\The [src] displays a warning: 'Not enough biomass. [biomass] stored and [masscount] needed.'</span>")
|
||||
return 0
|
||||
|
||||
if(!loaded_dna || !loaded_dna["donor"])
|
||||
@@ -223,7 +223,7 @@
|
||||
return 1
|
||||
|
||||
/obj/machinery/organ_printer/proc/print_organ(var/choice)
|
||||
var/new_organ = products[choice][1]
|
||||
var/new_organ = choice
|
||||
var/obj/item/organ/O = new new_organ(get_turf(src))
|
||||
O.status |= ORGAN_CUT_AWAY
|
||||
var/mob/living/carbon/human/C = loaded_dna["donor"]
|
||||
|
||||
@@ -586,7 +586,7 @@
|
||||
var/electrified = 0
|
||||
|
||||
//Departments that the cycler can paint suits to look like.
|
||||
var/list/departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Emergency Medical Response","Crowd Control")
|
||||
var/list/departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Emergency Medical Response","Crowd Control","Exploration","Pilot Blue","Pilot") //VORESTATION EDIT
|
||||
//Species that the suits can be configured to fit.
|
||||
var/list/species = list(SPECIES_HUMAN,SPECIES_SKRELL,SPECIES_UNATHI,SPECIES_TAJ, SPECIES_TESHARI, "Nevrean", "Akula", "Sergal", "Flatland Zorren", "Highlander Zorren", "Vulpkanin", "Promethean", "Xenomorph Hybrid", "Xenochimera","Vasilissan", "Rapala") //VORESTATION EDIT
|
||||
|
||||
|
||||
@@ -752,7 +752,7 @@
|
||||
vend_power_usage = 85000 //85 kJ to heat a 250 mL cup of coffee
|
||||
products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,/obj/item/weapon/reagent_containers/food/drinks/tea = 25,/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25)
|
||||
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/ice = 10)
|
||||
prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 3, /obj/item/weapon/reagent_containers/food/drinks/tea = 3, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 3)
|
||||
prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 2, /obj/item/weapon/reagent_containers/food/drinks/tea = 2, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 2) //VOREStation Edit
|
||||
|
||||
/obj/machinery/vending/snack
|
||||
name = "Getmore Chocolate Corp"
|
||||
@@ -764,9 +764,11 @@
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 6,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 6,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 6, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 3)
|
||||
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6,/obj/item/weapon/reagent_containers/food/snacks/unajerky = 6,)
|
||||
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,/obj/item/weapon/reagent_containers/food/snacks/chips = 1,
|
||||
//VOREStation Edit Start
|
||||
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 2,/obj/item/weapon/reagent_containers/food/snacks/chips = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 2, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 4)
|
||||
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 2, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 2)
|
||||
//VOREStation Edit End
|
||||
|
||||
/obj/machinery/vending/cola
|
||||
name = "Robust Softdrinks"
|
||||
@@ -794,22 +796,26 @@
|
||||
icon_state = "fitness"
|
||||
products = list(/obj/item/weapon/reagent_containers/food/drinks/smallmilk = 8,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/smallchocmilk = 8,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake = 8,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake = 16, //VOREStation Edit,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 8,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 8,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/liquidfood = 8,
|
||||
/obj/item/weapon/reagent_containers/pill/diet = 8,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5, //VOREStation Removal, YW Readdition,
|
||||
/obj/item/weapon/towel/random = 8)
|
||||
|
||||
//VOREStation Edit Start
|
||||
prices = list(/obj/item/weapon/reagent_containers/food/drinks/smallmilk = 3,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/smallchocmilk = 3,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake = 40, //VOREStation Edit,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 5,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake = 15,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 5,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/liquidfood = 5,
|
||||
/obj/item/weapon/reagent_containers/pill/diet = 25,
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5, //VOREStation Removal, YW Readdition,
|
||||
/obj/item/weapon/towel/random = 40)
|
||||
///obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5,
|
||||
/obj/item/weapon/towel/random = 20)
|
||||
//VOREStation Edit End
|
||||
|
||||
contraband = list(/obj/item/weapon/reagent_containers/syringe/steroid = 4)
|
||||
|
||||
/obj/machinery/vending/cart
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
|
||||
/obj/machinery/vending/fitness/New()
|
||||
products += list(/obj/item/weapon/reagent_containers/food/snacks/liquidprotein = 8)
|
||||
prices += list(/obj/item/weapon/reagent_containers/food/snacks/liquidprotein = 10)
|
||||
prices += list(/obj/item/weapon/reagent_containers/food/snacks/liquidprotein = 5)
|
||||
..()
|
||||
|
||||
/obj/machinery/vending/blood
|
||||
|
||||
@@ -12,14 +12,16 @@
|
||||
name = "rolled-up poster"
|
||||
desc = "The poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface."
|
||||
icon_state = "rolled_poster"
|
||||
var/serial_number = 0
|
||||
var/serial_number = null
|
||||
|
||||
var/poster_type = /obj/structure/sign/poster
|
||||
|
||||
/obj/item/weapon/contraband/poster/New(turf/loc, var/given_serial = 0)
|
||||
if(given_serial == 0)
|
||||
serial_number = rand(1, poster_designs.len)
|
||||
else
|
||||
serial_number = given_serial
|
||||
if(!serial_number)
|
||||
if(given_serial == 0)
|
||||
serial_number = rand(1, poster_designs.len)
|
||||
else
|
||||
serial_number = given_serial
|
||||
name += " - No. [serial_number]"
|
||||
..(loc)
|
||||
|
||||
@@ -57,7 +59,7 @@
|
||||
|
||||
user << "<span class='notice'>You start placing the poster on the wall...</span>" //Looks like it's uncluttered enough. Place the poster.
|
||||
|
||||
var/obj/structure/sign/poster/P = new(user.loc, placement_dir=get_dir(user, W), serial=serial_number)
|
||||
var/obj/structure/sign/poster/P = new poster_type(user.loc, placement_dir=get_dir(user, W), serial=serial_number, itemtype = src.type)
|
||||
|
||||
flick("poster_being_set", P)
|
||||
//playsound(W, 'sound/items/poster_being_created.ogg', 100, 1) //why the hell does placing a poster make printer sounds?
|
||||
@@ -74,6 +76,18 @@
|
||||
|
||||
qdel(oldsrc) //delete it now to cut down on sanity checks afterwards. Agouri's code supports rerolling it anyway
|
||||
|
||||
//NT subtype
|
||||
/obj/item/weapon/contraband/poster/nanotrasen
|
||||
icon_state = "rolled_poster_nt"
|
||||
poster_type = /obj/structure/sign/poster/nanotrasen
|
||||
|
||||
/obj/item/weapon/contraband/poster/nanotrasen/New(turf/loc, var/given_serial = 0)
|
||||
if(given_serial == 0)
|
||||
serial_number = rand(1, NT_poster_designs.len)
|
||||
else
|
||||
serial_number = given_serial
|
||||
..(loc)
|
||||
|
||||
//############################## THE ACTUAL DECALS ###########################
|
||||
|
||||
/obj/structure/sign/poster
|
||||
@@ -85,15 +99,22 @@
|
||||
var/poster_type //So mappers can specify a desired poster
|
||||
var/ruined = 0
|
||||
|
||||
/obj/structure/sign/poster/New(var/newloc, var/placement_dir=null, var/serial=null)
|
||||
var/roll_type
|
||||
var/poster_set = FALSE
|
||||
|
||||
/obj/structure/sign/poster/New(var/newloc, var/placement_dir=null, var/serial=null, var/itemtype = /obj/item/weapon/contraband/poster)
|
||||
..(newloc)
|
||||
|
||||
if(!serial)
|
||||
serial = rand(1, poster_designs.len) //use a random serial if none is given
|
||||
|
||||
serial_number = serial
|
||||
var/datum/poster/design = poster_designs[serial_number]
|
||||
set_poster(design)
|
||||
if(!poster_set)
|
||||
serial_number = serial
|
||||
var/datum/poster/design = poster_designs[serial_number]
|
||||
set_poster(design)
|
||||
|
||||
if(itemtype || !roll_type)
|
||||
roll_type = itemtype
|
||||
|
||||
switch (placement_dir)
|
||||
if (NORTH)
|
||||
@@ -121,6 +142,8 @@
|
||||
desc = "[initial(desc)] [design.desc]"
|
||||
icon_state = design.icon_state // poster[serial_number]
|
||||
|
||||
poster_set = TRUE
|
||||
|
||||
/obj/structure/sign/poster/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(W.is_wirecutter())
|
||||
playsound(src.loc, W.usesound, 100, 1)
|
||||
@@ -132,7 +155,6 @@
|
||||
roll_and_drop(user.loc)
|
||||
return
|
||||
|
||||
|
||||
/obj/structure/sign/poster/attack_hand(mob/user as mob)
|
||||
|
||||
if(ruined)
|
||||
@@ -152,7 +174,7 @@
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/structure/sign/poster/proc/roll_and_drop(turf/newloc)
|
||||
var/obj/item/weapon/contraband/poster/P = new(src, serial_number)
|
||||
var/obj/item/weapon/contraband/poster/P = new roll_type(src, serial_number)
|
||||
P.loc = newloc
|
||||
src.loc = P
|
||||
qdel(src)
|
||||
@@ -163,3 +185,17 @@
|
||||
// Description suffix
|
||||
var/desc=""
|
||||
var/icon_state=""
|
||||
|
||||
// NT poster subtype.
|
||||
/obj/structure/sign/poster/nanotrasen
|
||||
roll_type = /obj/item/weapon/contraband/poster/nanotrasen
|
||||
|
||||
/obj/structure/sign/poster/nanotrasen/New(var/newloc, var/placement_dir=null, var/serial=null, var/itemtype = /obj/item/weapon/contraband/poster/nanotrasen)
|
||||
if(!serial)
|
||||
serial = rand(1, NT_poster_designs.len)
|
||||
|
||||
serial_number = serial
|
||||
var/datum/poster/design = NT_poster_designs[serial_number]
|
||||
set_poster(design)
|
||||
|
||||
..(newloc, placement_dir, serial, itemtype)
|
||||
|
||||
@@ -44,3 +44,170 @@
|
||||
desc = "This poster appears to be reference material for maintenance personnel, instructing to always wear insulated gloves, that wirecutters and \
|
||||
a multitool are the optimal tools to use, and where to find the maintenance panel on most airlocks. Unfortunately, the poster does not mention any \
|
||||
wire codes."
|
||||
|
||||
/datum/poster/pol_10
|
||||
icon_state="polposter9"
|
||||
name = "orchid"
|
||||
desc = "This poster appears strangely familiar, depicting the flower of a tree native to the planet Earth."
|
||||
|
||||
// A new subset of poster datum for Security posters.
|
||||
/datum/poster/nanotrasen
|
||||
icon_state = "polposter1"
|
||||
name = "Safety!"
|
||||
desc = "A poster advising you to learn how to put on your internals at a moment's notice."
|
||||
|
||||
/datum/poster/nanotrasen/pol_2
|
||||
icon_state="polposter2"
|
||||
name = "Safety!"
|
||||
desc = "A blue and white colored poster. This one advises you to wear your safety goggles when handling chemicals."
|
||||
|
||||
/datum/poster/nanotrasen/pol_3
|
||||
icon_state="polposter3"
|
||||
name = "Safety!"
|
||||
desc = "A safety poster instructing you to comply with the authorities, especially in an emergency."
|
||||
|
||||
/datum/poster/nanotrasen/pol_4
|
||||
icon_state="polposter4"
|
||||
name = "Clean Hands Save Lives"
|
||||
desc = "A safety poster reminding you to wash your hands."
|
||||
|
||||
/datum/poster/nanotrasen/pol_5
|
||||
icon_state="polposter5"
|
||||
name = "Help!"
|
||||
desc = "This poster depicts a man helping another man get up."
|
||||
|
||||
/datum/poster/nanotrasen/pol_6
|
||||
icon_state="polposter6"
|
||||
name = "Walk!"
|
||||
desc = "This poster depicts a man walking, presumably to encourage you not to run in the halls."
|
||||
|
||||
/datum/poster/nanotrasen/pol_7
|
||||
icon_state="polposter7"
|
||||
name = "Place your signs!"
|
||||
desc = "A safety poster reminding custodial staff to place wet floor signs where needed. This reminder's rarely heeded."
|
||||
|
||||
/datum/poster/nanotrasen/pol_8
|
||||
icon_state="polposter8"
|
||||
name = "Safety!"
|
||||
desc = "An advertisement / safety poster for EVA training and certification. Training is available at your local Central Command."
|
||||
|
||||
/datum/poster/nanotrasen/pol_9
|
||||
icon_state="poster10"
|
||||
name = "Airlock Maintenance Reference"
|
||||
desc = "This poster appears to be reference material for maintenance personnel, instructing to always wear insulated gloves, that wirecutters and \
|
||||
a multitool are the optimal tools to use, and where to find the maintenance panel on most airlocks. Unfortunately, the poster does not mention any \
|
||||
wire codes."
|
||||
|
||||
/datum/poster/nanotrasen/pol_10
|
||||
icon_state="polposter9"
|
||||
name = "orchid"
|
||||
desc = "This poster suggests a feeling of peace. It depicts the flower of a tree native to the planet Earth."
|
||||
|
||||
/datum/poster/nanotrasen/bay_9
|
||||
icon_state="bsposter9"
|
||||
name = "Pinup Girl Amy"
|
||||
desc = "This particular one is of Amy, the nymphomaniac urban legend of deep space. How this photograph came to be is not known."
|
||||
|
||||
/datum/poster/nanotrasen/bay_21
|
||||
icon_state="bsposter21"
|
||||
name = "Join the Fuzz!"
|
||||
desc = "It's a nice recruitment poster of a white haired Chinese woman that says; \"Big Guns, Hot Women, Good Times. Security. We get it done.\""
|
||||
|
||||
/datum/poster/nanotrasen/bay_22
|
||||
icon_state="bsposter22"
|
||||
name = "Looking for a career with excitement?"
|
||||
desc = "A recruitment poster starring a dark haired woman with glasses and a purple shirt that has \"Got Brains? Got Talent? Not afraid of electric flying monsters that want to suck the soul out of you? Then Xenobiology could use someone like you!\" written on the bottom."
|
||||
|
||||
/datum/poster/nanotrasen/bay_23
|
||||
icon_state="bsposter23"
|
||||
name = "Safety first: because electricity doesn't wait!"
|
||||
desc = "A safety poster starring a clueless looking redhead with frazzled hair. \"Every year, hundreds of NT employees expose themselves to electric shock. Play it safe. Avoid suspicious doors after electrical storms, and always wear protection when doing electric maintenance.\""
|
||||
|
||||
/datum/poster/nanotrasen/bay_24
|
||||
icon_state="bsposter24"
|
||||
name = "Responsible medbay habits, No #259"
|
||||
desc = "A poster with a nervous looking geneticist on it states; \"Friends Tell Friends They're Clones. It can cause severe and irreparable emotional trauma if a person is not properly informed of their recent demise. Always follow your contractual obligation and inform them of their recent rejuvenation.\""
|
||||
|
||||
/datum/poster/nanotrasen/bay_25
|
||||
icon_state="bsposter25"
|
||||
name = "Irresponsible medbay habits, No #2"
|
||||
desc = "This is a safety poster starring a perverted looking naked doctor. \"Sexual harassment is never okay. REPORT any acts of sexual deviance or harassment that disrupt a healthy working environment.\""
|
||||
|
||||
/datum/poster/nanotrasen/bay_49
|
||||
icon_state="bsposter49"
|
||||
name = "Engineering recruitment"
|
||||
desc = "This is a poster showing an engineer relaxing by a computer, the text states \"Living the life! Join Engineering today!\""
|
||||
|
||||
/datum/poster/nanotrasen/bay_52
|
||||
icon_state="bsposter52"
|
||||
name = "fire safety poster"
|
||||
desc = "This is a poster reminding you of what you should do if you are on fire, or if you are at a dance party."
|
||||
|
||||
/datum/poster/nanotrasen/bay_53
|
||||
icon_state="bsposter53"
|
||||
name = "fire extinguisher poster"
|
||||
desc = "This is a poster reminding you of what you should use to put out a fire."
|
||||
|
||||
/datum/poster/nanotrasen/bay_54
|
||||
icon_state="bsposter54"
|
||||
name = "firefighter poster"
|
||||
desc = "This is a poster of a particularly stern looking firefighter. The caption reads, \"Only you can prevent space fires.\""
|
||||
|
||||
/datum/poster/nanotrasen/bay_57
|
||||
icon_state="bsposter57"
|
||||
name = "space carp warning poster"
|
||||
desc = "This poster tells of the dangers of space carp infestations."
|
||||
|
||||
/datum/poster/nanotrasen/bay_58
|
||||
icon_state="bsposter58"
|
||||
name = "space carp information poster"
|
||||
desc = "This poster showcases an old spacer saying on the dangers of migrant space carp."
|
||||
|
||||
/datum/poster/nanotrasen/nt_1
|
||||
icon_state = "ntposter01"
|
||||
name = "Security recruitment"
|
||||
desc = "This poster showcases an NT security guard in an excited pose, with a small blurb about the importance of Security."
|
||||
|
||||
/datum/poster/nanotrasen/nt_2
|
||||
icon_state = "ntposter02"
|
||||
name = "Security recruitment"
|
||||
desc = "This poster showcases an NT security guard in an excited pose, with a small blurb about Security Employee benefits."
|
||||
|
||||
/datum/poster/nanotrasen/nt_3
|
||||
icon_state = "ntposter03"
|
||||
name = "Mechatronic Safety"
|
||||
desc = "This poster displays three cutting-edge gygaxes standing in line in front of a man in plain clothes.\
|
||||
The poster's captions explain the importance of knowing how to operate a mechatronic vehicle safely, especially near other personnel.\
|
||||
The image seems important."
|
||||
|
||||
/datum/poster/nanotrasen/nt_4
|
||||
icon_state = "ntposter04"
|
||||
name = "Beware Aetotheans"
|
||||
desc = "This poster displays a distinctly hostile-looking red Promethean in a black coat. The fine-print around the edges warns the reader about the dangers posed by Almachi Prometheans."
|
||||
|
||||
/datum/poster/nanotrasen/nt_5
|
||||
icon_state = "ntposter05"
|
||||
name = "Promethean"
|
||||
desc = "This poster displays a friendly-looking green Promethean in a labcoat. The fine-print around the edges talks about the benefits Prometheans give in laboratories."
|
||||
|
||||
/datum/poster/nanotrasen/nt_6
|
||||
icon_state = "ntposter06"
|
||||
name = "NanoTrasen"
|
||||
desc = "This poster showcases an NT emblem. There is writing in the ring around the inner points, probably some sort of slogan no one bothers to memorize."
|
||||
|
||||
/datum/poster/nanotrasen/nt_7
|
||||
icon_state = "ntposter07"
|
||||
name = "SolGov"
|
||||
desc = "This poster showcases an SCG emblem. The outer ring reads,\
|
||||
\"<font face='times new roman ms'>NIL MORTALIBUS ARDUI EST</font>\".\
|
||||
Solar Confederate Government."
|
||||
|
||||
/datum/poster/nanotrasen/nt_8
|
||||
icon_state = "ntposter08"
|
||||
name = "wildlife hazard"
|
||||
desc = "This poster warns against attempting to kill a fully grown giant spider or other hostile life-form alone."
|
||||
|
||||
/datum/poster/nanotrasen/nt_9
|
||||
icon_state = "ntposter09"
|
||||
name = "Regulations and You"
|
||||
desc = "This poster showcases an NT security guard reading from her PDA. The blurb advocates for the reader to keep corporate regulations in mind at all times, as an emergency can occur at any time."
|
||||
|
||||
@@ -134,6 +134,8 @@
|
||||
var/travelling_in_vent = 0
|
||||
var/list/grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/nurse, /mob/living/simple_mob/animal/giant_spider/hunter)
|
||||
|
||||
var/stunted = FALSE
|
||||
|
||||
/obj/effect/spider/spiderling/frost
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider/frost)
|
||||
|
||||
@@ -261,9 +263,17 @@
|
||||
break
|
||||
if(amount_grown >= 100)
|
||||
var/spawn_type = pick(grow_as)
|
||||
new spawn_type(src.loc, src)
|
||||
var/mob/living/simple_mob/animal/giant_spider/GS = new spawn_type(src.loc, src)
|
||||
if(stunted)
|
||||
spawn(2)
|
||||
GS.make_spiderling()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spider/spiderling/stunted
|
||||
stunted = TRUE
|
||||
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/hunter)
|
||||
|
||||
/obj/effect/decal/cleanable/spiderling_remains
|
||||
name = "spiderling remains"
|
||||
desc = "Green squishy mess."
|
||||
|
||||
@@ -295,7 +295,7 @@
|
||||
desc = "A desk lamp with an adjustable mount."
|
||||
icon_state = "lamp"
|
||||
force = 10
|
||||
brightness_on = 5
|
||||
brightness_on = 10 //TFF 27/11/19 - post refactor fix for intensity levels.
|
||||
w_class = ITEMSIZE_LARGE
|
||||
power_use = 0
|
||||
on = 1
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
/obj/item/device/encryptionkey/heads/captain
|
||||
name = "colony director's encryption key"
|
||||
icon_state = "cap_cypherkey"
|
||||
channels = list("Command" = 1, "Security" = 1, "Engineering" = 0, "Science" = 0, "Medical" = 0, "Supply" = 0, "Service" = 0)
|
||||
channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "Service" = 1)
|
||||
|
||||
/obj/item/device/encryptionkey/heads/ai_integrated
|
||||
name = "ai integrated encryption key"
|
||||
@@ -99,7 +99,7 @@
|
||||
/obj/item/device/encryptionkey/heads/hop
|
||||
name = "head of personnel's encryption key"
|
||||
icon_state = "hop_cypherkey"
|
||||
channels = list("Supply" = 1, "Service" = 1, "Command" = 1, "Security" = 0)
|
||||
channels = list("Supply" = 1, "Service" = 1, "Command" = 1, "Security" = 1)
|
||||
/*
|
||||
/obj/item/device/encryptionkey/headset_mine
|
||||
name = "mining radio encryption key"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/device/encryptionkey/heads/hop
|
||||
name = "head of personnel's encryption key"
|
||||
icon_state = "hop_cypherkey"
|
||||
channels = list("Supply" = 1, "Service" = 1, "Command" = 1, "Security" = 0, "Explorer" = 0)
|
||||
channels = list("Supply" = 1, "Service" = 1, "Command" = 1, "Security" = 1, "Explorer" = 1)
|
||||
|
||||
/obj/item/device/encryptionkey/heads/ai_integrated
|
||||
name = "ai integrated encryption key"
|
||||
@@ -12,7 +12,7 @@
|
||||
/obj/item/device/encryptionkey/heads/captain
|
||||
name = "colony director's encryption key"
|
||||
icon_state = "cap_cypherkey"
|
||||
channels = list("Command" = 1, "Security" = 1, "Engineering" = 0, "Science" = 0, "Medical" = 0, "Supply" = 0, "Service" = 0, "Explorer" = 0)
|
||||
channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "Service" = 1, "Explorer" = 1)
|
||||
|
||||
/obj/item/device/encryptionkey/heads/rd
|
||||
name = "research director's encryption key"
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
SPECIES_WEREBEAST = 'icons/mob/species/werebeast/ears.dmi')
|
||||
|
||||
/obj/item/device/radio/headset/mob_headset //Adminbus headset for simplemob shenanigans.
|
||||
name = "nonhuman radio implant"
|
||||
desc = "An updated, modular intercom that requires no hands to operate. Takes encryption keys"
|
||||
name = "nonhuman radio receiver"
|
||||
desc = "An updated, self-adhesive modular intercom that requires no hands to operate or ears to hold, just stick it on. Takes encryption keys"
|
||||
|
||||
/obj/item/device/radio/headset/mob_headset/receive_range(freq, level)
|
||||
if(ismob(src.loc))
|
||||
return ..(freq, level)
|
||||
return ..(freq, level, 1)
|
||||
return -1
|
||||
|
||||
/obj/item/device/radio/headset/mob_headset/afterattack(var/atom/movable/target, mob/living/user, proximity)
|
||||
@@ -36,6 +36,7 @@
|
||||
if(istype(target,/mob/living/simple_mob))
|
||||
var/mob/living/simple_mob/M = target
|
||||
if(!M.mob_radio)
|
||||
user.drop_item()
|
||||
forceMove(M)
|
||||
M.mob_radio = src
|
||||
return
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
name = "broken bug"
|
||||
desc = "" //Even when it's broken it's inconspicuous
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "eshield0"
|
||||
icon_state = "eshield"
|
||||
item_state = "nothing"
|
||||
layer = TURF_LAYER+0.2
|
||||
w_class = ITEMSIZE_TINY
|
||||
@@ -75,7 +75,7 @@
|
||||
name = "bug"
|
||||
desc = "" //Nothing to see here
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "eshield0"
|
||||
icon_state = "eshield"
|
||||
item_state = "nothing"
|
||||
layer = TURF_LAYER+0.2
|
||||
w_class = ITEMSIZE_TINY
|
||||
|
||||
450
code/game/objects/items/devices/translocator_vr.dm
Normal file
450
code/game/objects/items/devices/translocator_vr.dm
Normal file
@@ -0,0 +1,450 @@
|
||||
//The perfect adminboos device?
|
||||
/obj/item/device/perfect_tele
|
||||
name = "personal translocator"
|
||||
desc = "Seems absurd, doesn't it? Yet, here we are. Generally considered dangerous contraband unless the user has permission from Central Command."
|
||||
icon = 'icons/obj/device_alt.dmi'
|
||||
icon_state = "hand_tele"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_MAGNET = 5, TECH_BLUESPACE = 5, TECH_ILLEGAL = 7)
|
||||
|
||||
var/cell_type = /obj/item/weapon/cell/device/weapon
|
||||
var/obj/item/weapon/cell/power_source
|
||||
var/charge_cost = 800 // cell/device/weapon has 2400
|
||||
var/battery_lock = 0 //If set, weapon cannot switch batteries
|
||||
|
||||
var/longrange = 0 //Can teleport very long distances
|
||||
var/abductor = 0 //Can be used on teleportation blocking turfs
|
||||
|
||||
var/list/beacons = list()
|
||||
var/ready = 1
|
||||
var/beacons_left = 3
|
||||
var/failure_chance = 5 //Percent
|
||||
var/obj/item/device/perfect_tele_beacon/destination
|
||||
var/datum/effect/effect/system/spark_spread/spk
|
||||
var/list/warned_users = list()
|
||||
var/list/logged_events = list()
|
||||
|
||||
/obj/item/device/perfect_tele/New()
|
||||
..()
|
||||
flags |= NOBLUDGEON
|
||||
if(cell_type)
|
||||
power_source = new cell_type(src)
|
||||
else
|
||||
power_source = new /obj/item/weapon/cell/device(src)
|
||||
spk = new(src)
|
||||
spk.set_up(5, 0, src)
|
||||
spk.attach(src)
|
||||
|
||||
/obj/item/device/perfect_tele/Destroy()
|
||||
// Must clear the beacon's backpointer or we won't GC. Someday maybe do something nicer even.
|
||||
for(var/obj/item/device/perfect_tele_beacon/B in beacons)
|
||||
B.tele_hand = null
|
||||
beacons.Cut()
|
||||
QDEL_NULL(power_source)
|
||||
QDEL_NULL(spk)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/perfect_tele/update_icon()
|
||||
if(!power_source)
|
||||
icon_state = "[initial(icon_state)]_o"
|
||||
else if(ready && (power_source.check_charge(charge_cost) || power_source.fully_charged()))
|
||||
icon_state = "[initial(icon_state)]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]_w"
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/device/perfect_tele/attack_hand(mob/user)
|
||||
if(user.get_inactive_hand() == src)
|
||||
unload_ammo(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/perfect_tele/proc/unload_ammo(mob/user)
|
||||
if(battery_lock)
|
||||
to_chat(user,"<span class='notice'>[src] does not have a battery port.</span>")
|
||||
return
|
||||
if(user.get_inactive_hand() == src && power_source)
|
||||
to_chat(user,"<span class='notice'>You eject \the [power_source] from \the [src].</span>")
|
||||
user.put_in_hands(power_source)
|
||||
power_source = null
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user,"<span class='notice'>[src] does not have a power cell.</span>")
|
||||
|
||||
/obj/item/device/perfect_tele/attack_self(mob/user)
|
||||
if(!(user.ckey in warned_users))
|
||||
warned_users |= user.ckey
|
||||
alert(user,"This device can be easily used to break ERP preferences due to the nature of teleporting \
|
||||
and tele-vore. Make sure you carefully examine someone's OOC prefs before teleporting them if you are \
|
||||
going to use this device for ERP purposes. This device records all warnings given and teleport events for \
|
||||
admin review in case of pref-breaking, so just don't do it.","OOC WARNING")
|
||||
|
||||
var/choice = alert(user,"What do you want to do?","[src]","Create Beacon","Cancel","Target Beacon")
|
||||
switch(choice)
|
||||
if("Create Beacon")
|
||||
if(beacons_left <= 0)
|
||||
alert("The translocator can't support any more beacons!","Error")
|
||||
return
|
||||
|
||||
var/new_name = html_encode(input(user,"New beacon's name (2-20 char):","[src]") as text|null)
|
||||
|
||||
if(length(new_name) > 20 || length(new_name) < 2)
|
||||
alert("Entered name length invalid (must be longer than 2, no more than than 20).","Error")
|
||||
return
|
||||
if(new_name in beacons)
|
||||
alert("No duplicate names, please. '[new_name]' exists already.","Error")
|
||||
return
|
||||
|
||||
var/obj/item/device/perfect_tele_beacon/nb = new(get_turf(src))
|
||||
nb.tele_name = new_name
|
||||
nb.tele_hand = src
|
||||
nb.creator = user.ckey
|
||||
beacons[new_name] = nb
|
||||
beacons_left--
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
L.put_in_any_hand_if_possible(nb)
|
||||
|
||||
if("Target Beacon")
|
||||
if(!beacons.len)
|
||||
to_chat(user,"<span class='warning'>\The [src] doesn't have any beacons!</span>")
|
||||
else
|
||||
var/target = input("Which beacon do you target?","[src]") in beacons|null
|
||||
if(target && (target in beacons))
|
||||
destination = beacons[target]
|
||||
to_chat(user,"<span class='notice'>Destination set to '[target]'.</span>")
|
||||
else
|
||||
return
|
||||
|
||||
/obj/item/device/perfect_tele/attackby(obj/W, mob/user)
|
||||
if(istype(W,cell_type) && !power_source)
|
||||
power_source = W
|
||||
power_source.update_icon() //Why doesn't a cell do this already? :|
|
||||
user.unEquip(power_source)
|
||||
power_source.forceMove(src)
|
||||
to_chat(user,"<span class='notice'>You insert \the [power_source] into \the [src].</span>")
|
||||
update_icon()
|
||||
|
||||
else if(istype(W,/obj/item/device/perfect_tele_beacon))
|
||||
var/obj/item/device/perfect_tele_beacon/tb = W
|
||||
if(tb.tele_name in beacons)
|
||||
to_chat(user,"<span class='notice'>You re-insert \the [tb] into \the [src].</span>")
|
||||
beacons -= tb.tele_name
|
||||
user.unEquip(tb)
|
||||
qdel(tb)
|
||||
beacons_left++
|
||||
else
|
||||
to_chat(user,"<span class='notice'>\The [tb] doesn't belong to \the [src].</span>")
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/perfect_tele/proc/teleport_checks(mob/living/target,mob/living/user)
|
||||
//Uhhuh, need that power source
|
||||
if(!power_source)
|
||||
to_chat(user,"<span class='warning'>\The [src] has no power source!</span>")
|
||||
return FALSE
|
||||
|
||||
//Check for charge
|
||||
if((!power_source.check_charge(charge_cost)) && (!power_source.fully_charged()))
|
||||
to_chat(user,"<span class='warning'>\The [src] does not have enough power left!</span>")
|
||||
return FALSE
|
||||
|
||||
//Only mob/living need apply.
|
||||
if(!istype(user) || !istype(target))
|
||||
return FALSE
|
||||
|
||||
//No, you can't teleport buckled people.
|
||||
if(target.buckled)
|
||||
to_chat(user,"<span class='warning'>The target appears to be attached to something...</span>")
|
||||
return FALSE
|
||||
|
||||
//No, you can't teleport if it's not ready yet.
|
||||
if(!ready)
|
||||
to_chat(user,"<span class='warning'>\The [src] is still recharging!</span>")
|
||||
return FALSE
|
||||
|
||||
//No, you can't teleport if there's no destination.
|
||||
if(!destination)
|
||||
to_chat(user,"<span class='warning'>\The [src] doesn't have a current valid destination set!</span>")
|
||||
return FALSE
|
||||
|
||||
//No, you can't teleport if there's a jammer.
|
||||
if(is_jammed(src) || is_jammed(destination))
|
||||
to_chat(user,"<span class='warning'>\The [src] refuses to teleport you, due to strong interference!</span>")
|
||||
return FALSE
|
||||
|
||||
//No, you can't port to or from away missions. Stupidly complicated check.
|
||||
var/turf/uT = get_turf(user)
|
||||
var/turf/dT = get_turf(destination)
|
||||
var/list/dat = list()
|
||||
dat["z_level_detection"] = using_map.get_map_levels(uT.z)
|
||||
|
||||
if(!uT || !dT)
|
||||
return FALSE
|
||||
|
||||
if(!longrange)
|
||||
if( (uT.z != dT.z) && (!(dT.z in dat["z_level_detection"])) )
|
||||
to_chat(user,"<span class='warning'>\The [src] can't teleport you that far!</span>")
|
||||
return FALSE
|
||||
|
||||
if(!abductor)
|
||||
if(uT.block_tele || dT.block_tele)
|
||||
to_chat(user,"<span class='warning'>Something is interfering with \the [src]!</span>")
|
||||
return FALSE
|
||||
|
||||
//Seems okay to me!
|
||||
return TRUE
|
||||
|
||||
/obj/item/device/perfect_tele/afterattack(mob/living/target, mob/living/user, proximity)
|
||||
//No, you can't teleport people from over there.
|
||||
if(!proximity)
|
||||
return
|
||||
|
||||
if(!teleport_checks(target,user))
|
||||
return //The checks proc can send them a message if it wants.
|
||||
|
||||
//Bzzt.
|
||||
ready = 0
|
||||
power_source.use(charge_cost)
|
||||
|
||||
//Failure chance
|
||||
if(prob(failure_chance) && beacons.len >= 2)
|
||||
var/list/wrong_choices = beacons - destination.tele_name
|
||||
var/wrong_name = pick(wrong_choices)
|
||||
destination = beacons[wrong_name]
|
||||
to_chat(user,"<span class='warning'>\The [src] malfunctions and sends you to the wrong beacon!</span>")
|
||||
|
||||
//Destination beacon vore checking
|
||||
var/turf/dT = get_turf(destination)
|
||||
var/atom/real_dest = dT
|
||||
|
||||
var/atom/real_loc = destination.loc
|
||||
if(isbelly(real_loc))
|
||||
real_dest = real_loc
|
||||
if(isliving(real_loc))
|
||||
var/mob/living/L = real_loc
|
||||
if(L.vore_selected)
|
||||
real_dest = L.vore_selected
|
||||
else if(L.vore_organs.len)
|
||||
real_dest = pick(L.vore_organs)
|
||||
|
||||
//Confirm televore
|
||||
var/televored = FALSE
|
||||
if(isbelly(real_dest))
|
||||
var/obj/belly/B = real_dest
|
||||
if(!target.can_be_drop_prey && B.owner != user)
|
||||
to_chat(target,"<span class='warning'>\The [src] narrowly avoids teleporting you right into \a [lowertext(real_dest.name)]!</span>")
|
||||
real_dest = dT //Nevermind!
|
||||
else
|
||||
televored = TRUE
|
||||
to_chat(target,"<span class='warning'>\The [src] teleports you right into \a [lowertext(real_dest.name)]!</span>")
|
||||
|
||||
//Phase-out effect
|
||||
phase_out(target,get_turf(target))
|
||||
|
||||
//Move them
|
||||
target.forceMove(real_dest)
|
||||
|
||||
//Phase-in effect
|
||||
phase_in(target,get_turf(target))
|
||||
|
||||
//And any friends!
|
||||
for(var/obj/item/weapon/grab/G in target.contents)
|
||||
if(G.affecting && (G.state >= GRAB_AGGRESSIVE))
|
||||
|
||||
//Phase-out effect for grabbed person
|
||||
phase_out(G.affecting,get_turf(G.affecting))
|
||||
|
||||
//Move them, and televore if necessary
|
||||
G.affecting.forceMove(real_dest)
|
||||
if(televored)
|
||||
to_chat(target,"<span class='warning'>\The [src] teleports you right into \a [lowertext(real_dest.name)]!</span>")
|
||||
|
||||
//Phase-in effect for grabbed person
|
||||
phase_in(G.affecting,get_turf(G.affecting))
|
||||
|
||||
update_icon()
|
||||
spawn(30 SECONDS)
|
||||
ready = 1
|
||||
update_icon()
|
||||
|
||||
logged_events["[world.time]"] = "[user] teleported [target] to [real_dest] [televored ? "(Belly: [lowertext(real_dest.name)])" : null]"
|
||||
|
||||
/obj/item/device/perfect_tele/proc/phase_out(var/mob/M,var/turf/T)
|
||||
|
||||
if(!M || !T)
|
||||
return
|
||||
|
||||
spk.set_up(5, 0, M)
|
||||
spk.attach(M)
|
||||
playsound(T, "sparks", 50, 1)
|
||||
anim(T,M,'icons/mob/mob.dmi',,"phaseout",,M.dir)
|
||||
|
||||
/obj/item/device/perfect_tele/proc/phase_in(var/mob/M,var/turf/T)
|
||||
|
||||
if(!M || !T)
|
||||
return
|
||||
|
||||
spk.start()
|
||||
playsound(T, 'sound/effects/phasein.ogg', 25, 1)
|
||||
playsound(T, 'sound/effects/sparks2.ogg', 50, 1)
|
||||
anim(T,M,'icons/mob/mob.dmi',,"phasein",,M.dir)
|
||||
spk.set_up(5, 0, src)
|
||||
spk.attach(src)
|
||||
|
||||
/obj/item/device/perfect_tele_beacon
|
||||
name = "translocator beacon"
|
||||
desc = "That's unusual."
|
||||
icon = 'icons/obj/device_alt.dmi'
|
||||
icon_state = "motion2"
|
||||
w_class = ITEMSIZE_TINY
|
||||
|
||||
var/tele_name
|
||||
var/obj/item/device/perfect_tele/tele_hand
|
||||
var/creator
|
||||
var/warned_users = list()
|
||||
var/tele_network = null
|
||||
|
||||
/obj/item/device/perfect_tele_beacon/New()
|
||||
..()
|
||||
flags |= NOBLUDGEON
|
||||
|
||||
/obj/item/device/perfect_tele_beacon/Destroy()
|
||||
tele_name = null
|
||||
tele_hand = null
|
||||
return ..()
|
||||
|
||||
/obj/item/device/perfect_tele_beacon/attack_hand(mob/user)
|
||||
if((user.ckey != creator) && !(user.ckey in warned_users))
|
||||
warned_users |= user.ckey
|
||||
var/choice = alert(user,"This device is a translocator beacon. Having it on your person may mean that anyone \
|
||||
who teleports to this beacon gets teleported into your selected vore-belly. If you are prey-only \
|
||||
or don't wish to potentially have a random person teleported into you, it's suggested that you \
|
||||
not carry this around.","OOC WARNING","Take It","Leave It")
|
||||
if(choice == "Leave It")
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/device/perfect_tele_beacon/stationary
|
||||
name = "stationary translocator beacon"
|
||||
icon = 'icons/obj/radio_vr.dmi'
|
||||
icon_state = "floor_beacon"
|
||||
w_class = ITEMSIZE_HUGE
|
||||
anchored = 1
|
||||
|
||||
GLOBAL_LIST_BOILERPLATE(premade_tele_beacons, /obj/item/device/perfect_tele_beacon/stationary)
|
||||
|
||||
/obj/item/device/perfect_tele_beacon/attack_self(mob/user)
|
||||
if(!isliving(user))
|
||||
return
|
||||
var/mob/living/L = user
|
||||
var/confirm = alert(user, "You COULD eat the beacon...", "Eat beacon?", "Eat it!", "No, thanks.")
|
||||
if(confirm == "Eat it!")
|
||||
var/obj/belly/bellychoice = input("Which belly?","Select A Belly") as null|anything in L.vore_organs
|
||||
if(bellychoice)
|
||||
user.visible_message("<span class='warning'>[user] is trying to stuff \the [src] into [user.gender == MALE ? "his" : user.gender == FEMALE ? "her" : "their"] [bellychoice]!</span>","<span class='notice'>You begin putting \the [src] into your [bellychoice]!</span>")
|
||||
if(do_after(user,5 SECONDS,src))
|
||||
user.unEquip(src)
|
||||
forceMove(bellychoice)
|
||||
user.visible_message("<span class='warning'>[user] eats a telebeacon!</span>","You eat the the beacon!")
|
||||
|
||||
// A single-beacon variant for use by miners (or whatever)
|
||||
/obj/item/device/perfect_tele/one_beacon
|
||||
name = "mini-translocator"
|
||||
desc = "A more limited translocator with a single beacon, useful for some things, like setting the mining department on fire accidentally. Legal for use in the pursuit of NanoTrasen interests, namely mining and exploration."
|
||||
icon_state = "minitrans"
|
||||
beacons_left = 1 //Just one
|
||||
cell_type = /obj/item/weapon/cell/device
|
||||
origin_tech = list(TECH_MAGNET = 5, TECH_BLUESPACE = 5)
|
||||
|
||||
/*
|
||||
/obj/item/device/perfect_tele/one_beacon/teleport_checks(mob/living/target,mob/living/user)
|
||||
var/turf/T = get_turf(destination)
|
||||
if(T && user.z != T.z)
|
||||
to_chat(user,"<span class='warning'>\The [src] is too far away from the beacon. Try getting closer first!</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
*/
|
||||
|
||||
/obj/item/device/perfect_tele/alien
|
||||
name = "alien translocator"
|
||||
desc = "This strange device allows one to teleport people and objects across large distances."
|
||||
|
||||
cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien
|
||||
charge_cost = 400
|
||||
beacons_left = 6
|
||||
failure_chance = 0 //Percent
|
||||
longrange = 1
|
||||
abductor = 1
|
||||
|
||||
/obj/item/device/perfect_tele/frontier
|
||||
icon_state = "minitrans"
|
||||
beacons_left = 1 //Just one
|
||||
battery_lock = 1
|
||||
unacidable = 1
|
||||
failure_chance = 0 //Percent
|
||||
var/loc_network = null
|
||||
var/phase_power = 75
|
||||
var/recharging = 0
|
||||
|
||||
/obj/item/device/perfect_tele/frontier/unload_ammo(var/mob/user)
|
||||
if(recharging)
|
||||
return
|
||||
recharging = 1
|
||||
update_icon()
|
||||
user.visible_message("<span class='notice'>[user] opens \the [src] and starts pumping the handle.</span>", \
|
||||
"<span class='notice'>You open \the [src] and start pumping the handle.</span>")
|
||||
while(recharging)
|
||||
if(!do_after(user, 10, src))
|
||||
break
|
||||
playsound(get_turf(src),'sound/items/change_drill.ogg',25,1)
|
||||
if(power_source.give(phase_power) < phase_power)
|
||||
break
|
||||
|
||||
recharging = 0
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/perfect_tele/frontier/update_icon()
|
||||
if(recharging)
|
||||
icon_state = "[initial(icon_state)]_o"
|
||||
update_held_icon()
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/device/perfect_tele/frontier/staff
|
||||
name = "centcom translocator"
|
||||
desc = "Similar to translocator technology, however, most of its destinations are hardcoded."
|
||||
charge_cost = 1200 // Enough for one person and their partner
|
||||
loc_network = "centcom"
|
||||
longrange = 1
|
||||
|
||||
/obj/item/device/perfect_tele/frontier/staff/New()
|
||||
..()
|
||||
for(var/obj/item/device/perfect_tele_beacon/stationary/nb in premade_tele_beacons)
|
||||
if(nb.tele_network == loc_network)
|
||||
beacons[nb.tele_name] = nb
|
||||
|
||||
/obj/item/device/perfect_tele/frontier/unknown
|
||||
name = "modified translocator"
|
||||
desc = "This crank-charged translocator has only one beacon, but it already has a destination preprogrammed into it."
|
||||
charge_cost = 1200 // Enough for one person and their partner
|
||||
longrange = 1
|
||||
abductor = 1
|
||||
|
||||
/obj/item/device/perfect_tele/frontier/unknown/New()
|
||||
..()
|
||||
for(var/obj/item/device/perfect_tele_beacon/stationary/nb in premade_tele_beacons)
|
||||
if(nb.tele_network == loc_network)
|
||||
beacons[nb.tele_name] = nb
|
||||
|
||||
/obj/item/device/perfect_tele/frontier/unknown/one
|
||||
loc_network = "unkone"
|
||||
/obj/item/device/perfect_tele/frontier/unknown/two
|
||||
loc_network = "unktwo"
|
||||
/obj/item/device/perfect_tele/frontier/unknown/three
|
||||
loc_network = "unkthree"
|
||||
/obj/item/device/perfect_tele/frontier/unknown/four
|
||||
loc_network = "unkfour"
|
||||
@@ -255,12 +255,14 @@
|
||||
name = "toy sword"
|
||||
desc = "A cheap, plastic replica of an energy sword. Realistic sounds! Ages 8 and up."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "sword0"
|
||||
icon_state = "esword"
|
||||
var/lcolor
|
||||
var/rainbow = FALSE
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
||||
)
|
||||
var/active = 0.0
|
||||
var/active = 0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list("attacked", "struck", "hit")
|
||||
|
||||
@@ -269,22 +271,54 @@
|
||||
if (src.active)
|
||||
user << "<span class='notice'>You extend the plastic blade with a quick flick of your wrist.</span>"
|
||||
playsound(user, 'sound/weapons/saberon.ogg', 50, 1)
|
||||
src.icon_state = "swordblue"
|
||||
src.item_state = "[icon_state]_blade"
|
||||
src.w_class = ITEMSIZE_LARGE
|
||||
else
|
||||
user << "<span class='notice'>You push the plastic blade back down into the handle.</span>"
|
||||
playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
|
||||
src.icon_state = "sword0"
|
||||
src.item_state = "[icon_state]"
|
||||
src.w_class = ITEMSIZE_SMALL
|
||||
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.update_inv_l_hand()
|
||||
H.update_inv_r_hand()
|
||||
|
||||
update_icon()
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/toy/sword/update_icon()
|
||||
. = ..()
|
||||
var/mutable_appearance/blade_overlay = mutable_appearance(icon, "[icon_state]_blade")
|
||||
blade_overlay.color = lcolor
|
||||
cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
|
||||
if(active)
|
||||
add_overlay(blade_overlay)
|
||||
if(istype(usr,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
H.update_inv_l_hand()
|
||||
H.update_inv_r_hand()
|
||||
|
||||
/obj/item/toy/sword/AltClick(mob/living/user)
|
||||
if(!in_range(src, user)) //Basic checks to prevent abuse
|
||||
return
|
||||
if(user.incapacitated() || !istype(user))
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
return
|
||||
|
||||
if(alert("Are you sure you want to recolor your blade?", "Confirm Recolor", "Yes", "No") == "Yes")
|
||||
var/energy_color_input = input(usr,"","Choose Energy Color",lcolor) as color|null
|
||||
if(energy_color_input)
|
||||
lcolor = sanitize_hexcolor(energy_color_input)
|
||||
update_icon()
|
||||
|
||||
/obj/item/toy/sword/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to recolor it.</span>")
|
||||
|
||||
/obj/item/toy/sword/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/device/multitool) && !active)
|
||||
if(!rainbow)
|
||||
rainbow = TRUE
|
||||
else
|
||||
rainbow = FALSE
|
||||
to_chat(user, "<span class='notice'>You manipulate the color controller in [src].</span>")
|
||||
update_icon()
|
||||
/obj/item/toy/katana
|
||||
name = "replica katana"
|
||||
desc = "Woefully underpowered in D20."
|
||||
|
||||
@@ -243,6 +243,13 @@
|
||||
electric_cost_coefficent = 41.66 // Twice as efficent, out of pity.
|
||||
toolspeed = 0.5 // Twice as fast, since borg versions typically have this.
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/borg/swarm
|
||||
can_remove_rwalls = FALSE
|
||||
name = "Rapid Assimilation Device"
|
||||
ranged = TRUE
|
||||
toolspeed = 0.7
|
||||
material_to_use = MAT_STEELHULL
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/borg/lesser
|
||||
can_remove_rwalls = FALSE
|
||||
|
||||
|
||||
@@ -197,6 +197,9 @@ var/last_chew = 0
|
||||
breakouttime = 200
|
||||
cuff_type = "duct tape"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/tape/cyborg
|
||||
dispenser = TRUE
|
||||
|
||||
//Legcuffs. Not /really/ handcuffs, but its close enough.
|
||||
/obj/item/weapon/handcuffs/legcuffs
|
||||
name = "legcuffs"
|
||||
|
||||
@@ -23,6 +23,26 @@
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
||||
)
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/green/New()
|
||||
colorable = FALSE
|
||||
lcolor = "#008000"
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/red/New()
|
||||
colorable = FALSE
|
||||
lcolor = "#FF0000"
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/blue/New()
|
||||
colorable = FALSE
|
||||
lcolor = "#0000FF"
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/purple/New()
|
||||
colorable = FALSE
|
||||
lcolor = "#800080"
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/white/New()
|
||||
colorable = FALSE
|
||||
lcolor = "#FFFFFF"
|
||||
|
||||
/obj/item/weapon/melee/energy/proc/activate(mob/living/user)
|
||||
if(active)
|
||||
return
|
||||
@@ -147,11 +167,12 @@
|
||||
/obj/item/weapon/melee/energy/update_icon()
|
||||
. = ..()
|
||||
var/mutable_appearance/blade_overlay = mutable_appearance(icon, "[icon_state]_blade")
|
||||
if(colorable)
|
||||
blade_overlay.color = lcolor
|
||||
if(rainbow || !colorable)
|
||||
blade_overlay.color = lcolor
|
||||
color = lcolor
|
||||
if(rainbow)
|
||||
blade_overlay = mutable_appearance(icon, "[icon_state]_blade_rainbow")
|
||||
blade_overlay.color = "FFFFFF"
|
||||
color = "FFFFFF"
|
||||
cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
|
||||
if(active)
|
||||
add_overlay(blade_overlay)
|
||||
@@ -368,6 +389,13 @@
|
||||
target.taunt(user)
|
||||
target.adjustFireLoss(force * 6) // 30 Burn, for 50 total.
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/ionic_rapier/lance
|
||||
name = "zero-point lance"
|
||||
desc = "Designed specifically for disrupting electronics at relatively close range, however it is still capable of dealing some damage to living beings."
|
||||
active_force = 20
|
||||
armor_penetration = 15
|
||||
reach = 2
|
||||
|
||||
/*
|
||||
* Charge blade. Uses a cell, and costs energy per strike.
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/obj/item/weapon/melee/energy/sword/imperial
|
||||
name = "energy gladius"
|
||||
desc = "A broad, short energy blade. You'll be glad to have this in a fight."
|
||||
icon_state = "sword0"
|
||||
icon_state = "impsword"
|
||||
icon = 'icons/obj/weapons_vr.dmi'
|
||||
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_melee_vr.dmi', slot_r_hand_str = 'icons/mob/items/righthand_melee_vr.dmi')
|
||||
|
||||
/obj/item/weapon/melee/energy/sword/imperial/activate(mob/living/user)
|
||||
..()
|
||||
icon_state = "sword1"
|
||||
colorable = FALSE
|
||||
lcolor = "#FFFFFF"
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "energy scutum"
|
||||
desc = "It's really easy to mispronounce the name of this shield if you've only read it in books."
|
||||
icon = 'icons/obj/weapons_vr.dmi'
|
||||
icon_state = "eshield0" // eshield1 for expanded
|
||||
icon_state = "impshield" // eshield1 for expanded
|
||||
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_melee_vr.dmi', slot_r_hand_str = 'icons/mob/items/righthand_melee_vr.dmi')
|
||||
|
||||
/obj/item/weapon/shield/fluff/wolfgirlshield
|
||||
|
||||
@@ -373,3 +373,17 @@
|
||||
max_w_class = ITEMSIZE_NORMAL
|
||||
w_class = ITEMSIZE_SMALL
|
||||
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks,/obj/item/weapon/reagent_containers/food/condiment)
|
||||
|
||||
// -----------------------------
|
||||
// Evidence Bag
|
||||
// -----------------------------
|
||||
/obj/item/weapon/storage/bag/detective
|
||||
name = "secure satchel"
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "detbag"
|
||||
desc = "A bag for storing investigation things. You know, securely."
|
||||
max_storage_space = ITEMSIZE_COST_NORMAL * 15
|
||||
max_w_class = ITEMSIZE_NORMAL
|
||||
w_class = ITEMSIZE_SMALL
|
||||
can_hold = list(/obj/item/weapon/forensics/swab,/obj/item/weapon/sample/print,/obj/item/weapon/sample/fibers,/obj/item/weapon/evidencebag)
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ Frequency:
|
||||
direct = "very weak"
|
||||
src.temp += "[W.code]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
|
||||
|
||||
src.temp += "<B>Extranneous Signals:</B><BR>"
|
||||
src.temp += "<B>Extraneous Signals:</B><BR>"
|
||||
for (var/obj/item/weapon/implant/tracking/W in all_tracking_implants)
|
||||
if (!W.implanted || !(istype(W.loc,/obj/item/organ/external) || ismob(W.loc) || W.malfunction))
|
||||
continue
|
||||
|
||||
@@ -4,14 +4,18 @@
|
||||
req_access = list(access_all_personal_lockers)
|
||||
var/registered_name = null
|
||||
|
||||
/* //VOREStation Removal
|
||||
starts_with = list(
|
||||
/obj/item/device/radio/headset)
|
||||
*/
|
||||
|
||||
/obj/structure/closet/secure_closet/personal/Initialize()
|
||||
/* //VOREStation Removal
|
||||
if(prob(50))
|
||||
starts_with += /obj/item/weapon/storage/backpack
|
||||
else
|
||||
starts_with += /obj/item/weapon/storage/backpack/satchel/norm
|
||||
*/
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/secure_closet/personal/patient
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
/obj/item/weapon/storage/belt/security,
|
||||
/obj/item/device/flash,
|
||||
/obj/item/weapon/melee/baton/loaded,
|
||||
/obj/item/weapon/gun/energy/gun,
|
||||
/obj/item/weapon/gun/magnetic/railgun/heater/pistol/hos,
|
||||
/obj/item/weapon/cell/device/weapon,
|
||||
/obj/item/clothing/accessory/holster/waist,
|
||||
/obj/item/weapon/melee/telebaton,
|
||||
@@ -226,6 +226,8 @@
|
||||
starts_with += /obj/item/weapon/storage/backpack/satchel/sec
|
||||
if(prob(50))
|
||||
starts_with += /obj/item/weapon/storage/backpack/dufflebag/sec
|
||||
if(prob(30))
|
||||
starts_with += /obj/item/weapon/contraband/poster/nanotrasen
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/secure_closet/security/cargo/Initialize()
|
||||
@@ -274,6 +276,7 @@
|
||||
/obj/item/weapon/reagent_containers/food/drinks/flask/detflask,
|
||||
/obj/item/weapon/storage/briefcase/crimekit,
|
||||
/obj/item/device/taperecorder,
|
||||
/obj/item/weapon/storage/bag/detective,
|
||||
/obj/item/device/tape/random = 3)
|
||||
|
||||
/obj/structure/closet/secure_closet/detective/update_icon()
|
||||
@@ -308,6 +311,17 @@ GLOBAL_LIST_BOILERPLATE(all_brig_closets, /obj/structure/closet/secure_closet/br
|
||||
/obj/item/clothing/under/color/prison,
|
||||
/obj/item/clothing/shoes/orange)
|
||||
|
||||
/obj/structure/closet/secure_closet/posters
|
||||
name = "morale storage"
|
||||
req_access = list(access_security)
|
||||
anchored = 1
|
||||
|
||||
starts_with = list(
|
||||
/obj/item/weapon/contraband/poster/nanotrasen,
|
||||
/obj/item/weapon/contraband/poster/nanotrasen,
|
||||
/obj/item/weapon/contraband/poster/nanotrasen,
|
||||
/obj/item/weapon/contraband/poster/nanotrasen,
|
||||
/obj/item/weapon/contraband/poster/nanotrasen)
|
||||
|
||||
/obj/structure/closet/secure_closet/courtroom
|
||||
name = "courtroom locker"
|
||||
|
||||
@@ -83,4 +83,13 @@
|
||||
to_chat(user, "<span class='warning'>Another spirit appears to have gotten to \the [src] before you. Sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = input(user, "Are you certain you wish to activate this pod?", "Control Pod") as null|anything in list("Yes", "No")
|
||||
|
||||
if(!choice || choice == "No")
|
||||
return
|
||||
|
||||
else if(used)
|
||||
to_chat(user, "<span class='warning'>Another spirit appears to have gotten to \the [src] before you. Sorry.</span>")
|
||||
return
|
||||
|
||||
create_occupant(user)
|
||||
246
code/game/objects/structures/ghost_pods/human.dm
Normal file
246
code/game/objects/structures/ghost_pods/human.dm
Normal file
@@ -0,0 +1,246 @@
|
||||
// Ghost variant.
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/human
|
||||
name = "mysterious cryopod"
|
||||
desc = "This is a pod which appears to contain a body."
|
||||
description_info = "This contains a body, which may wake at any time. The external controls\
|
||||
seem to be malfunctioning."
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "sleeper_1"
|
||||
icon_state_opened = "sleeper_0"
|
||||
density = TRUE
|
||||
ghost_query_type = /datum/ghost_query/stowaway
|
||||
anchored = FALSE
|
||||
|
||||
var/occupant_type = "stowaway"
|
||||
|
||||
var/allow_appearance_change = TRUE
|
||||
|
||||
var/make_antag = MODE_STOWAWAY
|
||||
|
||||
var/start_injured = FALSE
|
||||
var/spawn_with_emag = TRUE
|
||||
|
||||
var/list/clothing_possibilities
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/human/Initialize()
|
||||
..()
|
||||
|
||||
handle_clothing_setup()
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/human/proc/handle_clothing_setup()
|
||||
clothing_possibilities = list()
|
||||
|
||||
clothing_possibilities |= subtypesof(/obj/item/clothing/under/color)
|
||||
clothing_possibilities |= subtypesof(/obj/item/clothing/head/soft)
|
||||
clothing_possibilities |= /obj/item/clothing/shoes/black
|
||||
clothing_possibilities |= /obj/item/device/radio/headset
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/human/create_occupant(var/mob/M)
|
||||
..()
|
||||
var/turf/T = get_turf(src)
|
||||
var/mob/living/carbon/human/H = new(src)
|
||||
|
||||
H.adjustCloneLoss(rand(1,5))
|
||||
if(M.mind)
|
||||
M.mind.transfer_to(H)
|
||||
to_chat(M, "<span class='notice'>You are a [occupant_type]!</span>")
|
||||
if(make_antag)
|
||||
to_chat(M, "<span class='warning'>Your intent may not be completely beneficial.</span>")
|
||||
H.ckey = M.ckey
|
||||
visible_message("<span class='warning'>As \the [src] opens, the pipes on \the [src] surge, before it grows dark.</span>")
|
||||
log_and_message_admins("successfully opened \a [src] and became a [occupant_type].")
|
||||
|
||||
var/list/uniform_options
|
||||
var/list/shoe_options
|
||||
var/list/head_options
|
||||
var/list/headset_options
|
||||
|
||||
if(clothing_possibilities && clothing_possibilities.len)
|
||||
for(var/path in clothing_possibilities)
|
||||
if(ispath(path, /obj/item/clothing/under))
|
||||
if(!uniform_options)
|
||||
uniform_options = list()
|
||||
uniform_options |= path
|
||||
if(ispath(path, /obj/item/clothing/shoes))
|
||||
if(!shoe_options)
|
||||
shoe_options = list()
|
||||
shoe_options |= path
|
||||
if(ispath(path, /obj/item/clothing/head))
|
||||
if(!head_options)
|
||||
head_options = list()
|
||||
head_options |= path
|
||||
if(ispath(path, /obj/item/device/radio/headset))
|
||||
if(!headset_options)
|
||||
headset_options = list()
|
||||
headset_options |= path
|
||||
|
||||
if(uniform_options && uniform_options.len)
|
||||
var/newpath = pick(uniform_options)
|
||||
var/obj/item/clothing/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
if(shoe_options && shoe_options.len)
|
||||
var/newpath = pick(shoe_options)
|
||||
var/obj/item/clothing/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
if(head_options && head_options.len)
|
||||
var/newpath = pick(head_options)
|
||||
var/obj/item/clothing/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
if(headset_options && headset_options.len)
|
||||
var/newpath = pick(headset_options)
|
||||
var/obj/item/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
if(spawn_with_emag)
|
||||
var/obj/item/weapon/card/emag/E = new(H)
|
||||
E.name = "broken card"
|
||||
E.description_antag = "This is a 'disguised' emag, to make your escape from wherever you happen to be trapped."
|
||||
H.equip_to_appropriate_slot(E)
|
||||
|
||||
var/newname = sanitize(input(H, "Your mind feels foggy, and you recall your name might be [H.real_name]. Would you like to change your name?", "Name change") as null|text, MAX_NAME_LEN)
|
||||
if (newname)
|
||||
H.real_name = newname
|
||||
|
||||
icon_state = icon_state_opened
|
||||
|
||||
H.forceMove(T)
|
||||
|
||||
if(make_antag)
|
||||
var/datum/antagonist/antag = all_antag_types[make_antag]
|
||||
if(antag)
|
||||
if(antag.add_antagonist(H.mind, 1, 1, 0, 1, 1))
|
||||
log_admin("\The [src] made [key_name(src)] into a [antag.role_text].")
|
||||
|
||||
if(start_injured) // Done 3 different times to disperse damage.
|
||||
H.adjustBruteLoss(rand(1,20))
|
||||
H.adjustBruteLoss(rand(1,20))
|
||||
H.adjustBruteLoss(rand(1,20))
|
||||
|
||||
if(allow_appearance_change)
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
|
||||
|
||||
visible_message("<span class='aliem'>\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!</span>")
|
||||
|
||||
// Manual Variant
|
||||
// This one lacks the emag option due to the fact someone has to activate it, and they will probably help the person.
|
||||
/obj/structure/ghost_pod/manual/human
|
||||
name = "mysterious cryopod"
|
||||
desc = "This is a pod which appears to contain a body."
|
||||
description_info = "This contains a body, which may wake at any time. The external controls\
|
||||
seem to be functioning, though the warning lights that flash give no solace.."
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "sleeper_1"
|
||||
icon_state_opened = "sleeper_0"
|
||||
density = TRUE
|
||||
ghost_query_type = /datum/ghost_query/lost_passenger
|
||||
anchored = FALSE
|
||||
|
||||
var/occupant_type = "lost passenger"
|
||||
|
||||
var/allow_appearance_change = TRUE
|
||||
|
||||
var/make_antag = MODE_STOWAWAY
|
||||
|
||||
var/start_injured = TRUE
|
||||
|
||||
var/list/clothing_possibilities
|
||||
|
||||
/obj/structure/ghost_pod/manual/human/Initialize()
|
||||
..()
|
||||
|
||||
handle_clothing_setup()
|
||||
|
||||
/obj/structure/ghost_pod/manual/human/proc/handle_clothing_setup()
|
||||
clothing_possibilities = list()
|
||||
|
||||
clothing_possibilities |= subtypesof(/obj/item/clothing/under/utility)
|
||||
clothing_possibilities |= subtypesof(/obj/item/clothing/head/beret)
|
||||
clothing_possibilities |= /obj/item/clothing/shoes/black
|
||||
clothing_possibilities |= /obj/item/device/radio/headset
|
||||
|
||||
/obj/structure/ghost_pod/manual/human/create_occupant(var/mob/M)
|
||||
..()
|
||||
var/turf/T = get_turf(src)
|
||||
var/mob/living/carbon/human/H = new(src)
|
||||
|
||||
H.adjustCloneLoss(rand(1,5))
|
||||
if(M.mind)
|
||||
M.mind.transfer_to(H)
|
||||
to_chat(M, "<span class='notice'>You are a [occupant_type]!</span>")
|
||||
if(make_antag)
|
||||
to_chat(M, "<span class='warning'>Your intent may not be completely beneficial.</span>")
|
||||
H.ckey = M.ckey
|
||||
visible_message("<span class='warning'>As \the [src] opens, the pipes on \the [src] surge, before it grows dark.</span>")
|
||||
log_and_message_admins("successfully opened \a [src] and got a [occupant_type].")
|
||||
|
||||
var/list/uniform_options
|
||||
var/list/shoe_options
|
||||
var/list/head_options
|
||||
var/list/headset_options
|
||||
|
||||
if(clothing_possibilities && clothing_possibilities.len)
|
||||
for(var/path in clothing_possibilities)
|
||||
if(ispath(path, /obj/item/clothing/under))
|
||||
if(!uniform_options)
|
||||
uniform_options = list()
|
||||
uniform_options |= path
|
||||
if(ispath(path, /obj/item/clothing/shoes))
|
||||
if(!shoe_options)
|
||||
shoe_options = list()
|
||||
shoe_options |= path
|
||||
if(ispath(path, /obj/item/clothing/head))
|
||||
if(!head_options)
|
||||
head_options = list()
|
||||
head_options |= path
|
||||
if(ispath(path, /obj/item/device/radio/headset))
|
||||
if(!headset_options)
|
||||
headset_options = list()
|
||||
headset_options |= path
|
||||
|
||||
if(uniform_options && uniform_options.len)
|
||||
var/newpath = pick(uniform_options)
|
||||
var/obj/item/clothing/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
if(shoe_options && shoe_options.len)
|
||||
var/newpath = pick(shoe_options)
|
||||
var/obj/item/clothing/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
if(head_options && head_options.len)
|
||||
var/newpath = pick(head_options)
|
||||
var/obj/item/clothing/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
if(headset_options && headset_options.len)
|
||||
var/newpath = pick(headset_options)
|
||||
var/obj/item/C = new newpath(H)
|
||||
H.equip_to_appropriate_slot(C)
|
||||
|
||||
var/newname = sanitize(input(H, "Your mind feels foggy, and you recall your name might be [H.real_name]. Would you like to change your name?", "Name change") as null|text, MAX_NAME_LEN)
|
||||
if (newname)
|
||||
H.real_name = newname
|
||||
|
||||
icon_state = icon_state_opened
|
||||
|
||||
H.forceMove(T)
|
||||
|
||||
if(make_antag)
|
||||
var/datum/antagonist/antag = all_antag_types[make_antag]
|
||||
if(antag)
|
||||
if(antag.add_antagonist(H.mind, 1, 1, 0, 1, 1))
|
||||
log_admin("\The [src] made [key_name(src)] into a [antag.role_text].")
|
||||
|
||||
if(start_injured) // Done 3 different times to disperse damage.
|
||||
H.adjustBruteLoss(rand(1,20))
|
||||
H.adjustBruteLoss(rand(1,20))
|
||||
H.adjustBruteLoss(rand(1,20))
|
||||
|
||||
if(allow_appearance_change)
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
|
||||
|
||||
visible_message("<span class='aliem'>\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!</span>")
|
||||
@@ -59,3 +59,49 @@
|
||||
visible_message("<span class='warning'>As \the [src] opens, the eyes of the robot flicker as it is activated.</span>")
|
||||
R.Namepick()
|
||||
..()
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/swarm_drone
|
||||
name = "drone shell"
|
||||
desc = "A heavy metallic ball."
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "swarmer_unactivated"
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
|
||||
var/drone_class = "general"
|
||||
var/drone_type = /mob/living/silicon/robot/drone/swarm
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/swarm_drone/create_occupant(var/mob/M)
|
||||
var/mob/living/silicon/robot/drone/swarm/R = new drone_type(get_turf(src))
|
||||
if(M.mind)
|
||||
M.mind.transfer_to(R)
|
||||
to_chat(M, "<span class='cult'>You are <b>[R]</b>, the remnant of some distant species, mechanical or flesh, living or dead.</span>")
|
||||
R.ckey = M.ckey
|
||||
visible_message("<span class='cult'>As \the [src] shudders, it glows before lifting itself with three shimmering limbs!</span>")
|
||||
spawn(3 SECONDS)
|
||||
to_chat(R,"<span class='notice'>Many of your tools are standard drone devices, however others provide you with particular benefits.</span>")
|
||||
to_chat(R,"<span class='notice'>Unlike standard drones, you are capable of utilizing 'zero point wells', found in your 'spells' tab.</span>")
|
||||
to_chat(R,"<span class='notice'>Here you will also find your replication ability(s), depending on the type of drone you are.</span>")
|
||||
to_chat(R,"<span class='notice'>Gunners have a special anti-personnel gun capable of shocking or punching through armor with low damage.</span>")
|
||||
to_chat(R,"<span class='notice'>Impalers have an energy-lance.</span>")
|
||||
to_chat(R,"<span class='notice'>General drones have the unique ability to produce one of each of these two types of shells per generation.</span>")
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/Initialize()
|
||||
..()
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
say_dead_object("A <span class='notice'>[drone_class] swarm drone</span> shell is now available in \the [T.loc].", src)
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/gunner
|
||||
name = "gunner shell"
|
||||
|
||||
drone_class = "gunner"
|
||||
drone_type = /mob/living/silicon/robot/drone/swarm/gunner
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/melee
|
||||
name = "impaler shell"
|
||||
|
||||
drone_class = "impaler"
|
||||
drone_type = /mob/living/silicon/robot/drone/swarm/melee
|
||||
|
||||
150
code/game/objects/structures/props/swarm.dm
Normal file
150
code/game/objects/structures/props/swarm.dm
Normal file
@@ -0,0 +1,150 @@
|
||||
/obj/structure/cult/pylon/swarm
|
||||
name = "Swarm Construct"
|
||||
desc = "A small pod."
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "pod"
|
||||
light_color = "#00B2B2"
|
||||
|
||||
shatter_message = "The energetic field shatters!"
|
||||
impact_sound = 'sound/effects/Glasshit.ogg'
|
||||
shatter_sound = 'sound/effects/phasein.ogg'
|
||||
|
||||
var/list/active_beams
|
||||
|
||||
/obj/structure/cult/pylon/swarm/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living))
|
||||
var/mob/living/L = mover
|
||||
if(L.faction == "swarmer")
|
||||
return TRUE
|
||||
else if(istype(mover, /obj/item/projectile))
|
||||
var/obj/item/projectile/P = mover
|
||||
if(istype(P.firer) && P.firer.faction == "swarmer")
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/cult/pylon/swarm/Initialize()
|
||||
..()
|
||||
active_beams = list()
|
||||
|
||||
/obj/structure/cult/pylon/swarm/Destroy()
|
||||
for(var/datum/beam/B in active_beams)
|
||||
QDEL_NULL(B)
|
||||
active_beams = null
|
||||
..()
|
||||
|
||||
/obj/structure/cult/pylon/swarm/pylonhit(var/damage)
|
||||
if(!isbroken)
|
||||
if(prob(1 + damage * 3))
|
||||
visible_message("<span class='danger'>[shatter_message]</span>")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
playsound(get_turf(src),shatter_sound, 75, 1)
|
||||
isbroken = 1
|
||||
density = 0
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
set_light(0)
|
||||
|
||||
/obj/structure/cult/pylon/swarm/attackpylon(mob/user as mob, var/damage)
|
||||
if(!isbroken)
|
||||
if(prob(1 + damage * 3))
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] smashed \the [src]!</span>",
|
||||
"<span class='warning'>You hit \the [src], and its crystal breaks apart!</span>",
|
||||
"You hear a tinkle of crystalline shards."
|
||||
)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
user.do_attack_animation(src)
|
||||
playsound(get_turf(src),shatter_sound, 75, 1)
|
||||
isbroken = 1
|
||||
density = 0
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
set_light(0)
|
||||
else
|
||||
to_chat(user, "You hit \the [src]!")
|
||||
playsound(get_turf(src),impact_sound, 75, 1)
|
||||
else
|
||||
if(prob(damage * 2))
|
||||
to_chat(user, "You pulverize what was left of \the [src]!")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "You hit \the [src]!")
|
||||
playsound(get_turf(src),impact_sound, 75, 1)
|
||||
|
||||
/obj/structure/cult/pylon/swarm/pylon_unique()
|
||||
. = ..()
|
||||
|
||||
return .
|
||||
|
||||
/obj/structure/cult/pylon/swarm/zp_well
|
||||
name = "Zero Point Well"
|
||||
desc = "Infinite cosmic power, itty bitty usability."
|
||||
|
||||
icon_state = "trap"
|
||||
|
||||
description_info = "An infinitely small point in space that may or may not be used to supply power to some form of advanced machine."
|
||||
|
||||
activation_cooldown = 0 // These things run constantly.
|
||||
|
||||
/obj/structure/cult/pylon/swarm/zp_well/pylon_unique()
|
||||
. = ..()
|
||||
|
||||
for(var/mob/living/silicon/robot/drone/swarm/S in view(3, src))
|
||||
var/has_beam = FALSE
|
||||
for(var/datum/beam/B in active_beams)
|
||||
if(B.target == S)
|
||||
has_beam = TRUE
|
||||
break
|
||||
|
||||
if(!has_beam)
|
||||
active_beams |= Beam(S,icon='icons/effects/beam.dmi',icon_state="holo_beam",time=3 SECONDS,maxdistance=3,beam_type = /obj/effect/ebeam,beam_sleep_time=2)
|
||||
|
||||
if(S.cell)
|
||||
S.cell.give(rand(5, 30))
|
||||
|
||||
. = TRUE
|
||||
|
||||
return .
|
||||
|
||||
/obj/structure/cult/pylon/swarm/defender
|
||||
name = "Zero Point Wall"
|
||||
desc = "Infinite cosmic power, itty bitty passability."
|
||||
|
||||
icon_state = "barricade"
|
||||
|
||||
description_info = "An infinitely small point in space spread upon infinitely many finitely-bounded points in space. Nice."
|
||||
|
||||
/obj/structure/cult/pylon/swarm/defender/pylonhit(var/damage)
|
||||
if(!isbroken)
|
||||
if(prob(1 + damage * 3) && round(damage * 0.8) >= 30)
|
||||
visible_message("<span class='danger'>[shatter_message]</span>")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
playsound(get_turf(src),shatter_sound, 75, 1)
|
||||
isbroken = 1
|
||||
density = 0
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
set_light(0)
|
||||
|
||||
/obj/structure/cult/pylon/swarm/defender/attackpylon(mob/user as mob, var/damage)
|
||||
if(!isbroken)
|
||||
if(prob(1 + damage * 3) && round(damage * 0.8) >= 25)
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] smashed \the [src]!</span>",
|
||||
"<span class='warning'>You hit \the [src], and its crystal breaks apart!</span>",
|
||||
"You hear a tinkle of crystalline shards."
|
||||
)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
user.do_attack_animation(src)
|
||||
playsound(get_turf(src),shatter_sound, 75, 1)
|
||||
isbroken = 1
|
||||
density = 0
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
set_light(0)
|
||||
else
|
||||
to_chat(user, "You hit \the [src]!")
|
||||
playsound(get_turf(src),impact_sound, 75, 1)
|
||||
else
|
||||
if(prob(damage * 2))
|
||||
to_chat(user, "You pulverize what was left of \the [src]!")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "You hit \the [src]!")
|
||||
playsound(get_turf(src),impact_sound, 75, 1)
|
||||
@@ -7,11 +7,16 @@
|
||||
/datum/category_item/player_setup_item/player_global/pai/load_preferences(var/savefile/S)
|
||||
if(!candidate)
|
||||
candidate = new()
|
||||
|
||||
if(!preference_mob())
|
||||
var/preference_mob = preference_mob()
|
||||
if(!preference_mob)// No preference mob - this happens when we're called from client/New() before it calls ..() (via datum/preferences/New())
|
||||
spawn()
|
||||
preference_mob = preference_mob()
|
||||
if(!preference_mob)
|
||||
return
|
||||
candidate.savefile_load(preference_mob)
|
||||
return
|
||||
|
||||
candidate.savefile_load(preference_mob())
|
||||
candidate.savefile_load(preference_mob)
|
||||
|
||||
/datum/category_item/player_setup_item/player_global/pai/save_preferences(var/savefile/S)
|
||||
if(!candidate)
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
|
||||
/datum/gear_tweak/collar_tag/tweak_item(var/obj/item/clothing/accessory/collar/C, var/metadata)
|
||||
if(metadata == "")
|
||||
return
|
||||
return ..()
|
||||
else
|
||||
C.initialize_tag(metadata)
|
||||
@@ -337,6 +337,8 @@
|
||||
ckeywhitelist = list("jemli")
|
||||
character_name = list("Jemli")
|
||||
|
||||
//TFF 28/11/19 - Expired permit removal
|
||||
/*
|
||||
/datum/gear/fluff/jeremiah_permit
|
||||
path = /obj/item/clothing/accessory/permit/gun/fluff/ace
|
||||
display_name = "Ace's Gun Permit"
|
||||
@@ -357,6 +359,7 @@
|
||||
ckeywhitelist = list("jertheace")
|
||||
character_name = list("Jeremiah Acacius")
|
||||
allowed_roles = list("Colony Director", "Warden", "Head of Security")
|
||||
*/
|
||||
|
||||
/datum/gear/fluff/jeremiah_holster
|
||||
path = /obj/item/clothing/accessory/holster/armpit
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
sort_category = "Xenowear"
|
||||
whitelisted = "Vox"
|
||||
|
||||
/datum/gear/mask/transparent
|
||||
display_name = "transparent breath mask"
|
||||
path = /obj/item/clothing/mask/breath/transparent
|
||||
sort_category = "Xenowear"
|
||||
|
||||
/datum/gear/uniform/loincloth
|
||||
display_name = "loincloth"
|
||||
path = /obj/item/clothing/suit/storage/fluff/loincloth
|
||||
|
||||
@@ -80,6 +80,16 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
. = ..()
|
||||
if((. == 0) && LAZYLEN(accessories))
|
||||
for(var/obj/item/I in accessories)
|
||||
var/check = I.handle_shield(user, damage, damage_source, attacker, def_zone, attack_text)
|
||||
|
||||
if(check != 0) // Projectiles sometimes use negatives IIRC, 0 is only returned if something is not blocked.
|
||||
. = check
|
||||
break
|
||||
|
||||
/obj/item/clothing/proc/refit_for_species(var/target_species)
|
||||
if(!species_restricted)
|
||||
return //this item doesn't use the species_restricted system
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
if(H.wear_suit.body_parts_covered & ARMS)
|
||||
to_chat(H, "<span class='warning'>You can't wear \the [src] with \the [H.wear_suit], it's in the way.</span>")
|
||||
return 0
|
||||
for(var/obj/item/clothing/accessory/A in H.wear_suit)
|
||||
if(A.body_parts_covered & ARMS)
|
||||
to_chat(H, "<span class='warning'>You can't wear \the [src] with \the [H.wear_suit]'s [A], it's in the way.</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/gloves/arm_guard/laserproof
|
||||
|
||||
4
code/modules/clothing/masks/breath_vr.dm
Normal file
4
code/modules/clothing/masks/breath_vr.dm
Normal file
@@ -0,0 +1,4 @@
|
||||
/obj/item/clothing/mask/breath/transparent
|
||||
name = "transparent breath mask"
|
||||
item_state = "golem" //This is dumb and hacky but was here when I got here.
|
||||
sprite_sheets = list()
|
||||
@@ -14,6 +14,10 @@
|
||||
if(H.wear_suit.body_parts_covered & LEGS)
|
||||
H << "<span class='warning'>You can't wear \the [src] with \the [H.wear_suit], it's in the way.</span>"
|
||||
return 0
|
||||
for(var/obj/item/clothing/accessory/A in H.wear_suit)
|
||||
if(A.body_parts_covered & LEGS)
|
||||
to_chat(H, "<span class='warning'>You can't wear \the [src] with \the [H.wear_suit]'s [A], it's in the way.</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/shoes/leg_guard/laserproof
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
)
|
||||
|
||||
/obj/item/weapon/rig/pmc/security
|
||||
name = "ERT-S suit control module"
|
||||
name = "PMC-S suit control module"
|
||||
desc = "A suit worn by private military contractors. This one is setup for security. Armoured and space ready."
|
||||
suit_type = "PMC security"
|
||||
icon_state = "pmc_securitygrey_rig"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
to_chat(M, "This Shroud has already been customized!")
|
||||
return 0
|
||||
|
||||
suit_style = input(M, "Which suit style would you like?") in list("Engineer", "Spacer", "Knight", "Fashion", "Bishop", "Hegemony", "Rugged")
|
||||
suit_style = input(M, "Which suit style would you like?") in list("Engineer", "Spacer", "Knight", "Fashion", "Bishop", "Hegemony", "Rugged", "Soft")
|
||||
switch(suit_style)
|
||||
if("Engineer")
|
||||
name = "\improper Engineer's Guild Shroud"
|
||||
@@ -106,6 +106,17 @@
|
||||
helmet.desc = "Supposedly, this helmet should make humans more comfortable and familiar with the Zaddat."
|
||||
helmet.icon_state = "zaddat_rugged"
|
||||
helmet.item_state = "zaddat_rugged"
|
||||
if("Soft")
|
||||
name = "\improper soft Shroud"
|
||||
base_name = "\improper soft Shroud"
|
||||
desc = "Material and design is chosen for practical reasons, making it take as little space as possible when stowed whilst also providing reasonable comfort when worn for long periods."
|
||||
icon_state = "zaddat_soft"
|
||||
item_state = "zaddat_soft"
|
||||
if(helmet)
|
||||
helmet.name = "\improper soft Shroud hood"
|
||||
helmet.desc = "Not as solid as a proper helmet, but works nonetheless."
|
||||
helmet.icon_state = "zaddat_soft"
|
||||
helmet.item_state = "zaddat_soft"
|
||||
|
||||
to_chat(M, "You finish customizing your Shroud. Looking good!")
|
||||
has_been_customized = TRUE
|
||||
|
||||
@@ -520,6 +520,22 @@
|
||||
|ACCESSORY_SLOT_ARMOR_M)
|
||||
blood_overlay_type = "armor"
|
||||
|
||||
/obj/item/clothing/suit/armor/pcarrier/mob_can_equip(var/mob/living/carbon/human/H, slot)
|
||||
if(..()) //This will only run if no other problems occured when equiping.
|
||||
if(H.gloves)
|
||||
if(H.gloves.body_parts_covered & ARMS)
|
||||
for(var/obj/item/clothing/accessory/A in src)
|
||||
if(A.body_parts_covered & ARMS)
|
||||
to_chat(H, "<span class='warning'>You can't wear \the [A] with \the [H.gloves], they're in the way.</span>")
|
||||
return 0
|
||||
if(H.shoes)
|
||||
if(H.shoes.body_parts_covered & LEGS)
|
||||
for(var/obj/item/clothing/accessory/A in src)
|
||||
if(A.body_parts_covered & LEGS)
|
||||
to_chat(H, "<span class='warning'>You can't wear \the [A] with \the [H.shoes], they're in the way.</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/suit/armor/pcarrier/light
|
||||
starting_accessories = list(/obj/item/clothing/accessory/armor/armorplate)
|
||||
|
||||
@@ -549,6 +565,11 @@
|
||||
desc = "A lightweight blue plate carrier vest. It can be equipped with armor plates, but provides no protection of its own."
|
||||
icon_state = "pcarrier_blue"
|
||||
|
||||
/obj/item/clothing/suit/armor/pcarrier/press
|
||||
name = "light blue plate carrier"
|
||||
desc = "A lightweight light blue plate carrier vest. It can be equipped with armor plates, but provides no protection of its own."
|
||||
icon_state = "pcarrier_press"
|
||||
|
||||
/obj/item/clothing/suit/armor/pcarrier/blue/sol
|
||||
name = "peacekeeper plate carrier"
|
||||
desc = "A lightweight plate carrier vest in SCG Peacekeeper colors. It can be equipped with armor plates, but provides no protection of its own."
|
||||
|
||||
@@ -10,6 +10,24 @@
|
||||
icon_state = "pouches"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
|
||||
/obj/item/clothing/accessory/armor/on_attached(var/obj/item/clothing/S, var/mob/user)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.wear_suit == S)
|
||||
if((body_parts_covered & ARMS) && istype(H.gloves, /obj/item/clothing))
|
||||
var/obj/item/clothing/G = H.gloves
|
||||
if(G.body_parts_covered & ARMS)
|
||||
to_chat(H, "<span class='warning'>You can't wear \the [src] with \the [G], it's in the way.</span>")
|
||||
S.accessories -= src
|
||||
return
|
||||
else if((body_parts_covered & LEGS) && istype(H.shoes, /obj/item/clothing))
|
||||
var/obj/item/clothing/Sh = H.shoes
|
||||
if(Sh.body_parts_covered & LEGS)
|
||||
to_chat(H, "<span class='warning'>You can't wear \the [src] with \the [Sh], it's in the way.</span>")
|
||||
S.accessories -= src
|
||||
return
|
||||
..()
|
||||
|
||||
///////////
|
||||
//Pouches
|
||||
///////////
|
||||
@@ -74,6 +92,13 @@
|
||||
armor = list(melee = 30, bullet = 15, laser = 40, energy = 10, bomb = 25, bio = 0, rad = 0)
|
||||
slot = ACCESSORY_SLOT_ARMOR_C
|
||||
|
||||
/obj/item/clothing/accessory/armor/armorplate/stab
|
||||
name = "mesh armor plate"
|
||||
desc = "A mesh armor plate made of steel-reinforced synthetic fibers, great for dealing with small blades. Attaches to a plate carrier."
|
||||
icon_state = "armor_stab"
|
||||
armor = list(melee = 25, bullet = 5, laser = 20, energy = 10, bomb = 15, bio = 0, rad = 0)
|
||||
armorsoak = list(melee = 7, bullet = 5, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
|
||||
/obj/item/clothing/accessory/armor/armorplate/medium
|
||||
name = "medium armor plate"
|
||||
desc = "A plasteel-reinforced synthetic armor plate, providing good protection. Attaches to a plate carrier."
|
||||
@@ -92,6 +117,56 @@
|
||||
icon_state = "armor_merc"
|
||||
armor = list(melee = 60, bullet = 60, laser = 60, energy = 40, bomb = 40, bio = 0, rad = 0)
|
||||
|
||||
/obj/item/clothing/accessory/armor/armorplate/bulletproof
|
||||
name = "ballistic armor plate"
|
||||
desc = "A woven armor plate with additional plating, providing good protection against high-velocity trauma. Attaches to a plate carrier."
|
||||
icon_state = "armor_ballistic"
|
||||
slowdown = 0.6
|
||||
armor = list(melee = 10, bullet = 70, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0)
|
||||
armorsoak = list(melee = 0, bullet = 10, laser = 0, energy = 5, bomb = 0, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.7
|
||||
|
||||
/obj/item/clothing/accessory/armor/armorplate/riot
|
||||
name = "riot armor plate"
|
||||
desc = "A thick armor plate with additional padding, providing good protection against low-velocity trauma. Attaches to a plate carrier."
|
||||
icon_state = "armor_riot"
|
||||
slowdown = 0.6
|
||||
armor = list(melee = 70, bullet = 10, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0)
|
||||
armorsoak = list(melee = 10, bullet = 0, laser = 0, energy = 5, bomb = 0, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.7
|
||||
|
||||
/obj/item/clothing/accessory/armor/armorplate/laserproof
|
||||
name = "ablative armor plate"
|
||||
desc = "A durasteel-scaled synthetic armor plate, providing good protection against lasers. Attaches to a plate carrier."
|
||||
icon_state = "armor_medium"
|
||||
slowdown = 0.6
|
||||
armor = list(melee = 10, bullet = 10, laser = 70, energy = 50, bomb = 0, bio = 0, rad = 0)
|
||||
armorsoak = list(melee = 0, bullet = 0, laser = 10, energy = 15, bomb = 0, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.1
|
||||
|
||||
/obj/item/clothing/accessory/armor/armorplate/ablative/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
|
||||
var/obj/item/projectile/P = damage_source
|
||||
|
||||
if(P.reflected)
|
||||
return ..()
|
||||
|
||||
var/reflectchance = 40 - round(damage/3)
|
||||
if(!(def_zone in list(BP_TORSO, BP_GROIN)))
|
||||
reflectchance /= 2
|
||||
if(P.starting && prob(reflectchance))
|
||||
visible_message("<span class='danger'>\The [user]'s [src.name] reflects [attack_text]!</span>")
|
||||
|
||||
|
||||
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(user)
|
||||
|
||||
P.redirect(new_x, new_y, curloc, user)
|
||||
P.reflected = 1
|
||||
|
||||
return PROJECTILE_CONTINUE
|
||||
|
||||
//////////////
|
||||
//Arm guards
|
||||
//////////////
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
var/closed = 0
|
||||
var/scanning = 0
|
||||
var/scanner_progress = 0
|
||||
var/scanner_rate = 2.50
|
||||
var/scanner_rate = 5
|
||||
var/last_process_worldtime = 0
|
||||
var/report_num = 0
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
user << "<span class='notice'>The microscope whirrs as you examine \the [sample].</span>"
|
||||
|
||||
if(!do_after(user, 25) || !sample)
|
||||
if(!do_after(user, 2 SECONDS) || !sample)
|
||||
user << "<span class='notice'>You stop examining \the [sample].</span>"
|
||||
return
|
||||
|
||||
@@ -71,8 +71,8 @@
|
||||
report.info += "Surface analysis has determined unique fingerprint strings:<br><br>"
|
||||
for(var/prints in card.evidence)
|
||||
report.info += "<span class='notice'>Fingerprint string: </span>"
|
||||
if(!is_complete_print(prints))
|
||||
report.info += "INCOMPLETE PRINT"
|
||||
if(!is_complete_print(card.evidence[prints]))
|
||||
report.info += "INCOMPLETE PRINT:[card.evidence[prints]]"
|
||||
else
|
||||
report.info += "[prints]"
|
||||
report.info += "<br>"
|
||||
|
||||
201
code/modules/detectivework/tools/scanner.dm
Normal file
201
code/modules/detectivework/tools/scanner.dm
Normal file
@@ -0,0 +1,201 @@
|
||||
/obj/item/device/detective_scanner
|
||||
name = "forensic scanner"
|
||||
desc = "Used to scan objects for DNA and fingerprints."
|
||||
icon_state = "forensic"
|
||||
var/list/stored = list()
|
||||
w_class = ITEMSIZE_SMALL
|
||||
item_state = "electronic"
|
||||
flags = NOBLUDGEON
|
||||
slot_flags = SLOT_BELT
|
||||
|
||||
var/reveal_fingerprints = TRUE
|
||||
var/reveal_incompletes = FALSE
|
||||
var/reveal_blood = TRUE
|
||||
var/reveal_fibers = FALSE
|
||||
|
||||
/obj/item/device/detective_scanner/attack(mob/living/carbon/human/M as mob, mob/user as mob)
|
||||
if (!ishuman(M))
|
||||
to_chat(user, "<span class='warning'>\The [M] does not seem to be compatible with this device.</span>")
|
||||
flick("[icon_state]0",src)
|
||||
return 0
|
||||
|
||||
if(reveal_fingerprints)
|
||||
if((!( istype(M.dna, /datum/dna) ) || M.gloves))
|
||||
to_chat(user, "<span class='notice'>No fingerprints found on [M]</span>")
|
||||
flick("[icon_state]0",src)
|
||||
return 0
|
||||
else if(user.zone_sel.selecting == "r_hand" || user.zone_sel.selecting == "l_hand")
|
||||
var/obj/item/weapon/sample/print/P = new /obj/item/weapon/sample/print(user.loc)
|
||||
P.attack(M, user)
|
||||
to_chat(user,"<span class='notice'>Done printing.</span>")
|
||||
// user << "<span class='notice'>[M]'s Fingerprints: [md5(M.dna.uni_identity)]</span>"
|
||||
|
||||
if(reveal_blood && M.blood_DNA && M.blood_DNA.len)
|
||||
to_chat(user,"<span class='notice'>Blood found on [M]. Analysing...</span>")
|
||||
spawn(15)
|
||||
for(var/blood in M.blood_DNA)
|
||||
to_chat(user,"<span class='notice'>Blood type: [M.blood_DNA[blood]]\nDNA: [blood]</span>")
|
||||
return
|
||||
|
||||
/obj/item/device/detective_scanner/afterattack(atom/A as obj|turf, mob/user, proximity)
|
||||
if(!proximity) return
|
||||
if(ismob(A))
|
||||
return
|
||||
|
||||
/*
|
||||
if(istype(A,/obj/machinery/computer/forensic_scanning))
|
||||
user.visible_message("[user] takes a cord out of [src] and hooks its end into [A]" ,\
|
||||
"<span class='notice'>You download data from [src] to [A]</span>")
|
||||
var/obj/machinery/computer/forensic_scanning/F = A
|
||||
F.sync_data(stored)
|
||||
return
|
||||
*/
|
||||
|
||||
if(istype(A,/obj/item/weapon/sample/print))
|
||||
to_chat(user,"The scanner displays on the screen: \"ERROR 43: Object on Excluded Object List.\"")
|
||||
flick("[icon_state]0",src)
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(!(do_after(user, 1 SECOND)))
|
||||
to_chat(user,"<span class='warning'>You must remain still for the device to complete its work.</span>")
|
||||
return 0
|
||||
|
||||
//General
|
||||
if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA)
|
||||
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
|
||||
"<span class='warning'>Unable to locate any fingerprints, materials, fibers, or blood on [A]!</span>",\
|
||||
"You hear a faint hum of electrical equipment.")
|
||||
flick("[icon_state]0",src)
|
||||
return 0
|
||||
|
||||
if(add_data(A))
|
||||
to_chat(user,"<span class='notice'>Object already in internal memory. Consolidating data...</span>")
|
||||
flick("[icon_state]2",src)
|
||||
return
|
||||
|
||||
//PRINTS
|
||||
if(A.fingerprints && A.fingerprints.len)
|
||||
to_chat(user,"<span class='notice'>Isolated [A.fingerprints.len] fingerprints:</span>")
|
||||
if(!reveal_incompletes)
|
||||
to_chat(user,"<span class='warning'>Rapid Analysis Imperfect: Scan samples with H.R.F.S. equipment to determine nature of incomplete prints.</span>")
|
||||
var/list/complete_prints = list()
|
||||
var/list/incomplete_prints = list()
|
||||
for(var/i in A.fingerprints)
|
||||
var/print = A.fingerprints[i]
|
||||
if(stringpercent(print) <= FINGERPRINT_COMPLETE)
|
||||
complete_prints += print
|
||||
else
|
||||
incomplete_prints += print
|
||||
if(complete_prints.len < 1)
|
||||
to_chat(user,"<span class='notice'>No intact prints found</span>")
|
||||
else
|
||||
to_chat(user,"<span class='notice'>Found [complete_prints.len] intact prints</span>")
|
||||
if(reveal_fingerprints)
|
||||
for(var/i in complete_prints)
|
||||
to_chat(user,"<span class='notice'> [i]</span>")
|
||||
|
||||
to_chat(user,"<span class='notice'>Found [incomplete_prints.len] incomplete prints</span>")
|
||||
if(reveal_incompletes)
|
||||
for(var/i in incomplete_prints)
|
||||
to_chat(user,"<span class='notice'> [i]</span>")
|
||||
|
||||
|
||||
//FIBERS
|
||||
if(A.suit_fibers && A.suit_fibers.len)
|
||||
to_chat(user,"<span class='notice'>Fibers/Materials detected.[reveal_fibers ? " Analysing..." : " Acquisition of fibers for H.R.F.S. analysis advised."]</span>")
|
||||
flick("[icon_state]2",src)
|
||||
if(reveal_fibers && do_after(user, 5 SECONDS))
|
||||
to_chat(user,"<span class='notice'>Apparel samples scanned:</span>")
|
||||
for(var/sample in A.suit_fibers)
|
||||
to_chat(user," - <span class='notice'>[sample]</span>")
|
||||
|
||||
//Blood
|
||||
if (A.blood_DNA && A.blood_DNA.len)
|
||||
to_chat(user,"<span class='notice'>Blood detected.[reveal_blood ? " Analysing..." : " Acquisition of swab for H.R.F.S. analysis advised."]</span>")
|
||||
if(reveal_blood && do_after(user, 5 SECONDS))
|
||||
flick("[icon_state]2",src)
|
||||
for(var/blood in A.blood_DNA)
|
||||
to_chat(user,"Blood type: <span class='warning'>[A.blood_DNA[blood]]</span> DNA: <span class='warning'>[blood]</span>")
|
||||
|
||||
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
|
||||
"<span class='notice'>You finish scanning \the [A].</span>",\
|
||||
"You hear a faint hum of electrical equipment.")
|
||||
flick("[icon_state]2",src)
|
||||
return 0
|
||||
|
||||
/obj/item/device/detective_scanner/proc/add_data(atom/A as mob|obj|turf|area)
|
||||
var/datum/data/record/forensic/old = stored["\ref [A]"]
|
||||
var/datum/data/record/forensic/fresh = new(A)
|
||||
|
||||
if(old)
|
||||
fresh.merge(old)
|
||||
. = 1
|
||||
stored["\ref [A]"] = fresh
|
||||
|
||||
/obj/item/device/detective_scanner/verb/examine_data()
|
||||
set name = "Examine Forensic Data"
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
world << "usr is [usr]"
|
||||
display_data(usr)
|
||||
|
||||
/obj/item/device/detective_scanner/proc/display_data(var/mob/user)
|
||||
if(user && stored && stored.len)
|
||||
for(var/objref in stored)
|
||||
if(!do_after(user, 1 SECOND)) // So people can move and stop the spam, if they refuse to wipe data.
|
||||
break
|
||||
|
||||
var/datum/data/record/forensic/F = stored[objref]
|
||||
var/list/fprints = F.fields["fprints"]
|
||||
var/list/fibers = F.fields["fibers"]
|
||||
var/list/bloods = F.fields["blood"]
|
||||
|
||||
to_chat(user, "<span class='notice'>Data for: [F.fields["name"]]</span>")
|
||||
|
||||
if(reveal_fingerprints)
|
||||
var/list/complete_prints = list()
|
||||
var/list/incomplete_prints = list()
|
||||
for(var/i in fprints)
|
||||
var/print = fprints[i]
|
||||
if(stringpercent(print) <= FINGERPRINT_COMPLETE)
|
||||
complete_prints += print
|
||||
to_chat(user, " - <span class='notice'>[print]</span>")
|
||||
else
|
||||
incomplete_prints += print
|
||||
|
||||
if(complete_prints.len < 1)
|
||||
to_chat(user,"<span class='notice'>No intact prints found.</span>")
|
||||
|
||||
if(reveal_incompletes)
|
||||
for(var/print in incomplete_prints)
|
||||
to_chat(user, " - <span class='notice'>[print]</span>")
|
||||
|
||||
if(fibers && fibers.len)
|
||||
to_chat(user, "<span class='notice'>[fibers.len] samples of material were present.</span>")
|
||||
if(reveal_fibers)
|
||||
for(var/sample in fibers)
|
||||
to_chat(user," - <span class='notice'>[sample]</span>")
|
||||
|
||||
if(bloods && bloods.len)
|
||||
to_chat(user, "<span class='notice'>[bloods.len] samples of blood were present.</span>")
|
||||
if(reveal_blood)
|
||||
for(var/bloodsample in bloods)
|
||||
to_chat(user, " - <span class='warning'>[bloodsample]</span> Type: [bloods[bloodsample]]")
|
||||
|
||||
/obj/item/device/detective_scanner/verb/wipe()
|
||||
set name = "Wipe Forensic Data"
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
if (alert("Are you sure you want to wipe all data from [src]?",,"Yes","No") == "Yes")
|
||||
stored = list()
|
||||
to_chat(usr,"<span class='notice'>Forensic data erase complete.</span>")
|
||||
|
||||
/obj/item/device/detective_scanner/advanced
|
||||
name = "advanced forensic scanner"
|
||||
icon_state = "forensic_neo"
|
||||
reveal_fibers = TRUE
|
||||
reveal_incompletes = TRUE
|
||||
@@ -89,7 +89,7 @@
|
||||
desc = "It's beef. It's roasted. It's been a staple of dining tradition for centuries."
|
||||
icon = 'icons/obj/food_vr.dmi'
|
||||
icon_state = "roastbeef"
|
||||
trash = /obj/item/trash/waffles
|
||||
trash = /obj/item/trash/plate //TFF 30/11/19 - Roast beef are put on plates, not waffle trays, you dunce~
|
||||
nutriment_amt = 8
|
||||
nutriment_desc = list("cooked meat" = 5)
|
||||
|
||||
|
||||
10
code/modules/gamemaster/actions/drill_announcement.dm
Normal file
10
code/modules/gamemaster/actions/drill_announcement.dm
Normal file
@@ -0,0 +1,10 @@
|
||||
/datum/gm_action/security_drill
|
||||
name = "security drills"
|
||||
departments = list(ROLE_SECURITY, ROLE_EVERYONE)
|
||||
|
||||
/datum/gm_action/security_drill/announce()
|
||||
spawn(rand(1 MINUTE, 2 MINUTES))
|
||||
command_announcement.Announce("[pick("A NanoTrasen security director", "A Vir-Gov correspondant", "Local Sif authoritiy")] has advised the enactment of [pick("a rampant wildlife", "a fire", "a hostile boarding", "a nonstandard", "a bomb", "an emergent intelligence")] drill with the personnel onboard \the [station_name()].", "Security Advisement")
|
||||
|
||||
/datum/gm_action/security_drill/get_weight()
|
||||
return max(-20, 10 + gm.staleness - (gm.danger * 2)) + (metric.count_people_in_department(ROLE_SECURITY) * 5) + (metric.count_people_in_department(ROLE_EVERYONE) * 1.5)
|
||||
116
code/modules/gamemaster/actions/infestation.dm
Normal file
116
code/modules/gamemaster/actions/infestation.dm
Normal file
@@ -0,0 +1,116 @@
|
||||
#define LOC_KITCHEN 0
|
||||
#define LOC_ATMOS 1
|
||||
#define LOC_CHAPEL 2
|
||||
#define LOC_LIBRARY 3
|
||||
#define LOC_HYDRO 4
|
||||
#define LOC_VAULT 5
|
||||
#define LOC_CONSTR 6
|
||||
#define LOC_TECH 7
|
||||
#define LOC_GARDEN 8
|
||||
|
||||
#define VERM_MICE 0
|
||||
#define VERM_LIZARDS 1
|
||||
#define VERM_SPIDERS 2
|
||||
|
||||
/datum/gm_action/infestation
|
||||
name = "animal infestation"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
var/location
|
||||
var/locstring
|
||||
var/vermin
|
||||
var/vermstring
|
||||
|
||||
var/list/turf/simulated/floor/turfs = list()
|
||||
|
||||
var/spawn_types
|
||||
var/max_number
|
||||
|
||||
/datum/gm_action/infestation/set_up()
|
||||
location = rand(0,8)
|
||||
turfs.Cut()
|
||||
var/spawn_area_type
|
||||
switch(location)
|
||||
if(LOC_KITCHEN)
|
||||
spawn_area_type = /area/crew_quarters/kitchen
|
||||
locstring = "the kitchen"
|
||||
if(LOC_ATMOS)
|
||||
spawn_area_type = /area/engineering/atmos
|
||||
locstring = "atmospherics"
|
||||
if(LOC_CHAPEL)
|
||||
spawn_area_type = /area/chapel/main
|
||||
locstring = "the chapel"
|
||||
if(LOC_LIBRARY)
|
||||
spawn_area_type = /area/library
|
||||
locstring = "the library"
|
||||
if(LOC_HYDRO)
|
||||
spawn_area_type = /area/hydroponics
|
||||
locstring = "hydroponics"
|
||||
if(LOC_VAULT)
|
||||
spawn_area_type = /area/security/nuke_storage
|
||||
locstring = "the vault"
|
||||
if(LOC_CONSTR)
|
||||
spawn_area_type = /area/construction
|
||||
locstring = "the construction area"
|
||||
if(LOC_TECH)
|
||||
spawn_area_type = /area/storage/tech
|
||||
locstring = "technical storage"
|
||||
if(LOC_GARDEN)
|
||||
spawn_area_type = /area/hydroponics/garden
|
||||
locstring = "the public garden"
|
||||
|
||||
for(var/areapath in typesof(spawn_area_type))
|
||||
var/area/A = locate(areapath)
|
||||
for(var/turf/simulated/floor/F in A.contents)
|
||||
if(turf_clear(F))
|
||||
turfs += F
|
||||
|
||||
spawn_types = list()
|
||||
max_number = 0
|
||||
vermin = rand(0,2)
|
||||
switch(vermin)
|
||||
if(VERM_MICE)
|
||||
spawn_types = list(/mob/living/simple_mob/animal/passive/mouse/gray, /mob/living/simple_mob/animal/passive/mouse/brown, /mob/living/simple_mob/animal/passive/mouse/white, /mob/living/simple_mob/animal/passive/mouse/rat)
|
||||
max_number = 12
|
||||
vermstring = "mice"
|
||||
if(VERM_LIZARDS)
|
||||
spawn_types = list(/mob/living/simple_mob/animal/passive/lizard, /mob/living/simple_mob/animal/passive/lizard, /mob/living/simple_mob/animal/passive/lizard/large, /mob/living/simple_mob/animal/passive/lizard/large/defensive)
|
||||
max_number = 6
|
||||
vermstring = "lizards"
|
||||
if(VERM_SPIDERS)
|
||||
spawn_types = list(/obj/effect/spider/spiderling)
|
||||
max_number = 3
|
||||
vermstring = "spiders"
|
||||
|
||||
/datum/gm_action/infestation/start()
|
||||
spawn()
|
||||
var/num = rand(2,max_number)
|
||||
while(turfs.len > 0 && num > 0)
|
||||
var/turf/simulated/floor/T = pick(turfs)
|
||||
turfs.Remove(T)
|
||||
num--
|
||||
|
||||
if(vermin == VERM_SPIDERS)
|
||||
var/obj/effect/spider/spiderling/S = new(T)
|
||||
S.amount_grown = -1
|
||||
else
|
||||
var/spawn_type = pick(spawn_types)
|
||||
new spawn_type(T)
|
||||
|
||||
/datum/gm_action/infestation/announce()
|
||||
command_announcement.Announce("Bioscans indicate that [vermstring] have been breeding in [locstring]. Clear them out, before this starts to affect productivity.", "Vermin infestation")
|
||||
|
||||
/datum/gm_action/infestation/get_weight()
|
||||
return 5 + (metric.count_people_in_department(ROLE_EVERYONE) * 20)
|
||||
|
||||
#undef LOC_KITCHEN
|
||||
#undef LOC_ATMOS
|
||||
#undef LOC_CHAPEL
|
||||
#undef LOC_LIBRARY
|
||||
#undef LOC_HYDRO
|
||||
#undef LOC_VAULT
|
||||
#undef LOC_TECH
|
||||
#undef LOC_GARDEN
|
||||
|
||||
#undef VERM_MICE
|
||||
#undef VERM_LIZARDS
|
||||
#undef VERM_SPIDERS
|
||||
@@ -1,4 +1,6 @@
|
||||
/datum/gm_action/ionstorm
|
||||
name = "ion storm"
|
||||
departments = list(ROLE_SYNTHETIC)
|
||||
var/botEmagChance = 0.5
|
||||
var/list/players = list()
|
||||
var/active = FALSE
|
||||
@@ -41,3 +43,8 @@
|
||||
spawn(rand(5000,8000))
|
||||
if(prob(50))
|
||||
ion_storm_announcement()
|
||||
|
||||
/datum/gm_action/ionstorm/get_weight()
|
||||
var/bots = metric.count_people_in_department(ROLE_SYNTHETIC)
|
||||
var/weight = 5 + (bots * 20)
|
||||
return weight
|
||||
|
||||
52
code/modules/gamemaster/actions/manifest_malfunction.dm
Normal file
52
code/modules/gamemaster/actions/manifest_malfunction.dm
Normal file
@@ -0,0 +1,52 @@
|
||||
/datum/gm_action/manifest_malfunction
|
||||
name = "manifest malfunction"
|
||||
enabled = TRUE
|
||||
departments = list(ROLE_SECURITY, ROLE_SYNTHETIC, ROLE_EVERYONE)
|
||||
chaotic = 3
|
||||
reusable = FALSE
|
||||
length = 0
|
||||
|
||||
var/recordtype
|
||||
|
||||
/datum/gm_action/manifest_malfunction/set_up()
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = 6,
|
||||
EVENT_LEVEL_MODERATE = 2,
|
||||
EVENT_LEVEL_MAJOR = 1
|
||||
)
|
||||
|
||||
recordtype = pickweight("medical" = 10,"security" = (severity * 15))
|
||||
|
||||
return
|
||||
|
||||
/datum/gm_action/manifest_malfunction/get_weight()
|
||||
. = -10
|
||||
|
||||
var/security = metric.count_people_in_department(ROLE_SECURITY)
|
||||
|
||||
if(security && data_core)
|
||||
. += (metric.count_people_in_department(ROLE_EVERYONE) * 5) - (metric.count_people_in_department(ROLE_SYNTHETIC) * 5)
|
||||
|
||||
return .
|
||||
|
||||
/datum/gm_action/manifest_malfunction/start()
|
||||
..()
|
||||
|
||||
var/manifest_cut_count = 1 * severity
|
||||
|
||||
for(var/I = 1 to manifest_cut_count)
|
||||
var/datum/data/record/R
|
||||
|
||||
switch(recordtype)
|
||||
if("security")
|
||||
R = pick(data_core.security)
|
||||
|
||||
if("medical")
|
||||
R = pick(data_core.medical)
|
||||
|
||||
qdel(R)
|
||||
|
||||
/datum/gm_action/manifest_malfunction/announce()
|
||||
if(prob(30 * severity))
|
||||
spawn(rand(5 MINUTES, 10 MINUTES))
|
||||
command_announcement.Announce("An ongoing mass upload of malware for [recordtype] record cores has been detected onboard [station_name()]", "Data Breach Alert")
|
||||
return
|
||||
@@ -2,18 +2,38 @@
|
||||
|
||||
/datum/gm_action/meteor_defense
|
||||
name = "meteor defense"
|
||||
departments = list(ROLE_ENGINEERING)
|
||||
departments = list(ROLE_ENGINEERING, ROLE_CARGO)
|
||||
chaotic = 50
|
||||
var/direction = null
|
||||
var/dir_text = null
|
||||
var/waves = 0
|
||||
|
||||
var/meteor_types
|
||||
|
||||
/datum/gm_action/meteor_defense/get_weight()
|
||||
var/engineers = metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
var/weight = (max(engineers - 1, 0) * 25) // If only one engineer exists, no meteors for now.
|
||||
var/cargo = metric.count_people_in_department(ROLE_CARGO)
|
||||
var/bots = metric.count_people_in_department(ROLE_SYNTHETIC)
|
||||
var/weight = (max(engineers - 1, 0) * 20) // If only one engineer exists, no meteors for now.
|
||||
|
||||
if(engineers >= 2)
|
||||
weight += ((cargo - 1) * 10)
|
||||
weight += (bots * 15)
|
||||
|
||||
return weight
|
||||
|
||||
/datum/gm_action/meteor_defense/set_up()
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = 10,
|
||||
EVENT_LEVEL_MODERATE = 3
|
||||
)
|
||||
|
||||
switch(severity)
|
||||
if(EVENT_LEVEL_MUNDANE)
|
||||
meteor_types = meteors_threatening.Copy()
|
||||
|
||||
if(EVENT_LEVEL_MODERATE)
|
||||
meteor_types = meteors_catastrophic.Copy()
|
||||
|
||||
direction = pick(cardinal) // alldirs doesn't work with current meteor code unfortunately.
|
||||
waves = rand(5, 8)
|
||||
switch(direction)
|
||||
@@ -27,17 +47,17 @@
|
||||
dir_text = "starboard"
|
||||
|
||||
/datum/gm_action/meteor_defense/announce()
|
||||
var/announcement = "Alert! Two other asteroids have collided near [station_name()]. Chunks of it are expected to approach from the [dir_text] side. ETA to arrival is \
|
||||
approximately 10 minutes."
|
||||
var/announcement = "Alert! Two asteroids have collided near [station_name()]. Chunks of it are expected to approach from the [dir_text] side. ETA to arrival is \
|
||||
approximately [round(5 * severity * 2)] minutes."
|
||||
command_announcement.Announce(announcement, "Meteor Alert", new_sound = 'sound/AI/meteors.ogg')
|
||||
|
||||
/datum/gm_action/meteor_defense/start()
|
||||
..()
|
||||
spawn(0)
|
||||
sleep(5 MINUTES)
|
||||
var/announcement = "The incoming debris are expected to approach from the [dir_text] side. ETA to arrival is approximately 5 minutes."
|
||||
sleep(round(5 * severity) MINUTES)
|
||||
var/announcement = "The incoming debris are expected to approach from the [dir_text] side. ETA to arrival is approximately [round(5 * severity)] minutes."
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
sleep(5 MINUTES)
|
||||
sleep(round(5 * severity) MINUTES)
|
||||
announcement = "Incoming debris approaches from the [dir_text] side!"
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
while(waves)
|
||||
@@ -46,6 +66,6 @@
|
||||
spawn_meteors(rand(8, 12), meteors_threatening, reverse_dir[direction])
|
||||
waves--
|
||||
sleep(30 SECONDS)
|
||||
announcement = "The colony has cleared the incoming debris."
|
||||
announcement = "The station has cleared the incoming debris."
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
message_admins("Meteor defense event has ended.")
|
||||
49
code/modules/gamemaster/actions/security_advisement.dm
Normal file
49
code/modules/gamemaster/actions/security_advisement.dm
Normal file
@@ -0,0 +1,49 @@
|
||||
/datum/gm_action/security_screening
|
||||
name = "security screening"
|
||||
departments = list(ROLE_SECURITY, ROLE_EVERYONE)
|
||||
|
||||
var/list/species_weights = list(
|
||||
SPECIES_SKRELL = 9,
|
||||
SPECIES_UNATHI = 15,
|
||||
SPECIES_HUMAN_VATBORN = 6,
|
||||
SPECIES_TESHARI = 2,
|
||||
SPECIES_TAJ = 3,
|
||||
SPECIES_DIONA = 1,
|
||||
SPECIES_ZADDAT = 25,
|
||||
SPECIES_HUMAN = 3,
|
||||
SPECIES_PROMETHEAN = 30
|
||||
)
|
||||
|
||||
var/list/synth_weights = list(
|
||||
"Cybernetic" = 15,
|
||||
"Drone" = 30,
|
||||
"Positronic" = 25
|
||||
)
|
||||
|
||||
var/list/end_weights = list()
|
||||
|
||||
/datum/gm_action/security_screening/set_up()
|
||||
for(var/species_name in species_weights)
|
||||
var/giveweight = 0
|
||||
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if(R.fields["species"] == species_name)
|
||||
giveweight += species_weights[species_name]
|
||||
|
||||
end_weights[species_name] = giveweight
|
||||
|
||||
for(var/bottype in synth_weights)
|
||||
var/giveweight = 0
|
||||
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if(R.fields["brain_type"] == bottype)
|
||||
giveweight += synth_weights[bottype]
|
||||
|
||||
end_weights[bottype] = giveweight
|
||||
|
||||
/datum/gm_action/security_screening/announce()
|
||||
spawn(rand(1 MINUTE, 2 MINUTES))
|
||||
command_announcement.Announce("[pick("A nearby Navy vessel", "A Solar official", "A Vir-Gov official", "A NanoTrasen board director")] has requested the screening of [pick("every other", "every", "suspicious", "willing")] [pickweight(end_weights)] personnel onboard \the [station_name()].", "Security Advisement")
|
||||
|
||||
/datum/gm_action/security_screening/get_weight()
|
||||
return max(-20, 10 + round(gm.staleness * 1.5) - (gm.danger * 2)) + (metric.count_people_in_department(ROLE_SECURITY) * 10) + (metric.count_people_in_department(ROLE_EVERYONE) * 1.5)
|
||||
@@ -7,21 +7,28 @@
|
||||
|
||||
var/spawncount = 1
|
||||
|
||||
/datum/gm_action/spider_infestation/set_up()
|
||||
spawn(rand(600, 6000))
|
||||
announce()
|
||||
var/spawntype = /obj/effect/spider/spiderling
|
||||
|
||||
if(prob(40))
|
||||
severity = rand(2,3)
|
||||
else
|
||||
severity = 1
|
||||
/datum/gm_action/spider_infestation/set_up()
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = max(1,(12 - (3 * metric.count_people_in_department(ROLE_SECURITY)))),
|
||||
EVENT_LEVEL_MODERATE = (7 + (2 * metric.count_people_in_department(ROLE_SECURITY))),
|
||||
EVENT_LEVEL_MAJOR = (1 + (2 * metric.count_people_in_department(ROLE_SECURITY)))
|
||||
)
|
||||
|
||||
switch(severity)
|
||||
if(EVENT_LEVEL_MUNDANE)
|
||||
spawntype = /obj/effect/spider/spiderling/stunted
|
||||
if(EVENT_LEVEL_MODERATE)
|
||||
spawntype = /obj/effect/spider/spiderling
|
||||
if(EVENT_LEVEL_MAJOR)
|
||||
spawntype = /obj/effect/spider/spiderling
|
||||
|
||||
spawncount = rand(4 * severity, 6 * severity)
|
||||
|
||||
/datum/gm_action/spider_infestation/announce()
|
||||
command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
|
||||
|
||||
if(severity >= 3)
|
||||
if(severity >= EVENT_LEVEL_MAJOR)
|
||||
spawn(rand(600, 3000))
|
||||
command_announcement.Announce("Unidentified lifesigns previously detected coming aboard [station_name()] have been classified as a swarm of arachnids. Extreme caution is advised.", "Arachnid Alert")
|
||||
|
||||
|
||||
14
code/modules/gamemaster/actions/station_fundraise.dm
Normal file
14
code/modules/gamemaster/actions/station_fundraise.dm
Normal file
@@ -0,0 +1,14 @@
|
||||
/datum/gm_action/station_fund_raise
|
||||
name = "local funding drive"
|
||||
departments = list(ROLE_SECURITY, ROLE_CARGO, ROLE_EVERYONE)
|
||||
|
||||
/datum/gm_action/station_fund_raise/announce()
|
||||
spawn(rand(1 MINUTE, 2 MINUTES))
|
||||
command_announcement.Announce("Due to [pick("recent", "unfortunate", "possible future")] budget [pick("changes", "issues")], in-system stations are now advised to increase funding income.", "Security & Supply Advisement")
|
||||
|
||||
/datum/gm_action/station_fund_raise/get_weight()
|
||||
var/weight_modifier = 0.5
|
||||
if(station_account.money <= 80000)
|
||||
weight_modifier = 1
|
||||
|
||||
return (max(-20, 10 + gm.staleness) + ((metric.count_people_in_department(ROLE_SECURITY) + (metric.count_people_in_department(ROLE_CARGO))) * 5) + (metric.count_people_in_department(ROLE_EVERYONE) * 3)) * weight_modifier
|
||||
80
code/modules/gamemaster/actions/stowaway.dm
Normal file
80
code/modules/gamemaster/actions/stowaway.dm
Normal file
@@ -0,0 +1,80 @@
|
||||
/datum/gm_action/stowaway
|
||||
name = "stowaway pod"
|
||||
departments = list(ROLE_EVERYONE, ROLE_SECURITY)
|
||||
chaotic = 10
|
||||
observers_used = TRUE
|
||||
var/area/target_area // Chosen target area
|
||||
var/area/target_turf // Chosen target turf in target_area
|
||||
var/list/area/excluded = list(
|
||||
/area/submap,
|
||||
/area/shuttle,
|
||||
/area/crew_quarters,
|
||||
/area/holodeck,
|
||||
/area/engineering/engine_room
|
||||
)
|
||||
|
||||
var/list/area/included = list(
|
||||
/area/maintenance
|
||||
)
|
||||
|
||||
/datum/gm_action/stowaway/set_up()
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = 20,
|
||||
EVENT_LEVEL_MODERATE = 5,
|
||||
EVENT_LEVEL_MAJOR = 1
|
||||
)
|
||||
|
||||
var/list/area/grand_list_of_areas = get_station_areas(excluded)
|
||||
|
||||
for(var/area/Incl in included)
|
||||
for(var/area/A in grand_list_of_areas)
|
||||
if(!istype(A, Incl))
|
||||
grand_list_of_areas -= A
|
||||
|
||||
// Okay, now lets try and pick a target! Lets try 10 times, otherwise give up
|
||||
for(var/i in 1 to 10)
|
||||
var/area/A = pick(grand_list_of_areas)
|
||||
if(is_area_occupied(A))
|
||||
log_debug("[name] event: Rejected [A] because it is occupied.")
|
||||
continue
|
||||
// A good area, great! Lets try and pick a turf
|
||||
var/list/turfs = list()
|
||||
for(var/turf/simulated/floor/F in A)
|
||||
if(turf_clear(F))
|
||||
turfs += F
|
||||
if(turfs.len == 0)
|
||||
log_debug("[name] event: Rejected [A] because it has no clear turfs.")
|
||||
continue
|
||||
target_area = A
|
||||
target_turf = pick(turfs)
|
||||
|
||||
if(!target_area)
|
||||
log_debug("[name] event: Giving up after too many failures to pick target area")
|
||||
return
|
||||
|
||||
/datum/gm_action/stowaway/start()
|
||||
if(!target_turf)
|
||||
return
|
||||
..()
|
||||
|
||||
var/obj/structure/ghost_pod/ghost_activated/human/HP = new (target_turf)
|
||||
|
||||
if(severity == EVENT_LEVEL_MUNDANE || istype(ticker.mode, /datum/game_mode/extended))
|
||||
HP.make_antag = MODE_STOWAWAY
|
||||
|
||||
else if(severity == EVENT_LEVEL_MODERATE)
|
||||
HP.make_antag = MODE_RENEGADE
|
||||
HP.occupant_type = "renegade [HP.occupant_type]"
|
||||
|
||||
else if(severity == EVENT_LEVEL_MAJOR)
|
||||
HP.make_antag = MODE_INFILTRATOR
|
||||
HP.occupant_type = "volatile [HP.occupant_type]"
|
||||
|
||||
say_dead_object("A <span class='notice'>[HP.occupant_type]</span> pod is now available in \the [target_area].", HP)
|
||||
|
||||
/datum/gm_action/stowaway/get_weight()
|
||||
return -20 + (metric.count_people_in_department(ROLE_SECURITY) * 15 + metric.count_people_in_department(ROLE_SYNTHETIC) * 5 + metric.count_people_in_department(ROLE_EVERYONE) * 1)
|
||||
|
||||
/datum/gm_action/stowaway/announce()
|
||||
spawn(rand(15 MINUTES, 30 MINUTES))
|
||||
if(prob(20) && severity >= EVENT_LEVEL_MODERATE && atc && !atc.squelched)
|
||||
atc.msg("Attention civilian vessels in [using_map.starsys_name] shipping lanes, caution is advised as [pick("an unidentified vessel", "a known criminal's vessel", "a derelict vessel")] has been detected passing multiple local stations.")
|
||||
62
code/modules/gamemaster/actions/supply_conversion.dm
Normal file
62
code/modules/gamemaster/actions/supply_conversion.dm
Normal file
@@ -0,0 +1,62 @@
|
||||
/datum/gm_action/nanotrasen_budget_allocation
|
||||
name = "supply point to cargo budget"
|
||||
enabled = TRUE
|
||||
departments = list(ROLE_CARGO)
|
||||
chaotic = 0
|
||||
reusable = TRUE
|
||||
|
||||
var/datum/controller/supply/SC
|
||||
var/running = FALSE
|
||||
var/last_run
|
||||
|
||||
var/thaler_earned
|
||||
|
||||
/datum/gm_action/nanotrasen_budget_allocation/set_up()
|
||||
SC = supply_controller
|
||||
running = TRUE
|
||||
return
|
||||
|
||||
/datum/gm_action/nanotrasen_budget_allocation/get_weight()
|
||||
. = round(SC.points / 15)
|
||||
|
||||
var/cargo = metric.count_people_in_department(ROLE_CARGO)
|
||||
var/personnel = metric.count_people_in_department(ROLE_EVERYONE)
|
||||
if(cargo)
|
||||
. = round(SC.points / (10 + personnel)) + cargo * 10
|
||||
|
||||
if(running || ( world.time < (last_run + 30 MINUTES)))
|
||||
. = 0
|
||||
|
||||
return .
|
||||
|
||||
/datum/gm_action/nanotrasen_budget_allocation/start()
|
||||
. = ..()
|
||||
|
||||
last_run = world.time
|
||||
|
||||
var/point_difference = SC.points
|
||||
|
||||
if(SC.points >= 1000)
|
||||
SC.points = round(SC.points / 3)
|
||||
point_difference -= SC.points
|
||||
|
||||
else if(SC.points >= 500)
|
||||
SC.points -= 100 * (rand(5, 20) / 10)
|
||||
point_difference -= SC.points
|
||||
|
||||
else
|
||||
SC.points = round(SC.points / 1.25)
|
||||
point_difference -= SC.points
|
||||
|
||||
if(point_difference > 0)
|
||||
thaler_earned = round(point_difference / SC.points_per_money)
|
||||
|
||||
/datum/gm_action/nanotrasen_budget_allocation/end()
|
||||
spawn(5 MINUTES)
|
||||
running = FALSE
|
||||
return
|
||||
|
||||
/datum/gm_action/nanotrasen_budget_allocation/announce()
|
||||
spawn(rand(1 MINUTE, 5 MINUTES))
|
||||
command_announcement.Announce("[station_name()] Supply Department has earned a converted thaler budget of [thaler_earned] due to their backlogged daily requisition tokens.", "Supply Budget Conversion")
|
||||
return
|
||||
11
code/modules/gamemaster/actions/supplyrequest.dm
Normal file
11
code/modules/gamemaster/actions/supplyrequest.dm
Normal file
@@ -0,0 +1,11 @@
|
||||
/datum/gm_action/request
|
||||
name = "general request"
|
||||
departments = list(ROLE_CARGO)
|
||||
|
||||
/datum/gm_action/request/announce()
|
||||
spawn(rand(1 MINUTE, 2 MINUTES))
|
||||
command_announcement.Announce("[pick("A nearby vessel", "A Solar contractor", "A Skrellian contractor", "A NanoTrasen board director")] has requested the delivery of [pick("one","two","three","several")] [pick("medical","engineering","research","civilian")] supply packages. The [station_name()] has been tasked with completing this request.", "Supply Request")
|
||||
|
||||
/datum/gm_action/request/get_weight()
|
||||
return max(15, 15 + round(gm.staleness / 2) - gm.danger) + (metric.count_people_in_department(ROLE_CARGO) * 10)
|
||||
|
||||
75
code/modules/gamemaster/actions/swarmboarder.dm
Normal file
75
code/modules/gamemaster/actions/swarmboarder.dm
Normal file
@@ -0,0 +1,75 @@
|
||||
/datum/gm_action/swarm_boarder
|
||||
name = "swarmer shell"
|
||||
departments = list(ROLE_EVERYONE, ROLE_SECURITY, ROLE_ENGINEERING)
|
||||
chaotic = 30
|
||||
observers_used = TRUE
|
||||
var/area/target_area // Chosen target area
|
||||
var/area/target_turf // Chosen target turf in target_area
|
||||
var/list/area/excluded = list(
|
||||
/area/submap,
|
||||
/area/shuttle,
|
||||
/area/crew_quarters,
|
||||
/area/holodeck,
|
||||
/area/engineering/engine_room
|
||||
)
|
||||
|
||||
var/list/area/included = list(
|
||||
/area/maintenance
|
||||
)
|
||||
|
||||
/datum/gm_action/swarm_boarder/set_up()
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = 30,
|
||||
EVENT_LEVEL_MODERATE = 10,
|
||||
EVENT_LEVEL_MAJOR = 1
|
||||
)
|
||||
|
||||
var/list/area/grand_list_of_areas = get_station_areas(excluded)
|
||||
|
||||
for(var/area/Incl in included)
|
||||
for(var/area/A in grand_list_of_areas)
|
||||
if(!istype(A, Incl))
|
||||
grand_list_of_areas -= A
|
||||
|
||||
// Okay, now lets try and pick a target! Lets try 10 times, otherwise give up
|
||||
for(var/i in 1 to 10)
|
||||
var/area/A = pick(grand_list_of_areas)
|
||||
if(is_area_occupied(A))
|
||||
log_debug("[name] event: Rejected [A] because it is occupied.")
|
||||
continue
|
||||
// A good area, great! Lets try and pick a turf
|
||||
var/list/turfs = list()
|
||||
for(var/turf/simulated/floor/F in A)
|
||||
if(turf_clear(F))
|
||||
turfs += F
|
||||
if(turfs.len == 0)
|
||||
log_debug("[name] event: Rejected [A] because it has no clear turfs.")
|
||||
continue
|
||||
target_area = A
|
||||
target_turf = pick(turfs)
|
||||
|
||||
if(!target_area)
|
||||
log_debug("[name] event: Giving up after too many failures to pick target area")
|
||||
return
|
||||
|
||||
/datum/gm_action/swarm_boarder/start()
|
||||
if(!target_turf)
|
||||
return
|
||||
..()
|
||||
|
||||
var/swarmertype = /obj/structure/ghost_pod/ghost_activated/swarm_drone/event
|
||||
|
||||
if(severity == EVENT_LEVEL_MODERATE)
|
||||
swarmertype = /obj/structure/ghost_pod/ghost_activated/swarm_drone/event/melee
|
||||
|
||||
if(severity == EVENT_LEVEL_MAJOR)
|
||||
swarmertype = /obj/structure/ghost_pod/ghost_activated/swarm_drone/event/gunner
|
||||
|
||||
new swarmertype(target_turf)
|
||||
|
||||
/datum/gm_action/swarm_boarder/get_weight()
|
||||
return -60 + (metric.count_people_in_department(ROLE_SECURITY) * 20 + metric.count_people_in_department(ROLE_SYNTHETIC) * 5 + metric.count_people_in_department(ROLE_EVERYONE) * 1)
|
||||
|
||||
/datum/gm_action/swarm_boarder/announce()
|
||||
spawn(rand(5 MINUTES, 15 MINUTES))
|
||||
if(prob(80) && severity >= EVENT_LEVEL_MODERATE && atc && !atc.squelched)
|
||||
atc.msg("Attention civilian vessels in [using_map.starsys_name] shipping lanes, caution is advised as [pick("an unidentified vessel", "a known criminal's vessel", "a derelict vessel")] has been detected passing multiple local stations.")
|
||||
@@ -15,13 +15,22 @@
|
||||
var/next_action = 0 // Minimum amount of time of nothingness until the GM can pick something again.
|
||||
var/last_department_used = null // If an event was done for a specific department, it is written here, so it doesn't do it again.
|
||||
|
||||
|
||||
/datum/game_master/New()
|
||||
..()
|
||||
available_actions = init_subtypes(/datum/gm_action)
|
||||
for(var/datum/gm_action/action in available_actions)
|
||||
action.gm = src
|
||||
|
||||
var/config_setup_delay = TRUE
|
||||
spawn(0)
|
||||
while(config_setup_delay)
|
||||
if(config)
|
||||
config_setup_delay = FALSE
|
||||
if(config.enable_game_master)
|
||||
suspended = FALSE
|
||||
else
|
||||
sleep(30 SECONDS)
|
||||
|
||||
/datum/game_master/process()
|
||||
if(ticker && ticker.current_state == GAME_STATE_PLAYING && !suspended)
|
||||
adjust_staleness(1)
|
||||
|
||||
@@ -264,7 +264,9 @@ datum/unarmed_attack/holopugilism/unarmed_override(var/mob/living/carbon/human/u
|
||||
|
||||
/obj/item/weapon/holo/esword
|
||||
desc = "May the force be within you. Sorta."
|
||||
icon_state = "sword0"
|
||||
icon_state = "esword"
|
||||
var/lcolor
|
||||
var/rainbow = FALSE
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
||||
@@ -276,15 +278,12 @@ datum/unarmed_attack/holopugilism/unarmed_override(var/mob/living/carbon/human/u
|
||||
w_class = ITEMSIZE_SMALL
|
||||
flags = NOBLOODY
|
||||
var/active = 0
|
||||
var/item_color
|
||||
|
||||
/obj/item/weapon/holo/esword/green
|
||||
New()
|
||||
item_color = "green"
|
||||
/obj/item/weapon/holo/esword/green/New()
|
||||
lcolor = "#008000"
|
||||
|
||||
/obj/item/weapon/holo/esword/red
|
||||
New()
|
||||
item_color = "red"
|
||||
/obj/item/weapon/holo/esword/red/New()
|
||||
lcolor = "#FF0000"
|
||||
|
||||
/obj/item/weapon/holo/esword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if(active && default_parry_check(user, attacker, damage_source) && prob(50))
|
||||
@@ -297,32 +296,47 @@ datum/unarmed_attack/holopugilism/unarmed_override(var/mob/living/carbon/human/u
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/holo/esword/New()
|
||||
item_color = pick("red","blue","green","purple")
|
||||
|
||||
/obj/item/weapon/holo/esword/attack_self(mob/living/user as mob)
|
||||
active = !active
|
||||
if (active)
|
||||
force = 30
|
||||
icon_state = "sword[item_color]"
|
||||
item_state = "[icon_state]_blade"
|
||||
w_class = ITEMSIZE_LARGE
|
||||
playsound(user, 'sound/weapons/saberon.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>[src] is now active.</span>")
|
||||
else
|
||||
force = 3
|
||||
icon_state = "sword0"
|
||||
item_state = "[icon_state]"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>[src] can now be concealed.</span>")
|
||||
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.update_inv_l_hand()
|
||||
H.update_inv_r_hand()
|
||||
|
||||
update_icon()
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/weapon/holo/esword/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/device/multitool) && !active)
|
||||
if(!rainbow)
|
||||
rainbow = TRUE
|
||||
else
|
||||
rainbow = FALSE
|
||||
to_chat(user, "<span class='notice'>You manipulate the color controller in [src].</span>")
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/holo/esword/update_icon()
|
||||
. = ..()
|
||||
var/mutable_appearance/blade_overlay = mutable_appearance(icon, "[icon_state]_blade")
|
||||
blade_overlay.color = lcolor
|
||||
cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
|
||||
if(active)
|
||||
add_overlay(blade_overlay)
|
||||
if(istype(usr,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
H.update_inv_l_hand()
|
||||
H.update_inv_r_hand()
|
||||
|
||||
//BASKETBALL OBJECTS
|
||||
|
||||
/obj/item/weapon/beach_ball/holoball
|
||||
|
||||
@@ -134,6 +134,8 @@ var/list/holder_mob_icon_cache = list()
|
||||
/mob/living/MouseDrop(var/atom/over_object)
|
||||
var/mob/living/carbon/human/H = over_object
|
||||
if(holder_type && issmall(src) && istype(H) && !H.lying && Adjacent(H) && (src.a_intent == I_HELP && H.a_intent == I_HELP)) //VOREStation Edit
|
||||
if(istype(src, /mob/living/simple_mob/animal/passive/mouse)) //vorestation edit
|
||||
return ..() //vorestation edit
|
||||
if(!issmall(H) || !istype(src, /mob/living/carbon/human))
|
||||
get_scooped(H, (usr == src))
|
||||
return
|
||||
|
||||
@@ -116,6 +116,18 @@
|
||||
|
||||
return 0
|
||||
|
||||
/datum/language/swarmbot
|
||||
name = LANGUAGE_SWARMBOT
|
||||
desc = "A confusing mechanical language spoken by some form of ancient machine."
|
||||
speech_verb = "clatters"
|
||||
ask_verb = "chatters"
|
||||
exclaim_verb = "shrieks"
|
||||
colour = "changeling"
|
||||
key = "_"
|
||||
flags = NO_STUTTER | RESTRICTED
|
||||
syllables = list("^", "v", "-", ".", "~")
|
||||
space_chance = 60
|
||||
|
||||
//for your antag purposes.
|
||||
/datum/language/minbus
|
||||
name = LANGUAGE_MINBUS
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
var/will_patrol = 0 // If set to 1, will patrol, duh
|
||||
var/patrol_speed = 1 // How many times per tick we move when patrolling
|
||||
var/target_speed = 2 // Ditto for chasing the target
|
||||
var/panic_on_alert = FALSE // Will the bot go faster when the alert level is raised?
|
||||
var/min_target_dist = 1 // How close we try to get to the target
|
||||
var/max_target_dist = 50 // How far we are willing to go
|
||||
var/max_patrol_dist = 250
|
||||
@@ -156,7 +157,7 @@
|
||||
/mob/living/bot/Bump(var/atom/A)
|
||||
if(on && botcard && istype(A, /obj/machinery/door))
|
||||
var/obj/machinery/door/D = A
|
||||
if(!istype(D, /obj/machinery/door/firedoor) && !istype(D, /obj/machinery/door/blast) && D.check_access(botcard))
|
||||
if(!istype(D, /obj/machinery/door/firedoor) && !istype(D, /obj/machinery/door/blast) && !istype(D, /obj/machinery/door/airlock/lift) && D.check_access(botcard))
|
||||
D.open()
|
||||
else
|
||||
..()
|
||||
@@ -170,14 +171,20 @@
|
||||
if(!A || !A.loc || prob(1))
|
||||
ignore_list -= A
|
||||
handleRegular()
|
||||
|
||||
var/panic_speed_mod = 0
|
||||
|
||||
if(panic_on_alert)
|
||||
panic_speed_mod = handlePanic()
|
||||
|
||||
if(target && confirmTarget(target))
|
||||
if(Adjacent(target))
|
||||
handleAdjacentTarget()
|
||||
else
|
||||
handleRangedTarget()
|
||||
if(!wait_if_pulled || !pulledby)
|
||||
for(var/i = 1 to target_speed)
|
||||
sleep(20 / (target_speed + 1))
|
||||
for(var/i = 1 to (target_speed + panic_speed_mod))
|
||||
sleep(20 / (target_speed + panic_speed_mod + 1))
|
||||
stepToTarget()
|
||||
if(max_frustration && frustration > max_frustration * target_speed)
|
||||
handleFrustrated(1)
|
||||
@@ -186,7 +193,7 @@
|
||||
lookForTargets()
|
||||
if(will_patrol && !pulledby && !target)
|
||||
if(patrol_path && patrol_path.len)
|
||||
for(var/i = 1 to patrol_speed)
|
||||
for(var/i = 1 to (patrol_speed + panic_speed_mod))
|
||||
sleep(20 / (patrol_speed + 1))
|
||||
handlePatrol()
|
||||
if(max_frustration && frustration > max_frustration * patrol_speed)
|
||||
@@ -205,6 +212,32 @@
|
||||
/mob/living/bot/proc/handleRangedTarget()
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/handlePanic() // Speed modification based on alert level.
|
||||
. = 0
|
||||
switch(get_security_level())
|
||||
if("green")
|
||||
. = 0
|
||||
|
||||
if("yellow")
|
||||
. = 0
|
||||
|
||||
if("violet")
|
||||
. = 0
|
||||
|
||||
if("orange")
|
||||
. = 0
|
||||
|
||||
if("blue")
|
||||
. = 1
|
||||
|
||||
if("red")
|
||||
. = 2
|
||||
|
||||
if("delta")
|
||||
. = 2
|
||||
|
||||
return .
|
||||
|
||||
/mob/living/bot/proc/stepToTarget()
|
||||
if(!target || !target.loc)
|
||||
return
|
||||
|
||||
@@ -38,6 +38,32 @@
|
||||
spawn(600)
|
||||
ignore_list -= g
|
||||
|
||||
/mob/living/bot/cleanbot/handlePanic() // Speed modification based on alert level.
|
||||
. = 0
|
||||
switch(get_security_level())
|
||||
if("green")
|
||||
. = 0
|
||||
|
||||
if("yellow")
|
||||
. = 1
|
||||
|
||||
if("violet")
|
||||
. = 1
|
||||
|
||||
if("orange")
|
||||
. = 1
|
||||
|
||||
if("blue")
|
||||
. = 2
|
||||
|
||||
if("red")
|
||||
. = 2
|
||||
|
||||
if("delta")
|
||||
. = 2
|
||||
|
||||
return .
|
||||
|
||||
/mob/living/bot/cleanbot/lookForTargets()
|
||||
for(var/obj/effect/decal/cleanable/D in view(world.view, src)) // There was some odd code to make it start with nearest decals, it's unnecessary, this works
|
||||
if(confirmTarget(D))
|
||||
|
||||
@@ -203,7 +203,8 @@
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You complete the ED-209.</span>")
|
||||
var/turf/T = get_turf(src)
|
||||
new /mob/living/bot/secbot/ed209(T,created_name,lasercolor)
|
||||
var/mob/living/bot/secbot/ed209/S = new /mob/living/bot/secbot/ed209(T)
|
||||
S.name = created_name
|
||||
user.drop_item()
|
||||
qdel(W)
|
||||
user.drop_from_inventory(src)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "A large cleaning robot. It looks rather efficient."
|
||||
icon_state = "edCLN0"
|
||||
req_one_access = list(access_robotics, access_janitor)
|
||||
botcard_access = list(access_janitor, access_maint_tunnels)
|
||||
botcard_access = list(access_janitor)
|
||||
|
||||
locked = 0 // Start unlocked so roboticist can set them to patrol.
|
||||
wait_if_pulled = 0 // One big boi.
|
||||
@@ -229,7 +229,8 @@
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You complete the ED-CLN.</span>")
|
||||
var/turf/T = get_turf(src)
|
||||
new /mob/living/bot/cleanbot/edCLN(T,created_name)
|
||||
var/mob/living/bot/cleanbot/edCLN/S = new /mob/living/bot/cleanbot/edCLN(T)
|
||||
S.name = created_name
|
||||
user.drop_item()
|
||||
qdel(W)
|
||||
user.drop_from_inventory(src)
|
||||
|
||||
@@ -300,6 +300,32 @@
|
||||
else if(amount > maxAmount)
|
||||
amount = maxAmount
|
||||
|
||||
/mob/living/bot/floorbot/handlePanic() // Speed modification based on alert level.
|
||||
. = 0
|
||||
switch(get_security_level())
|
||||
if("green")
|
||||
. = 0
|
||||
|
||||
if("yellow")
|
||||
. = 0
|
||||
|
||||
if("violet")
|
||||
. = 0
|
||||
|
||||
if("orange")
|
||||
. = 1
|
||||
|
||||
if("blue")
|
||||
. = 1
|
||||
|
||||
if("red")
|
||||
. = 2
|
||||
|
||||
if("delta")
|
||||
. = 2
|
||||
|
||||
return .
|
||||
|
||||
/* Assembly */
|
||||
|
||||
/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/floor/T, mob/living/user as mob)
|
||||
|
||||
@@ -49,6 +49,32 @@
|
||||
/mob/living/bot/medbot/handleAdjacentTarget()
|
||||
UnarmedAttack(target)
|
||||
|
||||
/mob/living/bot/medbot/handlePanic() // Speed modification based on alert level.
|
||||
. = 0
|
||||
switch(get_security_level())
|
||||
if("green")
|
||||
. = 0
|
||||
|
||||
if("yellow")
|
||||
. = 0
|
||||
|
||||
if("violet")
|
||||
. = 1
|
||||
|
||||
if("orange")
|
||||
. = 0
|
||||
|
||||
if("blue")
|
||||
. = 1
|
||||
|
||||
if("red")
|
||||
. = 2
|
||||
|
||||
if("delta")
|
||||
. = 2
|
||||
|
||||
return .
|
||||
|
||||
/mob/living/bot/medbot/lookForTargets()
|
||||
for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient!
|
||||
if(confirmTarget(H))
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
patrol_speed = 2
|
||||
target_speed = 3
|
||||
|
||||
density = 1
|
||||
|
||||
var/default_icon_state = "secbot"
|
||||
var/idcheck = FALSE // If true, arrests for having weapons without authorization.
|
||||
var/check_records = FALSE // If true, arrests people without a record.
|
||||
@@ -53,6 +55,8 @@
|
||||
name = "Officer Beepsky"
|
||||
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
|
||||
will_patrol = TRUE
|
||||
maxHealth = 130
|
||||
health = 130
|
||||
|
||||
/mob/living/bot/secbot/slime
|
||||
name = "Slime Securitron"
|
||||
@@ -70,6 +74,8 @@
|
||||
/mob/living/bot/secbot/slime/slimesky
|
||||
name = "Doctor Slimesky"
|
||||
desc = "An old friend of Officer Beep O'sky. He prescribes beatings to rowdy slimes so that real doctors don't need to treat the xenobiologists."
|
||||
maxHealth = 130
|
||||
health = 130
|
||||
|
||||
/mob/living/bot/secbot/update_icons()
|
||||
if(on && busy)
|
||||
@@ -233,6 +239,32 @@
|
||||
global_announcer.autosay("[src] is [action] a level [threat] [action != "fighting" ? "suspect" : "threat"] <b>[target_name(target)]</b> in <b>[get_area(src)]</b>.", "[src]", "Security")
|
||||
UnarmedAttack(target)
|
||||
|
||||
/mob/living/bot/secbot/handlePanic() // Speed modification based on alert level.
|
||||
. = 0
|
||||
switch(get_security_level())
|
||||
if("green")
|
||||
. = 0
|
||||
|
||||
if("yellow")
|
||||
. = 0
|
||||
|
||||
if("violet")
|
||||
. = 0
|
||||
|
||||
if("orange")
|
||||
. = 0
|
||||
|
||||
if("blue")
|
||||
. = 1
|
||||
|
||||
if("red")
|
||||
. = 2
|
||||
|
||||
if("delta")
|
||||
. = 2
|
||||
|
||||
return .
|
||||
|
||||
// So Beepsky talks while beating up simple mobs.
|
||||
/mob/living/bot/secbot/proc/insult(var/mob/living/L)
|
||||
if(can_next_insult > world.time)
|
||||
|
||||
@@ -747,7 +747,7 @@
|
||||
twitch_v, vomit, whimper, wink, yawn. Synthetics: beep, buzz, yes, no, rcough, rsneeze, ping")
|
||||
|
||||
else
|
||||
to_chat(src, "<font color='blue'>Unusable emote '[act]'. Say *help for a list.</font>")
|
||||
to_chat(src, "<font color='blue'>Unusable emote '[act]'. Say *help or *vhelp for a list.</font>") //VOREStation Edit, mention *vhelp for Virgo-specific emotes located in emote_vr.dm.
|
||||
|
||||
if (message)
|
||||
custom_emote(m_type,message)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
message = "peeps like a bird."
|
||||
m_type = 2
|
||||
playsound(loc, 'sound/voice/peep.ogg', 50, 1, -1)
|
||||
if("chirp")
|
||||
if ("chirp")
|
||||
message = "chirps!"
|
||||
playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0)
|
||||
m_type = 2
|
||||
@@ -55,6 +55,10 @@
|
||||
message = "lets out a hiss."
|
||||
m_type = 2
|
||||
playsound(loc, 'sound/voice/hiss.ogg', 50, 1, -1)
|
||||
if ("squeak")
|
||||
message = "lets out a squeak."
|
||||
m_type = 2
|
||||
playsound(loc, 'sound/effects/mouse_squeak.ogg', 50, 1, -1)
|
||||
if ("nsay")
|
||||
nsay()
|
||||
return TRUE
|
||||
@@ -75,6 +79,8 @@
|
||||
src.SpinAnimation(7,1)
|
||||
message = "does a flip!"
|
||||
m_type = 1
|
||||
if ("vhelp") //Help for Virgo-specific emotes.
|
||||
to_chat(src, "vwag, vflap, mlem, awoo, nya, peep, chirp, weh, merp, bark, hiss, squeak, nsay, nme, flip")
|
||||
|
||||
if (message)
|
||||
custom_emote(m_type,message)
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/shadekin)
|
||||
|
||||
language = LANGUAGE_SHADEKIN
|
||||
assisted_langs = list()
|
||||
name_language = LANGUAGE_SHADEKIN
|
||||
species_language = LANGUAGE_SHADEKIN
|
||||
secondary_langs = list(LANGUAGE_SHADEKIN)
|
||||
num_alternate_languages = 3
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/shadekin, /datum/unarmed_attack/bite/sharp/shadekin)
|
||||
rarity_value = 15 //INTERDIMENSIONAL FLUFFERS
|
||||
|
||||
@@ -51,6 +54,8 @@
|
||||
base_color = "#f0f0f0"
|
||||
color_mult = 1
|
||||
|
||||
inherent_verbs = list(/mob/living/proc/shred_limb)
|
||||
|
||||
has_glowing_eyes = TRUE
|
||||
|
||||
death_message = "phases to somewhere far away!"
|
||||
|
||||
@@ -426,6 +426,10 @@
|
||||
|
||||
// Called in life() when the mob has no client.
|
||||
/datum/species/proc/handle_npc(var/mob/living/carbon/human/H)
|
||||
if(H.stat == CONSCIOUS && H.ai_holder)
|
||||
if(H.resting)
|
||||
H.resting = FALSE
|
||||
H.update_canmove()
|
||||
return
|
||||
|
||||
// Called when lying down on a water tile.
|
||||
|
||||
@@ -50,8 +50,10 @@
|
||||
if(H)
|
||||
if(H.looksSynthetic())
|
||||
return "flashing a 'system offline' light"
|
||||
else
|
||||
else if(!H.ai_holder)
|
||||
return show_ssd
|
||||
else
|
||||
return
|
||||
|
||||
/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H)
|
||||
if(H)
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
if(prob(1))
|
||||
H.emote(pick("scratch","jump","roll","tail"))
|
||||
|
||||
..()
|
||||
|
||||
/datum/species/monkey/get_random_name()
|
||||
return "[lowertext(name)] ([rand(100,999)])"
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
// ai_inactive = TRUE //Always off //VORESTATION AI TEMPORARY REMOVAL
|
||||
show_stat_health = FALSE //We will do it ourselves
|
||||
|
||||
response_help = "pats the"
|
||||
response_disarm = "gently pushes aside the"
|
||||
response_harm = "hits the"
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 2
|
||||
melee_damage_lower = 10
|
||||
|
||||
@@ -412,6 +412,9 @@
|
||||
base_color = "#EECEB3"
|
||||
wikilink="https://www.yawn.ocry.com/Human"
|
||||
|
||||
/datum/species/human/vatgrown
|
||||
spawn_flags = SPECIES_IS_RESTRICTED
|
||||
|
||||
/datum/species/vox
|
||||
gluttonous = 0
|
||||
spawn_flags = SPECIES_CAN_JOIN
|
||||
@@ -462,5 +465,113 @@ datum/species/harpy
|
||||
"Your overheated skin itches."
|
||||
)
|
||||
|
||||
/datum/species/human/vatgrown
|
||||
spawn_flags = SPECIES_IS_RESTRICTED
|
||||
/datum/species/crew_shadekin
|
||||
name = SPECIES_SHADEKIN_CREW
|
||||
name_plural = "Black-Eyed Shadekin"
|
||||
icobase = 'icons/mob/human_races/r_shadekin_vr.dmi'
|
||||
deform = 'icons/mob/human_races/r_shadekin_vr.dmi'
|
||||
tail = "tail"
|
||||
icobase_tail = 1
|
||||
blurb = "Very little is known about these creatures. They appear to be largely mammalian in appearance. \
|
||||
Seemingly very rare to encounter, there have been widespread myths of these creatures the galaxy over, \
|
||||
but next to no verifiable evidence to their existence. However, they have recently been more verifiably \
|
||||
documented in the Virgo system, following a mining bombardment of Virgo 3. The crew of NSB Adephagia have \
|
||||
taken to calling these creatures 'Shadekin', and the name has generally stuck and spread. " //TODO: Something more fitting for black-eyes
|
||||
wikilink = "https://wiki.vore-station.net/Shadekin"
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/shadekin)
|
||||
|
||||
language = LANGUAGE_SHADEKIN
|
||||
name_language = LANGUAGE_SHADEKIN
|
||||
species_language = LANGUAGE_SHADEKIN
|
||||
secondary_langs = list(LANGUAGE_SHADEKIN)
|
||||
num_alternate_languages = 3
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp)
|
||||
rarity_value = 5 //INTERDIMENSIONAL FLUFFERS
|
||||
|
||||
siemens_coefficient = 0
|
||||
darksight = 10
|
||||
|
||||
slowdown = 0.5
|
||||
item_slowdown_mod = 1.5
|
||||
|
||||
total_health = 75
|
||||
brute_mod = 1.25 // Frail
|
||||
burn_mod = 1.25 // Furry
|
||||
blood_volume = 500
|
||||
hunger_factor = 0.2
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = -1
|
||||
|
||||
warning_high_pressure = 300
|
||||
hazard_high_pressure = INFINITY
|
||||
|
||||
cold_level_1 = -1 //Immune to cold
|
||||
cold_level_2 = -1
|
||||
cold_level_3 = -1
|
||||
|
||||
heat_level_1 = 850 //Resistant to heat
|
||||
heat_level_2 = 1000
|
||||
heat_level_3 = 1150
|
||||
|
||||
flags = NO_SCAN
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE
|
||||
|
||||
reagent_tag = IS_SHADEKIN // for shadekin-unqiue chem interactions
|
||||
|
||||
flesh_color = "#FFC896"
|
||||
blood_color = "#A10808"
|
||||
base_color = "#f0f0f0"
|
||||
color_mult = 1
|
||||
|
||||
inherent_verbs = list(/mob/living/proc/shred_limb)
|
||||
|
||||
has_glowing_eyes = TRUE
|
||||
|
||||
male_cough_sounds = null
|
||||
female_cough_sounds = null
|
||||
male_sneeze_sound = null
|
||||
female_sneeze_sound = null
|
||||
|
||||
speech_bubble_appearance = "ghost"
|
||||
|
||||
genders = list(PLURAL, NEUTER) //no sexual dymorphism
|
||||
ambiguous_genders = TRUE //but just in case
|
||||
|
||||
breath_type = null
|
||||
poison_type = null
|
||||
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_SKIN_COLOR | HAS_UNDERWEAR
|
||||
|
||||
move_trail = /obj/effect/decal/cleanable/blood/tracks/paw
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_VOICE = /obj/item/organ/internal/voicebox,
|
||||
O_LIVER = /obj/item/organ/internal/liver,
|
||||
O_KIDNEYS = /obj/item/organ/internal/kidneys,
|
||||
O_BRAIN = /obj/item/organ/internal/brain,
|
||||
O_EYES = /obj/item/organ/internal/eyes,
|
||||
O_STOMACH = /obj/item/organ/internal/stomach,
|
||||
O_INTESTINE = /obj/item/organ/internal/intestine
|
||||
)
|
||||
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest/crewkin),
|
||||
BP_GROIN = list("path" = /obj/item/organ/external/groin/crewkin),
|
||||
BP_HEAD = list("path" = /obj/item/organ/external/head/vr/crewkin),
|
||||
BP_L_ARM = list("path" = /obj/item/organ/external/arm/crewkin),
|
||||
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/crewkin),
|
||||
BP_L_LEG = list("path" = /obj/item/organ/external/leg/crewkin),
|
||||
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/crewkin),
|
||||
BP_L_HAND = list("path" = /obj/item/organ/external/hand/crewkin),
|
||||
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/crewkin),
|
||||
BP_L_FOOT = list("path" = /obj/item/organ/external/foot/crewkin),
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/crewkin)
|
||||
)
|
||||
|
||||
/datum/species/shadekin/get_bodytype()
|
||||
return SPECIES_SHADEKIN
|
||||
|
||||
/datum/species/shadekin/can_breathe_water()
|
||||
return TRUE //they dont quite breathe
|
||||
@@ -35,9 +35,14 @@
|
||||
"Fox" = "pai-fox",
|
||||
"Parrot" = "pai-parrot",
|
||||
"Rabbit" = "pai-rabbit",
|
||||
"Bear" = "pai-bear", //VOREStation Edit
|
||||
"Fennec" = "pai-fen", // VOREStation Edit - Rykka
|
||||
"Fennec" = "pai-typezero" //VOREStation Edit
|
||||
//VOREStation Addition Start
|
||||
"Bear" = "pai-bear",
|
||||
"Fennec" = "pai-fen",
|
||||
"Type Zero" = "pai-typezero",
|
||||
"Raccoon" = "pai-raccoon",
|
||||
"Rat" = "rat",
|
||||
"Panther" = "panther"
|
||||
//VOREStation Addition End
|
||||
)
|
||||
|
||||
var/global/list/possible_say_verbs = list(
|
||||
@@ -46,7 +51,8 @@
|
||||
"Beep" = list("beeps","beeps loudly","boops"),
|
||||
"Chirp" = list("chirps","chirrups","cheeps"),
|
||||
"Feline" = list("purrs","yowls","meows"),
|
||||
"Canine" = list("yaps","barks","woofs")
|
||||
"Canine" = list("yaps","barks","woofs"),
|
||||
"Rodent" = list("squeaks", "SQUEAKS", "sqiks") //VOREStation Edit - TFF 22/11/19 - CHOMPStation port of pAI additions,
|
||||
)
|
||||
|
||||
var/obj/item/weapon/pai_cable/cable // The cable we produce and use when door or camera jacking
|
||||
@@ -320,6 +326,8 @@
|
||||
|
||||
close_up()
|
||||
|
||||
//VOREStation Removal Start - TFF 22/11/19 - Refactored in pai_vr.dm
|
||||
/*
|
||||
/mob/living/silicon/pai/proc/choose_chassis()
|
||||
set category = "pAI Commands"
|
||||
set name = "Choose Chassis"
|
||||
@@ -336,6 +344,8 @@
|
||||
|
||||
chassis = possible_chassis[choice]
|
||||
verbs |= /mob/living/proc/hide
|
||||
//VOREStation Removal End
|
||||
*/
|
||||
|
||||
/mob/living/silicon/pai/proc/choose_verbs()
|
||||
set category = "pAI Commands"
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/mob/living/silicon/pai
|
||||
var/people_eaten = 0
|
||||
icon = 'icons/mob/pai_vr.dmi'
|
||||
//TFF 22/11/19 - CHOMPStation port of pAI additions.
|
||||
var/global/list/wide_chassis = list(
|
||||
"rat",
|
||||
"panther"
|
||||
)
|
||||
|
||||
/mob/living/silicon/pai/proc/pai_nom(var/mob/living/T in oview(1))
|
||||
set name = "pAI Nom"
|
||||
@@ -31,6 +36,14 @@
|
||||
else if(people_eaten && resting)
|
||||
icon_state = "[chassis]_rest_full"
|
||||
|
||||
//TFF 22/11/19 - CHOMPStation port of pAI additions.
|
||||
if(chassis in wide_chassis)
|
||||
icon = 'icons/mob/pai_vr64x64.dmi'
|
||||
pixel_x = -16
|
||||
else
|
||||
icon = 'icons/mob/pai_vr.dmi'
|
||||
pixel_x = 0
|
||||
|
||||
/mob/living/silicon/pai/update_icons() //And other functions cause this to occur, such as digesting someone.
|
||||
..()
|
||||
update_fullness_pai()
|
||||
@@ -42,3 +55,22 @@
|
||||
icon_state = "[chassis]_full"
|
||||
else if(people_eaten && resting)
|
||||
icon_state = "[chassis]_rest_full"
|
||||
|
||||
//TFF 22/11/19 - CHOMPStation port of pAI additions.
|
||||
if(chassis in wide_chassis)
|
||||
icon = 'icons/mob/pai_vr64x64.dmi'
|
||||
pixel_x = -16
|
||||
else
|
||||
icon = 'icons/mob/pai_vr.dmi'
|
||||
pixel_x = 0
|
||||
//proc override to avoid pAI players being invisible while the chassis selection window is open
|
||||
/mob/living/silicon/pai/proc/choose_chassis()
|
||||
set category = "pAI Commands"
|
||||
set name = "Choose Chassis"
|
||||
var/choice
|
||||
|
||||
choice = input(usr,"What would you like to use for your mobile chassis icon?") as null|anything in possible_chassis
|
||||
if(!choice) return
|
||||
chassis = possible_chassis[choice]
|
||||
verbs |= /mob/living/proc/hide
|
||||
update_icon()
|
||||
|
||||
@@ -60,6 +60,8 @@ var/list/mob_hat_cache = list()
|
||||
var/serial_number = 0
|
||||
var/name_override = 0
|
||||
|
||||
var/foreign_droid = FALSE
|
||||
|
||||
holder_type = /obj/item/weapon/holder/drone
|
||||
|
||||
can_be_antagged = FALSE
|
||||
@@ -117,7 +119,8 @@ var/list/mob_hat_cache = list()
|
||||
updatename()
|
||||
|
||||
/mob/living/silicon/robot/drone/init()
|
||||
aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src)
|
||||
if(!scrambledcodes && !foreign_droid)
|
||||
aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src)
|
||||
additional_law_channels["Drone"] = ":d"
|
||||
if(!laws) laws = new law_type
|
||||
if(!module) module = new module_type(src)
|
||||
@@ -252,10 +255,10 @@ var/list/mob_hat_cache = list()
|
||||
//For some goddamn reason robots have this hardcoded. Redefining it for our fragile friends here.
|
||||
/mob/living/silicon/robot/drone/updatehealth()
|
||||
if(status_flags & GODMODE)
|
||||
health = 35
|
||||
health = maxHealth
|
||||
stat = CONSCIOUS
|
||||
return
|
||||
health = 35 - (getBruteLoss() + getFireLoss())
|
||||
health = maxHealth - (getBruteLoss() + getFireLoss())
|
||||
return
|
||||
|
||||
//Easiest to check this here, then check again in the robot proc.
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
for(var/mob/living/silicon/robot/drone/D in mob_list)
|
||||
if(D.z != src.z)
|
||||
continue
|
||||
if(D.foreign_droid)
|
||||
continue
|
||||
|
||||
dat += "<BR>[D.real_name] ([D.stat == 2 ? "<font color='red'>INACTIVE</FONT>" : "<font color='green'>ACTIVE</FONT>"])"
|
||||
dat += "<font dize = 9><BR>Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
|
||||
dat += "<BR>Currently located in: [get_area(D)]."
|
||||
|
||||
@@ -56,6 +56,22 @@
|
||||
/obj/item/weapon/stock_parts
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/security
|
||||
name = "security gripper"
|
||||
desc = "A simple grasping tool for corporate security work."
|
||||
icon_state = "gripper-sec"
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/paper,
|
||||
/obj/item/weapon/paper_bundle,
|
||||
/obj/item/weapon/pen,
|
||||
/obj/item/weapon/sample,
|
||||
/obj/item/weapon/forensics/sample_kit,
|
||||
/obj/item/device/taperecorder,
|
||||
/obj/item/device/tape,
|
||||
/obj/item/device/uv_light
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/paperwork
|
||||
name = "paperwork gripper"
|
||||
desc = "A simple grasping tool for clerical work."
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
/obj/machinery/drone_fabricator/examine(mob/user)
|
||||
..(user)
|
||||
if(produce_drones && drone_progress >= 100 && istype(user,/mob/observer/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
user << "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
|
||||
to_chat(user, "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>")
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
|
||||
|
||||
@@ -113,14 +113,14 @@
|
||||
return 0 //something is terribly wrong
|
||||
|
||||
if(jobban_isbanned(src,"Cyborg"))
|
||||
usr << "<span class='danger'>You are banned from playing synthetics and cannot spawn as a drone.</span>"
|
||||
to_chat(usr, "<span class='danger'>You are banned from playing synthetics and cannot spawn as a drone.</span>")
|
||||
return
|
||||
|
||||
if(!MayRespawn(1))
|
||||
return
|
||||
|
||||
var/deathtime = world.time - src.timeofdeath
|
||||
var/deathtimeminutes = round(deathtime / 600)
|
||||
var/deathtimeminutes = round(deathtime / (1 MINUTE))
|
||||
var/pluralcheck = "minute"
|
||||
if(deathtimeminutes == 0)
|
||||
pluralcheck = ""
|
||||
@@ -128,11 +128,11 @@
|
||||
pluralcheck = " [deathtimeminutes] minute and"
|
||||
else if(deathtimeminutes > 1)
|
||||
pluralcheck = " [deathtimeminutes] minutes and"
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10,1)
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 1 MINUTE) / 10,1)
|
||||
|
||||
if (deathtime < 6000)
|
||||
usr << "You have been dead for[pluralcheck] [deathtimeseconds] seconds."
|
||||
usr << "You must wait 10 minutes to respawn as a drone!"
|
||||
if (deathtime < 5 MINUTES)
|
||||
to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.")
|
||||
to_chat(usr, "You must wait 5 minutes to respawn as a drone!")
|
||||
return
|
||||
|
||||
var/list/all_fabricators = list()
|
||||
|
||||
98
code/modules/mob/living/silicon/robot/drone/swarm.dm
Normal file
98
code/modules/mob/living/silicon/robot/drone/swarm.dm
Normal file
@@ -0,0 +1,98 @@
|
||||
/mob/living/silicon/robot/drone/swarm
|
||||
name = "swarm drone"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "swarmer"
|
||||
faction = "swarmer"
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
cell_emp_mult = 0.5
|
||||
universal_speak = 0
|
||||
universal_understand = 1
|
||||
gender = NEUTER
|
||||
pass_flags = PASSTABLE
|
||||
braintype = "Drone"
|
||||
lawupdate = 0
|
||||
density = 1
|
||||
idcard_type = /obj/item/weapon/card/id/syndicate
|
||||
req_access = list(999)
|
||||
integrated_light_power = 3
|
||||
local_transmit = 0
|
||||
|
||||
can_pull_size = ITEMSIZE_NO_CONTAINER
|
||||
can_pull_mobs = MOB_PULL_SMALLER
|
||||
can_enter_vent_with = list(
|
||||
/obj)
|
||||
|
||||
mob_always_swap = 1
|
||||
|
||||
softfall = TRUE
|
||||
|
||||
mob_size = MOB_LARGE
|
||||
|
||||
law_type = /datum/ai_laws/swarm_drone
|
||||
module_type = /obj/item/weapon/robot_module/drone/swarm
|
||||
|
||||
hat_x_offset = 0
|
||||
hat_y_offset = -10
|
||||
|
||||
foreign_droid = TRUE
|
||||
scrambledcodes = TRUE
|
||||
|
||||
holder_type = /obj/item/weapon/holder/drone
|
||||
|
||||
can_be_antagged = TRUE
|
||||
|
||||
var/spell_setup = list(
|
||||
/spell/aoe_turf/conjure/swarmer,
|
||||
/spell/aoe_turf/conjure/forcewall/swarm,
|
||||
/spell/aoe_turf/blink/swarm,
|
||||
/spell/aoe_turf/conjure/swarmer/gunner,
|
||||
/spell/aoe_turf/conjure/swarmer/melee
|
||||
)
|
||||
|
||||
/mob/living/silicon/robot/drone/swarm/Initialize()
|
||||
..()
|
||||
|
||||
add_language(LANGUAGE_SWARMBOT, 1)
|
||||
|
||||
for(var/spell in spell_setup)
|
||||
src.add_spell(new spell, "nano_spell_ready", /obj/screen/movable/spell_master/swarm)
|
||||
|
||||
/mob/living/silicon/robot/drone/swarm/init()
|
||||
..()
|
||||
QDEL_NULL(aiCamera)
|
||||
flavor_text = "Some form of ancient machine."
|
||||
|
||||
/mob/living/silicon/robot/drone/swarm/gunner
|
||||
name = "swarm gunner"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "swarmer_ranged"
|
||||
faction = "swarmer"
|
||||
|
||||
law_type = /datum/ai_laws/swarm_drone/soldier
|
||||
module_type = /obj/item/weapon/robot_module/drone/swarm/ranged
|
||||
|
||||
spell_setup = list(
|
||||
/spell/aoe_turf/conjure/swarmer,
|
||||
/spell/aoe_turf/conjure/forcewall/swarm,
|
||||
/spell/aoe_turf/blink/swarm
|
||||
)
|
||||
|
||||
/mob/living/silicon/robot/drone/swarm/melee
|
||||
name = "swarm melee"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "swarmer_melee"
|
||||
faction = "swarmer"
|
||||
|
||||
law_type = /datum/ai_laws/swarm_drone/soldier
|
||||
module_type = /obj/item/weapon/robot_module/drone/swarm/melee
|
||||
|
||||
spell_setup = list(
|
||||
/spell/aoe_turf/conjure/swarmer,
|
||||
/spell/aoe_turf/conjure/forcewall/swarm,
|
||||
/spell/aoe_turf/blink/swarm
|
||||
)
|
||||
|
||||
117
code/modules/mob/living/silicon/robot/drone/swarm_abilities.dm
Normal file
117
code/modules/mob/living/silicon/robot/drone/swarm_abilities.dm
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
/spell/aoe_turf/conjure/swarmer
|
||||
name = "Self Replication"
|
||||
desc = "This ability constructs a standard swarmer shell that may activate at some point."
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 120 SECONDS
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event)
|
||||
|
||||
hud_state = "swarm_replicate"
|
||||
|
||||
/spell/aoe_turf/conjure/swarmer/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
|
||||
animation.icon_state = "deflect_static"
|
||||
flick("shield2",animation)
|
||||
spawn(1 SECOND)
|
||||
qdel(animation)
|
||||
|
||||
/spell/aoe_turf/conjure/forcewall/swarm
|
||||
name = "Null-Field"
|
||||
desc = "Create a bubble of null-point energy."
|
||||
summon_type = list(/obj/effect/forcefield/swarm)
|
||||
duration = 30 SECONDS
|
||||
charge_max = 60 SECONDS
|
||||
|
||||
school = "conjuration"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
hud_state = "wiz_shield"
|
||||
|
||||
/obj/effect/forcefield/swarm
|
||||
desc = "A pocket of strange energy."
|
||||
name = "Null-Field"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "shield-old"
|
||||
invisibility = 0
|
||||
|
||||
/spell/aoe_turf/conjure/zeropointwell
|
||||
name = "Zero-Point Well"
|
||||
desc = "This ability constructs a standard zero-point energy well, capable of charging nearby swarmers."
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 120 SECONDS
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/cult/pylon/swarm/zp_well)
|
||||
|
||||
hud_state = "swarm_zeropoint"
|
||||
|
||||
/spell/aoe_turf/conjure/zeropointbarricade
|
||||
name = "Zero-Point Barricade"
|
||||
desc = "This ability constructs a standard zero-point energy wall, used to create a secure passageway for allies, and a bastion for defense."
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 120 SECONDS
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/cult/pylon/swarm/defender)
|
||||
|
||||
hud_state = "swarm_barricade"
|
||||
|
||||
/spell/aoe_turf/blink/swarm
|
||||
name = "Warp"
|
||||
desc = "Your null-point drive jaunts you to a new location."
|
||||
|
||||
school = "abjuration"
|
||||
charge_max = 5 MINUTES
|
||||
spell_flags = Z2NOCAST | IGNOREDENSE
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 10
|
||||
inner_radius = 5
|
||||
hud_state = "swarm_warp"
|
||||
|
||||
/spell/aoe_turf/conjure/swarmer/gunner
|
||||
name = "Generate Gunner"
|
||||
desc = "This spell constructs a gunner swarmer shell that may activate at some point."
|
||||
|
||||
school = "conjuration"
|
||||
charge_type = Sp_CHARGES
|
||||
charge_max = 1
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/gunner)
|
||||
|
||||
hud_state = "swarm_replicate"
|
||||
|
||||
/spell/aoe_turf/conjure/swarmer/melee
|
||||
name = "Generate Impaler"
|
||||
desc = "This spell constructs an impaler swarmer shell that may activate at some point."
|
||||
|
||||
school = "conjuration"
|
||||
charge_type = Sp_CHARGES
|
||||
charge_max = 1
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/melee)
|
||||
|
||||
hud_state = "swarm_replicate"
|
||||
162
code/modules/mob/living/silicon/robot/drone/swarm_items.dm
Normal file
162
code/modules/mob/living/silicon/robot/drone/swarm_items.dm
Normal file
@@ -0,0 +1,162 @@
|
||||
|
||||
//Swarm Assimilator / Breacher
|
||||
/obj/item/weapon/matter_decompiler/swarm
|
||||
name = "matter assimilator"
|
||||
desc = "Used to eat some forms of simple machinery; and large, wall-shaped blocks of metal with energetic fields."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "decompiler_swarm"
|
||||
|
||||
var/field_cooldown = 1 MINUTE
|
||||
var/last_field = 0
|
||||
|
||||
/obj/item/weapon/matter_decompiler/swarm/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
|
||||
|
||||
if(!proximity) return //Not adjacent.
|
||||
|
||||
//We only want to deal with using this on turfs. Specific items aren't important.
|
||||
var/turf/T = get_turf(target)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
//Used to give the right message.
|
||||
var/grabbed_something = FALSE
|
||||
|
||||
for(var/mob/M in T)
|
||||
if(istype(M,/mob/living/simple_mob/animal/passive/lizard) || istype(M,/mob/living/simple_mob/animal/passive/mouse))
|
||||
src.loc.visible_message("<span class='danger'>[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.</span>","<span class='danger'>It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.</span>")
|
||||
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
|
||||
qdel(M)
|
||||
if(wood)
|
||||
wood.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(2000)
|
||||
return
|
||||
|
||||
else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
|
||||
|
||||
var/mob/living/silicon/robot/D = src.loc
|
||||
|
||||
if(!istype(D))
|
||||
return
|
||||
|
||||
to_chat(D, "<span class='danger'>You begin decompiling [M].</span>")
|
||||
|
||||
if(!do_after(D,50))
|
||||
to_chat(D, "<span class='danger'>You need to remain still while decompiling such a large object.</span>")
|
||||
return
|
||||
|
||||
if(!M || !D) return
|
||||
|
||||
to_chat(D, "<span class='danger'>You carefully and thoroughly decompile [M], storing as much of its resources as you can within yourself.</span>")
|
||||
qdel(M)
|
||||
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
|
||||
|
||||
if(metal)
|
||||
metal.add_charge(15000)
|
||||
if(glass)
|
||||
glass.add_charge(15000)
|
||||
if(wood)
|
||||
wood.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(1000)
|
||||
return
|
||||
else
|
||||
continue
|
||||
|
||||
for(var/obj/W in T)
|
||||
//Different classes of items give different commodities.
|
||||
if(istype(W,/obj/structure/girder))
|
||||
if(metal)
|
||||
metal.add_charge(500)
|
||||
else if(istype(W,/obj/machinery/power/emitter))
|
||||
if(metal)
|
||||
metal.add_charge(3000)
|
||||
if(plastic)
|
||||
plastic.add_charge(1000)
|
||||
else if(istype(W,/obj/machinery/space_heater))
|
||||
if(metal)
|
||||
metal.add_charge(1500)
|
||||
if(plastic)
|
||||
plastic.add_charge(750)
|
||||
else if(istype(W,/obj/structure/closet))
|
||||
var/obj/structure/closet/C = W
|
||||
if(!C.opened)
|
||||
continue
|
||||
if(istype(W,/obj/structure/closet/coffin))
|
||||
if(wood)
|
||||
wood.add_charge(1000)
|
||||
else if(istype(W,/obj/structure/closet/crate/plastic))
|
||||
if(plastic)
|
||||
plastic.add_charge(750)
|
||||
else
|
||||
if(metal)
|
||||
metal.add_charge(1000)
|
||||
else
|
||||
continue
|
||||
|
||||
qdel(W)
|
||||
grabbed_something = TRUE
|
||||
|
||||
if(istype(T,/turf/simulated/wall) && (last_field < world.time + field_cooldown))
|
||||
if(!(locate(/obj/effect/temporary_effect/pulse/disintegrate)))
|
||||
last_field = world.time
|
||||
to_chat(user, "<span class='alien'>You deploy an energetic field through \the [T], beginning its deconstruction.</span>")
|
||||
to_chat(user, "<span class='warning'>You should stand back.</span>")
|
||||
new /obj/effect/temporary_effect/pulse/disintegrate(T)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There is already a disintigration field affecting \the [T].</span>")
|
||||
|
||||
if(grabbed_something)
|
||||
to_chat(user, "<span class='notice'>You deploy your decompiler and clear out the contents of \the [T].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Nothing on \the [T] is useful to you.</span>")
|
||||
return
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate
|
||||
name = "molecular debonding field"
|
||||
desc = "This is something you do not want to near."
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "disintegrate_pulse"
|
||||
light_range = 4
|
||||
light_power = 5
|
||||
light_color = "#00B4D9"
|
||||
pulses_remaining = 5
|
||||
pulse_delay = 2 SECONDS
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate/emp_act()
|
||||
visible_message("<span class='warning'>\The [src] flickers, before dispersing energetically.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate/on_pulse()
|
||||
var/turf/T = get_turf(src)
|
||||
if(istype(T,/turf/simulated/wall))
|
||||
explosion(get_turf(src), -1, -1, 1, 3, adminlog = 0)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate/Destroy()
|
||||
if(istype(get_turf(src), /turf/simulated/wall))
|
||||
explosion(get_turf(src), -1, 1, 2, 5, adminlog = 1)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/energy/xray/swarm
|
||||
name = "spectral projector"
|
||||
desc = "A high-power laser gun capable of expelling concentrated gamma blasts, which are able to penetrate matter easier than \
|
||||
standard xray beams, resulting in an effective 'anti-everything' energy weapon."
|
||||
icon_state = "xray"
|
||||
item_state = "xray"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 3, TECH_MAGNET = 2)
|
||||
projectile_type = /obj/item/projectile/beam/shock
|
||||
charge_cost = 175
|
||||
|
||||
self_recharge = TRUE
|
||||
use_external_power = TRUE
|
||||
|
||||
firemodes = list(
|
||||
list(mode_name="kill", projectile_type=/obj/item/projectile/beam/gamma, charge_cost = 300),
|
||||
list(mode_name="deter", projectile_type=/obj/item/projectile/beam/shock, charge_cost = 175),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/energy/xray/swarm/Initialize()
|
||||
..()
|
||||
adjust_scale(-1, 1)
|
||||
@@ -529,6 +529,7 @@ var/global/list/robot_modules = list(
|
||||
// src.modules += new /obj/item/weapon/gun/energy/taser/xeno/sec/robot(src) // VOREStation Edit - We don't need these
|
||||
src.modules += new /obj/item/taperoll/police(src)
|
||||
src.modules += new /obj/item/weapon/reagent_containers/spray/pepper(src)
|
||||
src.modules += new /obj/item/weapon/gripper/security(src)
|
||||
src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src)
|
||||
|
||||
/obj/item/weapon/robot_module/robot/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user