Merge branch 'master' of https://github.com/PolarisSS13/Polaris into 10/28/2017_new_blob

# Conflicts:
#	code/game/atoms_movable.dm
This commit is contained in:
Neerti
2017-11-29 22:43:05 -05:00
518 changed files with 22619 additions and 17057 deletions

View File

@@ -36,9 +36,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 polaris.dme
- 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 polaris.dme
- DreamDaemon polaris.dmb -invisible -trusted -core 2>&1 | tee log.txt
- grep "All Unit Tests Passed" log.txt

View File

@@ -4,7 +4,7 @@ client/proc/ZoneTick()
var/result = air_master.Tick()
if(result)
src << "Sucessfully Processed."
src << "Successfully Processed."
else
src << "Failed to process! ([air_master.tick_progress])"

View File

@@ -6,6 +6,7 @@
#define OXY "oxy"
#define CLONE "clone"
#define HALLOSS "halloss"
#define ELECTROCUTE "electrocute"
#define CUT "cut"
#define BRUISE "bruise"
@@ -56,3 +57,4 @@
#define INFECTION_LEVEL_ONE 100
#define INFECTION_LEVEL_TWO 500
#define INFECTION_LEVEL_THREE 1000
#define INFECTION_LEVEL_MAX 1500

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.

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

@@ -51,6 +51,22 @@ avoid code duplication. This includes items that may sometimes act as a standard
return 0
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)
@@ -73,7 +89,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

@@ -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
name = "rifle magazine (5.45mm hunting)"
path =/obj/item/ammo_magazine/m545/hunter
/datum/category_item/autolathe/arms/machinegun_545
name = "machinegun box magazine (5.56)"
path =/obj/item/ammo_magazine/m545saw
hidden = 1
/datum/category_item/autolathe/arms/machinegun_545_hunter
name = "machinegun box magazine (5.56 hunting)"
path =/obj/item/ammo_magazine/m545saw/hunter
hidden = 1
/////// 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)"
@@ -298,6 +308,15 @@
name = "speedloader (.38 rubber)"
path =/obj/item/ammo_magazine/s38/rubber
/datum/category_item/autolathe/arms/speedloader_45
name = "speedloader (.45)"
path = /obj/item/ammo_magazine/s45
hidden = 1
/datum/category_item/autolathe/arms/speedloader_45r
name = "speedloader (.45 rubber)"
path = /obj/item/ammo_magazine/s45/rubber
// Commented out until metal exploits with autolathe is fixed.
/*/datum/category_item/autolathe/arms/pistol_clip_45
name = "ammo clip (.45)"
@@ -375,6 +394,10 @@
path =/obj/item/ammo_magazine/clip/c762
hidden = 1
/datum/category_item/autolathe/arms/rifle_clip_762_hunter
name = "ammo clip (7.62mm hunting)"
path =/obj/item/ammo_magazine/clip/c762/hunter
/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

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

@@ -3,6 +3,7 @@
belt = /obj/item/weapon/storage/belt/utility/full
l_ear = /obj/item/device/radio/headset/headset_eng
shoes = /obj/item/clothing/shoes/boots/workboots
r_pocket = /obj/item/device/t_scanner
backpack = /obj/item/weapon/storage/backpack/industrial
satchel_one = /obj/item/weapon/storage/backpack/satchel/eng
messenger_bag = /obj/item/weapon/storage/backpack/messenger/engi
@@ -22,7 +23,6 @@
name = OUTFIT_JOB_NAME("Engineer")
head = /obj/item/clothing/head/hardhat
uniform = /obj/item/clothing/under/rank/engineer
r_pocket = /obj/item/device/t_scanner
id_type = /obj/item/weapon/card/id/engineering/engineer
pda_type = /obj/item/device/pda/engineering

View File

@@ -103,3 +103,4 @@
/decl/hierarchy/outfit/job/medical/paramedic/emt
name = OUTFIT_JOB_NAME("Emergency Medical Technician")
uniform = /obj/item/clothing/under/rank/medical/paramedic
suit = /obj/item/clothing/suit/storage/toggle/labcoat/emt

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
@@ -63,11 +63,13 @@
/obj/item/clothing/suit/storage/vest/heavy/merc,
/obj/item/clothing/glasses/night,
/obj/item/weapon/storage/box/anti_photons,
/obj/item/ammo_magazine/clip/c12g/pellet, /obj/item/ammo_magazine/clip/c12g
/obj/item/ammo_magazine/clip/c12g/pellet,
/obj/item/ammo_magazine/clip/c12g
),
list( //the doc,
/obj/item/weapon/storage/firstaid/combat,
/obj/item/weapon/gun/projectile/dartgun, /obj/item/weapon/reagent_containers/hypospray,
/obj/item/weapon/gun/projectile/dartgun,
/obj/item/weapon/reagent_containers/hypospray,
/obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate,
/obj/item/weapon/reagent_containers/glass/bottle/cyanide,
/obj/item/ammo_magazine/chemdart
@@ -78,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

@@ -21,6 +21,48 @@
containertype = /obj/structure/closet/crate/engineering
containername = "Superconducting Magnetic Coil crate"
/datum/supply_packs/eng/shield_capacitor
name = "Shield Capacitor"
contains = list(/obj/machinery/shield_capacitor)
cost = 20
containertype = /obj/structure/closet/crate/engineering
containername = "shield capacitor crate"
/datum/supply_packs/eng/shield_capacitor/advanced
name = "Advanced Shield Capacitor"
contains = list(/obj/machinery/shield_capacitor/advanced)
cost = 30
containertype = /obj/structure/closet/crate/engineering
containername = "advanced shield capacitor crate"
/datum/supply_packs/eng/bubble_shield
name = "Bubble Shield Generator"
contains = list(/obj/machinery/shield_gen)
cost = 40
containertype = /obj/structure/closet/crate/engineering
containername = "shield bubble generator crate"
/datum/supply_packs/eng/bubble_shield/advanced
name = "Advanced Bubble Shield Generator"
contains = list(/obj/machinery/shield_gen/advanced)
cost = 60
containertype = /obj/structure/closet/crate/engineering
containername = "advanced bubble shield generator crate"
/datum/supply_packs/eng/hull_shield
name = "Hull Shield Generator"
contains = list(/obj/machinery/shield_gen/external)
cost = 80
containertype = /obj/structure/closet/crate/engineering
containername = "shield hull generator crate"
/datum/supply_packs/eng/hull_shield/advanced
name = "Advanced Hull Shield Generator"
contains = list(/obj/machinery/shield_gen/external/advanced)
cost = 120
containertype = /obj/structure/closet/crate/engineering
containername = "advanced hull shield generator crate"
/datum/supply_packs/eng/electrical
name = "Electrical maintenance crate"
contains = list(

View File

@@ -119,7 +119,7 @@
/obj/item/weapon/storage/belt/medical,
/obj/item/device/radio/headset/heads/cmo,
/obj/item/clothing/under/rank/chief_medical_officer,
/obj/item/weapon/reagent_containers/hypospray,
/obj/item/weapon/reagent_containers/hypospray/vial,
/obj/item/clothing/accessory/stethoscope,
/obj/item/clothing/glasses/hud/health,
/obj/item/clothing/suit/storage/toggle/labcoat/cmo,

View File

@@ -142,7 +142,7 @@
/obj/item/clothing/shoes/magboots = 2,
/obj/item/weapon/tank/oxygen = 2
)
cost = 50
cost = 60
containertype = "/obj/structure/closet/crate/secure"
containername = "Vey-Med Medical voidsuit crate"
access = access_medical_equip

View File

@@ -22,6 +22,14 @@
name = "Pistol Magazine (.45 AP)"
path = /obj/item/ammo_magazine/m45/ap
/datum/uplink_item/item/ammo/s45m
name = "Speedloader (.45)"
path = /obj/item/ammo_magazine/s45
/datum/uplink_item/item/ammo/s45map
name = "Speedloader (.45 AP)"
path = /obj/item/ammo_magazine/s45/ap
/datum/uplink_item/item/ammo/tommymag
name = "Tommygun Magazine (.45)"
path = /obj/item/ammo_magazine/m45tommy

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

@@ -78,7 +78,7 @@
/obj/item/weapon/cane
name = "cane"
desc = "A cane used by a true gentlemen. Or a clown."
desc = "A cane used by a true gentleman."
icon = 'icons/obj/weapons.dmi'
icon_state = "cane"
item_icons = list(
@@ -88,7 +88,7 @@
flags = CONDUCT
force = 5.0
throwforce = 7.0
w_class = ITEMSIZE_SMALL
w_class = ITEMSIZE_NORMAL
matter = list(DEFAULT_WALL_MATERIAL = 50)
attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed")
@@ -218,7 +218,7 @@
/obj/item/weapon/SWF_uplink
name = "station-bounced radio"
desc = "used to comunicate it appears."
desc = "Used to communicate, it appears."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
var/temp = null
@@ -607,7 +607,7 @@
/obj/item/weapon/ectoplasm
name = "ectoplasm"
desc = "spooky"
desc = "Spooky!"
gender = PLURAL
icon = 'icons/obj/wizard.dmi'
icon_state = "ectoplasm"

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

@@ -13,5 +13,5 @@ var/datum/antagonist/thug/thugs
Try to make sure other players have <i>fun</i>! If you are confused or at a loss, always adminhelp, \
and before taking extreme actions, please try to also contact the administration! \
Think through your actions and make the roleplay immersive! <b>Please remember all \
rules aside from those without explicit exceptions apply to antagonists.</b>"
rules aside from those with explicit exceptions apply to antagonists.</b>"
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE

View File

@@ -1,6 +1,6 @@
/atom/movable
layer = 3
appearance_flags = TILE_BOUND
appearance_flags = TILE_BOUND|PIXEL_SCALE
var/last_move = null
var/anchored = 0
// var/elevation = 2 - not used anywhere
@@ -15,6 +15,7 @@
var/moved_recently = 0
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
@@ -297,3 +298,12 @@
return null
return text2num(pickweight(candidates))
/atom/movable/proc/update_transform()
var/matrix/M = matrix()
M.Scale(icon_scale)
src.transform = M
// Use this to set the object's scale.
/atom/movable/proc/adjust_scale(new_scale)
icon_scale = new_scale
update_transform()

View File

@@ -4,6 +4,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/list/datum/absorbed_dna/absorbed_dna = list()
var/list/absorbed_languages = list() // Necessary because of set_species stuff
var/absorbedcount = 0
var/lingabsorbedcount = 1 //Starts at one, because that's us
var/chem_charges = 20
var/chem_recharge_rate = 0.5
var/chem_storage = 50
@@ -11,8 +12,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/changelingID = "Changeling"
var/geneticdamage = 0
var/isabsorbing = 0
var/geneticpoints = 5
var/max_geneticpoints = 5
var/geneticpoints = 7
var/max_geneticpoints = 7
var/readapts = 1
var/max_readapts = 2
var/list/purchased_powers = list()
@@ -22,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)
..()
@@ -219,7 +221,11 @@ turf/proc/AdjacentTurfsRangedSting()
victims += C
var/mob/living/carbon/T = input(src, "Who will we sting?") as null|anything in victims
if(!T) return
if(!T)
return
if(T.isSynthetic())
src << "<span class='notice'>We are unable to pierce the outer shell of [T].</span>"
return
if(!(T in view(changeling.sting_range))) return
if(!sting_can_reach(T, changeling.sting_range)) return
if(!changeling_power(required_chems)) return

View File

@@ -90,16 +90,23 @@
continue
absorbDNA(dna_data)
changeling.absorbedcount++
T.mind.changeling.absorbed_dna.len = 1
changeling.geneticpoints += 5
changeling.max_geneticpoints += 5
// This is where lings get boosts from eating eachother
if(T.mind.changeling.lingabsorbedcount)
for(var/a = 1 to T.mind.changeling.lingabsorbedcount)
changeling.lingabsorbedcount++
changeling.geneticpoints += 4
changeling.max_geneticpoints += 4
src << "<span class='notice'>We absorbed another changeling, and we grow stronger. Our genomes increase.</span>"
T.mind.changeling.chem_charges = 0
T.mind.changeling.geneticpoints = -1
T.mind.changeling.max_geneticpoints = -1 //To prevent revival.
T.mind.changeling.absorbedcount = 0
T.mind.changeling.lingabsorbedcount = 0
changeling.absorbedcount++
changeling.isabsorbing = 0

View File

@@ -135,3 +135,4 @@
name = "hand greatclaw"
force = 20
armor_penetration = 20
pry = 1

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

@@ -123,7 +123,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"])
return tearreality()
if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"])
return emp(src.loc,3)
return emp(src.loc,5)
if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"])
return drain()
if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"])

View File

@@ -43,10 +43,13 @@ var/global/datum/controller/gameticker/ticker
'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)
@@ -76,7 +79,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)
@@ -91,7 +94,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()
@@ -100,7 +103,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()
@@ -116,13 +119,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()
@@ -139,7 +142,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()
@@ -152,7 +155,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()
@@ -304,7 +307,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()
@@ -340,7 +343,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)
@@ -353,15 +356,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
@@ -371,7 +374,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()
@@ -385,7 +388,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))
@@ -426,9 +429,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

@@ -7,8 +7,8 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind'
/datum/game_mode/heist
name = "Heist"
config_tag = "heist"
required_players = 9
required_players_secret = 9
required_players = 12
required_players_secret = 12
required_enemies = 3
round_description = "An unidentified bluespace signature is approaching the station!"
extended_round_description = "The Company's majority control of phoron in the system has marked the \

View File

@@ -12,8 +12,8 @@ var/list/nuke_disks = list()
colony of sizable population and considerable wealth causes it to often be the target of various \
attempts of robbery, fraud and other malicious actions."
config_tag = "mercenary"
required_players = 9
required_players_secret = 9
required_players = 12
required_players_secret = 12
required_enemies = 3
end_on_antag_death = 0
var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station

View File

@@ -440,7 +440,7 @@ datum/objective/steal
"a chief medical officer's jumpsuit" = /obj/item/clothing/under/rank/chief_medical_officer,
"a head of security's jumpsuit" = /obj/item/clothing/under/rank/head_of_security,
"a head of personnel's jumpsuit" = /obj/item/clothing/under/rank/head_of_personnel,
"the hypospray" = /obj/item/weapon/reagent_containers/hypospray,
"the hypospray" = /obj/item/weapon/reagent_containers/hypospray/vial,
"the colony director's pinpointer" = /obj/item/weapon/pinpointer,
"an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof,
)

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

@@ -74,7 +74,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

@@ -55,31 +55,31 @@
if(shocked)
shock(user, 50)
var/dat = "<center><h1>Autolathe Control Panel</h1><hr/>"
var/list/dat = list()
dat += "<center><h1>Autolathe Control Panel</h1><hr/>"
if(!disabled)
dat += "<table width = '100%'>"
var/material_top = "<tr>"
var/material_bottom = "<tr>"
var/list/material_top = list("<tr>")
var/list/material_bottom = list("<tr>")
for(var/material in stored_material)
material_top += "<td width = '25%' align = center><b>[material]</b></td>"
material_bottom += "<td width = '25%' align = center>[stored_material[material]]<b>/[storage_capacity[material]]</b></td>"
dat += "[material_top]</tr>[material_bottom]</tr></table><hr>"
dat += "[material_top.Join()]</tr>[material_bottom.Join()]</tr></table><hr>"
dat += "<h2>Printable Designs</h2><h3>Showing: <a href='?src=\ref[src];change_category=1'>[current_category]</a>.</h3></center><table width = '100%'>"
for(var/datum/category_item/autolathe/R in current_category.items)
if(R.hidden && !hacked)
continue
var/can_make = 1
var/material_string = ""
var/multiplier_string = ""
var/list/material_string = list()
var/list/multiplier_string = list()
var/max_sheets
var/comma
if(!R.resources || !R.resources.len)
material_string = "No resources required.</td>"
material_string += "No resources required.</td>"
else
//Make sure it's buildable and list requires resources.
for(var/material in R.resources)
@@ -103,7 +103,7 @@
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[i]'>\[x[i]\]</a>"
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[max_sheets]'>\[x[max_sheets]\]</a>"
dat += "<tr><td width = 180>[R.hidden ? "<font color = 'red'>*</font>" : ""]<b>[can_make ? "<a href='?src=\ref[src];make=\ref[R];multiplier=1'>" : ""][R.name][can_make ? "</a>" : ""]</b>[R.hidden ? "<font color = 'red'>*</font>" : ""][multiplier_string]</td><td align = right>[material_string]</tr>"
dat += "<tr><td width = 180>[R.hidden ? "<font color = 'red'>*</font>" : ""]<b>[can_make ? "<a href='?src=\ref[src];make=\ref[R];multiplier=1'>" : ""][R.name][can_make ? "</a>" : ""]</b>[R.hidden ? "<font color = 'red'>*</font>" : ""][multiplier_string.Join()]</td><td align = right>[material_string.Join()]</tr>"
dat += "</table><hr>"
//Hacking.
@@ -113,7 +113,7 @@
dat += "<hr>"
user << browse(dat, "window=autolathe")
user << browse(dat.Join(), "window=autolathe")
onclose(user, "autolathe")
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)

View File

@@ -130,7 +130,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 +210,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

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

@@ -127,6 +127,36 @@
icon = 'icons/obj/doors/Doormaint.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_mai
/obj/machinery/door/airlock/maintenance/cargo
icon = 'icons/obj/doors/Doormaint_cargo.dmi'
req_one_access = list(access_cargo)
/obj/machinery/door/airlock/maintenance/command
icon = 'icons/obj/doors/Doormaint_command.dmi'
req_one_access = list(access_heads)
/obj/machinery/door/airlock/maintenance/common
icon = 'icons/obj/doors/Doormaint_common.dmi'
/obj/machinery/door/airlock/maintenance/engi
icon = 'icons/obj/doors/Doormaint_engi.dmi'
req_one_access = list(access_engine)
/obj/machinery/door/airlock/maintenance/int
icon = 'icons/obj/doors/Doormaint_int.dmi'
/obj/machinery/door/airlock/maintenance/medical
icon = 'icons/obj/doors/Doormaint_med.dmi'
req_one_access = list(access_medical)
/obj/machinery/door/airlock/maintenance/rnd
icon = 'icons/obj/doors/Doormaint_rnd.dmi'
req_one_access = list(access_research)
/obj/machinery/door/airlock/maintenance/sec
icon = 'icons/obj/doors/Doormaint_sec.dmi'
req_one_access = list(access_security)
/obj/machinery/door/airlock/external
name = "External Airlock"
icon = 'icons/obj/doors/Doorext.dmi'
@@ -386,6 +416,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

@@ -260,7 +260,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)

View File

@@ -2,15 +2,44 @@
/obj/machinery/door/airlock/multi_tile
width = 2
appearance_flags = 0
var/obj/machinery/filler_object/filler1
var/obj/machinery/filler_object/filler2
/obj/machinery/door/airlock/multi_tile/New()
..()
SetBounds()
if(opacity)
create_fillers()
/obj/machinery/door/airlock/multi_tile/Destroy()
qdel_null(filler1)
qdel_null(filler2)
return ..()
/obj/machinery/door/airlock/multi_tile/Move()
. = ..()
SetBounds()
/obj/machinery/door/airlock/multi_tile/open()
. = ..()
if(filler1)
filler1.set_opacity(opacity)
if(filler2)
filler2.set_opacity(opacity)
return .
/obj/machinery/door/airlock/multi_tile/close()
. = ..()
if(filler1)
filler1.set_opacity(opacity)
if(filler2)
filler2.set_opacity(opacity)
return .
/obj/machinery/door/airlock/multi_tile/proc/SetBounds()
if(dir in list(EAST, WEST))
bound_width = width * world.icon_size
@@ -19,9 +48,35 @@
bound_width = world.icon_size
bound_height = width * world.icon_size
/obj/machinery/door/airlock/multi_tile/proc/create_fillers()
if(src.dir > 3)
filler1 = new/obj/machinery/filler_object (src.loc)
filler2 = new/obj/machinery/filler_object (get_step(src,EAST))
else
filler1 = new/obj/machinery/filler_object (src.loc)
filler2 = new/obj/machinery/filler_object (get_step(src,NORTH))
filler1.density = 0
filler2.density = 0
filler1.set_opacity(opacity)
filler2.set_opacity(opacity)
/obj/machinery/door/airlock/multi_tile/glass
name = "Glass Airlock"
icon = 'icons/obj/doors/Door2x1glass.dmi'
opacity = 0
glass = 1
assembly_type = /obj/structure/door_assembly/multi_tile
/obj/machinery/door/airlock/multi_tile/metal
name = "Airlock"
icon = 'icons/obj/doors/Door2x1metal.dmi'
assembly_type = /obj/structure/door_assembly/multi_tile
/obj/machinery/filler_object
name = ""
icon = 'icons/obj/doors/rapid_pdoor.dmi'
icon_state = ""
density = 0
/obj/machinery/door/airlock/multi_tile/metal/mait
icon = 'icons/obj/doors/Door2x1_Maint.dmi'

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)
@@ -289,3 +295,27 @@
if(!usr.incapacitated())
return
go_in(usr)
/obj/machinery/recharge_station/ghost_pod_recharger
name = "drone pod"
desc = "This is a pod which used to contain a drone... Or maybe it still does?"
icon = 'icons/obj/structures.dmi'
/obj/machinery/recharge_station/ghost_pod_recharger/update_icon()
..()
if(stat & BROKEN)
icon_state = "borg_pod_closed"
desc = "It appears broken..."
return
if(occupant)
if((stat & NOPOWER) && !has_cell_power())
icon_state = "borg_pod_closed"
desc = "It appears to be unpowered..."
else
icon_state = "borg_pod_closed"
else
icon_state = "borg_pod_opened"
if(icon_update_tick == 0)
build_overlays()

View File

@@ -640,7 +640,7 @@
name = "Nonstandard suit cycler"
model_text = "Nonstandard"
req_access = list(access_syndicate)
departments = list("Mercenary")
departments = list("Mercenary", "Charring")
can_repair = 1
/obj/machinery/suit_cycler/attack_ai(mob/user as mob)
@@ -752,7 +752,7 @@
//Clear the access reqs, disable the safeties, and open up all paintjobs.
user << "<span class='danger'>You run the sequencer across the interface, corrupting the operating protocols.</span>"
departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Crowd Control","Emergency Medical Response","^%###^%$")
departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Crowd Control","Emergency Medical Response","^%###^%$", "Charring")
species = list("Human","Tajara","Skrell","Unathi", "Teshari")
emagged = 1
@@ -1073,6 +1073,15 @@
suit.name = "blood-red voidsuit"
suit.item_state = "syndie_voidsuit"
suit.icon_state = "rig-syndie"
if("Charring")
if(helmet)
helmet.name = "soot-covered voidsuit helmet"
helmet.icon_state = "rig0-firebug"
helmet.item_state = "rig0-firebug"
if(suit)
suit.name = "soot-covered voidsuit"
suit.item_state = "rig-firebug"
suit.icon_state = "rig-firebug"
if(helmet) helmet.name = "refitted [helmet.name]"
if(suit) suit.name = "refitted [suit.name]"

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

@@ -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
@@ -806,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."
@@ -821,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!"
@@ -865,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!"
@@ -1051,7 +1051,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."
@@ -1070,7 +1069,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

@@ -0,0 +1,226 @@
/obj/machinery/vr_sleeper
name = "VR 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"
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/vr_sleeper
var/mob/living/carbon/human/occupant = null
var/mob/living/carbon/human/avatar = null
var/datum/mind/vr_mind = null
use_power = 1
idle_power_usage = 15
active_power_usage = 200
light_color = "#FF0000"
/obj/machinery/vr_sleeper/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
RefreshParts()
/obj/machinery/vr_sleeper/initialize()
update_icon()
/obj/machinery/vr_sleeper/process()
if(stat & (NOPOWER|BROKEN))
return
/obj/machinery/vr_sleeper/update_icon()
icon_state = "syndipod_[occupant ? "1" : "0"]"
/obj/machinery/vr_sleeper/Topic(href, href_list)
if(..())
return 1
if(usr == occupant)
to_chat(usr, "<span class='warning'>You can't reach the controls from the inside.</span>")
return
add_fingerprint(usr)
if(href_list["eject"])
go_out()
return 1
/obj/machinery/vr_sleeper/attackby(var/obj/item/I, var/mob/user)
add_fingerprint(user)
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
/obj/machinery/vr_sleeper/MouseDrop_T(var/mob/target, var/mob/user)
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !isliving(target))
return
go_in(target, user)
/obj/machinery/sleeper/relaymove(var/mob/user)
..()
if(usr.incapacitated())
return
go_out()
/obj/machinery/vr_sleeper/emp_act(var/severity)
if(stat & (BROKEN|NOPOWER))
..(severity)
return
if(occupant)
// This will eject the user from VR
// ### Fry the brain?
go_out()
..(severity)
/obj/machinery/vr_sleeper/verb/eject()
set src in oview(1)
set category = "Object"
set name = "Eject VR Capsule"
if(usr.incapacitated())
return
if(usr != occupant && avatar && alert(avatar, "Someone wants to remove you from virtual reality. Do you want to leave?", "Leave VR?", "Yes", "No") == "No")
return
// The player in VR is fine with leaving, kick them out and reset avatar
avatar.exit_vr()
avatar = null
go_out()
add_fingerprint(usr)
/obj/machinery/vr_sleeper/verb/climb_in()
set src in oview(1)
set category = "Object"
set name = "Enter VR Capsule"
if(usr.incapacitated())
return
go_in(usr, usr)
add_fingerprint(usr)
/obj/machinery/vr_sleeper/relaymove(mob/user as mob)
if(user.incapacitated())
return 0 //maybe they should be able to get out with cuffs, but whatever
go_out()
/obj/machinery/vr_sleeper/proc/go_in(var/mob/M, var/mob/user)
if(!M)
return
if(stat & (BROKEN|NOPOWER))
return
if(!ishuman(M))
user << "<span class='warning'>\The [src] rejects [M] with a sharp beep.</span>"
if(occupant)
user << "<span class='warning'>\The [src] is already occupied.</span>"
return
if(M == user)
visible_message("\The [user] starts climbing into \the [src].")
else
visible_message("\The [user] starts putting [M] into \the [src].")
if(do_after(user, 20))
if(occupant)
to_chat(user, "<span class='warning'>\The [src] is already occupied.</span>")
return
M.stop_pulling()
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.loc = src
update_use_power(2)
occupant = M
update_icon()
enter_vr()
return
/obj/machinery/vr_sleeper/proc/go_out()
if(!occupant)
return
if(occupant.client)
occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE
occupant.loc = src.loc
occupant = null
for(var/atom/movable/A in src) // In case an object was dropped inside or something
if(A == circuit)
continue
if(A in component_parts)
continue
A.loc = src.loc
update_use_power(1)
update_icon()
/obj/machinery/vr_sleeper/proc/enter_vr()
// No mob to transfer a mind from
if(!occupant)
return
// No mind to transfer
if(!occupant.mind)
return
// Mob doesn't have an active consciousness to send/receive from
if(occupant.stat != CONSCIOUS)
return
avatar = occupant.vr_link
// If they've already enterred VR, and are reconnecting, prompt if they want a new body
if(avatar && alert(occupant, "You already have a Virtual Reality avatar. Would you like to use it?", "New avatar", "Yes", "No") == "No")
// Delink the mob
occupant.vr_link = null
avatar = null
if(!avatar)
// Get the desired spawn location to put the body
var/S = null
var/list/vr_landmarks = list()
for(var/obj/effect/landmark/virtual_reality/sloc in landmarks_list)
vr_landmarks += sloc.name
S = input(occupant, "Please select a location to spawn your avatar at:", "Spawn location") as null|anything in vr_landmarks
if(!S)
return 0
for(var/obj/effect/landmark/virtual_reality/i in landmarks_list)
if(i.name == S)
S = i
break
avatar = new(S, "Virtual Reality Avatar")
// If the user has a non-default (Human) bodyshape, make it match theirs.
if(occupant.species.name != "Promethean" && occupant.species.name != "Human")
avatar.shapeshifter_change_shape(occupant.species.name)
avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it
avatar.Sleeping(1)
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)
if (newname)
avatar.real_name = newname
else
occupant.enter_vr(avatar)

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

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

@@ -107,6 +107,18 @@
return 1
/obj/effect/landmark/virtual_reality
name = "virtual_reality"
icon = 'icons/mob/screen1.dmi'
icon_state = "x"
anchored = 1.0
/obj/effect/landmark/virtual_reality/New()
..()
tag = "virtual_reality*[name]"
invisibility = 101
return 1
//Costume spawner landmarks
/obj/effect/landmark/costume/New() //costume spawner, selects a random subclass and disappears

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>")
@@ -210,25 +210,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
@@ -249,6 +232,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."
@@ -261,7 +265,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

@@ -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/addblends // Icon overlay for ADD highlights when applicable.
/obj/item/New()
..()
@@ -456,7 +458,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)

View File

@@ -59,7 +59,7 @@
//..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri
return
else if(istype(W, /obj/item/weapon/wirecutters))
user << "You cut the tag off the bodybag"
to_chat(user, "You cut the tag off the bodybag")
src.name = "body bag"
src.overlays.Cut()
return
@@ -160,7 +160,7 @@
O.name = "used stasis bag"
O.icon = src.icon
O.icon_state = "bodybag_used"
O.desc = "Pretty useless now.."
O.desc = "Pretty useless now..."
qdel(src)
/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location)
@@ -211,9 +211,9 @@
/obj/structure/closet/body_bag/cryobag/examine(mob/user)
..()
if(Adjacent(user)) //The bag's rather thick and opaque from a distance.
user << "<span class='info'>You peer into \the [src].</span>"
to_chat(user, "<span class='info'>You peer into \the [src].</span>")
if(syringe)
user << "<span class='info'>It has a syringe added to it.</span>"
to_chat(user, "<span class='info'>It has a syringe added to it.</span>")
for(var/mob/living/L in contents)
L.examine(user)

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

@@ -62,7 +62,7 @@
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
@@ -75,9 +75,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
@@ -147,7 +144,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)

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

@@ -1,7 +1,7 @@
#define RAD_LEVEL_LOW 5 //10 // Around the level at which radiation starts to become harmful
#define RAD_LEVEL_MODERATE 15 //15
#define RAD_LEVEL_HIGH 50 //50
#define RAD_LEVEL_VERY_HIGH 100 //100
#define RAD_LEVEL_LOW 0.01 // Around the level at which radiation starts to become harmful
#define RAD_LEVEL_MODERATE 10
#define RAD_LEVEL_HIGH 25
#define RAD_LEVEL_VERY_HIGH 50
//Geiger counter
//Rewritten version of TG's geiger counter
@@ -19,7 +19,14 @@
/obj/item/device/geiger/New()
processing_objects |= src
/obj/item/device/geiger/Destroy()
processing_objects -= src
return ..()
/obj/item/device/geiger/process()
get_radiation()
/obj/item/device/geiger/proc/get_radiation()
if(!scanning)
return
radiation_count = radiation_repository.get_rads_at_turf(get_turf(src))
@@ -27,12 +34,29 @@
/obj/item/device/geiger/examine(mob/user)
..(user)
to_chat(user, "<span class='warning'>[scanning ? "ambient" : "stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.</span>")
get_radiation()
to_chat(user, "<span class='warning'>[scanning ? "Ambient" : "Stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.</span>")
/obj/item/device/geiger/rad_act(amount)
if(!amount || !scanning)
return FALSE
if(amount > radiation_count)
radiation_count = amount
var/sound = "geiger"
if(amount < 5)
sound = "geiger_weak"
playsound(src, sound, between(10, 10 + (radiation_count * 4), 100), 0)
if(sound == "geiger_weak") // A weak geiger sound every two seconds sounds too infrequent.
spawn(1 SECOND)
playsound(src, sound, between(10, 10 + (radiation_count * 4), 100), 0)
update_icon()
/obj/item/device/geiger/attack_self(var/mob/user)
scanning = !scanning
update_icon()
to_chat(user, "<span class='notice'>\icon[src] You switch [scanning ? "on" : "off"] [src].</span>")
to_chat(user, "<span class='notice'>\icon[src] You switch [scanning ? "on" : "off"] \the [src].</span>")
/obj/item/device/geiger/update_icon()
if(!scanning)
@@ -40,12 +64,18 @@
return 1
switch(radiation_count)
if(null) icon_state = "geiger_on_1"
if(-INFINITY to RAD_LEVEL_LOW) icon_state = "geiger_on_1"
if(RAD_LEVEL_LOW + 1 to RAD_LEVEL_MODERATE) icon_state = "geiger_on_2"
if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH) icon_state = "geiger_on_3"
if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH) icon_state = "geiger_on_4"
if(RAD_LEVEL_VERY_HIGH + 1 to INFINITY) icon_state = "geiger_on_5"
if(null)
icon_state = "geiger_on_1"
if(-INFINITY to RAD_LEVEL_LOW)
icon_state = "geiger_on_1"
if(RAD_LEVEL_LOW to RAD_LEVEL_MODERATE)
icon_state = "geiger_on_2"
if(RAD_LEVEL_MODERATE to RAD_LEVEL_HIGH)
icon_state = "geiger_on_3"
if(RAD_LEVEL_HIGH to RAD_LEVEL_VERY_HIGH)
icon_state = "geiger_on_4"
if(RAD_LEVEL_VERY_HIGH to INFINITY)
icon_state = "geiger_on_5"
#undef RAD_LEVEL_LOW
#undef RAD_LEVEL_MODERATE

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_MATERIALS = 2, TECH_BLUESPACE = 2, TECH_MAGNETS = 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_MATERIALS = 2, TECH_BLUESPACE = 3, TECH_MAGNETS = 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

@@ -8,7 +8,7 @@
var/spamcheck = 0
var/emagged = 0
var/insults = 0
var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TATER!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!")
var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TERRORIST!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "GLORY TO ALMACH!")
/obj/item/device/megaphone/attack_self(mob/living/user as mob)
if (user.client)

View File

@@ -0,0 +1,19 @@
/obj/item/gunbox
name = "detective's gun box"
desc = "A secure box containing a Detective's sidearm."
icon = 'icons/obj/storage.dmi'
icon_state = "gunbox"
w_class = ITEMSIZE_HUGE
/obj/item/gunbox/attack_self(mob/living/user)
var/list/options = list()
options[".45 Pistol"] = list(/obj/item/weapon/gun/projectile/colt/detective, /obj/item/ammo_magazine/m45/rubber, /obj/item/ammo_magazine/m45/rubber)
options[".45 Revolver"] = list(/obj/item/weapon/gun/projectile/revolver/detective45, /obj/item/ammo_magazine/s45/rubber, /obj/item/ammo_magazine/s45/rubber)
var/choice = input(user,"Would you prefer a pistol or a revolver?") as null|anything in options
if(src && choice)
var/list/things_to_spawn = options[choice]
for(var/new_type in things_to_spawn) // Spawn all the things, the gun and the ammo.
var/atom/movable/AM = new new_type(get_turf(src))
if(istype(AM, /obj/item/weapon/gun))
to_chat(user, "You have chosen \the [AM]. Say hello to your new friend.")
qdel(src)

View File

@@ -173,3 +173,23 @@
R.emag_items = 1
return 1
/obj/item/borg/upgrade/language
name = "language module"
desc = "Used to let cyborgs other than clerical or service speak a variety of languages."
icon_state = "cyborg_upgrade3"
item_state = "cyborg_upgrade"
/obj/item/borg/upgrade/language/action(var/mob/living/silicon/robot/R)
if(..()) return 0
R.add_language(LANGUAGE_SOL_COMMON, 1)
R.add_language(LANGUAGE_TRADEBAND, 1)
R.add_language(LANGUAGE_UNATHI, 1)
R.add_language(LANGUAGE_SIIK, 1)
R.add_language(LANGUAGE_SKRELLIAN, 1)
R.add_language(LANGUAGE_GUTTER, 1)
R.add_language(LANGUAGE_SCHECHI, 1)
R.add_language(LANGUAGE_ROOTLOCAL, 1)
return 1

View File

@@ -75,11 +75,11 @@
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
if(affecting.open)
user << "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>"
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
return
if(affecting.is_bandaged())
user << "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>"
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
return 1
else
user.visible_message("<span class='notice'>\The [user] starts treating [M]'s [affecting.name].</span>", \
@@ -93,9 +93,13 @@
if(used == amount)
break
if(!do_mob(user, M, W.damage/5))
user << "<span class='notice'>You must stand still to bandage wounds.</span>"
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
break
if(affecting.is_bandaged()) // We do a second check after the delay, in case it was bandaged after the first check.
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
return 1
if (W.current_stage <= W.max_bleeding_stage)
user.visible_message("<span class='notice'>\The [user] bandages \a [W.desc] on [M]'s [affecting.name].</span>", \
"<span class='notice'>You bandage \a [W.desc] on [M]'s [affecting.name].</span>" )
@@ -111,9 +115,9 @@
affecting.update_damages()
if(used == amount)
if(affecting.is_bandaged())
user << "<span class='warning'>\The [src] is used up.</span>"
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
else
user << "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>"
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
use(used)
/obj/item/stack/medical/ointment
@@ -135,17 +139,20 @@
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
if(affecting.open)
user << "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>"
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
return
if(affecting.is_salved())
user << "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>"
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
return 1
else
user.visible_message("<span class='notice'>\The [user] starts salving wounds on [M]'s [affecting.name].</span>", \
"<span class='notice'>You start salving the wounds on [M]'s [affecting.name].</span>" )
if(!do_mob(user, M, 10))
user << "<span class='notice'>You must stand still to salve wounds.</span>"
to_chat(user, "<span class='notice'>You must stand still to salve wounds.</span>")
return 1
if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check.
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
return 1
user.visible_message("<span class='notice'>[user] salved wounds on [M]'s [affecting.name].</span>", \
"<span class='notice'>You salved wounds on [M]'s [affecting.name].</span>" )
@@ -169,11 +176,11 @@
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
if(affecting.open)
user << "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>"
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
return
if(affecting.is_bandaged() && affecting.is_disinfected())
user << "<span class='warning'>The wounds on [M]'s [affecting.name] have already been treated.</span>"
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been treated.</span>")
return 1
else
user.visible_message("<span class='notice'>\The [user] starts treating [M]'s [affecting.name].</span>", \
@@ -187,8 +194,11 @@
if(used == amount)
break
if(!do_mob(user, M, W.damage/5))
user << "<span class='notice'>You must stand still to bandage wounds.</span>"
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
break
if(affecting.is_bandaged() && affecting.is_disinfected()) // We do a second check after the delay, in case it was bandaged after the first check.
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
return 1
if (W.current_stage <= W.max_bleeding_stage)
user.visible_message("<span class='notice'>\The [user] cleans \a [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.</span>", \
"<span class='notice'>You clean and seal \a [W.desc] on [M]'s [affecting.name].</span>" )
@@ -205,9 +215,9 @@
affecting.update_damages()
if(used == amount)
if(affecting.is_bandaged())
user << "<span class='warning'>\The [src] is used up.</span>"
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
else
user << "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>"
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
use(used)
/obj/item/stack/medical/advanced/ointment
@@ -228,16 +238,19 @@
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
if(affecting.open)
user << "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>"
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
if(affecting.is_salved())
user << "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>"
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
return 1
else
user.visible_message("<span class='notice'>\The [user] starts salving wounds on [M]'s [affecting.name].</span>", \
"<span class='notice'>You start salving the wounds on [M]'s [affecting.name].</span>" )
if(!do_mob(user, M, 10))
user << "<span class='notice'>You must stand still to salve wounds.</span>"
to_chat(user, "<span class='notice'>You must stand still to salve wounds.</span>")
return 1
if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check.
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
return 1
user.visible_message( "<span class='notice'>[user] covers wounds on [M]'s [affecting.name] with regenerative membrane.</span>", \
"<span class='notice'>You cover wounds on [M]'s [affecting.name] with regenerative membrane.</span>" )
@@ -264,20 +277,23 @@
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
var/limb = affecting.name
if(!(affecting.organ_tag in splintable_organs))
user << "<span class='danger'>You can't use \the [src] to apply a splint there!</span>"
to_chat(user, "<span class='danger'>You can't use \the [src] to apply a splint there!</span>")
return
if(affecting.splinted)
user << "<span class='danger'>[M]'s [limb] is already splinted!</span>"
to_chat(user, "<span class='danger'>[M]'s [limb] is already splinted!</span>")
return
if (M != user)
user.visible_message("<span class='danger'>[user] starts to apply \the [src] to [M]'s [limb].</span>", "<span class='danger'>You start to apply \the [src] to [M]'s [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
else
if(( !user.hand && (affecting.organ_tag in list(BP_R_ARM, BP_R_HAND)) || \
user.hand && (affecting.organ_tag in list(BP_L_ARM, BP_L_HAND)) ))
user << "<span class='danger'>You can't apply a splint to the arm you're using!</span>"
to_chat(user, "<span class='danger'>You can't apply a splint to the arm you're using!</span>")
return
user.visible_message("<span class='danger'>[user] starts to apply \the [src] to their [limb].</span>", "<span class='danger'>You start to apply \the [src] to your [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
if(do_after(user, 50, M))
if(affecting.splinted)
to_chat(user, "<span class='danger'>[M]'s [limb] is already splinted!</span>")
return
if(M == user && prob(75))
user.visible_message("<span class='danger'>\The [user] fumbles [src].</span>", "<span class='danger'>You fumble [src].</span>", "<span class='danger'>You hear something being wrapped.</span>")
return

View File

@@ -6,6 +6,7 @@
icon_state = "nanopaste"
origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3)
amount = 10
toolspeed = 0.75 //Used in surgery, shouldn't be the same speed as a normal screwdriver on mechanical organ repair.
w_class = ITEMSIZE_SMALL
no_variants = FALSE
@@ -15,6 +16,7 @@
if (istype(M,/mob/living/silicon/robot)) //Repairing cyborgs
var/mob/living/silicon/robot/R = M
if (R.getBruteLoss() || R.getFireLoss())
if(do_after(user,7 * toolspeed))
R.adjustBruteLoss(-15)
R.adjustFireLoss(-15)
R.updatehealth()
@@ -28,13 +30,16 @@
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/S = H.get_organ(user.zone_sel.selecting)
if(S.open >= 2)
if (S && (S.robotic >= ORGAN_ROBOT))
if(!S.get_damage())
user << "<span class='notice'>Nothing to fix here.</span>"
else if(can_use(1))
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
S.heal_damage(15, 15, robo_repair = 1)
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)
else if(do_after(user,5 * toolspeed))
S.heal_damage(10,10, robo_repair =1)
H.updatehealth()
use(1)
user.visible_message("<span class='notice'>\The [user] applies some nanite paste on [user != M ? "[M]'s [S.name]" : "[S]"] with [src].</span>",\

View File

@@ -699,54 +699,6 @@
desc = "A \"Space Life\" brand Emergency Response Team Commander action figure."
icon_state = "ert"
/obj/item/toy/therapy_red
name = "red therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is red."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyred"
item_state = "egg4" // It's the red egg in items_left/righthand
w_class = ITEMSIZE_TINY
/obj/item/toy/therapy_purple
name = "purple therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is purple."
icon = 'icons/obj/toy.dmi'
icon_state = "therapypurple"
item_state = "egg1" // It's the magenta egg in items_left/righthand
w_class = ITEMSIZE_TINY
/obj/item/toy/therapy_blue
name = "blue therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is blue."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyblue"
item_state = "egg2" // It's the blue egg in items_left/righthand
w_class = ITEMSIZE_TINY
/obj/item/toy/therapy_yellow
name = "yellow therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is yellow."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyyellow"
item_state = "egg5" // It's the yellow egg in items_left/righthand
w_class = ITEMSIZE_TINY
/obj/item/toy/therapy_orange
name = "orange therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is orange."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyorange"
item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless
w_class = ITEMSIZE_TINY
/obj/item/toy/therapy_green
name = "green therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is green."
icon = 'icons/obj/toy.dmi'
icon_state = "therapygreen"
item_state = "egg3" // It's the green egg in items_left/righthand
w_class = ITEMSIZE_TINY
/*
* Plushies
*/
@@ -800,9 +752,10 @@
//Small plushies.
/obj/item/toy/plushie
name = "generic small plush"
desc = "A very generic small plushie. It seems to not want to exist."
desc = "A small toy plushie. It's very cute."
icon = 'icons/obj/toy.dmi'
icon_state = "nymphplushie"
w_class = ITEMSIZE_TINY
var/last_message = 0
/obj/item/toy/plushie/attack_self(mob/user as mob)
@@ -815,9 +768,24 @@
else if (user.a_intent == I_GRAB)
user.visible_message("<span class='warning'><b>\The [user]</b> attempts to strangle [src]!</span>","<span class='warning'>You attempt to strangle [src]!</span>")
else
user.visible_message("<span class='notice'><b>\The [user]</b> pokes the [src].</span>","<span class='notice'>You poke the [src].</span>")
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()
set name = "Name Plushie"
set category = "Object"
set desc = "Give your plushie a cute name!"
var/mob/M = usr
if(!M.mind)
return 0
var/input = sanitizeSafe(input("What do you want to name the plushie?", ,""), MAX_NAME_LEN)
if(src && input && !M.stat && in_range(M,src))
name = input
to_chat(M, "You name the plushie [input], giving it a hug for good luck.")
return 1
/obj/item/toy/plushie/nymph
name = "diona nymph plush"
desc = "A plushie of an adorable diona nymph! While its level of self-awareness is still being debated, its level of cuteness is not."
@@ -830,7 +798,7 @@
/obj/item/toy/plushie/kitten
name = "kitten plush"
desc = "A plushie of a cute kitten! Watch as it purrs it's way right into your heart."
desc = "A plushie of a cute kitten! Watch as it purrs its way right into your heart."
icon_state = "kittenplushie"
/obj/item/toy/plushie/lizard
@@ -848,6 +816,49 @@
desc = "A farwa plush doll. It's soft and comforting!"
icon_state = "farwaplushie"
/obj/item/toy/plushie/therapy/red
name = "red therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is red."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyred"
item_state = "egg4" // It's the red egg in items_left/righthand
/obj/item/toy/plushie/therapy/purple
name = "purple therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is purple."
icon = 'icons/obj/toy.dmi'
icon_state = "therapypurple"
item_state = "egg1" // It's the magenta egg in items_left/righthand
/obj/item/toy/plushie/therapy/blue
name = "blue therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is blue."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyblue"
item_state = "egg2" // It's the blue egg in items_left/righthand
/obj/item/toy/plushie/therapy/yellow
name = "yellow therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is yellow."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyyellow"
item_state = "egg5" // It's the yellow egg in items_left/righthand
/obj/item/toy/plushie/therapy/orange
name = "orange therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is orange."
icon = 'icons/obj/toy.dmi'
icon_state = "therapyorange"
item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless
/obj/item/toy/plushie/therapy/green
name = "green therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is green."
icon = 'icons/obj/toy.dmi'
icon_state = "therapygreen"
item_state = "egg3" // It's the green egg in items_left/righthand
//Toy cult sword
/obj/item/toy/cultsword
name = "foam sword"

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)
@@ -202,6 +202,15 @@
/obj/item/weapon/reagent_containers/syringe = 3,
/obj/item/stack/material/glass/reinforced = 2)
/obj/item/weapon/circuitboard/vr_sleeper
name = T_BOARD("VR sleeper")
build_path = /obj/machinery/vr_sleeper
board_type = new /datum/frame/frame_types/medical_pod
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
req_components = list(
/obj/item/weapon/stock_parts/scanning_module = 1,
/obj/item/stack/material/glass/reinforced = 2)
/obj/item/weapon/circuitboard/dna_analyzer
name = T_BOARD("dna analyzer")
build_path = /obj/machinery/dnaforensics

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

@@ -373,8 +373,8 @@
job_access_type = /datum/job/bartender
/obj/item/weapon/card/id/civilian/botanist
assignment = "Gardener"
rank = "Gardener"
assignment = "Botanist"
rank = "Botanist"
job_access_type = /datum/job/hydro
/obj/item/weapon/card/id/civilian/chaplain

View File

@@ -92,3 +92,11 @@
desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products."
force_divisor = 0.25 // 15 when wielded with hardness 60 (steel)
attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
/obj/item/weapon/material/hatchet/tacknife/survival
name = "survival knife"
desc = "A hunting grade survival knife."
icon = 'icons/obj/kitchen.dmi'
icon_state = "survivalknife"
item_state = "knife"
applies_material_colour = FALSE

View File

@@ -217,7 +217,7 @@
var/obj/O = AM
O.emp_act(3) // A weaker severity is used because this has infinite uses.
playsound(get_turf(O), 'sound/effects/EMPulse.ogg', 100, 1)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) // A lot of objects don't set click delay.
user.setClickCooldown(user.get_attack_speed(src)) // A lot of objects don't set click delay.
return ..()
/obj/item/weapon/melee/energy/sword/ionic_rapier/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)

View File

@@ -247,6 +247,7 @@
icon = 'icons/obj/abductor.dmi'
icon_state = "belt"
item_state = "security"
storage_slots = 8
can_hold = list(
/obj/item/device/healthanalyzer,
/obj/item/weapon/dnainjector,
@@ -284,6 +285,7 @@
new /obj/item/weapon/surgical/FixOVein/alien(src)
new /obj/item/weapon/surgical/bone_clamp/alien(src)
new /obj/item/weapon/surgical/cautery/alien(src)
new /obj/item/weapon/surgical/surgicaldrill/alien(src)
/obj/item/weapon/storage/belt/champion
name = "championship belt"

View File

@@ -426,12 +426,12 @@
for(var/obj/item/weapon/light/L in src.contents)
if(L.status == 0)
if(LP.uses < LP.max_uses)
LP.AddUses(1)
LP.add_uses(1)
amt_inserted++
remove_from_storage(L, T)
qdel(L)
if(amt_inserted)
user << "You inserted [amt_inserted] light\s into \the [LP.name]. You have [LP.uses] light\s remaining."
to_chat(user, "You inserted [amt_inserted] light\s into \the [LP.name]. You have [LP.uses] light\s remaining.")
return
if(!can_be_inserted(W))
@@ -441,14 +441,14 @@
var/obj/item/weapon/tray/T = W
if(T.calc_carry() > 0)
if(prob(85))
user << "<span class='warning'>The tray won't fit in [src].</span>"
to_chat(user, "<span class='warning'>The tray won't fit in [src].</span>")
return
else
W.forceMove(get_turf(user))
if ((user.client && user.s_active != src))
user.client.screen -= W
W.dropped(user)
user << "<span class='warning'>God damnit!</span>"
to_chat(user, "<span class='warning'>God damn it!</span>")
W.add_fingerprint(user)
return handle_item_insertion(W)
@@ -506,9 +506,9 @@
collection_mode = !collection_mode
switch (collection_mode)
if(1)
usr << "[src] now picks up all items in a tile at once."
to_chat(usr, "[src] now picks up all items on a tile at once.")
if(0)
usr << "[src] now picks up one item at a time."
to_chat(usr, "[src] now picks up one item at a time.")
/obj/item/weapon/storage/verb/quick_empty()
@@ -539,7 +539,7 @@
var/total_storage_space = 0
for(var/obj/item/I in contents)
total_storage_space += I.get_storage_cost()
max_storage_space = max(total_storage_space,max_storage_space) //prevents spawned containers from being too small for their contents
max_storage_space = max(total_storage_space,max_storage_space) //Prevents spawned containers from being too small for their contents.
src.boxes = new /obj/screen/storage( )
src.boxes.name = "storage"

View File

@@ -69,14 +69,24 @@
origin_tech = list(TECH_COMBAT = 1, TECH_ILLEGAL = 1)
force = 14
/obj/item/weapon/storage/toolbox/syndicate/New()
/obj/item/weapon/storage/toolbox/syndicate/New() // This is found in maint, so it should have the basics, plus some gloves.
..()
new /obj/item/clothing/gloves/yellow(src)
new /obj/item/weapon/screwdriver(src)
new /obj/item/weapon/wrench(src)
new /obj/item/weapon/weldingtool(src)
new /obj/item/weapon/crowbar(src)
new /obj/item/weapon/wirecutters(src)
new /obj/item/device/multitool(src)
/obj/item/weapon/storage/toolbox/syndicate/powertools/New() // Available in the uplink and is the 'real' syndie toolbox.
// ..() isn't called or else this box would contain the basic tools, power tools, and duplicate gloves.
new /obj/item/clothing/gloves/yellow(src)
new /obj/item/weapon/screwdriver/power(src)
new /obj/item/stack/cable_coil/random(src,30)
new /obj/item/weapon/weldingtool/experimental(src)
new /obj/item/weapon/crowbar/power(src)
new /obj/item/device/multitool(src)
new /obj/item/stack/cable_coil/random(src,30)
new /obj/item/device/analyzer(src)
/obj/item/weapon/storage/toolbox/lunchbox

View File

@@ -133,7 +133,7 @@ Frequency:
/obj/item/weapon/hand_tele/attack_self(mob/user as mob)
var/turf/current_location = get_turf(user)//What turf is the user on?
if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist.
if(!current_location||current_location.z==2||current_location.z>=7 || current_location.block_tele)//If turf was not found or they're on z level 2 or >7 which does not currently exist.
user << "<span class='notice'>\The [src] is malfunctioning.</span>"
return
var/list/L = list( )
@@ -148,6 +148,7 @@ Frequency:
for(var/turf/T in orange(10))
if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb
if(T.y>world.maxy-8 || T.y<8) continue
if(T.block_tele) continue
turfs += T
if(turfs.len)
L["None (Dangerous)"] = pick(turfs)

View File

@@ -656,6 +656,61 @@
nextrefueltick = world.time + 10
reagents.add_reagent("fuel", 1)
/*
* Backpack Welder.
*/
/obj/item/weapon/weldingtool/tubefed
name = "tube-fed welding tool"
desc = "A bulky, cooler-burning welding tool that draws from a worn welding tank."
icon_state = "tubewelder"
max_fuel = 10
w_class = ITEMSIZE_NO_CONTAINER
matter = null
toolspeed = 1.25
change_icons = 0
flame_intensity = 1
eye_safety_modifier = 1
always_process = TRUE
var/obj/item/weapon/weldpack/mounted_pack = null
/obj/item/weapon/weldingtool/tubefed/New(location)
..()
if(istype(location, /obj/item/weapon/weldpack))
var/obj/item/weapon/weldpack/holder = location
mounted_pack = holder
else
qdel(src)
/obj/item/weapon/weldingtool/tubefed/Destroy()
mounted_pack.nozzle = null
mounted_pack = null
return ..()
/obj/item/weapon/weldingtool/tubefed/process()
if(mounted_pack)
if(!istype(mounted_pack.loc,/mob/living/carbon/human))
mounted_pack.return_nozzle()
else
var/mob/living/carbon/human/H = mounted_pack.loc
if(H.back != mounted_pack)
mounted_pack.return_nozzle()
if(mounted_pack.loc != src.loc && src.loc != mounted_pack)
mounted_pack.return_nozzle()
visible_message("<span class='notice'>\The [src] retracts to its fueltank.</span>")
if(get_fuel() <= get_max_fuel())
mounted_pack.reagents.trans_to_obj(src, 1)
..()
/obj/item/weapon/weldingtool/tubefed/dropped(mob/user)
..()
if(src.loc != user)
mounted_pack.return_nozzle()
to_chat(user, "<span class='notice'>\The [src] retracts to its fueltank.</span>")
/*
* Electric/Arc Welder
*/

View File

@@ -17,7 +17,7 @@
var/max_carry = 10
/obj/item/weapon/tray/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
// Drop all the things. All of them.
overlays.Cut()
for(var/obj/item/I in carrying)

View File

@@ -21,7 +21,7 @@
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>)")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
user.do_attack_animation(M)
if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
@@ -134,7 +134,7 @@
qdel(src)
/obj/effect/energy_net/user_unbuckle_mob(mob/user)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
visible_message("<span class='danger'>[user] begins to tear at \the [src]!</span>")
if(do_after(usr, escape_time, src, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY)))
if(!buckled_mob)

View File

@@ -6,46 +6,140 @@
icon_state = "welderpack"
w_class = ITEMSIZE_LARGE
var/max_fuel = 350
var/obj/item/weapon/nozzle = null //Attached welder, or other spray device.
var/nozzle_attached = 0
/obj/item/weapon/weldpack/New()
var/datum/reagents/R = new/datum/reagents(max_fuel) //Lotsa refills
reagents = R
R.my_atom = src
R.add_reagent("fuel", max_fuel)
nozzle = new/obj/item/weapon/weldingtool/tubefed(src)
nozzle_attached = 1
/obj/item/weapon/weldpack/Destroy()
qdel(nozzle)
nozzle = null
return ..()
/obj/item/weapon/weldpack/dropped(mob/user)
..()
if(nozzle)
user.remove_from_mob(nozzle)
return_nozzle()
to_chat(user, "<span class='notice'>\The [nozzle] retracts to its fueltank.</span>")
/obj/item/weapon/weldpack/proc/get_nozzle(var/mob/living/user)
if(!ishuman(user))
return 0
var/mob/living/carbon/human/H = user
if(H.hands_are_full()) //Make sure our hands aren't full.
to_chat(H, "<span class='warning'>Your hands are full. Drop something first.</span>")
return 0
var/obj/item/weapon/F = nozzle
H.put_in_hands(F)
nozzle_attached = 0
return 1
/obj/item/weapon/weldpack/proc/return_nozzle(var/mob/living/user)
nozzle.forceMove(src)
nozzle_attached = 1
/obj/item/weapon/weldpack/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/weldingtool))
if(istype(W, /obj/item/weapon/weldingtool) && !(W == nozzle))
var/obj/item/weapon/weldingtool/T = W
if(T.welding & prob(50))
message_admins("[key_name_admin(user)] triggered a fueltank explosion.")
log_game("[key_name(user)] triggered a fueltank explosion.")
user << "<span class='danger'>That was stupid of you.</span>"
to_chat(user,"<span class='danger'>That was stupid of you.</span>")
explosion(get_turf(src),-1,0,2)
if(src)
qdel(src)
return
else
else if(T.status)
if(T.welding)
user << "<span class='danger'>That was close!</span>"
to_chat(user,"<span class='danger'>That was close!</span>")
src.reagents.trans_to_obj(W, T.max_fuel)
user << "<span class='notice'>Welder refilled!</span>"
to_chat(user, "<span class='notice'>Welder refilled!</span>")
playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
return
user << "<span class='warning'>The tank scoffs at your insolence. It only provides services to welders.</span>"
else if(nozzle)
if(nozzle == W)
if(!user.unEquip(W))
to_chat(user,"<span class='notice'>\The [W] seems to be stuck to your hand.</span>")
return
if(!nozzle_attached)
return_nozzle()
to_chat(user,"<span class='notice'>You attach \the [W] to the [src].</span>")
return
else
to_chat(user,"<span class='notice'>The [src] already has a nozzle!</span>")
else
to_chat(user,"<span class='warning'>The tank scoffs at your insolence. It only provides services to welders.</span>")
return
/obj/item/weapon/weldpack/attack_hand(mob/user as mob)
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/wearer = user
if(wearer.back == src)
if(nozzle && nozzle_attached)
if(!wearer.incapacitated())
get_nozzle(user)
else
to_chat(user,"<span class='notice'>\The [src] does not have a nozzle attached!</span>")
else
..()
else
..()
/obj/item/weapon/weldpack/afterattack(obj/O as obj, mob/user as mob, proximity)
if(!proximity) // this replaces and improves the get_dist(src,O) <= 1 checks used previously
return
if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume < max_fuel)
O.reagents.trans_to_obj(src, max_fuel)
user << "<span class='notice'>You crack the cap off the top of the pack and fill it back up again from the tank.</span>"
to_chat(user,"<span class='notice'>You crack the cap off the top of the pack and fill it back up again from the tank.</span>")
playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
return
else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume == max_fuel)
user << "<span class='warning'>The pack is already full!</span>"
to_chat(user,"<span class='warning'>The pack is already full!</span>")
return
/obj/item/weapon/weldpack/MouseDrop(obj/over_object as obj) //This is terrifying.
if(!canremove)
return
if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
return
if (!( istype(over_object, /obj/screen) ))
return ..()
//makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
//there's got to be a better way of doing this.
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
return
if (( usr.restrained() ) || ( usr.stat ))
return
if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
return
switch(over_object.name)
if("r_hand")
usr.u_equip(src)
usr.put_in_r_hand(src)
if("l_hand")
usr.u_equip(src)
usr.put_in_l_hand(src)
src.add_fingerprint(usr)
/obj/item/weapon/weldpack/examine(mob/user)
..(user)
user << text("\icon[] [] units of fuel left!", src, src.reagents.total_volume)

View File

@@ -313,7 +313,6 @@
prob(2);/obj/item/weapon/gun/projectile/shotgun/pump/combat,
prob(4);/obj/item/weapon/gun/projectile/shotgun/pump/rifle,
prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever,
prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin,
prob(2);/obj/item/weapon/gun/projectile/silenced)
/obj/random/projectile/sec
@@ -504,12 +503,12 @@
/obj/random/toy/item_to_spawn()
return pick(/obj/item/toy/bosunwhistle,
/obj/item/toy/therapy_red,
/obj/item/toy/therapy_purple,
/obj/item/toy/therapy_blue,
/obj/item/toy/therapy_yellow,
/obj/item/toy/therapy_orange,
/obj/item/toy/therapy_green,
/obj/item/toy/plushie/therapy/red,
/obj/item/toy/plushie/therapy/purple,
/obj/item/toy/plushie/therapy/blue,
/obj/item/toy/plushie/therapy/yellow,
/obj/item/toy/plushie/therapy/orange,
/obj/item/toy/plushie/therapy/green,
/obj/item/toy/cultsword,
/obj/item/toy/katana,
/obj/item/toy/snappop,
@@ -1061,3 +1060,21 @@ var/list/multi_point_spawns
/obj/item/clothing/head/helmet/space/void/security/riot
)
)
/obj/random/multiple/voidsuit/mining
name = "Random Mining Voidsuit"
desc = "This is a random mining voidsuit."
icon = 'icons/obj/clothing/suits.dmi'
icon_state = "rig-mining"
/obj/random/multiple/voidsuit/mining/item_to_spawn()
return pick(
prob(5);list(
/obj/item/clothing/suit/space/void/mining,
/obj/item/clothing/head/helmet/space/void/mining
),
prob(1);list(
/obj/item/clothing/suit/space/void/mining/alt,
/obj/item/clothing/head/helmet/space/void/mining/alt
)
)

View File

@@ -0,0 +1,79 @@
// These contain structures to make certain 'alien' (as in the ayyy ones, not xenomorphs) submaps more filled, and don't really do anything.
/obj/structure/prop/alien
name = "some alien thing"
desc = "My description is broken, bug a developer."
icon = 'icons/obj/abductor.dmi'
density = TRUE
anchored = TRUE
var/interaction_message = null
/obj/structure/prop/alien/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything.
if(!istype(user))
return FALSE
if(!interaction_message)
return ..()
else
to_chat(user, interaction_message)
/obj/structure/prop/alien/computer
name = "alien console"
desc = "The console flashes what appear to be symbols you've never seen before."
icon_state = "console-c"
interaction_message = "<span class='warning'>The console flashes a series of unknown symbols as you press a button on what is presumably a keyboard. It probably some sort of \
authentication error. Since you're not an alien, you should probably leave it alone.</span>"
/obj/structure/prop/alien/computer/camera
desc = "This console is briefly flashing video feeds of various locations close by."
icon_state = "camera"
/obj/structure/prop/alien/computer/camera/flipped
icon_state = "camera_flipped"
/obj/structure/prop/alien/dispenser
name = "alien dispenser"
desc = "This looks like it dispenses... something?"
icon_state = "dispenser"
interaction_message = "<span class='warning'>You don't see any mechanism to operate this. Probably for the best.</span>"
/obj/structure/prop/alien/pod
name = "alien pod"
desc = "This seems to be a container for something."
icon_state = "experiment"
interaction_message = "<span class='warning'>You don't see any mechanism to open this thing. Probably for the best.</span>"
/obj/structure/prop/alien/pod/open
name = "opened alien pod"
desc = "At one point, this probably contained something interesting..."
icon_state = "experiment-open"
interaction_message = "<span class='warning'>You don't see any mechanism to close this thing.</span>"
/obj/structure/prop/alien/power
name = "void core"
icon_state = "core"
desc = "An alien machine that seems to be producing energy seemingly out of nowhere."
interaction_message = "<span class='warning'>Messing with something that makes energy out of nowhere seems very unwise.</span>"
/obj/item/prop/alien
name = "some alien item"
desc = "My description is broken, bug a developer."
icon = 'icons/obj/abductor.dmi'
// Mostly useless. Research might like it, however.
/obj/item/prop/alien/junk
name = "alien object"
desc = "You have no idea what this thing does."
icon_state = "health"
w_class = ITEMSIZE_SMALL
var/static/list/possible_states = list("health", "spider", "slime", "emp", "species", "egg", "vent", "mindshock", "viral", "gland")
var/static/list/possible_tech = list(TECH_MATERIAL, TECH_ENGINEERING, TECH_PHORON, TECH_POWER, TECH_BIO, TECH_COMBAT, TECH_MAGNET, TECH_DATA)
/obj/item/prop/alien/junk/initialize()
..()
icon_state = pick(possible_states)
var/list/techs = possible_tech.Copy()
origin_tech = list()
for(var/i = 1 to rand(1, 4))
var/new_tech = pick(techs)
techs -= new_tech
origin_tech[new_tech] = rand(5, 9)

View File

@@ -81,7 +81,7 @@
health = maxhealth
else
take_damage(C.force)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(C))
return ..()
/obj/structure/catwalk/Crossed()

View File

@@ -36,7 +36,7 @@
playsound(user, 'sound/machines/lockreset.ogg', 50, 1)
if(do_after(user, 20 * O.toolspeed))
src.locked = 0
user << "<span class = 'caution'> You disable the locking modules.</span>"
to_chat(user, "<span class = 'caution'> You disable the locking modules.</span>")
update_icon()
return
else if(istype(O, /obj/item/weapon))
@@ -50,7 +50,7 @@
else
playsound(user, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time
if(W.force < 15)
user << "<span class='notice'>The cabinet's protective glass glances off the hit.</span>"
to_chat(user, "<span class='notice'>The cabinet's protective glass glances off the hit.</span>")
else
src.hitstaken++
if(src.hitstaken == 4)
@@ -63,12 +63,14 @@
if (istype(O, /obj/item/weapon/material/twohanded/fireaxe) && src.localopened)
if(!fireaxe)
if(O:wielded)
user << "<span class='warning'>Unwield the axe first.</span>"
return
O:wielded = 0
O.update_icon()
//to_chat(user, "<span class='warning'>Unwield the axe first.</span>")
//return
fireaxe = O
user.remove_from_mob(O)
src.contents += O
user << "<span class='notice'>You place the fire axe back in the [src.name].</span>"
to_chat(user, "<span class='notice'>You place the fire axe back in the [src.name].</span>")
update_icon()
else
if(src.smashed)
@@ -91,11 +93,11 @@
spawn(10) update_icon()
return
else
user << "<span class='warning'>Resetting circuitry...</span>"
to_chat(user, "<span class='warning'>Resetting circuitry...</span>")
playsound(user, 'sound/machines/lockenable.ogg', 50, 1)
if(do_after(user,20 * O.toolspeed))
src.locked = 1
user << "<span class = 'caution'> You re-enable the locking modules.</span>"
to_chat(user, "<span class = 'caution'> You re-enable the locking modules.</span>")
return
else
localopened = !localopened
@@ -116,13 +118,13 @@
hasaxe = 1
if(src.locked)
user <<"<span class='warning'>The cabinet won't budge!</span>"
to_chat(user, "<span class='warning'>The cabinet won't budge!</span>")
return
if(localopened)
if(fireaxe)
user.put_in_hands(fireaxe)
fireaxe = null
user << "<span class='notice'>You take the fire axe from the [name].</span>"
to_chat (user, "<span class='notice'>You take the fire axe from the [name].</span>")
src.add_fingerprint(user)
update_icon()
else
@@ -149,7 +151,7 @@
attack_tk(mob/user as mob)
if(localopened && fireaxe)
fireaxe.forceMove(loc)
user << "<span class='notice'>You telekinetically remove the fire axe.</span>"
to_chat(user, "<span class='notice'>You telekinetically remove the fire axe.</span>")
fireaxe = null
update_icon()
return
@@ -161,9 +163,9 @@
if (isrobot(usr) || src.locked || src.smashed)
if(src.locked)
usr << "<span class='warning'>The cabinet won't budge!</span>"
to_chat(usr, "<span class='warning'>The cabinet won't budge!</span>")
else if(src.smashed)
usr << "<span class='notice'>The protective glass is broken!</span>"
to_chat(usr, "<span class='notice'>The protective glass is broken!</span>")
return
localopened = !localopened
@@ -180,23 +182,23 @@
if(fireaxe)
usr.put_in_hands(fireaxe)
fireaxe = null
usr << "<span class='notice'>You take the Fire axe from the [name].</span>"
to_chat(usr, "<span class='notice'>You take the Fire axe from the [name].</span>")
else
usr << "<span class='notice'>The [src.name] is empty.</span>"
to_chat(usr, "<span class='notice'>The [src.name] is empty.</span>")
else
usr << "<span class='notice'>The [src.name] is closed.</span>"
to_chat(usr, "<span class='notice'>The [src.name] is closed.</span>")
update_icon()
attack_ai(mob/user as mob)
if(src.smashed)
user << "<span class='warning'>The security of the cabinet is compromised.</span>"
to_chat(user, "<span class='warning'>The security of the cabinet is compromised.</span>")
return
else
locked = !locked
if(locked)
user << "<span class='warning'>Cabinet locked.</span>"
to_chat(user, "<span class='warning'>Cabinet locked.</span>")
else
user << "<span class='notice'>Cabinet unlocked.</span>"
to_chat(user, "<span class='notice'>Cabinet unlocked.</span>")
return
update_icon() //Template: fireaxe[has fireaxe][is opened][hits taken][is smashed]. If you want the opening or closing animations, add "opening" or "closing" right after the numbers

View File

@@ -134,3 +134,12 @@
new /obj/item/clothing/head/helmet/thunderdome(src)
new /obj/item/clothing/head/helmet/thunderdome(src)
new /obj/item/clothing/head/helmet/thunderdome(src)
/obj/structure/closet/alien
name = "alien container"
desc = "Contains secrets of the universe."
icon = 'icons/obj/abductor.dmi'
icon_state = "alien_locker"
icon_closed = "alien_locker"
icon_opened = "alien_locker_open"
anchored = TRUE

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