Security / PseudoCargo Expansion

This commit is contained in:
Mechoid
2019-11-24 14:22:25 -08:00
committed by VirgoBot
parent b34f14b3cc
commit 99bc3dcdbc
83 changed files with 2722 additions and 67 deletions

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

@@ -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 = FALSE // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable.
var/give_free_ai_shell = FALSE // 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(
@@ -85,7 +234,25 @@
containertype = /obj/structure/closet/crate/secure/gear
containername = "Ballistic armor crate"
access = access_armory
<<<<<<< HEAD
/* 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
>>>>>>> 7ecdcb4... Security / PseudoCargo Expansion (#6482)
/datum/supply_pack/security/combat_armor
name = "Armor - Combat"
contains = list(
@@ -209,13 +376,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 +578,16 @@
containertype = /obj/structure/closet/crate/secure
containername = "Security biohazard gear"
access = access_security
<<<<<<< HEAD
=======
/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
>>>>>>> 7ecdcb4... Security / PseudoCargo Expansion (#6482)

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

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

@@ -12,10 +12,12 @@
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(!serial_number)
if(given_serial == 0)
serial_number = rand(1, poster_designs.len)
else
@@ -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,16 +99,23 @@
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
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)
pixel_x = 0
@@ -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

@@ -44,3 +44,170 @@
desc = "This poster appears to be reference material for maintenance personnel, instructing to always wear insulated gloves, that wirecutters and \
a multitool are the optimal tools to use, and where to find the maintenance panel on most airlocks. Unfortunately, the poster does not mention any \
wire codes."
/datum/poster/pol_10
icon_state="polposter9"
name = "orchid"
desc = "This poster appears strangely familiar, depicting the flower of a tree native to the planet Earth."
// A new subset of poster datum for Security posters.
/datum/poster/nanotrasen
icon_state = "polposter1"
name = "Safety!"
desc = "A poster advising you to learn how to put on your internals at a moment's notice."
/datum/poster/nanotrasen/pol_2
icon_state="polposter2"
name = "Safety!"
desc = "A blue and white colored poster. This one advises you to wear your safety goggles when handling chemicals."
/datum/poster/nanotrasen/pol_3
icon_state="polposter3"
name = "Safety!"
desc = "A safety poster instructing you to comply with the authorities, especially in an emergency."
/datum/poster/nanotrasen/pol_4
icon_state="polposter4"
name = "Clean Hands Save Lives"
desc = "A safety poster reminding you to wash your hands."
/datum/poster/nanotrasen/pol_5
icon_state="polposter5"
name = "Help!"
desc = "This poster depicts a man helping another man get up."
/datum/poster/nanotrasen/pol_6
icon_state="polposter6"
name = "Walk!"
desc = "This poster depicts a man walking, presumably to encourage you not to run in the halls."
/datum/poster/nanotrasen/pol_7
icon_state="polposter7"
name = "Place your signs!"
desc = "A safety poster reminding custodial staff to place wet floor signs where needed. This reminder's rarely heeded."
/datum/poster/nanotrasen/pol_8
icon_state="polposter8"
name = "Safety!"
desc = "An advertisement / safety poster for EVA training and certification. Training is available at your local Central Command."
/datum/poster/nanotrasen/pol_9
icon_state="poster10"
name = "Airlock Maintenance Reference"
desc = "This poster appears to be reference material for maintenance personnel, instructing to always wear insulated gloves, that wirecutters and \
a multitool are the optimal tools to use, and where to find the maintenance panel on most airlocks. Unfortunately, the poster does not mention any \
wire codes."
/datum/poster/nanotrasen/pol_10
icon_state="polposter9"
name = "orchid"
desc = "This poster suggests a feeling of peace. It depicts the flower of a tree native to the planet Earth."
/datum/poster/nanotrasen/bay_9
icon_state="bsposter9"
name = "Pinup Girl Amy"
desc = "This particular one is of Amy, the nymphomaniac urban legend of deep space. How this photograph came to be is not known."
/datum/poster/nanotrasen/bay_21
icon_state="bsposter21"
name = "Join the Fuzz!"
desc = "It's a nice recruitment poster of a white haired Chinese woman that says; \"Big Guns, Hot Women, Good Times. Security. We get it done.\""
/datum/poster/nanotrasen/bay_22
icon_state="bsposter22"
name = "Looking for a career with excitement?"
desc = "A recruitment poster starring a dark haired woman with glasses and a purple shirt that has \"Got Brains? Got Talent? Not afraid of electric flying monsters that want to suck the soul out of you? Then Xenobiology could use someone like you!\" written on the bottom."
/datum/poster/nanotrasen/bay_23
icon_state="bsposter23"
name = "Safety first: because electricity doesn't wait!"
desc = "A safety poster starring a clueless looking redhead with frazzled hair. \"Every year, hundreds of NT employees expose themselves to electric shock. Play it safe. Avoid suspicious doors after electrical storms, and always wear protection when doing electric maintenance.\""
/datum/poster/nanotrasen/bay_24
icon_state="bsposter24"
name = "Responsible medbay habits, No #259"
desc = "A poster with a nervous looking geneticist on it states; \"Friends Tell Friends They're Clones. It can cause severe and irreparable emotional trauma if a person is not properly informed of their recent demise. Always follow your contractual obligation and inform them of their recent rejuvenation.\""
/datum/poster/nanotrasen/bay_25
icon_state="bsposter25"
name = "Irresponsible medbay habits, No #2"
desc = "This is a safety poster starring a perverted looking naked doctor. \"Sexual harassment is never okay. REPORT any acts of sexual deviance or harassment that disrupt a healthy working environment.\""
/datum/poster/nanotrasen/bay_49
icon_state="bsposter49"
name = "Engineering recruitment"
desc = "This is a poster showing an engineer relaxing by a computer, the text states \"Living the life! Join Engineering today!\""
/datum/poster/nanotrasen/bay_52
icon_state="bsposter52"
name = "fire safety poster"
desc = "This is a poster reminding you of what you should do if you are on fire, or if you are at a dance party."
/datum/poster/nanotrasen/bay_53
icon_state="bsposter53"
name = "fire extinguisher poster"
desc = "This is a poster reminding you of what you should use to put out a fire."
/datum/poster/nanotrasen/bay_54
icon_state="bsposter54"
name = "firefighter poster"
desc = "This is a poster of a particularly stern looking firefighter. The caption reads, \"Only you can prevent space fires.\""
/datum/poster/nanotrasen/bay_57
icon_state="bsposter57"
name = "space carp warning poster"
desc = "This poster tells of the dangers of space carp infestations."
/datum/poster/nanotrasen/bay_58
icon_state="bsposter58"
name = "space carp information poster"
desc = "This poster showcases an old spacer saying on the dangers of migrant space carp."
/datum/poster/nanotrasen/nt_1
icon_state = "ntposter01"
name = "Security recruitment"
desc = "This poster showcases an NT security guard in an excited pose, with a small blurb about the importance of Security."
/datum/poster/nanotrasen/nt_2
icon_state = "ntposter02"
name = "Security recruitment"
desc = "This poster showcases an NT security guard in an excited pose, with a small blurb about Security Employee benefits."
/datum/poster/nanotrasen/nt_3
icon_state = "ntposter03"
name = "Mechatronic Safety"
desc = "This poster displays three cutting-edge gygaxes standing in line in front of a man in plain clothes.\
The poster's captions explain the importance of knowing how to operate a mechatronic vehicle safely, especially near other personnel.\
The image seems important."
/datum/poster/nanotrasen/nt_4
icon_state = "ntposter04"
name = "Beware Aetotheans"
desc = "This poster displays a distinctly hostile-looking red Promethean in a black coat. The fine-print around the edges warns the reader about the dangers posed by Almachi Prometheans."
/datum/poster/nanotrasen/nt_5
icon_state = "ntposter05"
name = "Promethean"
desc = "This poster displays a friendly-looking green Promethean in a labcoat. The fine-print around the edges talks about the benefits Prometheans give in laboratories."
/datum/poster/nanotrasen/nt_6
icon_state = "ntposter06"
name = "NanoTrasen"
desc = "This poster showcases an NT emblem. There is writing in the ring around the inner points, probably some sort of slogan no one bothers to memorize."
/datum/poster/nanotrasen/nt_7
icon_state = "ntposter07"
name = "SolGov"
desc = "This poster showcases an SCG emblem. The outer ring reads,\
\"<font face='times new roman ms'>NIL MORTALIBUS ARDUI EST</font>\".\
Solar Confederate Government."
/datum/poster/nanotrasen/nt_8
icon_state = "ntposter08"
name = "wildlife hazard"
desc = "This poster warns against attempting to kill a fully grown giant spider or other hostile life-form alone."
/datum/poster/nanotrasen/nt_9
icon_state = "ntposter09"
name = "Regulations and You"
desc = "This poster showcases an NT security guard reading from her PDA. The blurb advocates for the reader to keep corporate regulations in mind at all times, as an emergency can occur at any time."

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

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

@@ -368,6 +368,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

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

@@ -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,
@@ -223,6 +223,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()
@@ -271,6 +273,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()
@@ -305,6 +308,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
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

@@ -59,3 +59,49 @@
visible_message("<span class='warning'>As \the [src] opens, the eyes of the robot flicker as it is activated.</span>")
R.Namepick()
..()
/obj/structure/ghost_pod/ghost_activated/swarm_drone
name = "drone shell"
desc = "A heavy metallic ball."
icon = 'icons/mob/swarmbot.dmi'
icon_state = "swarmer_unactivated"
density = FALSE
anchored = FALSE
var/drone_class = "general"
var/drone_type = /mob/living/silicon/robot/drone/swarm
/obj/structure/ghost_pod/ghost_activated/swarm_drone/create_occupant(var/mob/M)
var/mob/living/silicon/robot/drone/swarm/R = new drone_type(get_turf(src))
if(M.mind)
M.mind.transfer_to(R)
to_chat(M, "<span class='cult'>You are <b>[R]</b>, the remnant of some distant species, mechanical or flesh, living or dead.</span>")
R.ckey = M.ckey
visible_message("<span class='cult'>As \the [src] shudders, it glows before lifting itself with three shimmering limbs!</span>")
spawn(3 SECONDS)
to_chat(R,"<span class='notice'>Many of your tools are standard drone devices, however others provide you with particular benefits.</span>")
to_chat(R,"<span class='notice'>Unlike standard drones, you are capable of utilizing 'zero point wells', found in your 'spells' tab.</span>")
to_chat(R,"<span class='notice'>Here you will also find your replication ability(s), depending on the type of drone you are.</span>")
to_chat(R,"<span class='notice'>Gunners have a special anti-personnel gun capable of shocking or punching through armor with low damage.</span>")
to_chat(R,"<span class='notice'>Impalers have an energy-lance.</span>")
to_chat(R,"<span class='notice'>General drones have the unique ability to produce one of each of these two types of shells per generation.</span>")
if(!QDELETED(src))
qdel(src)
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/Initialize()
..()
var/turf/T = get_turf(src)
say_dead_object("A <span class='notice'>[drone_class] swarm drone</span> shell is now available in \the [T.loc].", src)
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/gunner
name = "gunner shell"
drone_class = "gunner"
drone_type = /mob/living/silicon/robot/drone/swarm/gunner
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/melee
name = "impaler shell"
drone_class = "impaler"
drone_type = /mob/living/silicon/robot/drone/swarm/melee

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

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

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

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

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

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

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

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

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

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

@@ -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,6 +119,7 @@ var/list/mob_hat_cache = list()
updatename()
/mob/living/silicon/robot/drone/init()
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
@@ -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

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

View File

@@ -526,6 +526,7 @@ var/global/list/robot_modules = list(
// src.modules += new /obj/item/weapon/gun/energy/taser/xeno/sec/robot(src) // VOREStation Edit - We don't need these
src.modules += new /obj/item/taperoll/police(src)
src.modules += new /obj/item/weapon/reagent_containers/spray/pepper(src)
src.modules += new /obj/item/weapon/gripper/security(src)
src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src)
/obj/item/weapon/robot_module/robot/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)

View File

@@ -0,0 +1,29 @@
/obj/item/weapon/robot_module/drone/swarm
name = "swarm drone module"
var/id
/obj/item/weapon/robot_module/drone/swarm/New(var/mob/living/silicon/robot/robot)
..()
id = robot.idcard
src.modules += id
src.modules += new /obj/item/weapon/rcd/electric/mounted/borg/swarm(src)
src.modules += new /obj/item/device/flash/robot(src)
src.modules += new /obj/item/weapon/handcuffs/cable/tape/cyborg(src)
src.modules += new /obj/item/weapon/melee/baton/robot(src)
src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg/swarm(src)
src.modules += new /obj/item/weapon/matter_decompiler/swarm(src)
/obj/item/weapon/robot_module/drone/swarm/ranged
name = "swarm gunner module"
/obj/item/weapon/robot_module/drone/swarm/ranged/New(var/mob/living/silicon/robot/robot)
..()
src.modules += new /obj/item/weapon/gun/energy/xray/swarm(src)
/obj/item/weapon/robot_module/drone/swarm/melee/New(var/mob/living/silicon/robot/robot)
..()
src.modules += new /obj/item/weapon/melee/energy/sword/ionic_rapier/lance(src)

View File

@@ -117,3 +117,17 @@
if(prob(poison_chance))
to_chat(L, "<span class='warning'>You feel a tiny prick.</span>")
L.reagents.add_reagent(poison_type, poison_per_bite)
/mob/living/simple_mob/animal/giant_spider/proc/make_spiderling()
adjust_scale(icon_scale_x * 0.7, icon_scale_y * 0.7)
maxHealth = round(maxHealth * 0.5)
health = round(health * 0.5)
melee_damage_lower *= 0.7
melee_damage_upper *= 0.7
response_harm = "kicks"
see_in_dark = max(2, round(see_in_dark * 0.6))
if(poison_per_bite)
poison_per_bite *= 1.3

View File

@@ -22,3 +22,23 @@
speak_emote = list("hisses")
say_list_type = /datum/say_list/lizard
/mob/living/simple_mob/animal/passive/lizard/large
desc = "A cute, big lizard."
maxHealth = 20
health = 20
melee_damage_lower = 5
melee_damage_upper = 15
attack_sharp = TRUE
/mob/living/simple_mob/animal/passive/lizard/large/Initialize()
..()
adjust_scale(rand(12, 20) / 10)
/mob/living/simple_mob/animal/passive/lizard/large/defensive
maxHealth = 30
health = 30
ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative

View File

@@ -103,6 +103,17 @@
body_color = "brown"
icon_state = "mouse_brown"
/mob/living/simple_mob/animal/passive/mouse/rat
name = "rat"
maxHealth = 20
health = 20
ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive
/mob/living/simple_mob/animal/passive/mouse/rat/Initialize()
..()
adjust_scale(1.2)
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_mob/animal/passive/mouse/brown/Tom
name = "Tom"

View File

@@ -425,6 +425,20 @@ proc/is_blind(A)
lname = "<span class='name'>[lname]</span> "
M << "<span class='deadsay'>" + create_text_tag("dead", "DEAD:", M.client) + " [lname][follow][message]</span>"
/proc/say_dead_object(var/message, var/obj/subject = null)
for(var/mob/M in player_list)
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights)) && M.is_preference_enabled(/datum/client_preference/show_dsay))
var/follow
var/lname = "Game Master"
if(M.forbid_seeing_deadchat && !M.client.holder)
continue
if(subject)
lname = "[subject.name] ([subject.x],[subject.y],[subject.z])"
lname = "<span class='name'>[lname]</span> "
M << "<span class='deadsay'>" + create_text_tag("event_dead", "EVENT:", M.client) + " [lname][follow][message]</span>"
//Announces that a ghost has joined/left, mainly for use with wizards
/proc/announce_ghost_joinleave(O, var/joined_ghosts = 1, var/message = "")
var/client/C

View File

@@ -22,6 +22,12 @@
charge_cost = 400
recharge_time = 7 //Time it takes for shots to recharge (in ticks)
/obj/item/weapon/gun/energy/taser/mounted/cyborg/swarm
name = "disabler"
desc = "An archaic device which attacks the target's nervous-system or control circuits."
projectile_type = /obj/item/projectile/beam/stun/disabler
charge_cost = 200
recharge_time = 0.5 SECONDS
/obj/item/weapon/gun/energy/stunrevolver
name = "stun revolver"
@@ -32,7 +38,6 @@
projectile_type = /obj/item/projectile/energy/electrode/strong
charge_cost = 300
/obj/item/weapon/gun/energy/crossbow
name = "mini energy-crossbow"
desc = "A weapon favored by many mercenary stealth specialists."

View File

@@ -108,3 +108,89 @@
list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, one_handed_penalty=15, burst_accuracy=null, dispersion=null),
list(mode_name="short bursts", burst=3, fire_delay=null, move_delay=5, one_handed_penalty=30, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)),
)
/obj/item/weapon/gun/magnetic/railgun/heater
name = "coil rifle"
desc = "A large rifle designed and produced after the Grey Hour."
description_info = "The MI-51B is a Martian weapon designed in the days after the Grey Hour, in preparation for the need for updated equipment by Solar forces.<br>\
The design is based upon a larger rail-type weapon design."
icon_state = "railgun_sec"
item_state = "cshotgun"
removable_components = TRUE
initial_cell_type = /obj/item/weapon/cell/high
initial_capacitor_type = /obj/item/weapon/stock_parts/capacitor
fire_delay = 8
slot_flags = SLOT_BACK
slowdown = 0
slowdown_held = 0
slowdown_worn = 0
power_cost = 400
projectile_type = /obj/item/projectile/bullet/magnetic/heated
loaded = null
empty_sound = 'sound/weapons/smg_empty_alarm.ogg'
firemodes = list(
list(mode_name="high power", power_cost = 400, projectile_type = /obj/item/projectile/bullet/magnetic/heated, burst=1, fire_delay=8, move_delay=null, one_handed_penalty=15),
list(mode_name="low power", power_cost = 150, projectile_type = /obj/item/projectile/bullet/magnetic/heated/weak, burst=1, fire_delay=5, move_delay=null, one_handed_penalty=15),
)
/obj/item/weapon/gun/magnetic/railgun/heater/pistol
name = "coil pistol"
desc = "A large pistol designed and produced after the Grey Hour."
description_info = "The MI-60D `Peacemaker` is a Martian weapon designed in the days after the Grey Hour, in preparation for the need for updated equipment by Solar forces.<br>\
The design is based upon a larger rail-type hybrid weapon design, though much smaller in scale."
icon_state = "peacemaker"
item_state = "revolver"
w_class = ITEMSIZE_NORMAL
initial_cell_type = /obj/item/weapon/cell/high
initial_capacitor_type = /obj/item/weapon/stock_parts/capacitor
slot_flags = SLOT_BELT|SLOT_HOLSTER
firemodes = list(
list(mode_name="lethal", power_cost = 2000, projectile_type = /obj/item/projectile/bullet/magnetic/heated, burst=1, fire_delay=8, move_delay=null, one_handed_penalty=0),
list(mode_name="stun", power_cost = 1500, projectile_type = /obj/item/projectile/energy/electrode/stunshot, burst=1, fire_delay=5, move_delay=null, one_handed_penalty=0),
)
/obj/item/weapon/gun/magnetic/railgun/heater/pistol/hos
name = "prototype peacemaker"
dna_lock = TRUE
description_antag = "This weapon starts with a DNA locking chip attached. Using an EMAG on the weapon will disarm it, and allow you to use the chip as your own."
firemodes = list(
list(mode_name="lethal", power_cost = 1500, projectile_type = /obj/item/projectile/bullet/magnetic/heated, burst=1, fire_delay=8, move_delay=null, one_handed_penalty=0),
list(mode_name="stun", power_cost = 1200, projectile_type = /obj/item/projectile/energy/electrode/stunshot, burst=1, fire_delay=5, move_delay=null, one_handed_penalty=0),
)
/obj/item/weapon/gun/magnetic/railgun/flechette/sif
name = "shredder rifle"
desc = "The MI-12B Kaldr is a burst fire capable coilgun that fires modified slugs intended for damaging soft targets."
description_fluff = "The Kaldr is a weapon recently deployed to various outposts on Sif, as well as local hunting guilds for the rapid dispatching of invasive wildlife."
icon_state = "railgun_sifguard"
item_state = "z8carbine"
initial_cell_type = /obj/item/weapon/cell/high
initial_capacitor_type = /obj/item/weapon/stock_parts/capacitor/adv
slot_flags = SLOT_BACK
slowdown = 0.3
power_cost = 200
projectile_type = /obj/item/projectile/bullet/magnetic/flechette/hunting
empty_sound = 'sound/weapons/smg_empty_alarm.ogg'
firemodes = list(
list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, one_handed_penalty=15, burst_accuracy=null, dispersion=null),
list(mode_name="short bursts", burst=3, fire_delay=null, move_delay=5, one_handed_penalty=30, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)),
)

View File

@@ -86,6 +86,19 @@
tracer_type = /obj/effect/projectile/tracer/xray
impact_type = /obj/effect/projectile/impact/xray
/obj/item/projectile/beam/gamma
name = "gamma beam"
icon_state = "xray"
fire_sound = 'sound/weapons/eluger.ogg'
damage = 10
armor_penetration = 90
irradiate = 20
light_color = "#00CC33"
muzzle_type = /obj/effect/projectile/muzzle/xray
tracer_type = /obj/effect/projectile/tracer/xray
impact_type = /obj/effect/projectile/impact/xray
/obj/item/projectile/beam/cyan
name = "cyan beam"
icon_state = "cyan"
@@ -215,6 +228,23 @@
icon_state = "stun"
agony = 30
/obj/item/projectile/beam/stun/disabler
muzzle_type = /obj/effect/projectile/muzzle/laser_omni
tracer_type = /obj/effect/projectile/tracer/laser_omni
impact_type = /obj/effect/projectile/impact/laser_omni
/obj/item/projectile/beam/stun/disabler/on_hit(atom/target, blocked = 0, def_zone)
. = ..(target, blocked, def_zone)
if(. && istype(target, /mob/living/silicon/robot) && prob(agony))
var/mob/living/silicon/robot/R = target
var/drainamt = agony * (rand(5, 15) / 10)
R.drain_power(0, 0, drainamt)
if(istype(firer, /mob/living/silicon/robot)) // Mischevious sappers, the swarm drones are.
var/mob/living/silicon/robot/A = firer
if(A.cell)
A.cell.give(drainamt * 2)
/obj/item/projectile/beam/shock
name = "shock beam"
icon_state = "lightning"

View File

@@ -22,6 +22,28 @@
damage = 20
armor_penetration = 100
/obj/item/projectile/bullet/magnetic/flechette/hunting
name = "shredder slug"
armor_penetration = 30
SA_bonus_damage = 40
SA_vulnerability = SA_ANIMAL
/obj/item/projectile/bullet/magnetic/heated
name = "slug"
icon_state = "gauss"
weaken = 0
stun = 0
damage = 30
damage_type = SEARING
embed_chance = 0
/obj/item/projectile/bullet/magnetic/heated/weak
icon_state = "gauss_silenced"
damage = 15
agony = 5
embed_chance = 0
armor_penetration = 50
/obj/item/projectile/bullet/magnetic/fuelrod
name = "fuel rod"
icon_state = "fuel-deuterium"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 73 KiB

BIN
icons/mob/swarmbot.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -483,6 +483,7 @@
#include "code\game\antagonist\station\renegade.dm"
#include "code\game\antagonist\station\revolutionary.dm"
#include "code\game\antagonist\station\rogue_ai.dm"
#include "code\game\antagonist\station\stowaway.dm"
#include "code\game\antagonist\station\thug.dm"
#include "code\game\antagonist\station\traitor.dm"
#include "code\game\area\ai_monitored.dm"
@@ -1308,6 +1309,7 @@
#include "code\game\objects\structures\flora\grass.dm"
#include "code\game\objects\structures\flora\trees.dm"
#include "code\game\objects\structures\ghost_pods\ghost_pods.dm"
#include "code\game\objects\structures\ghost_pods\human.dm"
#include "code\game\objects\structures\ghost_pods\mysterious.dm"
#include "code\game\objects\structures\ghost_pods\silicon.dm"
#include "code\game\objects\structures\ghost_pods\silicon_vr.dm"
@@ -1319,6 +1321,7 @@
#include "code\game\objects\structures\props\projectile_lock.dm"
#include "code\game\objects\structures\props\prop.dm"
#include "code\game\objects\structures\props\puzzledoor.dm"
#include "code\game\objects\structures\props\swarm.dm"
#include "code\game\objects\structures\props\transmitter.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\alien_nests.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\bed.dm"
@@ -1770,6 +1773,7 @@
#include "code\modules\detectivework\tools\luminol.dm"
#include "code\modules\detectivework\tools\rag.dm"
#include "code\modules\detectivework\tools\sample_kits.dm"
#include "code\modules\detectivework\tools\scanner.dm"
#include "code\modules\detectivework\tools\storage.dm"
#include "code\modules\detectivework\tools\swabs.dm"
#include "code\modules\detectivework\tools\uvlight.dm"
@@ -1913,12 +1917,15 @@
#include "code\modules\gamemaster\actions\carp_migration.dm"
#include "code\modules\gamemaster\actions\carp_migration_vr.dm"
#include "code\modules\gamemaster\actions\comms_blackout.dm"
#include "code\modules\gamemaster\actions\drill_announcement.dm"
#include "code\modules\gamemaster\actions\dust.dm"
#include "code\modules\gamemaster\actions\electrical_storm.dm"
#include "code\modules\gamemaster\actions\electrified_door.dm"
#include "code\modules\gamemaster\actions\gravity.dm"
#include "code\modules\gamemaster\actions\grid_check.dm"
#include "code\modules\gamemaster\actions\infestation.dm"
#include "code\modules\gamemaster\actions\ion_storm.dm"
#include "code\modules\gamemaster\actions\manifest_malfunction.dm"
#include "code\modules\gamemaster\actions\meteor_defense.dm"
#include "code\modules\gamemaster\actions\money_hacker.dm"
#include "code\modules\gamemaster\actions\money_lotto.dm"
@@ -1928,13 +1935,19 @@
#include "code\modules\gamemaster\actions\radiation_storm.dm"
#include "code\modules\gamemaster\actions\random_antagonist.dm"
#include "code\modules\gamemaster\actions\rogue_drones.dm"
#include "code\modules\gamemaster\actions\security_advisement.dm"
#include "code\modules\gamemaster\actions\shipping_error.dm"
#include "code\modules\gamemaster\actions\solar_storm.dm"
#include "code\modules\gamemaster\actions\spacevine.dm"
#include "code\modules\gamemaster\actions\spider_infestation.dm"
#include "code\modules\gamemaster\actions\spontaneous_appendicitis.dm"
#include "code\modules\gamemaster\actions\station_fundraise.dm"
#include "code\modules\gamemaster\actions\stowaway.dm"
#include "code\modules\gamemaster\actions\supply_conversion.dm"
#include "code\modules\gamemaster\actions\supplyrequest.dm"
#include "code\modules\gamemaster\actions\surprise_carp_attack.dm"
#include "code\modules\gamemaster\actions\surprise_meteor.dm"
#include "code\modules\gamemaster\actions\swarmboarder.dm"
#include "code\modules\gamemaster\actions\viral_infection.dm"
#include "code\modules\gamemaster\actions\viral_outbreak.dm"
#include "code\modules\gamemaster\actions\wallrot.dm"
@@ -2379,11 +2392,21 @@
#include "code\modules\mob\living\silicon\robot\drone\drone_items.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_say.dm"
<<<<<<< HEAD:vorestation.dme
#include "code\modules\mob\living\silicon\robot\drone\drone_vr.dm"
=======
#include "code\modules\mob\living\silicon\robot\drone\swarm.dm"
#include "code\modules\mob\living\silicon\robot\drone\swarm_abilities.dm"
#include "code\modules\mob\living\silicon\robot\drone\swarm_items.dm"
>>>>>>> 7ecdcb4... Security / PseudoCargo Expansion (#6482):polaris.dme
#include "code\modules\mob\living\silicon\robot\robot_modules\event.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\event_vr.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\station.dm"
<<<<<<< HEAD:vorestation.dme
#include "code\modules\mob\living\silicon\robot\robot_modules\station_vr.dm"
=======
#include "code\modules\mob\living\silicon\robot\robot_modules\swarm.dm"
>>>>>>> 7ecdcb4... Security / PseudoCargo Expansion (#6482):polaris.dme
#include "code\modules\mob\living\silicon\robot\robot_modules\syndicate.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\gravekeeper.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\lost_drone.dm"