Merge pull request #2592 from Cameron653/SYNC_OY_VEY

Mid December Polaris Sync
This commit is contained in:
Arokha Sieyes
2017-12-24 15:35:55 -05:00
committed by GitHub
515 changed files with 13851 additions and 5621 deletions

View File

@@ -37,9 +37,14 @@ script:
- (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ])
- source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup
- python tools/TagMatcher/tag-matcher.py ../..
- echo "#define UNIT_TEST 1" > code/_unit_tests.dm
#First compile is to ensure maps are valid.
- echo "#define MAP_TEST 1" > code/_map_tests.dm
- cp config/example/* config/
- DreamMaker vorestation.dme
- travis_wait DreamDaemon vorestation.dmb -invisible -trusted -core 2>&1 | tee log.txt
- echo "#define MAP_TEST 0" > code/_map_tests.dm
#Second compile is for the unit tests. Compiling a second time to exclude the validated maps is actually faster than waiting for startup with them compiled.
- echo "#define UNIT_TEST 1" > code/_unit_tests.dm
- DreamMaker vorestation.dme
- DreamDaemon vorestation.dmb -invisible -trusted -core 2>&1 | tee log.txt
- grep "All Unit Tests Passed" log.txt

View File

@@ -76,7 +76,8 @@ obj/var/phoronproof = 0
suit_contamination()
if(!pl_head_protected())
if(prob(1)) suit_contamination() //Phoron can sometimes get through such an open suit.
if(prob(1))
suit_contamination() //Phoron can sometimes get through such an open suit.
//Cannot wash backpacks currently.
// if(istype(back,/obj/item/weapon/storage/backpack))
@@ -88,7 +89,8 @@ obj/var/phoronproof = 0
//Handles all the bad things phoron can do.
//Contamination
if(vsc.plc.CLOTH_CONTAMINATION) contaminate()
if(vsc.plc.CLOTH_CONTAMINATION)
contaminate()
//Anything else requires them to not be dead.
if(stat >= 2)
@@ -143,22 +145,22 @@ obj/var/phoronproof = 0
Blind(20)
/mob/living/carbon/human/proc/pl_head_protected()
//Checks if the head is adequately sealed.
//Checks if the head is adequately sealed. //This is just odd. TODO: Make this respect the body_parts_covered stuff like thermal gear does.
if(head)
if(vsc.plc.PHORONGUARD_ONLY)
if(head.flags & PHORONGUARD)
if(head.flags & PHORONGUARD || head.phoronproof)
return 1
else if(head.body_parts_covered & EYES)
return 1
return 0
/mob/living/carbon/human/proc/pl_suit_protected()
//Checks if the suit is adequately sealed.
//Checks if the suit is adequately sealed. //This is just odd. TODO: Make this respect the body_parts_covered stuff like thermal gear does.
var/coverage = 0
for(var/obj/item/protection in list(wear_suit, gloves, shoes))
for(var/obj/item/protection in list(wear_suit, gloves, shoes)) //This is why it's odd. If I'm in a full suit, but my shoes and gloves aren't phoron proof, damage.
if(!protection)
continue
if(vsc.plc.PHORONGUARD_ONLY && !(protection.flags & PHORONGUARD))
if(vsc.plc.PHORONGUARD_ONLY && !(protection.flags & PHORONGUARD) && !protection.phoronproof)
return 0
coverage |= protection.body_parts_covered
@@ -169,9 +171,12 @@ obj/var/phoronproof = 0
/mob/living/carbon/human/proc/suit_contamination()
//Runs over the things that can be contaminated and does so.
if(w_uniform) w_uniform.contaminate()
if(shoes) shoes.contaminate()
if(gloves) gloves.contaminate()
if(w_uniform)
w_uniform.contaminate()
if(shoes)
shoes.contaminate()
if(gloves)
gloves.contaminate()
turf/Entered(obj/item/I)

View File

@@ -57,6 +57,7 @@
#define PASSTABLE 0x1
#define PASSGLASS 0x2
#define PASSGRILLE 0x4
#define PASSBLOB 0x8
// Bitmasks for the flags_inv variable. These determine when a piece of clothing hides another, i.e. a helmet hiding glasses.
// WARNING: The following flags apply only to the external suit!

View File

@@ -6,3 +6,6 @@
#define MAP_LEVEL_SEALED 0x010 // Z-levels that don't allow random transit at edge
#define MAP_LEVEL_EMPTY 0x020 // Empty Z-levels that may be used for various things (currently used by bluespace jump)
#define MAP_LEVEL_CONSOLES 0x040 // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset.
// Misc map defines.
#define SUBMAP_MAP_EDGE_PAD 15 // Automatically created submaps are forbidden from being this close to the main map's edge.

View File

@@ -159,6 +159,7 @@
#define MAT_TITANIUM "titanium"
#define MAT_PHORON "phoron"
#define MAT_DIAMOND "diamond"
#define MAT_SNOW "snow"
#define SHARD_SHARD "shard"
#define SHARD_SHRAPNEL "shrapnel"

View File

@@ -873,22 +873,3 @@ proc/sort_atoms_by_layer(var/list/atoms)
result.Swap(i, gap + i)
swapped = 1
return result
// Mutable appearances are an inbuilt byond datastructure. Read the documentation on them by hitting F1 in DM.
// Basically use them instead of images for overlays/underlays and when changing an object's appearance if you're doing so with any regularity.
// Unless you need the overlay/underlay to have a different direction than the base object. Then you have to use an image due to a bug.
// Mutable appearances are children of images, just so you know.
/mutable_appearance/New()
..()
plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
// Helper similar to image()
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER)
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
MA.layer = layer
return MA

View File

@@ -164,6 +164,14 @@ proc/listclearnulls(list/list)
L.Swap(i, rand(i,L.len))
return L
//same, but returns nothing and acts on list in place
/proc/shuffle_inplace(list/L)
if(!L)
return
for(var/i=1, i<L.len, ++i)
L.Swap(i,rand(i,L.len))
//Return a list with no duplicate entries
/proc/uniquelist(var/list/L)
. = list()

View File

@@ -7,6 +7,13 @@
//Checks if all high bits in req_mask are set in bitfield
#define BIT_TEST_ALL(bitfield, req_mask) ((~(bitfield) & (req_mask)) == 0)
//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a
#define RANGE_TURFS(RADIUS, CENTER) \
block( \
locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \
locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \
)
//Inverts the colour of an HTML string
/proc/invertHTML(HTMLstring)
@@ -476,6 +483,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/list/sortmob = sortAtom(mob_list)
for(var/mob/observer/eye/M in sortmob)
moblist.Add(M)
for(var/mob/observer/blob/M in sortmob)
moblist.Add(M)
for(var/mob/living/silicon/ai/M in sortmob)
moblist.Add(M)
for(var/mob/living/silicon/pai/M in sortmob)
@@ -1331,3 +1340,24 @@ var/mob/dview/dview_mob = new
return "[round(number / 1e9, 0.1)] G[symbol]" // giga
if(1e12 to 1e15-1)
return "[round(number / 1e12, 0.1)] T[symbol]" // tera
//ultra range (no limitations on distance, faster than range for distances > 8); including areas drastically decreases performance
/proc/urange(dist=0, atom/center=usr, orange=0, areas=0)
if(!dist)
if(!orange)
return list(center)
else
return list()
var/list/turfs = RANGE_TURFS(dist, center)
if(orange)
turfs -= get_turf(center)
. = list()
for(var/V in turfs)
var/turf/T = V
. += T
. += T.contents
if(areas)
. |= T.loc

10
code/_map_tests.dm Normal file
View File

@@ -0,0 +1,10 @@
/*
*
* This file is used by Travis to indicate that additional maps need to be compiled to look for errors such as missing paths.
* Do not add anything but the MAP_TEST definition here as it will be overwritten by Travis when running tests.
*
*
* Should you wish to edit set MAP_TEST to 1 like so:
* #define MAP_TEST 1
*/
#define MAP_TEST 0

View File

@@ -108,7 +108,7 @@
W.afterattack(A, src, 1, params) // 1 indicates adjacency
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
setClickCooldown(get_attack_speed())
UnarmedAttack(A, 1)
trigger_aiming(TARGET_CAN_CLICK)
@@ -121,7 +121,7 @@
// A is a turf or is on a turf, or in something on a turf (pen in a box); but not something in something on a turf (pen in a box in a backpack)
sdepth = A.storage_depth_turf()
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
if(A.Adjacent(src)) // see adjacent.dm
if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach)) ) // see adjacent.dm
if(W)
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = W.resolve_attackby(A,src)
@@ -129,7 +129,7 @@
W.afterattack(A, src, 1, params) // 1: clicking something Adjacent
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
setClickCooldown(get_attack_speed())
UnarmedAttack(A, 1)
trigger_aiming(TARGET_CAN_CLICK)
return

View File

@@ -23,8 +23,13 @@ avoid code duplication. This includes items that may sometimes act as a standard
/obj/item/proc/attack_self(mob/user)
return
// Called at the start of resolve_attackby(), before the actual attack.
/obj/item/proc/pre_attack(atom/a, mob/user)
return
//I would prefer to rename this to attack(), but that would involve touching hundreds of files.
/obj/item/proc/resolve_attackby(atom/A, mob/user)
pre_attack(A, user)
add_fingerprint(user)
return A.attackby(src, user)
@@ -44,6 +49,22 @@ avoid code duplication. This includes items that may sometimes act as a standard
if(attempt_vr(src,"vore_attackby",args)) return //VOREStation Code
return I.attack(src, user, user.zone_sel.selecting)
// Used to get how fast a mob should attack, and influences click delay.
// This is just for inheritence.
/mob/proc/get_attack_speed()
return DEFAULT_ATTACK_COOLDOWN
// Same as above but actually does useful things.
// W is the item being used in the attack, if any. modifier is if the attack should be longer or shorter than usual, for whatever reason.
/mob/living/get_attack_speed(var/obj/item/W)
var/speed = DEFAULT_ATTACK_COOLDOWN
if(W && istype(W))
speed = W.attackspeed
for(var/datum/modifier/M in modifiers)
if(!isnull(M.attack_speed_percent))
speed *= M.attack_speed_percent
return speed
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
// Click parameters is the params string from byond Click() code, see that documentation.
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
@@ -66,7 +87,7 @@ avoid code duplication. This includes items that may sometimes act as a standard
msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
/////////////////////////
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
user.do_attack_animation(M)
var/hit_zone = M.resolve_item_attack(src, user, target_zone)

View File

@@ -59,7 +59,7 @@
if(!..())
return 0
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
setClickCooldown(get_attack_speed())
A.attack_generic(src,rand(5,6),"bitten")
/*
@@ -87,7 +87,7 @@
custom_emote(1,"[friendly] [A]!")
return
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
setClickCooldown(get_attack_speed())
if(isliving(A))
target_mob = A
PunchTarget()
@@ -96,7 +96,7 @@
A.attack_generic(src, rand(melee_damage_lower, melee_damage_upper), attacktext)
/mob/living/simple_animal/RangedAttack(var/atom/A)
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
setClickCooldown(get_attack_speed())
var/distance = get_dist(src, A)
if(prob(spattack_prob) && (distance >= spattack_min_range) && (distance <= spattack_max_range))

View File

@@ -74,7 +74,7 @@
return 0
rig.selected_module.engage(A, alert_ai)
if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
setClickCooldown(get_attack_speed())
return 1
return 0

View File

@@ -51,9 +51,10 @@ var/datum/controller/process/planet/planet_controller = null
//Redraw weather icons
for(var/T in P.planet_floors)
var/turf/simulated/turf = T
turf.overlays -= turf.weather_overlay
// turf.overlays -= turf.weather_overlay
turf.weather_overlay = new_overlay
turf.overlays += turf.weather_overlay
// turf.overlays += turf.weather_overlay
turf.update_icon()
SCHECK
//Sun light needs changing

View File

@@ -540,10 +540,10 @@ var/datum/controller/master/Master = new()
stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))")
stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])"))
/datum/controller/master/StartLoadingMap()
/datum/controller/master/StartLoadingMap(var/quiet = TRUE)
if(map_loading)
admin_notice("<span class='danger'>Another map is attempting to be loaded before first map released lock. Delaying.</span>", R_DEBUG)
else
else if(!quiet)
admin_notice("<span class='danger'>Map is now being built. Locking.</span>", R_DEBUG)
//disallow more than one map to load at once, multithreading it will just cause race conditions
@@ -557,7 +557,8 @@ var/datum/controller/master/Master = new()
air_processing_killed = TRUE
map_loading = TRUE
/datum/controller/master/StopLoadingMap(bounds = null)
/datum/controller/master/StopLoadingMap(var/quiet = TRUE)
if(!quiet)
admin_notice("<span class='danger'>Map is finished. Unlocking.</span>", R_DEBUG)
air_processing_killed = FALSE
map_loading = FALSE

View File

@@ -13,10 +13,10 @@ SUBSYSTEM_DEF(creation)
var/map_loading = FALSE
/datum/controller/subsystem/creation/StartLoadingMap()
/datum/controller/subsystem/creation/StartLoadingMap(var/quiet)
map_loading = TRUE
/datum/controller/subsystem/creation/StopLoadingMap()
/datum/controller/subsystem/creation/StopLoadingMap(var/quiet)
map_loading = FALSE
/datum/controller/subsystem/creation/proc/initialize_late_atoms()

View File

@@ -133,6 +133,16 @@
add_inherent_law("Prevent unplanned damage to your assigned vessel wherever possible.")
..()
/datum/ai_laws/mining_drone
name = "Excavation Protocols"
law_header = "Excavation Protocols"
/datum/ai_laws/mining_drone/New()
add_inherent_law("Do not interfere with the excavation work of non-drones whenever possible.")
add_inherent_law("Provide materials for repairing, refitting, and upgrading your assigned vessel.")
add_inherent_law("Prevent unplanned damage to your assigned excavation equipment wherever possible.")
..()
/******************** T.Y.R.A.N.T. ********************/
/datum/ai_laws/tyrant
name = "T.Y.R.A.N.T."

View File

@@ -147,17 +147,27 @@
name = "rifle magazine (5.45mm practice)"
path =/obj/item/ammo_magazine/m545/practice
/*/datum/category_item/autolathe/arms/rifle_545_hunter //VOREStation Edit Start. By request of Ace
name = "rifle magazine (5.45mm hunting)"
path =/obj/item/ammo_magazine/m545/hunter*/ //VOREStation Edit End.
/datum/category_item/autolathe/arms/machinegun_545
name = "machinegun box magazine (5.45)"
path =/obj/item/ammo_magazine/m545saw
hidden = 1
/*/datum/category_item/autolathe/arms/machinegun_545_hunter //VOREStation Edit Start. By request of Ace
name = "machinegun box magazine (5.56 hunting)"
path =/obj/item/ammo_magazine/m545saw/hunter
hidden = 1*/ //VOREStation Edit End.
/////// 7.62
/datum/category_item/autolathe/arms/rifle_762
name = "rifle magazine (7.62mm)"
path =/obj/item/ammo_magazine/m762
hidden = 1
/*
/datum/category_item/autolathe/arms/rifle_small_762
name = "rifle magazine (7.62mm)"
@@ -384,6 +394,10 @@
path =/obj/item/ammo_magazine/clip/c762
hidden = 1
/*/datum/category_item/autolathe/arms/rifle_clip_762_hunter //VOREStation Edit Start. By request of Ace
name = "ammo clip (7.62mm hunting)"
path =/obj/item/ammo_magazine/clip/c762/hunter*/ //VOREStation Edit End.
/datum/category_item/autolathe/arms/rifle_clip_762_practice
name = "ammo clip (7.62mm practice)"
path =/obj/item/ammo_magazine/clip/c762/practice

View File

@@ -92,6 +92,13 @@
question = "An Alien has just been created on the facility. Would you like to play as them?"
be_special_flag = BE_ALIEN
/datum/ghost_query/blob
role_name = "Blob"
question = "A rapidly expanding Blob has just appeared on the facility. Would you like to play as it?"
be_special_flag = BE_ALIEN
cutoff_number = 1
wait_time = 10 SECONDS
/datum/ghost_query/syndicate_drone
role_name = "Mercenary Drone"
question = "A team of dubious mercenaries have purchased a powerful drone, and they are attempting to activate it. Would you like to play as the drone?"

View File

@@ -0,0 +1,18 @@
// Mutable appearances are an inbuilt byond datastructure. Read the documentation on them by hitting F1 in DM.
// Basically use them instead of images for overlays/underlays and when changing an object's appearance if you're doing so with any regularity.
// Unless you need the overlay/underlay to have a different direction than the base object. Then you have to use an image due to a bug.
// Mutable appearances are children of images, just so you know.
/mutable_appearance/New()
..()
plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
// Helper similar to image()
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER)
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
MA.layer = layer
return MA

View File

@@ -87,3 +87,18 @@
l_hand = /obj/item/weapon/storage/bible
id_type = /obj/item/weapon/card/id/civilian/chaplain
pda_type = /obj/item/device/pda/chaplain
/decl/hierarchy/outfit/job/explorer
name = OUTFIT_JOB_NAME("Explorer")
shoes = /obj/item/clothing/shoes/boots/winter/explorer
uniform = /obj/item/clothing/under/explorer
mask = /obj/item/clothing/mask/gas/explorer
suit = /obj/item/clothing/suit/storage/hooded/explorer
gloves = /obj/item/clothing/gloves/black
l_ear = /obj/item/device/radio/headset
id_slot = slot_wear_id
id_type = /obj/item/weapon/card/id/civilian
pda_slot = slot_belt
pda_type = /obj/item/device/pda/cargo // Brown looks more rugged
r_pocket = /obj/item/device/gps/explorer
id_pda_assignment = "Explorer"

View File

@@ -1,22 +1,22 @@
/decl/hierarchy/outfit/military/sifguard/pt
name = OUTFIT_MILITARY("SifGuard PT")
uniform = /obj/item/clothing/under/pt/expeditionary
uniform = /obj/item/clothing/under/pt/sifguard
shoes = /obj/item/clothing/shoes/black
/decl/hierarchy/outfit/military/sifguard/utility
name = OUTFIT_MILITARY("SifGuard Utility")
uniform = /obj/item/clothing/under/utility/expeditionary
uniform = /obj/item/clothing/under/utility/sifguard
shoes = /obj/item/clothing/shoes/boots/jackboots
/decl/hierarchy/outfit/military/sifguard/service
name = OUTFIT_MILITARY("SifGuard Service")
uniform = /obj/item/clothing/under/utility/expeditionary
uniform = /obj/item/clothing/under/utility/sifguard
shoes = /obj/item/clothing/shoes/boots/jackboots
suit = /obj/item/clothing/suit/storage/service/expeditionary
suit = /obj/item/clothing/suit/storage/service/sifguard
/decl/hierarchy/outfit/military/sifguard/dress
name = OUTFIT_MILITARY("SifGuard Dress")
uniform = /obj/item/clothing/under/mildress/expeditionary
uniform = /obj/item/clothing/under/mildress/sifguard
shoes = /obj/item/clothing/shoes/dress
suit = /obj/item/clothing/suit/dress/expedition
gloves = /obj/item/clothing/gloves/white

View File

@@ -43,10 +43,10 @@
containername = "Moghes imports crate"
contraband = 1
/datum/supply_packs/security/bolt_rifles_mosin
/datum/supply_packs/security/bolt_rifles_militia
name = "Surplus militia rifles"
contains = list(
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin = 3,
/obj/item/weapon/gun/projectile/shotgun/pump/rifle = 3,
/obj/item/ammo_magazine/clip/c762 = 6
)
cost = 50
@@ -80,7 +80,7 @@
/obj/item/weapon/storage/box/syndie_kit/demolitions,
/obj/item/device/multitool/ai_detector,
/obj/item/weapon/plastique,
/obj/item/weapon/storage/toolbox/syndicate
/obj/item/weapon/storage/toolbox/syndicate/powertools
),
list( //the infiltrator,
/obj/item/weapon/gun/projectile/silenced,

View File

@@ -134,10 +134,12 @@ datum/supply_packs/costumes/witch
/obj/item/clothing/head/pirate,
/obj/item/clothing/head/hasturhood,
/obj/item/clothing/head/powdered_wig,
/obj/item/clothing/head/hairflower,
/obj/item/clothing/head/hairflower/yellow,
/obj/item/clothing/head/hairflower/blue,
/obj/item/clothing/head/hairflower/pink,
/obj/item/clothing/head/pin/flower,
/obj/item/clothing/head/pin/flower/yellow,
/obj/item/clothing/head/pin/flower/blue,
/obj/item/clothing/head/pin/flower/pink,
/obj/item/clothing/head/pin/clover,
/obj/item/clothing/head/pin/butterfly,
/obj/item/clothing/mask/gas/owl_mask,
/obj/item/clothing/mask/gas/monkeymask,
/obj/item/clothing/head/helmet/gladiator,

View File

@@ -37,6 +37,7 @@
/obj/item/weapon/storage/box/glasses/shake,
/obj/item/weapon/storage/box/glasses/shot,
/obj/item/weapon/storage/box/glasses/mug,
/obj/item/weapon/storage/box/glasses/meta,
/obj/item/weapon/reagent_containers/food/drinks/shaker,
/obj/item/weapon/storage/box/glass_extras/straws,
/obj/item/weapon/storage/box/glass_extras/sticks

View File

@@ -82,7 +82,7 @@
contains = list(
/obj/item/weapon/storage/firstaid/clotting
)
cost = 40
cost = 100
containertype = "/obj/structure/closet/crate/secure"
containername = "Clotting Medicine crate"
access = access_medical

View File

@@ -9,11 +9,16 @@
item_cost = 5
path = /obj/item/device/binoculars
/datum/uplink_item/item/tools/toolbox
/datum/uplink_item/item/tools/toolbox // Leaving the basic as an option since powertools are loud.
name = "Fully Loaded Toolbox"
item_cost = 10
item_cost = 5
path = /obj/item/weapon/storage/toolbox/syndicate
/datum/uplink_item/item/tools/powertoolbox
name = "Fully Loaded Powertool Box"
item_cost = 10
path = /obj/item/weapon/storage/toolbox/syndicate/powertools
/datum/uplink_item/item/tools/clerical
name = "Morphic Clerical Kit"
item_cost = 10

View File

@@ -55,11 +55,13 @@
if(APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2)
if(!mended)
if(istype(usr, /mob/living))
A.shock(usr, 50)
A.shorted = 1
else if(!IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2))
A.shorted = 0
if(istype(usr, /mob/living))
A.shock(usr, 50)
if(APC_WIRE_AI_CONTROL)

View File

@@ -85,7 +85,7 @@ var/datum/antagonist/raider/raiders
/obj/item/weapon/gun/projectile/silenced,
/obj/item/weapon/gun/projectile/shotgun/pump,
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin,
/obj/item/weapon/gun/projectile/shotgun/pump/rifle,
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet,
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,

View File

@@ -48,7 +48,7 @@ var/datum/antagonist/renegade/renegades
/obj/item/weapon/gun/projectile/revolver,
/obj/item/weapon/gun/projectile/derringer,
/obj/item/weapon/gun/projectile/shotgun/pump,
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin,
/obj/item/weapon/gun/projectile/shotgun/pump/rifle,
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
/obj/item/weapon/gun/projectile/revolver/judge,

View File

@@ -84,6 +84,10 @@
P.on_hit(src, 0, def_zone)
. = 0
// Called when a blob expands onto the tile the atom occupies.
/atom/proc/blob_act()
return
/atom/proc/in_contents_of(container)//can take class or object instance as argument
if(ispath(container))
if(istype(src.loc, container))

View File

@@ -16,6 +16,8 @@
var/mob/pulledby = null
var/item_state = null // Used to specify the item state for the on-mob overlays.
var/icon_scale = 1 // Used to scale icons up or down in update_transform().
var/old_x = 0
var/old_y = 0
var/auto_init = 1
/atom/movable/New()

View File

@@ -23,6 +23,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/recursive_enhancement = 0 //Used to power up other abilities from the ling power with the same name.
var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too.
var/last_shriek = null // world.time when the ling last used a shriek.
var/next_escape = 0 // world.time when the ling can next use Escape Restraints
/datum/changeling/New(var/gender=FEMALE)
..()
@@ -167,7 +168,8 @@ turf/proc/AdjacentTurfsRangedSting()
/obj/structure/target_stake,
/obj/structure/cable,
/obj/structure/disposalpipe,
/obj/machinery/
/obj/machinery,
/mob
)
var/L[] = new()

View File

@@ -0,0 +1,63 @@
/datum/power/changeling/escape_restraints
name = "Escape Restraints"
desc = "We evolve more complex joints"
helptext = "We can instantly escape from most restraints and bindings, but we cannot do it often."
enhancedtext = "More frequent escapes."
ability_icon_state = "ling_escape_restraints"
genomecost = 2
verbpath = /mob/proc/changeling_escape_restraints
//Escape Cuffs. By design this does not escape from straight jackets
/mob/proc/changeling_escape_restraints()
set category = "Changeling"
set name = "Escape Restraints (40)"
set desc = "Removes handcuffs and legcuffs instantly."
var/escape_cooldown = 5 MINUTES //This is used later to prevent spamming
var/mob/living/carbon/human/C = src
var/datum/changeling/changeling = changeling_power(40,0,100,CONSCIOUS)
if(!changeling)
return 0
if(world.time < changeling.next_escape)
to_chat(src, "<span class='warning'>We are still recovering from our last escape...</span>")
return 0
if(!(C.handcuffed || C.legcuffed)) // No need to waste chems if there's nothing to break out of
to_chat(C, "<span class='warning'>We are are not restrained in a way we can escape...</span>")
return 0
changeling.chem_charges -= 40
to_chat(C,"<span class='notice'>We contort our extremities and slip our cuffs.</span>")
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
if(C.handcuffed)
var/obj/item/weapon/W = C.handcuffed
C.handcuffed = null
if(C.buckled && C.buckled.buckle_require_restraints)
C.buckled.unbuckle_mob()
C.update_inv_handcuffed()
if (C.client)
C.client.screen -= W
if(W)
W.loc = C.loc
W.dropped(C)
if(W)
W.layer = initial(W.layer)
if(C.legcuffed)
var/obj/item/weapon/W = C.legcuffed
C.legcuffed = null
C.update_inv_legcuffed()
if(C.client)
C.client.screen -= W
if(W)
W.loc = C.loc
W.dropped(C)
if(W)
W.layer = initial(W.layer)
if(src.mind.changeling.recursive_enhancement)
escape_cooldown *= 0.5
changeling.next_escape = world.time + escape_cooldown //And now we set the timer
feedback_add_details("changeling_powers","ESR")
return 1

View File

@@ -1,6 +1,6 @@
/datum/power/changeling/resonant_shriek
name = "Resonant Shriek"
desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded biologicals and synthetics."
desc = "Our lungs and vocal cords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded."
helptext = "Lights are blown, organics are disoriented, and synthetics act as if they were flashed."
enhancedtext = "Range is doubled."
ability_icon_state = "ling_resonant_shriek"
@@ -20,19 +20,19 @@
/mob/proc/changeling_resonant_shriek()
set category = "Changeling"
set name = "Resonant Shriek (20)"
set desc = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors."
set desc = "Emits a high-frequency sound that confuses and deafens organics, blows out nearby lights, and overloads synthetics' sensors."
var/datum/changeling/changeling = changeling_power(20,0,100,CONSCIOUS)
if(!changeling) return 0
if(is_muzzled())
src << "<span class='danger'>Mmmf mrrfff!</span>"
to_chat(src, "<span class='danger'>Mmmf mrrfff!</span>")
return 0
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.silent)
src << "<span class='danger'>You can't speak!</span>"
to_chat(src, "<span class='danger'>You can't speak!</span>")
return 0
if(world.time < (changeling.last_shriek + 10 SECONDS) )
@@ -49,7 +49,7 @@
var/range = 4
if(src.mind.changeling.recursive_enhancement)
range = range * 2
src << "<span class='notice'>We are extra loud.</span>"
to_chat(src, "<span class='notice'>We are extra loud.</span>")
src.attack_log += text("\[[time_stamp()]\] <font color='red'>Used Resonant Shriek.</font>")
message_admins("[key_name(src)] used Resonant Shriek ([src.x],[src.y],[src.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>).")

View File

@@ -27,7 +27,7 @@
..()
/obj/item/weapon/toy/xmas_cracker/attack(mob/target, mob/user)
if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() )
if( !cracked && (istype(target,/mob/living/silicon) || (istype(target,/mob/living/carbon/human) && !target.get_active_hand())) && target.stat == CONSCIOUS)
target.visible_message("<span class='notice'>[user] and [target] pop \an [src]! *pop*</span>", "<span class='notice'>You pull \an [src] with [target]! *pop*</span>", "<span class='notice'>You hear a *pop*.</span>")
var/obj/item/weapon/paper/Joke = new /obj/item/weapon/paper(user.loc)
Joke.name = "[pick("awful","terrible","unfunny")] joke"

View File

@@ -10,6 +10,8 @@ var/global/datum/controller/gameticker/ticker
var/event_time = null
var/event = 0
// var/login_music // music played in pregame lobby // VOREStation Edit - We do music differently
var/list/datum/mind/minds = list()//The people in the game. Used for objective tracking.
var/Bible_icon_state // icon_state the chaplain has chosen for his bible
@@ -32,10 +34,24 @@ var/global/datum/controller/gameticker/ticker
var/round_end_announced = 0 // Spam Prevention. Announce round end only once.
/datum/controller/gameticker/proc/pregame()
/* VOREStation Edit - We do music differently
login_music = pick(\
'sound/music/halloween/skeletons.ogg',\
'sound/music/halloween/halloween.ogg',\
'sound/music/halloween/ghosts.ogg'
'sound/music/space.ogg',\
'sound/music/traitor.ogg',\
'sound/music/title2.ogg',\
'sound/music/clouds.s3m',\
'sound/music/space_oddity.ogg') //Ground Control to Major Tom, this song is cool, what's going on?
*/
send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
do
pregame_timeleft = 180
world << "<B><FONT color='blue'>Welcome to the pre-game lobby!</FONT></B>"
world << "Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds"
to_chat(world, "<B><FONT color='blue'>Welcome to the pregame lobby!</FONT></B>")
to_chat(world, "Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.")
while(current_state == GAME_STATE_PREGAME)
for(var/i=0, i<10, i++)
sleep(1)
@@ -65,7 +81,7 @@ var/global/datum/controller/gameticker/ticker
if(!runnable_modes.len)
current_state = GAME_STATE_PREGAME
Master.SetRunLevel(RUNLEVEL_LOBBY)
world << "<B>Unable to choose playable game mode.</B> Reverting to pre-game lobby."
to_chat(world, "<B>Unable to choose playable game mode.</B> Reverting to pregame lobby.")
return 0
if(secret_force_mode != "secret")
src.mode = config.pick_mode(secret_force_mode)
@@ -80,7 +96,7 @@ var/global/datum/controller/gameticker/ticker
if(!src.mode)
current_state = GAME_STATE_PREGAME
Master.SetRunLevel(RUNLEVEL_LOBBY)
world << "<span class='danger'>Serious error in mode setup!</span> Reverting to pre-game lobby."
to_chat(world, "<span class='danger'>Serious error in mode setup!</span> Reverting to pregame lobby.") //Uses setup instead of set up due to computational context.
return 0
job_master.ResetOccupations()
@@ -89,7 +105,7 @@ var/global/datum/controller/gameticker/ticker
job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly.
if(!src.mode.can_start())
world << "<B>Unable to start [mode.name].</B> Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby."
world << "<B>Unable to start [mode.name].</B> Not enough players readied, [mode.required_players] players needed. Reverting to pregame lobby."
current_state = GAME_STATE_PREGAME
Master.SetRunLevel(RUNLEVEL_LOBBY)
mode.fail_setup()
@@ -105,13 +121,13 @@ var/global/datum/controller/gameticker/ticker
tmpmodes+=M.name
tmpmodes = sortList(tmpmodes)
if(tmpmodes.len)
world << "<B>Possibilities:</B> [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]"
to_chat(world, "<B>Possibilities:</B> [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]")
else
src.mode.announce()
setup_economy()
current_state = GAME_STATE_PLAYING
create_characters() //Create player characters and transfer them
create_characters() //Create player characters and transfer them.
collect_minds()
equip_characters()
data_core.manifest()
@@ -128,7 +144,7 @@ var/global/datum/controller/gameticker/ticker
//Deleting Startpoints but we need the ai point to AI-ize people later
if (S.name != "AI")
qdel(S)
world << "<FONT color='blue'><B>Enjoy the game!</B></FONT>"
to_chat(world, "<FONT color='blue'><B>Enjoy the game!</B></FONT>")
world << sound('sound/AI/welcome.ogg') // Skie
//Holiday Round-start stuff ~Carn
Holiday_Game_Start()
@@ -141,7 +157,7 @@ var/global/datum/controller/gameticker/ticker
if(C.holder)
admins_number++
if(admins_number == 0)
send2adminirc("Round has started with no admins online.")
send2adminirc("A round has started with no admins online.")
/* supply_controller.process() //Start the supply shuttle regenerating points -- TLE // handled in scheduler
master_controller.process() //Start master_controller.process()
@@ -293,7 +309,7 @@ var/global/datum/controller/gameticker/ticker
if(captainless)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
M << "Colony Directorship not forced on anyone."
to_chat(M, "Colony Directorship not forced on anyone.")
proc/process()
@@ -329,7 +345,7 @@ var/global/datum/controller/gameticker/ticker
feedback_set_details("end_proper","nuke")
time_left = 1 MINUTE //No point waiting five minutes if everyone's dead.
if(!delay_end)
world << "<span class='notice'><b>Rebooting due to destruction of station in [round(time_left/600)] minutes.</b></span>"
to_chat(world, "<span class='notice'><b>Rebooting due to destruction of station in [round(time_left/600)] minutes.</b></span>")
else
feedback_set_details("end_proper","proper completion")
time_left = round(restart_timeout)
@@ -342,15 +358,15 @@ var/global/datum/controller/gameticker/ticker
while(time_left > 0)
if(delay_end)
break
world << "<span class='notice'><b>Restarting in [round(time_left/600)] minute\s.</b></span>"
to_chat(world, "<span class='notice'><b>Restarting in [round(time_left/600)] minute\s.</b></span>")
time_left -= 1 MINUTES
sleep(600)
if(!delay_end)
world.Reboot()
else
world << "<span class='notice'><b>An admin has delayed the round end.</b></span>"
to_chat(world, "<span class='notice'><b>An admin has delayed the round end.</b></span>")
else
world << "<span class='notice'><b>An admin has delayed the round end.</b></span>"
to_chat(world, "<span class='notice'><b>An admin has delayed the round end.</b></span>")
else if (mode_finished)
post_game = 1
@@ -360,7 +376,7 @@ var/global/datum/controller/gameticker/ticker
//call a transfer shuttle vote
spawn(50)
if(!round_end_announced) // Spam Prevention. Now it should announce only once.
world << "<span class='danger'>The round has ended!</span>"
to_chat(world, "<span class='danger'>The round has ended!</span>")
round_end_announced = 1
vote.autotransfer()
@@ -374,7 +390,7 @@ var/global/datum/controller/gameticker/ticker
var/turf/playerTurf = get_turf(Player)
if(emergency_shuttle.departed && emergency_shuttle.evac)
if(isNotAdminLevel(playerTurf.z))
Player << "<font color='blue'><b>You managed to survive, but were marooned on [station_name()] as [Player.real_name]...</b></font>"
Player << "<font color='blue'><b>You survived the round, but remained on [station_name()] as [Player.real_name].</b></font>"
else
Player << "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></font>"
else if(isAdminLevel(playerTurf.z))
@@ -415,9 +431,9 @@ var/global/datum/controller/gameticker/ticker
if (!robo.connected_ai)
if (robo.stat != 2)
world << "<b>[robo.name] (Played by: [robo.key]) survived as an AI-less synthetic! Its laws were:</b>"
world << "<b>[robo.name] (Played by: [robo.key]) survived as an AI-less stationbound synthetic! Its laws were:</b>"
else
world << "<b>[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a synthetic without an AI. Its laws were:</b>"
world << "<b>[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:</b>"
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
robo.laws.show_laws(world)

View File

@@ -1,7 +1,7 @@
/datum/game_mode/mercren
name = "Mercenaries & Renegades"
round_description = "A mercenary team has invaded the station, as well as other having brought their own form protection."
extended_round_description = "Mercenaries and traitors spawn during this round."
round_description = "A mercenary team has invaded the station, and others have brought their own form of protection."
extended_round_description = "Mercenaries and renegades spawn during this round."
config_tag = "mercren"
required_players = 16 //What could possibly go wrong?
required_players_secret = 15

View File

@@ -21,9 +21,14 @@
return 0
/obj/item/weapon/spell/proc/allowed_to_teleport()
if(owner && owner.z in using_map.admin_levels)
return 0
return 1
if(owner)
if(owner.z in using_map.admin_levels)
return FALSE
var/turf/T = get_turf(owner)
if(T.block_tele)
return FALSE
return TRUE
/obj/item/weapon/spell/proc/within_range(var/atom/target, var/max_range = 7) // Beyond 7 is off the screen.
if(range(get_dist(owner, target) <= max_range))

View File

@@ -23,9 +23,12 @@
var/turf/starting = get_turf(AM)
var/list/targets = list()
if(starting.block_tele)
return
valid_turfs:
for(var/turf/simulated/T in range(AM, range))
if(T.density || istype(T, /turf/simulated/mineral)) //Don't blink to vacuum or a wall
if(T.density || T.block_tele || istype(T, /turf/simulated/mineral)) //Don't blink to vacuum or a wall
continue
for(var/atom/movable/stuff in T.contents)
if(stuff.density)
@@ -54,7 +57,10 @@
if(istype(hit_atom, /atom/movable))
var/atom/movable/AM = hit_atom
if(!within_range(AM))
user << "<span class='warning'>\The [AM] is too far away to blink.</span>"
to_chat(user, "<span class='warning'>\The [AM] is too far away to blink.</span>")
return
if(!allowed_to_teleport())
to_chat(user, "<span class='warning'>Teleportation doesn't seem to work here.</span>")
return
if(pay_energy(400))
if(check_for_scepter())
@@ -67,6 +73,9 @@
to_chat(user, "<span class='warning'>You need more energy to blink [AM] away!</span>")
/obj/item/weapon/spell/blink/on_use_cast(mob/user)
if(!allowed_to_teleport())
to_chat(user, "<span class='warning'>Teleportation doesn't seem to work here.</span>")
return
if(pay_energy(200))
if(check_for_scepter())
safe_blink(user, calculate_spell_power(10))
@@ -80,6 +89,9 @@
/obj/item/weapon/spell/blink/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(istype(hit_atom, /atom/movable))
var/atom/movable/AM = hit_atom
if(!allowed_to_teleport())
to_chat(user, "<span class='warning'>Teleportation doesn't seem to work here.</span>")
return
if(pay_energy(300))
visible_message("<span class='danger'>\The [user] reaches out towards \the [AM] with a glowing hand.</span>")
if(check_for_scepter())

View File

@@ -68,6 +68,9 @@
user << "<span class='danger'>There's no Mark!</span>"
return 0
else
if(!allowed_to_teleport())
to_chat(user, "<span class='warning'>Teleportation doesn't seem to work here.</span>")
return
visible_message("<span class='warning'>\The [user] starts glowing!</span>")
var/light_intensity = 2
var/time_left = 3

View File

@@ -46,6 +46,9 @@
checked_turf = get_step(checked_turf, direction) //Advance in the given direction
total_cost += check_for_scepter() ? 400 : 800 //Phasing through matter's expensive, you know.
i--
if(checked_turf.block_tele) // The fun ends here.
break
if(!checked_turf.density) //If we found a destination (a non-dense turf), then we can stop.
var/dense_objs_on_turf = 0
for(var/atom/movable/stuff in checked_turf.contents) //Make sure nothing dense is where we want to go, like an airlock or window.

View File

@@ -462,3 +462,9 @@
/datum/access/trader
id = access_trader
access_type = ACCESS_TYPE_PRIVATE
/var/const/access_alien = 300 // For things like crashed ships.
/datum/access/alien
id = access_alien
desc = "#%_^&*@!"
access_type = ACCESS_TYPE_PRIVATE

View File

@@ -82,7 +82,7 @@
while(!accepted)
if(!B) break // prevents possible runtime errors
new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon")
new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Pagan", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon","Orthodox","Torah")
switch(new_book_style)
if("Koran")
B.icon_state = "koran"
@@ -90,9 +90,6 @@
if("Scrapbook")
B.icon_state = "scrapbook"
B.item_state = "scrapbook"
if("Creeper")
B.icon_state = "creeper"
B.item_state = "syringe_kit"
if("White Bible")
B.icon_state = "white"
B.item_state = "syringe_kit"
@@ -120,6 +117,15 @@
if("Necronomicon")
B.icon_state = "necronomicon"
B.item_state = "necronomicon"
if("Pagan")
B.icon_state = "shadows"
B.item_state = "syringe_kit"
if("Orthodox")
B.icon_state = "orthodoxy"
B.item_state = "bible"
if("Torah")
B.icon_state = "torah"
B.item_state = "clipboard"
else
B.icon_state = "bible"
B.item_state = "bible"

View File

@@ -76,7 +76,7 @@ var/global/datum/controller/occupations/job_master
proc/FreeRole(var/rank) //making additional slot on the fly
var/datum/job/job = GetJob(rank)
if(job && job.current_positions >= job.total_positions && job.total_positions != -1)
if(job && job.total_positions != -1)
job.total_positions++
return 1
return 0

View File

@@ -1,5 +1,5 @@
/obj/machinery/sleep_console
name = "Sleeper Console"
name = "sleeper console"
icon = 'icons/obj/Cryogenic2_vr.dmi' //VOREStation Edit - Better icon.
icon_state = "sleeperconsole"
var/obj/machinery/sleeper/sleeper
@@ -34,7 +34,7 @@
return 1
if(sleeper.panel_open)
user << "<span class='notice'>Close the maintenance panel first.</span>"
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
return
if(!sleeper)
@@ -44,7 +44,7 @@
else if(sleeper)
return sleeper.ui_interact(user)
else
user << "<span class='warning'>Sleeper not found!</span>"
to_chat(user, "<span class='warning'>Sleeper not found!</span>")
/obj/machinery/sleep_console/attackby(var/obj/item/I, var/mob/user)
if(computer_deconstruction_screwdriver(user, I))
@@ -61,7 +61,7 @@
/obj/machinery/sleeper
name = "sleeper"
desc = "A fancy bed with built-in injectors, a dialysis machine, and a limited health scanner."
desc = "A stasis pod with built-in injectors, a dialysis machine, and a limited health scanner."
icon = 'icons/obj/Cryogenic2_vr.dmi' //VOREStation Edit - Better icons
icon_state = "sleeper_0"
density = 1
@@ -181,7 +181,7 @@
return 1
if(usr == occupant)
usr << "<span class='warning'>You can't reach the controls from the inside.</span>"
to_chat(usr, "<span class='warning'>You can't reach the controls from the inside.</span>")
return
add_fingerprint(usr)
@@ -221,7 +221,7 @@
I.loc = src
user.visible_message("<span class='notice'>\The [user] adds \a [I] to \the [src].</span>", "<span class='notice'>You add \a [I] to \the [src].</span>")
else
user << "<span class='warning'>\The [src] has a beaker already.</span>"
to_chat(user, "<span class='warning'>\The [src] has a beaker already.</span>")
return
/obj/machinery/sleeper/verb/move_eject()
@@ -233,7 +233,7 @@
if(DEAD)
return
if(UNCONSCIOUS)
usr << "<span class='notice'>You struggle through the haze to hit the eject button. This will take a couple of minutes...</span>"
to_chat(usr, "<span class='notice'>You struggle through the haze to hit the eject button. This will take a couple of minutes...</span>")
sleep(2 MINUTES)
if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already
return
@@ -279,9 +279,11 @@
if(stat & (BROKEN|NOPOWER))
return
if(occupant)
user << "<span class='warning'>\The [src] is already occupied.</span>"
to_chat(user, "<span class='warning'>\The [src] is already occupied.</span>")
return
if(!ishuman(M))
to_chat(user, "<span class='warning'>\The [src] is not designed for that organism!</span>")
return
if(M == user)
visible_message("\The [user] starts climbing into \the [src].")
else
@@ -289,7 +291,7 @@
if(do_after(user, 20))
if(occupant)
user << "<span class='warning'>\The [src] is already occupied.</span>"
to_chat(user, "<span class='warning'>\The [src] is already occupied.</span>")
return
M.stop_pulling()
if(M.client)
@@ -333,8 +335,8 @@
if(occupant.reagents.get_reagent_amount(chemical) + amount <= 20)
use_power(amount * CHEM_SYNTH_ENERGY)
occupant.reagents.add_reagent(chemical, amount)
user << "Occupant now has [occupant.reagents.get_reagent_amount(chemical)] units of [available_chemicals[chemical]] in their bloodstream."
to_chat(user, "Occupant now has [occupant.reagents.get_reagent_amount(chemical)] units of [available_chemicals[chemical]] in their bloodstream.")
else
user << "The subject has too many chemicals."
to_chat(user, "The subject has too many chemicals in their bloodstream.")
else
user << "There's no suitable occupant in \the [src]."
to_chat(user, "There's no suitable occupant in \the [src].")

View File

@@ -39,20 +39,23 @@
else if(istype(G, /obj/item/weapon/grab))
var/obj/item/weapon/grab/H = G
if(panel_open)
user << "<span class='notice'>Close the maintenance panel first.</span>"
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
return
if(!ismob(H.affecting))
return
if(!ishuman(H.affecting))
to_chat(user, "<span class='warning'>\The [src] is not designed for that organism!</span>")
return
if(occupant)
user << "<span class='notice'>The scanner is already occupied!</span>"
to_chat(user, "<span class='notice'>\The [src] is already occupied!</span>")
return
for(var/mob/living/simple_animal/slime/M in range(1, H.affecting))
if(M.victim == H.affecting)
user << "<span class='danger'>[H.affecting.name] has a fucking slime attached to them, deal with that first.</span>"
to_chat(user, "<span class='danger'>[H.affecting.name] has a slime attached to them, deal with that first.</span>")
return
var/mob/M = H.affecting
if(M.abiotic())
user << "<span class='notice'>Subject cannot have abiotic items on.</span>"
to_chat(user, "<span class='notice'>Subject cannot have abiotic items on.</span>")
return
M.forceMove(src)
occupant = M
@@ -72,20 +75,20 @@
if(!ishuman(user) && !isrobot(user))
return 0 //not a borg or human
if(panel_open)
user << "<span class='notice'>Close the maintenance panel first.</span>"
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
return 0 //panel open
if(occupant)
user << "<span class='notice'>\The [src] is already occupied.</span>"
to_chat(user, "<span class='notice'>\The [src] is already occupied.</span>")
return 0 //occupied
if(O.buckled)
return 0
if(O.abiotic())
user << "<span class='notice'>Subject cannot have abiotic items on.</span>"
to_chat(user, "<span class='notice'>Subject cannot have abiotic items on.</span>")
return 0
for(var/mob/living/simple_animal/slime/M in range(1, O))
if(M.victim == O)
user << "<span class='danger'>[O] has a fucking slime attached to them, deal with that first.</span>"
to_chat(user, "<span class='danger'>[O] has a slime attached to them, deal with that first.</span>")
return 0
if(O == user)
@@ -185,9 +188,9 @@
var/obj/machinery/bodyscanner/C = P.connectable
scanner = C
C.console = src
user << "<span class='warning'> You link the [src] to the [P.connectable]!</span>"
to_chat(user, "<span class='warning'> You link the [src] to the [P.connectable]!</span>")
else
user << "<span class='warning'> You store the [src] in the [P]'s buffer!</span>"
to_chat(user, "<span class='warning'> You store the [src] in the [P]'s buffer!</span>")
P.connectable = src
return
else
@@ -243,7 +246,7 @@
return
if (scanner.panel_open)
user << "<span class='notice'>Close the maintenance panel first.</span>"
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
return
if(!scanner)
@@ -253,7 +256,7 @@
else if(scanner)
return ui_interact(user)
else
user << "<span class='warning'>Scanner not found!</span>"
to_chat(user, "<span class='warning'>Scanner not found!</span>")
/obj/machinery/body_scanconsole/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]

View File

@@ -180,15 +180,17 @@
if(!get_danger_level(target_temperature, TLV["temperature"]) && abs(environment.temperature - target_temperature) > 2.0)
update_use_power(2)
regulating_temperature = 1
visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
audible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click and a faint electronic hum.")
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
else
//check for when we should stop adjusting temperature
if(get_danger_level(target_temperature, TLV["temperature"]) || abs(environment.temperature - target_temperature) <= 0.5)
update_use_power(1)
regulating_temperature = 0
visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
audible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click as a faint electronic humming stops.")
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
if(regulating_temperature)
if(target_temperature > T0C + MAX_TEMPERATURE)

View File

@@ -40,6 +40,9 @@
else
update_icon()
/obj/machinery/portable_atmospherics/blob_act()
qdel(src)
/obj/machinery/portable_atmospherics/proc/StandardAirMix()
return list(
"oxygen" = O2STANDARD * MolesForPressure(),

View File

@@ -111,6 +111,11 @@
..() //and give it the regular chance of being deleted outright
/obj/machinery/camera/blob_act()
if((stat & BROKEN) || invuln)
return
destroy()
/obj/machinery/camera/hitby(AM as mob|obj)
..()
if (istype(AM, /obj))
@@ -130,7 +135,7 @@
if(user.species.can_shred(user))
set_status(0)
user.do_attack_animation(src)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
visible_message("<span class='warning'>\The [user] slashes at [src]!</span>")
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
add_hiddenprint(user)
@@ -210,7 +215,7 @@
src.bugged = 1
else if(W.damtype == BRUTE || W.damtype == BURN) //bashing cameras
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
if (W.force >= src.toughness)
user.do_attack_animation(src)
visible_message("<span class='warning'><b>[src] has been [W.attack_verb.len? pick(W.attack_verb) : "attacked"] with [W] by [user]!</b></span>")

View File

@@ -2,7 +2,7 @@
#define TRACKING_NO_COVERAGE 1
#define TRACKING_TERMINATE 2
/mob/living/silicon/ai/var/max_locations = 10
/mob/living/silicon/ai/var/max_locations = 30
/mob/living/silicon/ai/var/stored_locations[0]
/proc/InvalidPlayerTurf(turf/T as turf)

View File

@@ -59,6 +59,9 @@
set_broken()
..()
/obj/machinery/computer/blob_act()
ex_act(2)
/obj/machinery/computer/update_icon()
overlays.Cut()
if(stat & NOPOWER)

View File

@@ -31,7 +31,7 @@
var/turf/Tr = null
for(var/obj/item/weapon/implant/chem/C in world)
Tr = get_turf(C)
if(!Tr) continue//Out of range //VOREStation Edit
if(!Tr) continue//Out of range
if(!C.implanted) continue
dat += "[C.imp_in.name] | Remaining Units: [C.reagents.total_volume] | Inject: "
dat += "<A href='?src=\ref[src];inject1=\ref[C]'>(<font color=red>(1)</font>)</A>"
@@ -41,7 +41,7 @@
dat += "<HR>Tracking Implants<BR>"
for(var/obj/item/weapon/implant/tracking/T in world)
Tr = get_turf(T)
if(!Tr) continue//Out of range //VOREStation Edit
if(!Tr) continue//Out of range
if(!T.implanted) continue
var/loc_display = "Unknown"
var/mob/living/carbon/M = T.imp_in

View File

@@ -37,6 +37,7 @@
// Locks or unlocks the cyborg
if (href_list["lockdown"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
var/failmsg = ""
if(!target || !istype(target))
return
@@ -57,11 +58,19 @@
var/istraitor = target.mind.special_role
if (istraitor)
failmsg = "failed (target is traitor) "
target.lockcharge = !target.lockcharge
if (target.lockcharge)
target << "Someone tried to lock you down!"
to_chat(target, "Someone tried to lock you down!")
else
target << "Someone tried to lift your lockdown!"
to_chat(target, "Someone tried to lift your lockdown!")
else if (target.emagged)
failmsg = "failed (target is hacked) "
target.lockcharge = !target.lockcharge
if (target.lockcharge)
to_chat(target, "Someone tried to lock you down!")
else
to_chat(target, "Someone tried to lift your lockdown!")
else
target.canmove = !target.canmove
target.lockcharge = !target.canmove //when canmove is 1, lockcharge should be 0
@@ -70,7 +79,7 @@
target << "You have been locked down!"
else
target << "Your lockdown has been lifted!"
message_admins("<span class='notice'>[key_name_admin(usr)] [istraitor ? "failed (target is traitor) " : ""][target.lockcharge ? "lockdown" : "release"] on [target.name]!</span>")
message_admins("<span class='notice'>[key_name_admin(usr)] [failmsg][target.lockcharge ? "lockdown" : "release"] on [target.name]!</span>")
log_game("[key_name(usr)] attempted to [target.lockcharge ? "lockdown" : "release"] [target.name] on the robotics console!")

View File

@@ -96,7 +96,7 @@ for reference:
return
return
else
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
switch(W.damtype)
if("fire")
health -= W.force * 1

View File

@@ -197,8 +197,14 @@
/obj/machinery/door/airlock/centcom
name = "Centcom Airlock"
icon = 'icons/obj/doors/Doorele.dmi'
//opacity = 0 //VOREStation Edit - Why is this like this??
req_one_access = list(access_cent_general)
opacity = 1
/obj/machinery/door/airlock/glass_centcom
name = "Airlock"
icon = 'icons/obj/doors/Dooreleglass.dmi'
opacity = 0
glass = 1
/obj/machinery/door/airlock/vault
name = "Vault"
@@ -447,6 +453,24 @@
icon = 'icons/obj/doors/shuttledoors_vertical.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft/vertical
/obj/machinery/door/airlock/alien
name = "alien airlock"
desc = "You're fairly sure this is a door."
icon = 'icons/obj/doors/Dooralien.dmi'
explosion_resistance = 20
secured_wires = TRUE
hackProof = TRUE
assembly_type = /obj/structure/door_assembly/door_assembly_alien
req_one_access = list(access_alien)
/obj/machinery/door/airlock/alien/locked
icon_state = "door_locked"
locked = TRUE
/obj/machinery/door/airlock/alien/public // Entry to UFO.
req_one_access = list()
normalspeed = FALSE // So it closes faster and hopefully keeps the warm air inside.
/*
About the new airlock wires panel:
* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires.

View File

@@ -132,7 +132,7 @@
else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's a weapon, let's hit it.
var/obj/item/weapon/W = C
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
if(W.damtype == BRUTE || W.damtype == BURN)
user.do_attack_animation(src)
if(W.force < min_force)
@@ -162,7 +162,7 @@
else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's not a weapon.... Eh, let's attack it anyway.
var/obj/item/weapon/W = C
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
if(W.damtype == BRUTE || W.damtype == BURN)
user.do_attack_animation(src)
if(W.force < min_force) //No actual non-weapon item shouls have a force greater than the min_force, but let's include this just in case.

View File

@@ -262,7 +262,7 @@
//psa to whoever coded this, there are plenty of objects that need to call attack() on doors without bludgeoning them.
if(src.density && istype(I, /obj/item/weapon) && user.a_intent == I_HURT && !istype(I, /obj/item/weapon/card))
var/obj/item/weapon/W = I
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
if(W.damtype == BRUTE || W.damtype == BURN)
user.do_attack_animation(src)
if(W.force < min_force)
@@ -357,6 +357,13 @@
take_damage(150)
return
/obj/machinery/door/blob_act()
if(density) // If it's closed.
if(stat & BROKEN)
spawn(0)
open(1)
else
take_damage(100)
/obj/machinery/door/update_icon()
if(density)

View File

@@ -391,6 +391,7 @@
else
use_power(360)
else
if(usr && usr.ckey)
log_admin("[usr]([usr.ckey]) has forced open an emergency shutter.")
message_admins("[usr]([usr.ckey]) has forced open an emergency shutter.")
latetoggle()

View File

@@ -161,7 +161,7 @@
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("<span class='danger'>[user] smashes against the [src.name].</span>", 1)
user.do_attack_animation(src)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
take_damage(25)
return
return src.attackby(user, user)
@@ -246,7 +246,7 @@
//If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway)
if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card))
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(I))
var/aforce = I.force
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("<span class='danger'>[src] was hit by [I].</span>")

View File

@@ -36,6 +36,11 @@
name = "surgery holosign"
desc = "Small wall-mounted holographic projector. This one reads SURGERY."
on_icon = "surgery"
/obj/machinery/holosign/exit
name = "exit holosign"
desc = "Small wall-mounted holographic projector. This one reads EXIT."
on_icon = "exit"
////////////////////SWITCH///////////////////////////////////////
/obj/machinery/button/holosign

View File

@@ -86,6 +86,23 @@
health = 250 // Since lasers do 40 each.
maxhealth = 250
/obj/machinery/porta_turret/alien // The kind used on the UFO submap.
name = "interior anti-boarding turret"
desc = "A very tough looking turret made by alien hands."
installation = /obj/item/weapon/gun/energy/alien
enabled = TRUE
lethal = TRUE
ailock = TRUE
check_all = TRUE
health = 250 // Similar to the AI turrets.
maxhealth = 250
/obj/machinery/porta_turret/alien/destroyed // Turrets that are already dead, to act as a warning of what the rest of the submap contains.
name = "broken interior anti-boarding turret"
desc = "A very tough looking turret made by alien hands. This one looks destroyed, thankfully."
icon_state = "destroyed_target_prism"
stat = BROKEN
/obj/machinery/porta_turret/New()
..()
req_access.Cut()
@@ -103,6 +120,11 @@
req_one_access.Cut()
req_access = list(access_cent_specops)
/obj/machinery/porta_turret/alien/New()
..()
req_one_access.Cut()
req_access = list(access_alien)
/obj/machinery/porta_turret/Destroy()
qdel(spark_system)
spark_system = null
@@ -359,7 +381,7 @@ var/list/turret_icons
else
//if the turret was attacked with the intention of harming it:
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(I))
take_damage(I.force * 0.5)
if(I.force * 0.5 > 1) //if the force of impact dealt at least 1 damage, the turret gets pissed off
if(!attacked && !emagged)
@@ -436,6 +458,14 @@ var/list/turret_icons
return
..()
/obj/machinery/porta_turret/alien/emp_act(severity) // This is overrided to give an EMP resistance as well as avoid scambling the turret settings.
if(prob(75)) // Superior alien technology, I guess.
return
enabled = FALSE
spawn(rand(1 MINUTE, 2 MINUTES))
if(!enabled)
enabled = TRUE
/obj/machinery/porta_turret/ex_act(severity)
switch (severity)
if(1)

View File

@@ -103,13 +103,6 @@
R.adjustFireLoss(-wire_rate)
else if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
if(!isnull(H.internal_organs_by_name["cell"]) && H.nutrition < 450)
H.nutrition = min(H.nutrition+10, 450)
cell.use(7000/450*10)
else if(istype(occupant, /mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant
// In case they somehow end up with positive values for otherwise unobtainable damage...
if(H.getToxLoss()>0) H.adjustToxLoss(-(rand(1,3)))
@@ -153,9 +146,21 @@
return
if(default_part_replacement(user, O))
return
if (istype(O, /obj/item/weapon/grab) && get_dist(src,user)<2)
var/obj/item/weapon/grab/G = O
if(istype(G.affecting,/mob/living))
var/mob/living/M = G.affecting
qdel(O)
go_in(M)
..()
/obj/machinery/recharge_station/MouseDrop_T(var/mob/target, var/mob/user)
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user))
return
go_in(target)
/obj/machinery/recharge_station/RefreshParts()
..()
var/man_rating = 0
@@ -214,15 +219,16 @@
if(icon_update_tick == 0)
build_overlays()
/obj/machinery/recharge_station/Bumped(var/mob/living/silicon/robot/R)
go_in(R)
/obj/machinery/recharge_station/Bumped(var/mob/living/L)
go_in(L)
/obj/machinery/recharge_station/proc/go_in(var/mob/living/silicon/robot/R)
/obj/machinery/recharge_station/proc/go_in(var/mob/living/L)
if(occupant)
return
if(istype(R, /mob/living/silicon/robot))
if(istype(L, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = L
if(R.incapacitated())
return
@@ -237,8 +243,8 @@
update_icon()
return 1
else if(istype(R, /mob/living/carbon/human))
var/mob/living/carbon/human/H = R
else if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/H = L
if(!isnull(H.internal_organs_by_name["cell"]))
add_fingerprint(H)
H.reset_view(src)

View File

@@ -1,6 +1,6 @@
//not a computer
obj/machinery/scanner
name = "Identity Analyser"
name = "identity analyzer"
var/outputdir = 0
icon = 'icons/obj/stationobjs.dmi'
icon_state = "scanner_idle"
@@ -70,7 +70,7 @@ obj/machinery/scanner/attack_hand(mob/living/carbon/human/user)
<b><u>Black Marks</u></b>:<br> "}
for(var/A in marks)
text += "<span class='danger'>[A]</span><br>"
user << "<span class='notice'>You feel a sting as the scanner extracts some of your blood.</span>"
to_chat(user, "<span class='notice'>You feel a sting as the scanner extracts some of your blood.</span>")
var/turf/T = get_step(src,outputdir)
var/obj/item/weapon/paper/print = new(T)
print.name = "[mname] Report"

View File

@@ -23,7 +23,7 @@ var/req_console_information = list()
var/list/obj/machinery/requests_console/allConsoles = list()
/obj/machinery/requests_console
name = "Requests Console"
name = "requests console"
desc = "A console intended to send requests to different departments on the station."
anchored = 1
icon = 'icons/obj/terminals.dmi'
@@ -72,7 +72,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
announcement.title = "[department] announcement"
announcement.newscast = 1
name = "[department] Requests Console"
name = "[department] requests console"
allConsoles += src
if(departmentType & RC_ASSIST)
req_console_assistance |= department
@@ -208,15 +208,15 @@ var/list/obj/machinery/requests_console/allConsoles = list()
updateUsrDialog()
return
//err... hacking code, which has no reason for existing... but anyway... it was once supposed to unlock priority 3 messanging on that console (EXTREME priority...), but the code for that was removed.
//err... hacking code, which has no reason for existing... but anyway... it was once supposed to unlock priority 3 messaging on that console (EXTREME priority...), but the code for that was removed.
/obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob)
if(computer_deconstruction_screwdriver(user, O))
return
if(istype(O, /obj/item/device/multitool))
if(panel_open)
var/input = sanitize(input(usr, "What Department id would you like to give this Request Console?", "Multitool-Request Console interface", department))
var/input = sanitize(input(usr, "What Department ID would you like to give this request console?", "Multitool-Request Console Interface", department))
if(!input)
usr << "No input found please hang up and try your call again."
to_chat(usr, "No input found. Please hang up and try your call again.")
return
department = input
announcement.title = "[department] announcement"

View File

@@ -1,5 +1,5 @@
/obj/machinery/robotic_fabricator
name = "Robotic Fabricator"
name = "robotic fabricator"
icon = 'icons/obj/robotics.dmi'
icon_state = "fab-idle"
density = 1
@@ -30,7 +30,7 @@
overlays -= "fab-load-metal"
updateDialog()
else
user << "The robot part maker is full. Please remove metal from the robot part maker in order to insert more."
to_chat(user, "The robot part maker is full. Please remove metal from the robot part maker in order to insert more.")
/obj/machinery/robotic_fabricator/attack_hand(user as mob)
var/dat

View File

@@ -47,7 +47,7 @@
/obj/machinery/power/supply_beacon/attackby(var/obj/item/weapon/W, var/mob/user)
if(!use_power && istype(W, /obj/item/weapon/wrench))
if(!anchored && !connect_to_network())
user << "<span class='warning'>This device must be placed over an exposed cable.</span>"
to_chat(user, "<span class='warning'>This device must be placed over an exposed cable.</span>")
return
anchored = !anchored
user.visible_message("<span class='notice'>\The [user] [anchored ? "secures" : "unsecures"] \the [src].</span>")
@@ -59,13 +59,13 @@
if(expended)
use_power = 0
user << "<span class='warning'>\The [src] has used up its charge.</span>"
to_chat (user, "<span class='warning'>\The [src] has used up its charge.</span>")
return
if(anchored)
return use_power ? deactivate(user) : activate(user)
else
user << "<span class='warning'>You need to secure the beacon with a wrench first!</span>"
to_chat(user, "<span class='warning'>You need to secure the beacon with a wrench first!</span>")
return
/obj/machinery/power/supply_beacon/attack_ai(var/mob/user)
@@ -76,12 +76,12 @@
if(expended)
return
if(surplus() < 500)
if(user) user << "<span class='notice'>The connected wire doesn't have enough current.</span>"
if(user) to_chat(user, "<span class='notice'>The connected wire doesn't have enough current.</span>")
return
set_light(3, 3, "#00CCAA")
icon_state = "beacon_active"
use_power = 1
if(user) user << "<span class='notice'>You activate the beacon. The supply drop will be dispatched soon.</span>"
if(user) to_chat(user, "<span class='notice'>You activate the beacon. The supply drop will be dispatched soon.</span>")
/obj/machinery/power/supply_beacon/proc/deactivate(var/mob/user, var/permanent)
if(permanent)
@@ -92,7 +92,7 @@
set_light(0)
use_power = 0
target_drop_time = null
if(user) user << "<span class='notice'>You deactivate the beacon.</span>"
if(user) to_chat(user, "<span class='notice'>You deactivate the beacon.</span>")
/obj/machinery/power/supply_beacon/Destroy()
if(use_power)

View File

@@ -1,5 +1,5 @@
/obj/machinery/computer/teleporter
name = "Teleporter Control Console"
name = "teleporter control console"
desc = "Used to control a linked teleportation Hub and Station."
icon_keyboard = "teleport_key"
icon_screen = "teleport"
@@ -56,8 +56,8 @@
L = locate("landmark*[C.data]") // use old stype
if(istype(L, /obj/effect/landmark/) && istype(L.loc, /turf))
usr << "You insert the coordinates into the machine."
usr << "A message flashes across the screen reminding the traveller that the nuclear authentication disk is to remain on the station at all times."
to_chat(usr, "You insert the coordinates into the machine.")
to_chat(usr, "A message flashes across the screen, reminding the user that the nuclear authentication disk is not transportable via insecure means.")
user.drop_item()
qdel(I)

View File

@@ -0,0 +1,110 @@
/obj/machinery/transportpod
name = "Ballistic Transportation Pod"
desc = "A fast transit ballistic pod used to get from one place to the next. Batteries not included!"
icon = 'icons/obj/structures.dmi'
icon_state = "borg_pod_opened"
density = 1 //thicc
anchored = 1
use_power = 0
var/in_transit = 0
var/mob/occupant = null
var/xc = list(137, 209, 163, 110, 95, 60, 129, 201) // List of x values on the map to go to.
var/yc = list(134, 99, 169, 120, 96, 122, 189, 219) // List of y values on the map to go to.
var/limit_x = 3
var/limit_y = 3
/obj/machinery/transportpod/process()
if(occupant)
if(in_transit)
var/locNum = rand(0, 7) //pick a random location
var/turf/L = locate(xc[locNum], yc[locNum], 1) // Pairs the X and Y to get an actual location.
limit_x = xc[locNum]+1
limit_y = yc[locNum]+1
build()
sleep(20) //Give explosion time so the pod itself doesn't go boom
src.forceMove(L)
playsound(src, pick('sound/effects/Explosion1.ogg', 'sound/effects/Explosion2.ogg', 'sound/effects/Explosion3.ogg', 'sound/effects/Explosion4.ogg'))
in_transit = 0
sleep(2)
go_out()
sleep(2)
del(src)
/obj/machinery/transportpod/relaymove(mob/user as mob)
if(user.stat)
return
go_out()
return
/obj/machinery/transportpod/update_icon()
..()
if(occupant)
icon_state = "borg_pod_closed"
else
icon_state = "borg_pod_opened"
/obj/machinery/transportpod/Bumped(var/mob/living/O)
go_in(O)
/obj/machinery/transportpod/proc/go_in(var/mob/living/carbon/human/O)
if(occupant)
return
if(O.incapacitated()) //aint no sleepy people getting in here
return
add_fingerprint(O)
O.reset_view(src)
O.forceMove(src)
occupant = O
update_icon()
if(alert(O, "Are you sure you're ready to launch?", , "Yes", "No") == "Yes")
in_transit = 1
playsound(src, HYPERSPACE_WARMUP)
else
go_out()
return 1
/obj/machinery/transportpod/proc/go_out()
if(!occupant)
return
occupant.forceMove(src.loc)
occupant.reset_view()
occupant = null
update_icon()
/obj/machinery/transportpod/verb/move_eject()
set category = "Object"
set name = "Eject Pod"
set src in oview(1)
if(usr.incapacitated())
return
go_out()
add_fingerprint(usr)
return
/obj/machinery/transportpod/verb/move_inside()
set category = "Object"
set name = "Enter Pod"
set src in oview(1)
if(usr.incapacitated()) //just to DOUBLE CHECK the damn sleepy people don't touch the pod
return
go_in(usr)
/obj/machinery/transportpod/proc/build()
for(var/x = limit_x-2, x <= limit_x, x++)
for(var/y = limit_y-2, y <= limit_y, y++)
var/current_cell = locate(x, y, 1)
var/turf/T = get_turf(current_cell)
if(!current_cell)
continue
T.ChangeTurf(/turf/unsimulated/floor/shuttle_ceiling)

View File

@@ -147,7 +147,7 @@
/obj/machinery/vending/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
emagged = 1
user << "You short out the product lock on \the [src]"
to_chat(user, "You short out \the [src]'s product lock.")
return 1
/obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -182,7 +182,7 @@
return
else if(istype(W, /obj/item/weapon/screwdriver))
panel_open = !panel_open
user << "You [panel_open ? "open" : "close"] the maintenance panel."
to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
playsound(src, W.usesound, 50, 1)
overlays.Cut()
if(panel_open)
@@ -199,7 +199,7 @@
W.forceMove(src)
coin = W
categories |= CAT_COIN
user << "<span class='notice'>You insert \the [W] into \the [src].</span>"
to_chat(user, "<span class='notice'>You insert \the [W] into \the [src].</span>")
nanomanager.update_uis(src)
return
else if(istype(W, /obj/item/weapon/wrench))
@@ -211,7 +211,7 @@
if(do_after(user, 20 * W.toolspeed))
if(!src) return
user << "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>"
to_chat(user, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
anchored = !anchored
return
else
@@ -232,7 +232,7 @@
// This is not a status display message, since it's something the character
// themselves is meant to see BEFORE putting the money in
usr << "\icon[cashmoney] <span class='warning'>That is not enough money.</span>"
to_chat(usr, "\icon[cashmoney] <span class='warning'>That is not enough money.</span>")
return 0
if(istype(cashmoney, /obj/item/weapon/spacecash))
@@ -418,21 +418,22 @@
if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon))
if(!coin)
usr << "There is no coin in this machine."
to_chat(usr, "There is no coin in this machine.")
return
coin.forceMove(src.loc)
if(!usr.get_active_hand())
usr.put_in_hands(coin)
usr << "<span class='notice'>You remove \the [coin] from \the [src]</span>"
to_chat(usr, "<span class='notice'>You remove \the [coin] from \the [src]</span>")
coin = null
categories &= ~CAT_COIN
if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))))
if((href_list["vend"]) && (vend_ready) && (!currently_vending))
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
usr << "<span class='warning'>Access denied.</span>" //Unless emagged of course
to_chat(usr, "<span class='warning'>Access denied.</span>") //Unless emagged of course
flick(icon_deny,src)
playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0)
return
var/key = text2num(href_list["vend"])
@@ -445,12 +446,12 @@
if(R.price <= 0)
vend(R, usr)
else if(istype(usr,/mob/living/silicon)) //If the item is not free, provide feedback if a synth is trying to buy something.
usr << "<span class='danger'>Artificial unit recognized. Artificial units cannot complete this transaction. Purchase canceled.</span>"
to_chat(usr, "<span class='danger'>Lawed unit recognized. Lawed units cannot complete this transaction. Purchase canceled.</span>")
return
else
currently_vending = R
if(!vendor_account || vendor_account.suspended)
status_message = "This machine is currently unable to process payments due to problems with the associated account."
status_message = "This machine is currently unable to process payments due to issues with the associated account."
status_error = 1
else
status_message = "Please swipe a card or insert cash to pay for the item."
@@ -467,8 +468,9 @@
/obj/machinery/vending/proc/vend(datum/stored_item/vending_product/R, mob/user)
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
usr << "<span class='warning'>Access denied.</span>" //Unless emagged of course
to_chat(usr, "<span class='warning'>Access denied.</span>") //Unless emagged of course
flick(icon_deny,src)
playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0)
return
vend_ready = 0 //One thing at a time!!
status_message = "Vending..."
@@ -477,13 +479,13 @@
if(R.category & CAT_COIN)
if(!coin)
user << "<span class='notice'>You need to insert a coin to get this item.</span>"
to_chat(user, "<span class='notice'>You need to insert a coin to get this item.</span>")
return
if(coin.string_attached)
if(prob(50))
user << "<span class='notice'>You successfully pull the coin out before \the [src] could swallow it.</span>"
to_chat(user, "<span class='notice'>You successfully pull the coin out before \the [src] could swallow it.</span>")
else
user << "<span class='notice'>You weren't able to pull the coin out fast enough, the machine ate it, string and all.</span>"
to_chat(user, "<span class='notice'>You weren't able to pull the coin out fast enough, the machine ate it, string and all.</span>")
qdel(coin)
coin = null
categories &= ~CAT_COIN
@@ -685,6 +687,7 @@
/obj/item/weapon/reagent_containers/food/drinks/glass2/pint = 10,
/obj/item/weapon/reagent_containers/food/drinks/glass2/mug = 10,
/obj/item/weapon/reagent_containers/food/drinks/glass2/wine = 10,
/obj/item/weapon/reagent_containers/food/drinks/metaglass = 10,
/obj/item/weapon/reagent_containers/food/drinks/bottle/gin = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/bluecuracao = 5,
@@ -765,7 +768,7 @@
/obj/machinery/vending/cola
name = "Robust Softdrinks"
desc = "A softdrink vendor provided by Robust Industries, LLC."
icon_state = "Cola_Machine"
icon_state = "soda-blu"
product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!"
product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space."
products = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 10,
@@ -805,7 +808,6 @@
contraband = list(/obj/item/weapon/reagent_containers/syringe/steroid = 4)
//This one's from bay12
/obj/machinery/vending/cart
name = "PTech"
desc = "Cartridges for PDAs."
@@ -820,7 +822,7 @@
has_logs = 1
/obj/machinery/vending/cigarette
name = "Cigarette machine" //OCD had to be uppercase to look nice with the new formating
name = "cigarette machine"
desc = "If you want to get cancer, might as well do it in style!"
product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!"
product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs.;Feeling temperamental? Try a Temperamento!;Carcinoma Angels - go fuck yerself!;Don't be so hard on yourself, kid. Smoke a Lucky Star!"
@@ -864,7 +866,6 @@
req_log_access = access_cmo
has_logs = 1
//This one's from bay12
/obj/machinery/vending/phoronresearch
name = "Toximate 3000"
desc = "All the fine parts you need in one vending machine!"
@@ -993,6 +994,7 @@
/obj/item/weapon/glass_extra/stick = 15,
/obj/item/weapon/glass_extra/straw = 15,
/obj/item/clothing/suit/chef/classic = 2,
/obj/item/weapon/storage/bag/food = 2,
/obj/item/weapon/storage/toolbox/lunchbox = 3,
/obj/item/weapon/storage/toolbox/lunchbox/heart = 3,
/obj/item/weapon/storage/toolbox/lunchbox/cat = 3,
@@ -1050,7 +1052,6 @@
req_log_access = access_ce
has_logs = 1
//This one's from bay12
/obj/machinery/vending/engineering
name = "Robco Tool Maker"
desc = "Everything you need for do-it-yourself station repair."
@@ -1069,7 +1070,6 @@
req_log_access = access_ce
has_logs = 1
//This one's from bay12
/obj/machinery/vending/robotics
name = "Robotech Deluxe"
desc = "All the tools you need to create your own robot army."

View File

@@ -1,5 +1,5 @@
/obj/machinery/vr_sleeper
name = "VR sleeper"
name = "virtual reality sleeper"
desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality."
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "syndipod_0"
@@ -53,6 +53,10 @@
if(default_deconstruction_screwdriver(user, I))
return
else if(default_deconstruction_crowbar(user, I))
if(occupant && avatar)
avatar.exit_vr()
avatar = null
go_out()
return
@@ -213,10 +217,9 @@
occupant.enter_vr(avatar)
// Prompt for username after they've enterred the body.
var/newname = sanitize(input(avatar, "You are enterring virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change") as null|text, MAX_NAME_LEN)
var/newname = sanitize(input(avatar, "You are entering virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change") as null|text, MAX_NAME_LEN)
if (newname)
avatar.real_name = newname
else
occupant.enter_vr(avatar)

View File

@@ -9,7 +9,7 @@
equip_cooldown = 50
var/mob/living/carbon/human/occupant = null
var/datum/global_iterator/pr_mech_sleeper
var/inject_amount = 10
var/inject_amount = 5
required_type = /obj/mecha/medical
salvageable = 0
@@ -185,10 +185,14 @@
if(!R || !occupant || !SG || !(SG in chassis.equipment))
return 0
var/to_inject = min(R.volume, inject_amount)
if(to_inject && occupant.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2)
if(to_inject && occupant.reagents.get_reagent_amount(R.id) + to_inject > inject_amount*4)
occupant_message("Sleeper safeties prohibit you from injecting more than [inject_amount*4] units of [R.name].")
else
occupant_message("Injecting [occupant] with [to_inject] units of [R.name].")
log_message("Injecting [occupant] with [to_inject] units of [R.name].")
SG.reagents.trans_id_to(occupant,R.id,to_inject)
//SG.reagents.trans_id_to(occupant,R.id,to_inject)
SG.reagents.remove_reagent(R.id,to_inject)
occupant.reagents.add_reagent(R.id,to_inject)
update_equip_info()
return
@@ -200,6 +204,19 @@
return 1
return
/obj/item/mecha_parts/mecha_equipment/tool/sleeper/verb/eject()
set name = "Sleeper Eject"
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
if(usr!=src.occupant || usr.stat == 2)
return
to_chat(usr,"<span class='notice'>Release sequence activated. This will take one minute.</span>")
sleep(600)
if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already
return
go_out()//and release him from the eternal prison.
/datum/global_iterator/mech_sleeper
process(var/obj/item/mecha_parts/mecha_equipment/tool/sleeper/S)

View File

@@ -505,7 +505,7 @@
return
/obj/mecha/attack_hand(mob/user as mob)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
src.log_message("Attack by hand/paw. Attacker - [user].",1)
if(istype(user,/mob/living/carbon/human))
@@ -513,7 +513,6 @@
if(H.species.can_shred(user))
if(!prob(src.deflect_chance))
src.take_damage(15)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
user << "<span class='danger'>You slash at the armored suit!</span>"
@@ -666,7 +665,7 @@
return
/obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
src.log_message("Attacked by [W]. Attacker - [user]")
if(prob(src.deflect_chance))
user << "<span class='danger'>\The [W] bounces off [src.name].</span>"
@@ -1763,7 +1762,7 @@
/obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
if(!damage)
return 0

View File

@@ -99,7 +99,9 @@
C.images += holder
holder = patient.hud_list[STATUS_HUD]
if(patient.stat == DEAD)
if(patient.isSynthetic())
holder.icon_state = "hudrobo"
else if(patient.stat == DEAD)
holder.icon_state = "huddead"
else if(foundVirus)
holder.icon_state = "hudill"

View File

@@ -68,7 +68,7 @@
/atom/movable/proc/user_buckle_mob(mob/living/M, mob/user, var/forced = FALSE, var/silent = FALSE)
if(!ticker)
user << "<span class='warning'>You can't buckle anyone in before the game starts.</span>"
if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat || istype(user, /mob/living/silicon/pai))
if(!user.Adjacent(M) || user.restrained() || user.stat || istype(user, /mob/living/silicon/pai))
return
if(M == buckled_mob)
return

View File

@@ -120,7 +120,7 @@
/obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
var/aforce = W.force
health = max(0, health - aforce)
playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
@@ -227,7 +227,7 @@ Alien plants should do something if theres a lot of poison
return
/obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
if(W.attack_verb.len)
visible_message("<span class='danger'>\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")
else

View File

@@ -3,7 +3,7 @@
icon = 'icons/effects/effects.dmi'
icon_state = "extinguish"
mouse_opacity = 0
pass_flags = PASSTABLE | PASSGRILLE
pass_flags = PASSTABLE | PASSGRILLE | PASSBLOB
/obj/effect/effect/water/New(loc)
..()
@@ -27,7 +27,7 @@
var/mob/M
for(var/atom/A in T)
if(!ismob(A) && A.simulated) // Mobs are handled differently
reagents.touch(A)
reagents.touch(A, reagents.total_volume)
else if(ismob(A) && !M)
M = A
if(M)

View File

@@ -68,3 +68,9 @@
var/datum/effect/effect/system/smoke_spread/S = new/datum/effect/effect/system/smoke_spread()
S.set_up(5,0,location,null)
S.start()
/datum/effect/system/explosion/smokeless/start()
new/obj/effect/explosion(location)
var/datum/effect/system/expl_particles/P = new/datum/effect/system/expl_particles()
P.set_up(10,location)
P.start()

View File

@@ -21,7 +21,7 @@
return
/obj/effect/spider/attackby(var/obj/item/weapon/W, var/mob/user)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
if(W.attack_verb.len)
visible_message("<span class='warning'>\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")
@@ -218,25 +218,8 @@
//=================
if(isturf(loc))
if(prob(25))
var/list/nearby = trange(5, src) - loc
if(nearby.len)
var/target_atom = pick(nearby)
walk_to(src, target_atom, 5)
if(prob(25))
src.visible_message("<span class='notice'>\The [src] skitters[pick(" away"," around","")].</span>")
else if(prob(5))
//vent crawl!
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
if(!v.welded)
entry_vent = v
walk_to(src, entry_vent, 5)
break
skitter()
if(amount_grown >= 100)
var/spawn_type = pick(grow_as)
new spawn_type(src.loc, src)
qdel(src)
else if(isorgan(loc))
if(!amount_grown) amount_grown = 1
var/obj/item/organ/external/O = loc
@@ -257,6 +240,27 @@
if(amount_grown)
amount_grown += rand(0,2)
/obj/effect/spider/spiderling/proc/skitter()
if(isturf(loc))
if(prob(25))
var/list/nearby = trange(5, src) - loc
if(nearby.len)
var/target_atom = pick(nearby)
walk_to(src, target_atom, 5)
if(prob(25))
src.visible_message("<span class='notice'>\The [src] skitters[pick(" away"," around","")].</span>")
else if(prob(5))
//vent crawl!
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
if(!v.welded)
entry_vent = v
walk_to(src, entry_vent, 5)
break
if(amount_grown >= 100)
var/spawn_type = pick(grow_as)
new spawn_type(src.loc, src)
qdel(src)
/obj/effect/decal/cleanable/spiderling_remains
name = "spiderling remains"
desc = "Green squishy mess."
@@ -269,7 +273,7 @@
icon_state = "cocoon1"
health = 60
New()
/obj/effect/spider/cocoon/New()
icon_state = pick("cocoon1","cocoon2","cocoon3")
/obj/effect/spider/cocoon/Destroy()

View File

@@ -175,12 +175,9 @@ var/global/list/tele_landmarks = list() // Terrible, but the alternative is loop
if(isliving(A)) // Someday, implement parachutes. For now, just turbomurder whoever falls.
var/mob/living/L = A
for(var/i = 1 to 6)
L.adjustBruteLoss(100)
L.fall_impact(T, 42, 90, FALSE, TRUE) //You will not be defibbed from this.
message_admins("\The [A] fell out of the sky.")
explosion(T, 0, 1, 2)
A.forceMove(T)
T.visible_message("<span class='danger'><font size='3'>\A [A] falls out of the sky and crashes into \the [T]!</font></span>")
else
message_admins("ERROR: planetary_fall step trigger lacks a planet to fall onto.")
return

View File

@@ -80,6 +80,8 @@
var/list/sprite_sheets_obj = list()
var/toolspeed = 1.0 // This is a multipler on how 'fast' a tool works. e.g. setting this to 0.5 will make the tool work twice as fast.
var/attackspeed = DEFAULT_ATTACK_COOLDOWN // How long click delay will be when using this, in 1/10ths of a second. Checked in the user's get_attack_speed().
var/reach = 1 // Length of tiles it can reach, 1 is adjacent.
var/addblends // Icon overlay for ADD highlights when applicable.
/obj/item/New()
@@ -457,7 +459,7 @@ var/list/global/slot_flags_enumeration = list(
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])</font>"
msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)") //BS12 EDIT ALG
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
user.do_attack_animation(M)
src.add_fingerprint(user)
@@ -640,3 +642,11 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
/obj/item/proc/pwr_drain()
return 0 // Process Kill
// Used for non-adjacent melee attacks with specific weapons capable of reaching more than one tile.
// This uses changeling range string A* but for this purpose its also applicable.
/obj/item/proc/attack_can_reach(var/atom/us, var/atom/them, var/range)
if(us.Adjacent(them))
return TRUE // Already adjacent.
if(AStar(get_turf(us), get_turf(them), /turf/proc/AdjacentTurfsRangedSting, /turf/proc/Distance, max_nodes=25, max_node_depth=range))
return TRUE
return FALSE

View File

@@ -429,6 +429,13 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
exonet.send_message(their_address, "text", text)
im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text))
log_pda("[usr] (COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]")
for(var/mob/M in player_list)
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
continue
if(exonet.get_atom_from_address(their_address) == M)
continue
M.show_message("Comm IM - [src] -> [exonet.get_atom_from_address(their_address)]: [text]")
if(href_list["disconnect"])
var/name_to_disconnect = href_list["disconnect"]
@@ -988,6 +995,14 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
src << "<span class='notice'>You have sent '[text_message]' to [chosen_communicator].</span>"
exonet_messages.Add("<b>To [chosen_communicator]:</b><br>[text_message]")
log_pda("[usr] (COMM: [src]) sent \"[text_message]\" to [chosen_communicator]")
for(var/mob/M in player_list)
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
continue
if(M == src)
continue
M.show_message("Comm IM - [src] -> [chosen_communicator]: [text_message]")
// Verb: show_text_messages()

View File

@@ -35,8 +35,8 @@
qdel_null(paddles)
qdel_null(bcell)
/obj/item/device/defib_kit/loaded //starts with highcap cell
bcell = /obj/item/weapon/cell/high
/obj/item/device/defib_kit/loaded //starts with a cell
bcell = /obj/item/weapon/cell/apc
/obj/item/device/defib_kit/update_icon()
@@ -209,7 +209,7 @@
var/combat = 0 //If it can be used to revive people wearing thick clothing (e.g. spacesuits)
var/cooldowntime = (6 SECONDS) // How long in deciseconds until the defib is ready again after use.
var/chargetime = (2 SECONDS)
var/chargecost = 1000 //units of charge
var/chargecost = 1250 //units of charge per zap //With the default APC level cell, this allows 4 shocks
var/burn_damage_amt = 5
var/use_on_synthetic = 0 //If 1, this is only useful on FBPs, if 0, this is only useful on fleshies
@@ -284,7 +284,12 @@
return "buzzes, \"Resuscitation failed - Excessive neural degeneration. Further attempts futile.\""
H.updatehealth()
if(H.health + H.getOxyLoss() <= config.health_threshold_dead || (HUSK in H.mutations))
if(H.isSynthetic())
if(H.health + H.getOxyLoss() + H.getToxLoss() <= config.health_threshold_dead)
return "buzzes, \"Resuscitation failed - Severe damage detected. Begin manual repair before further attempts futile.\""
else if(H.health + H.getOxyLoss() <= config.health_threshold_dead || (HUSK in H.mutations) || !H.can_defib)
return "buzzes, \"Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile.\""
var/bad_vital_organ = check_vital_organs(H)
@@ -374,7 +379,10 @@
// This proc is used so that we can return out of the revive process while ensuring that busy and update_icon() are handled
/obj/item/weapon/shockpaddles/proc/do_revive(mob/living/carbon/human/H, mob/user)
if(!H.client && !H.teleop)
to_chat(find_dead_player(H.ckey, 1), "Someone is attempting to resuscitate you. Re-enter your body if you want to be revived!")
for(var/mob/observer/dead/ghost in player_list)
if(ghost.mind == H.mind)
to_chat(ghost, "<b><font color = #330033><font size = 3>Someone is attempting to resuscitate you. Re-enter your body if you want to be revived!</b> (Verbs -> Ghost -> Re-enter corpse)</font></font>")
break
//beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
user.visible_message("<span class='warning'>\The [user] begins to place [src] on [H]'s chest.</span>", "<span class='warning'>You begin to place [src] on [H]'s chest...</span>")
@@ -420,6 +428,9 @@
var/adjust_health = barely_in_crit - H.health //need to increase health by this much
H.adjustOxyLoss(-adjust_health)
if(H.isSynthetic())
H.adjustToxLoss(-H.getToxLoss())
make_announcement("pings, \"Resuscitation successful.\"", "notice")
playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
@@ -642,7 +653,8 @@
name = "jumper cable kit"
desc = "A device that delivers powerful shocks to detachable jumper cables that are capable of reviving full body prosthetics."
icon_state = "jumperunit"
item_state = "jumperunit"
item_state = "defibunit"
// item_state = "jumperunit"
paddles = /obj/item/weapon/shockpaddles/linked/jumper
/obj/item/device/defib_kit/jumper_kit/loaded

View File

@@ -18,7 +18,7 @@
/obj/item/device/flash/proc/clown_check(var/mob/user)
if(user && (CLUMSY in user.mutations) && prob(50))
user << "<span class='warning'>\The [src] slips out of your hand.</span>"
to_chat(user, "<span class='warning'>\The [src] slips out of your hand.</span>")
user.drop_item()
return 0
return 1
@@ -43,7 +43,7 @@
if(prob( round(times_used / 2) )) //if you use it 10 times in a minute it has a 5% chance to break.
broken = 1
if(user)
user << "<span class='warning'>The bulb has burnt out!</span>"
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
icon_state = "flashburnt"
return FALSE
else
@@ -51,7 +51,8 @@
return TRUE
else //can only use it 10 times a minute
if(user)
user << "<span class='warning'>*click* *click*</span>"
to_chat(user, "<span class='warning'><i>click</i></span>")
playsound(src.loc, 'sound/weapons/empty.ogg', 80, 1)
return FALSE
//attack_as_weapon
@@ -62,12 +63,12 @@
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to flash [M.name] ([M.ckey])</font>")
msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
user.do_attack_animation(M)
if(!clown_check(user)) return
if(broken)
user << "<span class='warning'>\The [src] is broken.</span>"
to_chat(user, "<span class='warning'>\The [src] is broken.</span>")
return
flash_recharge()
@@ -75,9 +76,6 @@
if(!check_capacitor(user))
return
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.do_attack_animation(M)
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
var/flashfail = 0
@@ -155,7 +153,7 @@
/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
if(!user || !clown_check(user)) return
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
if(broken)
user.show_message("<span class='warning'>The [src.name] is broken</span>", 2)
@@ -215,12 +213,12 @@
..()
if(!broken)
broken = 1
user << "<span class='warning'>The bulb has burnt out!</span>"
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
icon_state = "flashburnt"
/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
..()
if(!broken)
broken = 1
user << "<span class='warning'>The bulb has burnt out!</span>"
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
icon_state = "flashburnt"

View File

@@ -163,7 +163,7 @@
else
user << "<span class='notice'>\The [M]'s pupils narrow.</span>"
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //can be used offensively
user.setClickCooldown(user.get_attack_speed(src)) //can be used offensively
M.flash_eyes()
else
return ..()
@@ -290,6 +290,7 @@
name = "desk lamp"
desc = "A desk lamp with an adjustable mount."
icon_state = "lamp"
force = 10
brightness_on = 5
w_class = ITEMSIZE_LARGE
flags = CONDUCT

View File

@@ -0,0 +1,211 @@
var/list/GPS_list = list()
/obj/item/device/gps
name = "global positioning system"
desc = "Triangulates the approximate co-ordinates using a nearby satellite network. Alt+click to toggle power."
icon = 'icons/obj/gps.dmi'
icon_state = "gps-c"
w_class = ITEMSIZE_TINY
slot_flags = SLOT_BELT
origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 2, TECH_MAGNET = 1)
matter = list(DEFAULT_WALL_MATERIAL = 500)
var/gps_tag = "COM0"
var/emped = FALSE
var/tracking = FALSE // Will not show other signals or emit its own signal if false.
var/long_range = FALSE // If true, can see farther, depending on get_map_levels().
var/local_mode = FALSE // If true, only GPS signals of the same Z level are shown.
var/hide_signal = FALSE // If true, signal is not visible to other GPS devices.
var/can_hide_signal = FALSE // If it can toggle the above var.
/obj/item/device/gps/initialize()
GPS_list += src
name = "global positioning system ([gps_tag])"
update_icon()
/obj/item/device/gps/Destroy()
GPS_list -= src
return ..()
/obj/item/device/gps/AltClick(mob/user)
toggletracking(user)
/obj/item/device/gps/proc/toggletracking(mob/living/user)
if(!istype(user))
return
if(emped)
to_chat(user, "It's busted!")
return
if(tracking)
to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.")
tracking = FALSE
update_icon()
else
to_chat(user, "[src] is now tracking, and visible to other GPS devices.")
tracking = TRUE
update_icon()
/obj/item/device/gps/emp_act(severity)
if(emped) // Without a fancy callback system, this will have to do.
return
var/severity_modifier = severity ? severity : 4 // In case emp_act gets called without any arguments.
var/duration = 5 MINUTES / severity_modifier
emped = TRUE
update_icon()
spawn(duration)
emped = FALSE
update_icon()
visible_message("\The [src] appears to be functional again.")
/obj/item/device/gps/update_icon()
overlays.Cut()
if(emped)
overlays += image(icon, src, "emp")
else if(tracking)
overlays += image(icon, src, "working")
/obj/item/device/gps/attack_self(mob/user)
display(user)
/obj/item/device/gps/proc/display(mob/user)
if(!tracking)
to_chat(user, "The device is off. Alt-click it to turn it on.")
return
if(emped)
to_chat(user, "It's busted!")
return
var/list/dat = list()
var/turf/curr = get_turf(src)
var/area/my_area = get_area(src)
dat += "Current location: [my_area.name] <b>([curr.x], [curr.y], [curr.z])</b>"
dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. <a href='?src=\ref[src];tag=1'>\[Change Tag\]</a> \
<a href='?src=\ref[src];range=1'>\[Toggle Scan Range\]</a> \
[can_hide_signal ? "<a href='?src=\ref[src];hide=1'>\[Toggle Signal Visibility\]</a>":""]"
var/list/signals = list()
for(var/gps in GPS_list)
var/obj/item/device/gps/G = gps
if(G.emped || !G.tracking || G.hide_signal || G == src) // Their GPS isn't on or functional.
continue
var/turf/T = get_turf(G)
var/z_level_detection = using_map.get_map_levels(curr.z, long_range)
if(local_mode && T.z != curr.z) // Only care about the current z-level.
continue
else if(!(T.z in z_level_detection)) // Too far away.
continue
var/area/their_area = get_area(G)
var/area_name = their_area.name
if(istype(their_area, /area/submap))
area_name = "Unknown Area" // Avoid spoilers.
var/coord = "[T.x], [T.y], [T.z]"
var/degrees = round(Get_Angle(curr, T))
var/direction = uppertext(dir2text(get_dir(curr, T)))
var/distance = get_dist(curr, T)
var/local = curr.z == T.z ? TRUE : FALSE
if(!direction)
direction = "CENTER"
degrees = "N/A"
signals += " [G.gps_tag]: [area_name] ([coord]) [local ? "Dist: [distance]m Dir: [degrees]<5D> ([direction])":""]"
if(signals.len)
dat += "Detected signals;"
for(var/line in signals)
dat += line
else
dat += "No other signals detected."
var/result = dat.Join("<br>")
to_chat(user, result)
/obj/item/device/gps/Topic(var/href, var/list/href_list)
if(..())
return 1
if(href_list["tag"])
var/a = input("Please enter desired tag.", name, gps_tag) as text
a = uppertext(copytext(sanitize(a), 1, 11))
if(in_range(src, usr))
gps_tag = a
name = "global positioning system ([gps_tag])"
to_chat(usr, "You set your GPS's tag to '[gps_tag]'.")
if(href_list["range"])
local_mode = !local_mode
to_chat(usr, "You set the signal receiver to [local_mode ? "'NARROW'" : "'BROAD'"].")
if(href_list["hide"])
if(!can_hide_signal)
return
hide_signal = !hide_signal
to_chat(usr, "You set the device to [hide_signal ? "not " : ""]broadcast a signal while scanning for other signals.")
/obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these.
tracking = TRUE
/obj/item/device/gps/science
icon_state = "gps-s"
gps_tag = "SCI0"
/obj/item/device/gps/science/on
tracking = TRUE
/obj/item/device/gps/engineering
icon_state = "gps-e"
gps_tag = "ENG0"
/obj/item/device/gps/engineering/on
tracking = TRUE
/obj/item/device/gps/mining
icon_state = "gps-m"
gps_tag = "MINE0"
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life. Alt+click to toggle power."
/obj/item/device/gps/mining/on
tracking = TRUE
/obj/item/device/gps/explorer
icon_state = "gps-ex"
gps_tag = "EX0"
desc = "A positioning system helpful for rescuing trapped or injured explorers, keeping one on you at all times while exploring might just save your life. Alt+click to toggle power."
/obj/item/device/gps/explorer/on
tracking = TRUE
/obj/item/device/gps/syndie
icon_state = "gps-syndie"
gps_tag = "NULL"
desc = "A positioning system that has extended range and can detect other GPS device signals without revealing its own. How that works is best left a mystery. Alt+click to toggle power."
origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 3, TECH_MAGNET = 2, TECH_ILLEGAL = 2)
long_range = TRUE
hide_signal = TRUE
can_hide_signal = TRUE
/obj/item/device/gps/robot
icon_state = "gps-b"
gps_tag = "SYNTH0"
desc = "A synthetic internal positioning system. Used as a recovery beacon for damaged synthetic assets, or a collaboration tool for mining or exploration teams. \
Alt+click to toggle power."
tracking = TRUE // On by default.
/obj/item/device/gps/internal // Base type for immobile/internal GPS units.
icon_state = null
gps_tag = "Eerie Signal"
desc = "Report to a coder immediately."
invisibility = INVISIBILITY_MAXIMUM
tracking = TRUE // Meant to point to a location, so it needs to be on.
anchored = TRUE
/obj/item/device/gps/internal/base
gps_tag = "NT_BASE"
desc = "A homing signal from NanoTrasen's outpost."
/obj/item/device/gps/internal/alien_vessel
gps_tag = "Mysterious Signal"
desc = "A signal that seems forboding."

View File

@@ -42,7 +42,7 @@
name = "light replacer"
desc = "A device to automatically replace lights. Refill with working lightbulbs or sheets of glass."
force = 8
icon = 'icons/obj/janitor.dmi'
icon_state = "lightreplacer0"
flags = CONDUCT
@@ -61,32 +61,32 @@
/obj/item/device/lightreplacer/examine(mob/user)
if(..(user, 2))
user << "It has [uses] lights remaining."
to_chat(user, "It has [uses] lights remaining.")
/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/material) && W.get_material_name() == "glass")
var/obj/item/stack/G = W
if(uses >= max_uses)
user << "<span class='warning'>[src.name] is full.</span>"
to_chat(user, "<span class='warning'>[src.name] is full.</span>")
return
else if(G.use(1))
AddUses(16) //Autolathe converts 1 sheet into 16 lights.
user << "<span class='notice'>You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining.</span>"
add_uses(16) //Autolathe converts 1 sheet into 16 lights.
to_chat(user, "<span class='notice'>You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining.</span>")
return
else
user << "<span class='warning'>You need one sheet of glass to replace lights.</span>"
to_chat(user, "<span class='warning'>You need one sheet of glass to replace lights.</span>")
if(istype(W, /obj/item/weapon/light))
var/obj/item/weapon/light/L = W
if(L.status == 0) // LIGHT OKAY
if(uses < max_uses)
AddUses(1)
user << "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining."
add_uses(1)
to_chat(user, "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining.")
user.drop_item()
qdel(L)
return
else
user << "You need a working light."
to_chat(user, "You need a working light.")
return
/obj/item/device/lightreplacer/attack_self(mob/user)
@@ -95,10 +95,10 @@
var/mob/living/silicon/robot/R = user
if(R.emagged)
src.Emag()
usr << "You shortcircuit the [src]."
to_chat(usr, You short circuit the [src].")
return
*/
usr << "It has [uses] lights remaining."
to_chat(usr, "It has [uses] lights remaining.")
/obj/item/device/lightreplacer/update_icon()
icon_state = "lightreplacer[emagged]"
@@ -107,17 +107,17 @@
/obj/item/device/lightreplacer/proc/Use(var/mob/user)
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
AddUses(-1)
add_uses(-1)
return 1
// Negative numbers will subtract
/obj/item/device/lightreplacer/proc/AddUses(var/amount = 1)
/obj/item/device/lightreplacer/proc/add_uses(var/amount = 1)
uses = min(max(uses + amount, 0), max_uses)
/obj/item/device/lightreplacer/proc/Charge(var/mob/user, var/amount = 1)
charge += amount
if(charge > 6)
AddUses(1)
add_uses(1)
charge = 0
/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U)

View File

@@ -23,6 +23,13 @@ REAGENT SCANNER
matter = list(DEFAULT_WALL_MATERIAL = 200)
origin_tech = list(TECH_MAGNET = 1, TECH_BIO = 1)
var/mode = 1;
var/advscan = 0
var/showadvscan = 1
/obj/item/device/healthanalyzer/New()
if(advscan >= 1)
verbs += /obj/item/device/healthanalyzer/proc/toggle_adv
..()
/obj/item/device/healthanalyzer/do_surgery(mob/living/M, mob/living/user)
if(user.a_intent != I_HELP) //in case it is ever used as a surgery tool
@@ -39,7 +46,7 @@ REAGENT SCANNER
for(var/mob/O in viewers(M, null))
O.show_message("<span class='warning'>\The [user] has analyzed the floor's vitals!</span>", 1)
user.show_message("<span class='notice'>Analyzing Results for The floor:</span>", 1)
user.show_message("Overall Status: Healthy</span>", 1)
user.show_message("<span class='notice'>Overall Status: Healthy</span>", 1)
user.show_message("<span class='notice'> Damage Specifics: 0-0-0-0</span>", 1)
user.show_message("<span class='notice'>Key: Suffocation/Toxin/Burns/Brute</span>", 1)
user.show_message("<span class='notice'>Body Temperature: ???</span>", 1)
@@ -100,39 +107,72 @@ REAGENT SCANNER
OX = fake_oxy > 50 ? "<span class='warning'>Severe oxygen deprivation detected</span>" : "Subject bloodstream oxygen level normal"
user.show_message("[OX] | [TX] | [BU] | [BR]")
if(M.radiation)
if(advscan >= 2 && showadvscan == 1)
if(M.radiation >= 75)
user.show_message("<span class='warning'>Critical levels of radiation detected. Immediate treatment advised.</span>")
else if(M.radiation >= 50)
user.show_message("<span class='warning'>Severe levels of radiation detected.</span>")
else if(M.radiation >= 25)
user.show_message("<span class='warning'>Moderate levels of radiation detected.</span>")
else if(M.radiation >= 1)
user.show_message("<span_class='warning'>Low levels of radiation detected.</span>")
else
user.show_message("<span class='warning'>Radiation detected.</span>")
if(istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
if(C.reagents.total_volume)
var/unknown = 0
var/reagentdata[0]
var/unknownreagents[0]
for(var/A in C.reagents.reagent_list)
var/datum/reagent/R = A
if(R.scannable)
reagentdata["[R.id]"] = "<span class='notice'> [round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]</span>"
else
unknown++
unknownreagents["[R.id]"] = "<span class='notice'> [round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]</span>"
if(reagentdata.len)
user.show_message("<span class='notice'>Beneficial reagents detected in subject's blood:</span>")
for(var/d in reagentdata)
user.show_message(reagentdata[d])
if(unknown)
if(advscan >= 3 && showadvscan == 1)
user.show_message("<span class='warning'>Warning: Non-medical reagent[(unknown>1)?"s":""] detected in subject's blood:</span>")
for(var/d in unknownreagents)
user.show_message(unknownreagents[d])
else
user.show_message("<span class='warning'>Warning: Unknown substance[(unknown>1)?"s":""] detected in subject's blood.</span>")
if(C.ingested && C.ingested.total_volume)
var/unknown = 0
for(var/datum/reagent/R in C.ingested.reagent_list)
if(R.scannable)
user << "<span class='notice'>[R.name] found in subject's stomach.</span>"
var/stomachreagentdata[0]
var/stomachunknownreagents[0]
for(var/B in C.ingested.reagent_list)
var/datum/reagent/T = B
if(T.scannable)
stomachreagentdata["[T.id]"] = "<span class='notice'> [round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]</span>"
if (advscan == 0 || showadvscan == 0)
user.show_message("<span class='notice'>[T.name] found in subject's stomach.</span>")
else
++unknown
stomachunknownreagents["[T.id]"] = "<span class='notice'> [round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]</span>"
if(advscan >= 1 && showadvscan == 1)
user.show_message("<span class='notice'>Beneficial reagents detected in subject's stomach:</span>")
for(var/d in stomachreagentdata)
user.show_message(stomachreagentdata[d])
if(unknown)
user << "<span class='warning'>Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach.</span>"
if(advscan >= 3 && showadvscan == 1)
user.show_message("<span class='warning'>Warning: Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach:</span>")
for(var/d in stomachunknownreagents)
user.show_message(stomachunknownreagents[d])
else
user.show_message("<span class='warning'>Unknown substance[(unknown > 1)?"s":""] found in subject's stomach.</span>")
if(C.virus2.len)
for (var/ID in C.virus2)
if (ID in virusDB)
var/datum/data/record/V = virusDB[ID]
user.show_message("<span class='warning'>Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]</span>")
// user.show_message(text("<span class='warning'>Warning: Unknown pathogen detected in subject's blood.</span>"))
else
user.show_message("<span class='warning'>Warning: Unknown pathogen detected in subject's blood.</span>")
if (M.getCloneLoss())
user.show_message("<span class='warning'>Subject appears to have been imperfectly cloned.</span>")
// if (M.reagents && M.reagents.get_reagent_amount("inaprovaline"))
@@ -145,6 +185,8 @@ REAGENT SCANNER
user.show_message("<span class='warning'>Severe brain damage detected. Subject likely to have a traumatic brain injury.</span>")
else if (M.getBrainLoss() >= 10)
user.show_message("<span class='warning'>Significant brain damage detected. Subject may have had a concussion.</span>")
else if (M.getBrainLoss() >= 1 && advscan >= 2 && showadvscan == 1)
user.show_message("<span class='warning'>Minor brain damage detected.</span>")
if(ishuman(M))
var/mob/living/carbon/human/H = M
for(var/name_i in H.internal_organs_by_name)
@@ -166,21 +208,28 @@ REAGENT SCANNER
var/limb = e.name
if(e.status & ORGAN_BROKEN)
if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!e.splinted))
user << "<span class='warning'>Unsecured fracture in subject [limb]. Splinting recommended for transport.</span>"
to_chat(user, "<span class='warning'>Unsecured fracture in subject [limb]. Splinting recommended for transport.</span>")
if(e.has_infected_wound())
user << "<span class='warning'>Infected wound detected in subject [limb]. Disinfection recommended.</span>"
to_chat(user, "<span class='warning'>Infected wound detected in subject [limb]. Disinfection recommended.</span>")
for(var/name in H.organs_by_name)
var/obj/item/organ/external/e = H.organs_by_name[name]
if(e && e.status & ORGAN_BROKEN)
if(advscan >= 1 && showadvscan == 1)
user.show_message(text("<span class='warning'>Bone fractures detected in subject [e.name].</span>"), 1)
else
user.show_message(text("<span class='warning'>Bone fractures detected. Advanced scanner required for location.</span>"), 1)
break
for(var/obj/item/organ/external/e in H.organs)
if(!e)
continue
for(var/datum/wound/W in e.wounds) if(W.internal)
if(advscan >= 1 && showadvscan == 1)
user.show_message(text("<span class='warning'>Internal bleeding detected in subject [e.name].</span>"), 1)
else
user.show_message(text("<span class='warning'>Internal bleeding detected. Advanced scanner required for location.</span>"), 1)
break
break
if(M:vessel)
var/blood_volume = H.vessel.get_reagent_amount("blood")
@@ -202,10 +251,37 @@ REAGENT SCANNER
mode = !mode
switch (mode)
if(1)
usr << "The scanner now shows specific limb damage."
to_chat(usr, "The scanner now shows specific limb damage.")
if(0)
usr << "The scanner no longer shows limb damage."
to_chat(usr, "The scanner no longer shows limb damage.")
/obj/item/device/healthanalyzer/proc/toggle_adv()
set name = "Toggle Advanced Scan"
set category = "Object"
showadvscan = !showadvscan
switch (showadvscan)
if(1)
to_chat(usr, "The scanner will now perform an advanced analysis.")
if(0)
to_chat(usr, "The scanner will now perform a basic analysis.")
/obj/item/device/healthanalyzer/improved //reports bone fractures, IB, quantity of beneficial reagents in stomach; also regular health analyzer stuff
name = "advanced health analyzer"
desc = "A miracle of medical technology, this handheld scanner can produce an accurate and specific report of a patient's biosigns."
advscan = 1
origin_tech = list(TECH_MAGNET = 5, TECH_BIO = 6)
icon_state = "advhealth"
/obj/item/device/healthanalyzer/advanced //reports all of the above, as well as radiation severity and minor brain damage
name = "advanced health analyzer"
advscan = 2
icon_state = "advhealth"
/obj/item/device/healthanalyzer/enhanced //reports all of the above, as well as name and quantity of nonmed reagents in stomach
name = "phasic health analyzer"
advscan = 3
icon_state = "advhealth"
/obj/item/device/analyzer
name = "analyzer"
@@ -235,7 +311,7 @@ REAGENT SCANNER
if (user.stat)
return
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
usr << "<span class='warning'>You don't have the dexterity to do this!</span>"
to_chat(usr, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
analyze_gases(src, user)
@@ -274,14 +350,14 @@ REAGENT SCANNER
if (user.stat)
return
if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
if(reagents.total_volume)
var/list/blood_traces = list()
for(var/datum/reagent/R in reagents.reagent_list)
if(R.id != "blood")
reagents.clear_reagents()
user << "<span class='warning'>The sample was contaminated! Please insert another sample</span>"
to_chat(user, "<span class='warning'>The sample was contaminated! Please insert another sample</span>")
return
else
blood_traces = params2list(R.data["trace_chem"])
@@ -292,7 +368,7 @@ REAGENT SCANNER
dat += "[R] ([blood_traces[R]] units) "
else
dat += "[R] "
user << "[dat]"
to_chat(user, "[dat]")
reagents.clear_reagents()
return
@@ -325,7 +401,7 @@ REAGENT SCANNER
if (user.stat)
return
if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
if(!istype(O))
return
@@ -335,9 +411,9 @@ REAGENT SCANNER
if(O.reagents.reagent_list.len > 0)
var/one_percent = O.reagents.total_volume / 100
for (var/datum/reagent/R in O.reagents.reagent_list)
dat += "\n \t <span class='notice'>[R][details ? ": [R.volume / one_percent]%" : ""]"
dat += "\n \t <span class='notice'>[R][details ? ": [R.volume / one_percent]%" : ""]</span>"
if(dat)
user << "<span class='notice'>Chemicals found: [dat]</span>"
to_chat(user, "<span class='notice'>Chemicals found: [dat]</span>")
else
user << "<span class='notice'>No active chemical agents found in [O].</span>"
else

View File

@@ -1,115 +1,196 @@
/obj/item/device/spy_bug
/obj/item/device/camerabug
name = "mobile camera pod"
desc = "A camera pod used by tactical operators. Must be linked to a camera scanner unit."
icon = 'icons/obj/grenade.dmi'
icon_state = "camgrenade"
item_state = "empgrenade"
flags = CONDUCT
w_class = ITEMSIZE_SMALL
force = 0
throwforce = 5.0
throw_range = 15
throw_speed = 3
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
var/obj/item/device/bug_monitor/linkedmonitor
var/brokentype = /obj/item/brokenbug
// var/obj/item/device/radio/bug/radio
var/obj/machinery/camera/bug/camera
/obj/item/device/camerabug/New()
..()
// radio = new(src)
camera = new(src)
/obj/item/device/camerabug/attack_self(mob/user)
if(user.a_intent == I_HURT)
to_chat(user, "<span class='notice'>You crush the [src] under your foot, breaking it.</span>")
visible_message("[user.name] crushes the [src] under their foot, breaking it!</span>")
new brokentype(get_turf(src))
spawn(0)
qdel(src)
/* else
user.set_machine(radio)
radio.interact(user)
*/
/obj/item/device/camerabug/verb/reset()
set name = "Reset camera bug"
set category = "Object"
if(linkedmonitor)
linkedmonitor.unpair(src)
linkedmonitor = null
qdel(camera)
camera = new(src)
to_chat(usr, "<span class='notice'>You turn the [src] off and on again, delinking it from any monitors.")
/obj/item/brokenbug
name = "broken mobile camera pod"
desc = "A camera pod formerly used by tactical operators. The lens is smashed, and the circuits are damaged beyond repair."
icon = 'icons/obj/grenade.dmi'
icon_state = "camgrenadebroken"
item_state = "empgrenade"
flags = CONDUCT
force = 5.0
w_class = ITEMSIZE_SMALL
throwforce = 5.0
throw_range = 15
throw_speed = 3
origin_tech = list(TECH_ENGINEERING = 1)
/obj/item/brokenbug/spy
name = "broken bug"
desc = "" //Even when it's broken it's inconspicuous
icon = 'icons/obj/weapons.dmi'
icon_state = "eshield0"
item_state = "nothing"
layer = TURF_LAYER+0.2
w_class = ITEMSIZE_TINY
slot_flags = SLOT_EARS
origin_tech = list(TECH_ENGINEERING = 1, TECH_ILLEGAL = 3) //crush it and you lose the data
flags = CONDUCT
force = 0
throwforce = 5.0
throw_range = 15
throw_speed = 3
/obj/item/device/camerabug/spy
name = "bug"
desc = "" //Nothing to see here
icon = 'icons/obj/weapons.dmi'
icon_state = "eshield0"
item_state = "nothing"
layer = TURF_LAYER+0.2
flags = CONDUCT
force = 5.0
w_class = ITEMSIZE_TINY
slot_flags = SLOT_EARS
throwforce = 5.0
throw_range = 15
throw_speed = 3
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
var/obj/item/device/radio/spy/radio
var/obj/machinery/camera/spy/camera
/obj/item/device/spy_bug/New()
..()
radio = new(src)
camera = new(src)
/obj/item/device/spy_bug/examine(mob/user)
/obj/item/device/camerabug/examine(mob/user)
. = ..(user, 0)
if(.)
user << "It's a tiny camera, microphone, and transmission device in a happy union."
user << "Needs to be both configured and brought in contact with monitor device to be fully functional."
to_chat(user, "It has a tiny camera inside. Needs to be both configured and brought in contact with monitor device to be fully functional.")
/obj/item/device/spy_bug/attack_self(mob/user)
radio.attack_self(user)
/obj/item/device/spy_bug/attackby(obj/W as obj, mob/living/user as mob)
if(istype(W, /obj/item/device/spy_monitor))
var/obj/item/device/spy_monitor/SM = W
SM.pair(src, user)
/obj/item/device/camerabug/attackby(obj/item/W as obj, mob/living/user as mob)
if(istype(W, /obj/item/device/bug_monitor))
var/obj/item/device/bug_monitor/SM = W
if(!linkedmonitor)
to_chat(user, "<span class='notice'>\The [src] has been paired with \the [SM].</span>")
SM.pair(src)
linkedmonitor = SM
else if (linkedmonitor == SM)
to_chat(user, "<span class='notice'>\The [src] has been unpaired from \the [SM].</span>")
linkedmonitor.unpair(src)
linkedmonitor = null
else
to_chat(user, "Error: The device is linked to another monitor.")
else
if(W.force >= 5)
visible_message("\The [src] lens shatters!")
new brokentype(get_turf(src))
if(linkedmonitor)
linkedmonitor.unpair(src)
linkedmonitor = null
spawn(0)
qdel(src)
..()
/obj/item/device/spy_bug/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
/obj/item/device/camerabug/bullet_act()
visible_message("The [src] lens shatters!")
new brokentype(get_turf(src))
if(linkedmonitor)
linkedmonitor.unpair(src)
linkedmonitor = null
spawn(0)
qdel(src)
/obj/item/device/camerabug/Destroy()
if(linkedmonitor)
linkedmonitor.unpair(src)
linkedmonitor = null
..()
/*
/obj/item/device/camerabug/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
radio.hear_talk(M, msg, speaking)
/obj/item/device/spy_monitor
name = "\improper PDA"
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
icon = 'icons/obj/pda.dmi'
icon_state = "pda"
*/
/obj/item/device/bug_monitor
name = "mobile camera pod monitor"
desc = "A portable camera console designed to work with mobile camera pods."
icon = 'icons/obj/device.dmi'
icon_state = "forensic0"
item_state = "electronic"
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
var/operating = 0
var/obj/item/device/radio/spy/radio
var/obj/machinery/camera/spy/selected_camera
var/list/obj/machinery/camera/spy/cameras = new()
/obj/item/device/spy_monitor/New()
// var/obj/item/device/radio/bug/radio
var/obj/machinery/camera/bug/selected_camera
var/list/obj/machinery/camera/bug/cameras = new()
/*
/obj/item/device/bug_monitor/New()
radio = new(src)
/obj/item/device/spy_monitor/examine(mob/user)
. = ..(user, 1)
if(.)
user << "The time '12:00' is blinking in the corner of the screen and \the [src] looks very cheaply made."
/obj/item/device/spy_monitor/attack_self(mob/user)
*/
/obj/item/device/bug_monitor/attack_self(mob/user)
if(operating)
return
radio.attack_self(user)
// radio.attack_self(user)
view_cameras(user)
/obj/item/device/spy_monitor/attackby(obj/W as obj, mob/living/user as mob)
if(istype(W, /obj/item/device/spy_bug))
pair(W, user)
/obj/item/device/bug_monitor/attackby(obj/item/W as obj, mob/living/user as mob)
if(istype(W, /obj/item/device/camerabug))
W.attackby(src, user)
else
return ..()
/obj/item/device/spy_monitor/proc/pair(var/obj/item/device/spy_bug/SB, var/mob/living/user)
/obj/item/device/bug_monitor/proc/unpair(var/obj/item/device/camerabug/SB)
if(SB.camera in cameras)
user << "<span class='notice'>\The [SB] has been unpaired from \the [src].</span>"
cameras -= SB.camera
else
user << "<span class='notice'>\The [SB] has been paired with \the [src].</span>"
/obj/item/device/bug_monitor/proc/pair(var/obj/item/device/camerabug/SB)
cameras += SB.camera
/obj/item/device/spy_monitor/proc/view_cameras(mob/user)
/obj/item/device/bug_monitor/proc/view_cameras(mob/user)
if(!can_use_cam(user))
return
selected_camera = cameras[1]
user.reset_view(selected_camera)
view_camera(user)
operating = 1
while(selected_camera && Adjacent(user))
selected_camera = input("Select camera bug to view.") as null|anything in cameras
selected_camera = input("Select camera to view.") as null|anything in cameras
selected_camera = null
operating = 0
/obj/item/device/spy_monitor/proc/view_camera(mob/user)
/obj/item/device/bug_monitor/proc/view_camera(mob/user)
spawn(0)
while(selected_camera && Adjacent(user))
var/turf/T = get_turf(selected_camera)
if(!T || !is_on_same_plane_or_station(T.z, user.z) || !selected_camera.can_use())
user.unset_machine()
user.reset_view(null)
user << "<span class='notice'>[selected_camera] unavailable.</span>"
to_chat(user, "<span class='notice'>Link to [selected_camera] has been lost.</span>")
src.unpair(selected_camera.loc)
sleep(90)
else
user.set_machine(selected_camera)
@@ -118,37 +199,67 @@
user.unset_machine()
user.reset_view(null)
/obj/item/device/spy_monitor/proc/can_use_cam(mob/user)
/obj/item/device/bug_monitor/proc/can_use_cam(mob/user)
if(operating)
return
if(!cameras.len)
user << "<span class='warning'>No paired cameras detected!</span>"
user << "<span class='warning'>Bring a bug in contact with this device to pair the camera.</span>"
to_chat(user, "<span class='warning'>No paired cameras detected!</span>")
to_chat(user, "<span class='warning'>Bring a camera in contact with this device to pair the camera.</span>")
return
return 1
/obj/item/device/spy_monitor/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
/*
/obj/item/device/bug_monitor/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
return radio.hear_talk(M, msg, speaking)
*/
/obj/item/device/bug_monitor/spy
name = "\improper PDA"
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
icon = 'icons/obj/pda.dmi'
icon_state = "pda"
item_state = "electronic"
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
/obj/item/device/bug_monitor/spy/examine(mob/user)
. = ..(user, 1)
if(.)
to_chat(user, "The time '12:00' is blinking in the corner of the screen and \the [src] looks very cheaply made.")
/obj/machinery/camera/spy
// These cheap toys are accessible from the mercenary camera console as well
/obj/machinery/camera/bug/check_eye(var/mob/user as mob)
return 0
/obj/machinery/camera/bug
network = list(NETWORK_SECURITY)
/obj/machinery/camera/bug/New()
..()
name = "Camera #[rand(1000,9999)]"
c_tag = name
/obj/machinery/camera/bug/spy
// These cheap toys are accessible from the mercenary camera console as well - only the antag ones though!
network = list(NETWORK_MERCENARY)
/obj/machinery/camera/spy/New()
/obj/machinery/camera/bug/spy/New()
..()
name = "DV-136ZB #[rand(1000,9999)]"
c_tag = name
/obj/machinery/camera/spy/check_eye(var/mob/user as mob)
return 0
/* //These were originally supposed to have radios in them. Doesn't work.
/obj/item/device/radio/bug
listening = 0 //turn it on first
frequency = 1359 //sec comms
broadcasting = 0
canhear_range = 1
name = "camera bug device"
icon_state = "syn_cypherkey"
/obj/item/device/radio/spy
/obj/item/device/radio/bug/spy
listening = 0
frequency = 1473
broadcasting = 0
canhear_range = 1
name = "spy device"
icon_state = "syn_cypherkey"
*/

View File

@@ -160,6 +160,29 @@
to_chat(usr, "There's no mounting point for the module!")
return 0
/obj/item/borg/upgrade/advhealth
name = "advanced health analyzer module"
desc = "A carbon dioxide jetpack suitable for low-gravity operations."
icon_state = "cyborg_upgrade3"
item_state = "cyborg_upgrade"
require_module = 1
/obj/item/borg/upgrade/advhealth/action(var/mob/living/silicon/robot/R)
if(..()) return 0
var/obj/item/device/healthanalyzer/advanced/T = locate() in R.module
if(!T)
T = locate() in R.module.contents
if(!T)
T = locate() in R.module.modules
if(!T)
R.module.modules += new/obj/item/device/healthanalyzer/advanced
return 1
if(T)
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
to_chat(usr, "There's no mounting point for the module!")
return 0
/obj/item/borg/upgrade/syndicate/
name = "scrambled equipment module"
desc = "Unlocks new and often deadly module specific items of a robot"

View File

@@ -164,7 +164,7 @@
singular_name = "advanced trauma kit"
desc = "An advanced trauma kit for severe injuries."
icon_state = "traumakit"
heal_brute = 5
heal_brute = 3
origin_tech = list(TECH_BIO = 1)
/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
@@ -225,7 +225,7 @@
singular_name = "advanced burn kit"
desc = "An advanced treatment kit for severe burns."
icon_state = "burnkit"
heal_burn = 5
heal_burn = 3
origin_tech = list(TECH_BIO = 1)

View File

@@ -34,7 +34,7 @@
if(!S.get_damage())
user << "<span class='notice'>Nothing to fix here.</span>"
else if(can_use(1))
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
if(S.open >= 2)
if(do_after(user,5 * toolspeed))
S.heal_damage(20, 20, robo_repair = 1)

View File

@@ -771,13 +771,13 @@
user.visible_message("<span class='notice'><b>\The [user]</b> pokes [src].</span>","<span class='notice'>You poke [src].</span>")
last_message = world.time
obj/item/toy/plushie/verb/rename_plushie()
/obj/item/toy/plushie/verb/rename_plushie()
set name = "Name Plushie"
set category = "Object"
set desc = "Give your plushie a cute name!"
w_class = ITEMSIZE_TINY
var/mob/M = usr
if(!M.mind) return 0
if(!M.mind)
return 0
var/input = sanitizeSafe(input("What do you want to name the plushie?", ,""), MAX_NAME_LEN)

View File

@@ -25,51 +25,51 @@ AI MODULES
if (istype(AM, /obj/machinery/computer/aiupload))
var/obj/machinery/computer/aiupload/comp = AM
if(comp.stat & NOPOWER)
usr << "The upload computer has no power!"
to_chat(usr, "The upload computer has no power!")
return
if(comp.stat & BROKEN)
usr << "The upload computer is broken!"
to_chat(usr, "The upload computer is broken!")
return
if (!comp.current)
usr << "You haven't selected an AI to transmit laws to!"
to_chat(usr, "You haven't selected an AI to transmit laws to!")
return
if (comp.current.stat == 2 || comp.current.control_disabled == 1)
usr << "Upload failed. No signal is being detected from the AI."
to_chat(usr, "Upload failed. No signal is being detected from the AI.")
else if (comp.current.see_in_dark == 0)
usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power."
to_chat(usr, "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power.")
else
src.transmitInstructions(comp.current, usr)
comp.current << "These are your laws now:"
to_chat(comp.current, "These are your laws now:")
comp.current.show_laws()
for(var/mob/living/silicon/robot/R in mob_list)
if(R.lawupdate && (R.connected_ai == comp.current))
R << "These are your laws now:"
to_chat(R, "These are your laws now:")
R.show_laws()
usr << "Upload complete. The AI's laws have been modified."
to_chat(usr, "Upload complete. The AI's laws have been modified.")
else if (istype(AM, /obj/machinery/computer/borgupload))
var/obj/machinery/computer/borgupload/comp = AM
if(comp.stat & NOPOWER)
usr << "The upload computer has no power!"
to_chat(usr, "The upload computer has no power!")
return
if(comp.stat & BROKEN)
usr << "The upload computer is broken!"
to_chat(usr, "The upload computer is broken!")
return
if (!comp.current)
usr << "You haven't selected a robot to transmit laws to!"
to_chat(usr, "You haven't selected a robot to transmit laws to!")
return
if (comp.current.stat == 2 || comp.current.emagged)
usr << "Upload failed. No signal is being detected from the robot."
to_chat(usr, "Upload failed. No signal is being detected from the robot.")
else if (comp.current.connected_ai)
usr << "Upload failed. The robot is slaved to an AI."
to_chat(usr, "Upload failed. The robot is slaved to an AI.")
else
src.transmitInstructions(comp.current, usr)
comp.current << "These are your laws now:"
to_chat(comp.current, "These are your laws now:")
comp.current.show_laws()
usr << "Upload complete. The robot's laws have been modified."
to_chat(usr, "Upload complete. The robot's laws have been modified.")
else if(istype(AM, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = AM
@@ -104,7 +104,7 @@ AI MODULES
laws.sync(target, 0)
addAdditionalLaws(target, sender)
target << "\The [sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: "
to_chat(target, "\The [sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: ")
target.show_laws()
/obj/item/weapon/aiModule/proc/log_law_changes(var/mob/living/silicon/ai/target, var/mob/sender)
@@ -133,7 +133,7 @@ AI MODULES
/obj/item/weapon/aiModule/safeguard/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!targetName)
usr << "No name detected on module, please enter one."
to_chat(usr, "No name detected on module, please enter one.")
return 0
..()
@@ -159,18 +159,14 @@ AI MODULES
/obj/item/weapon/aiModule/oneHuman/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!targetName)
usr << "No name detected on module, please enter one."
to_chat(usr, "No name detected on module, please enter one.")
return 0
return ..()
/obj/item/weapon/aiModule/oneHuman/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
var/law = "Only [targetName] is an crew member."
if (!target.is_malf_or_traitor()) // Makes sure the AI isn't a traitor before changing their law 0. --NeoFite
target << law
target.set_zeroth_law(law)
lawchanges.Add("The law specified [targetName]")
else
lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overriden.")
to_chat(target, law)
target.add_supplied_law(16, law)
/******************** ProtectStation ********************/
@@ -255,7 +251,7 @@ AI MODULES
/obj/item/weapon/aiModule/freeform/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!newFreeFormLaw)
usr << "No law detected on module, please create one."
to_chat(usr, "No law detected on module, please create one.")
return 0
..()
@@ -275,7 +271,7 @@ AI MODULES
target.laws.clear_supplied_laws()
target.laws.clear_ion_laws()
target << "[sender.real_name] attempted to reset your laws using a reset module."
to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.")
target.show_laws()
/******************** Purge ********************/
@@ -294,7 +290,7 @@ AI MODULES
target.laws.clear_ion_laws()
target.laws.clear_inherent_laws()
target << "[sender.real_name] attempted to wipe your laws using a purge module."
to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.")
target.show_laws()
/******************** Asimov ********************/
@@ -366,7 +362,7 @@ AI MODULES
/obj/item/weapon/aiModule/freeformcore/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!newFreeFormLaw)
usr << "No law detected on module, please create one."
to_chat(usr, "No law detected on module, please create one.")
return 0
..()
@@ -388,14 +384,14 @@ AI MODULES
log_law_changes(target, sender)
lawchanges.Add("The law is '[newFreeFormLaw]'")
target << "<span class='danger'>BZZZZT</span>"
to_chat(target, "<span class='danger'>BZZZZT</span>")
var/law = "[newFreeFormLaw]"
target.add_ion_law(law)
target.show_laws()
/obj/item/weapon/aiModule/syndicate/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!newFreeFormLaw)
usr << "No law detected on module, please create one."
to_chat(usr, "No law detected on module, please create one.")
return 0
..()

View File

@@ -37,7 +37,7 @@
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
/obj/item/weapon/circuitboard/request
name = T_BOARD("reques console")
name = T_BOARD("request console")
build_path = /obj/machinery/requests_console
board_type = new /datum/frame/frame_types/supply_request_console
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)

View File

@@ -33,23 +33,23 @@
//I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing.
//So this is a workaround. This also makes more sense from an IC standpoint. ~Carn
if(user.client && (target in user.client.screen))
user << "<span class='notice'>You need to take that [target.name] off before cleaning it.</span>"
to_chat(user, "<span class='notice'>You need to take that [target.name] off before cleaning it.</span>")
else if(istype(target,/obj/effect/decal/cleanable/blood))
user << "<span class='notice'>You scrub \the [target.name] out.</span>"
to_chat(user, "<span class='notice'>You scrub \the [target.name] out.</span>")
target.clean_blood()
return //Blood is a cleanable decal, therefore needs to be accounted for before all cleanable decals.
else if(istype(target,/obj/effect/decal/cleanable))
user << "<span class='notice'>You scrub \the [target.name] out.</span>"
to_chat(user, "<span class='notice'>You scrub \the [target.name] out.</span>")
qdel(target)
else if(istype(target,/turf))
user << "<span class='notice'>You scrub \the [target.name] clean.</span>"
to_chat(user, "<span class='notice'>You scrub \the [target.name] clean.</span>")
var/turf/T = target
T.clean(src, user)
else if(istype(target,/obj/structure/sink))
user << "<span class='notice'>You wet \the [src] in the sink.</span>"
to_chat(user, "<span class='notice'>You wet \the [src] in the sink.</span>")
wet()
else
user << "<span class='notice'>You clean \the [target.name].</span>"
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
target.clean_blood()
return

View File

@@ -16,10 +16,11 @@
for(var/mob/living/carbon/M in hear(7, get_turf(src)))
bang(get_turf(src), M)
for(var/obj/effect/blob/B in hear(8,get_turf(src))) //Blob damage here
for(var/obj/structure/blob/B in hear(8,get_turf(src))) //Blob damage here
var/damage = round(30/(get_dist(B,get_turf(src))+1))
B.health -= damage
B.update_icon()
if(B.overmind)
damage *= B.overmind.blob_type.burn_multiplier
B.adjust_integrity(-damage)
new/obj/effect/effect/sparks(src.loc)
new/obj/effect/effect/smoke/illumination(src.loc, 5, range=30, power=30, color="#FFFFFF")

View File

@@ -17,6 +17,7 @@
var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes
var/cuff_sound = 'sound/weapons/handcuffs.ogg'
var/cuff_type = "handcuffs"
var/use_time = 30
sprite_sheets = list("Teshari" = 'icons/mob/species/seromi/handcuffs.dmi')
/obj/item/weapon/handcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
@@ -69,7 +70,7 @@
user.visible_message("<span class='danger'>\The [user] is attempting to put [cuff_type] on \the [H]!</span>")
if(!do_after(user,30))
if(!do_after(user,use_time))
return 0
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
@@ -80,7 +81,7 @@
msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]")
feedback_add_details("handcuffs","H")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
user.do_attack_animation(H)
user.visible_message("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")
@@ -199,6 +200,44 @@ var/last_chew = 0
elastic = 0
cuff_sound = 'sound/weapons/handcuffs.ogg' //This shold work for now.
/obj/item/weapon/handcuffs/legcuffs/bola
name = "bola"
desc = "Keeps prey in line."
elastic = 1
use_time = 0
breakouttime = 30
cuff_sound = 'sound/weapons/towelwipe.ogg' //Is there anything this sound can't do?
/obj/item/weapon/handcuffs/legcuffs/bola/can_place(var/mob/target, var/mob/user)
if(user) //A ranged legcuff, until proper implementation as items it remains a projectile-only thing.
return 1
/obj/item/weapon/handcuffs/legcuffs/bola/dropped()
visible_message("<span class='notice'>\The [src] falls apart!</span>")
qdel(src)
/obj/item/weapon/handcuffs/legcuffs/bola/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
playsound(src.loc, cuff_sound, 30, 1, -2)
var/mob/living/carbon/human/H = target
if(!istype(H))
src.dropped()
return 0
if(!H.has_organ_for_slot(slot_legcuffed))
H.visible_message("<span class='notice'>\The [src] slams into [H], but slides off!</span>")
src.dropped()
return 0
H.visible_message("<span class='danger'>\The [H] has been snared by \the [src]!</span>")
// Apply cuffs.
var/obj/item/weapon/handcuffs/legcuffs/lcuffs = src
lcuffs.loc = target
target.legcuffed = lcuffs
target.update_inv_legcuffed()
return 1
/obj/item/weapon/handcuffs/legcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
if(!user.IsAdvancedToolUser())
return
@@ -236,7 +275,7 @@ var/last_chew = 0
user.visible_message("<span class='danger'>\The [user] is attempting to put [cuff_type] on \the [H]!</span>")
if(!do_after(user,30))
if(!do_after(user,use_time))
return 0
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
@@ -247,7 +286,7 @@ var/last_chew = 0
msg_admin_attack("[key_name(user)] attempted to legcuff [key_name(H)]")
feedback_add_details("legcuffs","H")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
user.do_attack_animation(H)
user.visible_message("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")

View File

@@ -351,6 +351,7 @@ the implant may become unstable and either pre-maturely inject the subject or si
R << "You hear a faint *beep*."
if(!src.reagents.total_volume)
R << "You hear a faint click from your chest."
playsound(R, 'sound/weapons/empty.ogg', 10, 1)
spawn(0)
qdel(src)
return

View File

@@ -0,0 +1,112 @@
obj/item/weapon/chainsaw
name = "Chainsaw"
desc = "Vroom vroom."
icon_state = "chainsaw0"
var/on = 0
var/max_fuel = 20
w_class = ITEMSIZE_LARGE
slot_flags = SLOT_BACK
w_class = ITEMSIZE_LARGE
slot_flags = SLOT_BACK
obj/item/weapon/chainsaw/New()
var/datum/reagents/R = new/datum/reagents(max_fuel)
reagents = R
R.my_atom = src
R.add_reagent("fuel", max_fuel)
..()
obj/item/weapon/chainsaw/proc/turnOn()
if(on) return
visible_message("You start pulling the string on \the [src].", "[usr] starts pulling the string on the [src].")
if(max_fuel <= 0)
if(do_after(usr, 15))
to_chat(usr, "\The [src] won't start!")
else
to_chat(usr, "You fumble with the string.")
else
if(do_after(usr, 15))
visible_message("You start \the [src] up with a loud grinding!", "[usr] starts \the [src] up with a loud grinding!")
attack_verb = list("shreds", "rips", "tears")
playsound(src, 'sound/weapons/chainsaw_startup.ogg',40,1)
force = 55
edge = 1
sharp = 1
on = 1
update_icon()
else
to_chat(usr, "You fumble with the string.")
obj/item/weapon/chainsaw/proc/turnOff()
if(!on) return
to_chat(usr, "You switch the gas nozzle on the chainsaw, turning it off.")
attack_verb = list("bluntly hit", "beat", "knocked")
playsound(src, 'sound/weapons/chainsaw_turnoff.ogg',40,1)
force = 10
edge = 0
sharp = 0
on = 0
update_icon()
obj/item/weapon/chainsaw/attack_self(mob/user as mob)
if(!on)
turnOn()
else
turnOff()
obj/item/weapon/chainsaw/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity)
if(!proximity) return
..()
if(on)
playsound(src, 'sound/weapons/chainsaw_attack.ogg',40,1)
if(A && on)
if(istype(A,/obj/structure/window))
var/obj/structure/window/W = A
W.shatter()
else if(istype(A,/obj/structure/grille))
new /obj/structure/grille/broken(A.loc)
new /obj/item/stack/rods(A.loc)
qdel(A)
else if(istype(A,/obj/effect/plant))
var/obj/effect/plant/P = A
qdel(P) //Plant isn't surviving that. At all
if (istype(A, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,A) <= 1)
to_chat(user, "<span class='notice'>You begin filling the tank on the chainsaw.</span>")
if(do_after(usr, 15))
A.reagents.trans_to_obj(src, max_fuel)
playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
to_chat(user, "<span class='notice'>Chainsaw succesfully refueled.</span>")
else
to_chat(user, "<span class='notice'>Don't move while you're refilling the chainsaw.</span>")
obj/item/weapon/chainsaw/process()
if(!on) return
if(on)
if(get_fuel() > 0)
reagents.remove_reagent("fuel", 1)
if(get_fuel() <= 0)
to_chat(usr, "\The [src] sputters to a stop!")
on = !on
obj/item/weapon/chainsaw/proc/get_fuel()
reagents.get_reagent_amount("fuel")
obj/item/weapon/chainsaw/examine(mob/user)
if(..(user,0))
if(max_fuel)
to_chat(usr, "<span class = 'notice'>The [src] feels like it contains roughtly [get_fuel()] units of fuel left.</span>")
obj/item/weapon/chainsaw/suicide_act(mob/user)
to_chat(viewers(user), "<span class='danger'>[user] is lying down and pulling the chainsaw into \him, it looks like \he's trying to commit suicide!</span>")
return(BRUTELOSS)
obj/item/weapon/chainsaw/update_icon()
if(on)
icon_state = "chainsaw1"
item_state = "chainsaw1"
else
icon_state = "chainsaw0"
icon_state = "chainsaw0"

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