Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Hawk_v3
2019-12-08 18:15:35 +00:00
214 changed files with 52675 additions and 16169 deletions

View File

@@ -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()

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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.

View File

@@ -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//
/////////////////////////////////////////

View File

@@ -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)

View File

@@ -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."

View File

@@ -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. \

View File

@@ -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(

View File

@@ -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

View 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

View File

@@ -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"

View File

@@ -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

View File

@@ -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."

View File

@@ -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

View File

@@ -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"]

View File

@@ -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

View File

@@ -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,10 +764,12 @@
/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"
desc = "A softdrink vendor provided by Robust Industries, LLC."
@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -43,4 +43,171 @@
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."
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."

View File

@@ -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."

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View 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"

View File

@@ -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."

View File

@@ -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

View File

@@ -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"

View File

@@ -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.
*/

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -83,4 +83,13 @@
to_chat(user, "<span class='warning'>Another spirit appears to have gotten to \the [src] before you. Sorry.</span>")
return
create_occupant(user)
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)

View 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>")

View File

@@ -58,4 +58,50 @@
R.ckey = M.ckey
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

View 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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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
@@ -887,7 +890,7 @@
character_name = list("Chakat Tempest Venosare")
allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Psychiatrist","Paramedic", "Field Medic")
slot = slot_glasses
/datum/gear/fluff/tempest_hypospray
path = /obj/item/weapon/reagent_containers/hypospray/vial/tempest
display_name = "Tempest's Hypospray"
@@ -895,14 +898,14 @@
character_name = list("Chakat Tempest Venosare")
allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Psychiatrist","Paramedic", "Field Medic")
slot = slot_belt
/datum/gear/fluff/tempest_backpack
path = /obj/item/weapon/storage/backpack/saddlebag/tempest
display_name = "Tempest's Saddlebag"
ckeywhitelist = list("wickedtemp")
character_name = list("Chakat Tempest Venosare")
slot = slot_back
/datum/gear/fluff/tempest_implant
path = /obj/item/weapon/implanter/reagent_generator/tempest
display_name = "Tempest's Implant"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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()

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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."

View File

@@ -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
//////////////

View File

@@ -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

View File

@@ -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>"

View 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'>&nbsp;&nbsp;&nbsp;&nbsp;[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'>&nbsp;&nbsp;&nbsp;&nbsp;[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

View File

@@ -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)

View 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)

View File

@@ -14,4 +14,4 @@
/datum/gm_action/dust/start()
..()
dust_swarm("norm")
dust_swarm("norm")

View 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

View File

@@ -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

View 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

View File

@@ -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.")
message_admins("Meteor defense event has ended.")

View 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)

View File

@@ -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")

View 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

View 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.")

View 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

View 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)

View 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.")

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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!"

View File

@@ -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.

View File

@@ -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)

View File

@@ -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)])"

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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()

View File

@@ -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.

View File

@@ -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)]."

View File

@@ -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."

View File

@@ -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()

View 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
)

View 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"

View 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)

Some files were not shown because too many files have changed in this diff Show More