Merge remote-tracking branch 'refs/remotes/Citadel-Station-13/master' into IHAVENOIDEAWHATTHEFUCKIMDOING

This commit is contained in:
deathride58
2017-11-20 00:21:38 -05:00
1218 changed files with 80559 additions and 76738 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
#define GLOBAL_PROTECT(X)\
/datum/controller/global_vars/InitGlobal##X(){\
..();\
gvars_datum_protected_varlist += #X;\
gvars_datum_protected_varlist[#X] = TRUE;\
}
#else
#define GLOBAL_PROTECT(X)
+12 -12
View File
@@ -116,17 +116,17 @@
#define R_MAXPERMISSION 4096 //This holds the maximum value for a permission. It is used in iteration, so keep it updated.
#define ADMIN_QUE(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminmoreinfo=\ref[user]'>?</a>)"
#define ADMIN_FLW(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayerobservefollow=\ref[user]'>FLW</a>)"
#define ADMIN_PP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayeropts=\ref[user]'>PP</a>)"
#define ADMIN_VV(atom) "(<a href='?_src_=vars;[HrefToken(TRUE)];Vars=\ref[atom]'>VV</a>)"
#define ADMIN_SM(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];subtlemessage=\ref[user]'>SM</a>)"
#define ADMIN_TP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];traitor=\ref[user]'>TP</a>)"
#define ADMIN_KICK(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];boot2=\ref[user]'>KICK</a>)"
#define ADMIN_CENTCOM_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];CentComReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SYNDICATE_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];SyndicateReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SC(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminspawncookie=\ref[user]'>SC</a>)"
#define ADMIN_SMITE(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminsmite=\ref[user]'>SMITE</a>)"
#define ADMIN_QUE(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminmoreinfo=[REF(user)]'>?</a>)"
#define ADMIN_FLW(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayerobservefollow=[REF(user)]'>FLW</a>)"
#define ADMIN_PP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayeropts=[REF(user)]'>PP</a>)"
#define ADMIN_VV(atom) "(<a href='?_src_=vars;[HrefToken(TRUE)];Vars=[REF(atom)]'>VV</a>)"
#define ADMIN_SM(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];subtlemessage=[REF(user)]'>SM</a>)"
#define ADMIN_TP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];traitor=[REF(user)]'>TP</a>)"
#define ADMIN_KICK(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];boot2=[REF(user)]'>KICK</a>)"
#define ADMIN_CENTCOM_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];CentComReply=[REF(user)]'>RPLY</a>)"
#define ADMIN_SYNDICATE_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];SyndicateReply=[REF(user)]'>RPLY</a>)"
#define ADMIN_SC(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminspawncookie=[REF(user)]'>SC</a>)"
#define ADMIN_SMITE(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminsmite=[REF(user)]'>SMITE</a>)"
#define ADMIN_LOOKUP(user) "[key_name_admin(user)][ADMIN_QUE(user)]"
#define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]"
#define ADMIN_SET_SD_CODE "(<a href='?_src_=holder;[HrefToken(TRUE)];set_selfdestruct_code=1'>SETCODE</a>)"
@@ -135,7 +135,7 @@
#define ADMIN_JMP(src) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)"
#define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]"
#define ADMIN_COORDJMP(src) "[src ? "[COORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]"
#define ADMIN_INDIVIDUALLOG(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];individuallog=\ref[user]'>LOGS</a>)"
#define ADMIN_INDIVIDUALLOG(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];individuallog=[REF(user)]'>LOGS</a>)"
#define ADMIN_PUNISHMENT_LIGHTNING "Lightning bolt"
#define ADMIN_PUNISHMENT_BRAINDAMAGE "Brain damage"
+2 -1
View File
@@ -28,6 +28,7 @@
#define NORMPIPERATE 30 //pipe-insulation rate divisor
#define HEATPIPERATE 8 //heat-exch pipe insulation
#define FLOWFRAC 0.99 //fraction of gas transfered per process
#define TANK_MELT_TEMPERATURE 1000000
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) //Tank starts leaking
#define TANK_RUPTURE_PRESSURE (35.*ONE_ATMOSPHERE) //Tank spills all contents into atmosphere
#define TANK_FRAGMENT_PRESSURE (40.*ONE_ATMOSPHERE) //Boom 3x3 base explosion
@@ -109,7 +110,7 @@
#define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
#define MAX_HIGH_PRESSURE_DAMAGE 4
#define LOW_PRESSURE_DAMAGE 2 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
#define LOW_PRESSURE_DAMAGE 4 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
#define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
+6 -3
View File
@@ -66,13 +66,10 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define ARK_SUMMON_COST 5 //how many of each component an Ark costs to summon
#define ARK_CONSUME_COST 15 //how many of each component an Ark needs to consume to activate
//Objective text define
#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."
//misc clockcult stuff
#define MARAUDER_EMERGE_THRESHOLD 65 //marauders cannot emerge unless host is at this% or less health
#define SIGIL_ACCESS_RANGE 2 //range at which transmission sigils can access power
@@ -83,3 +80,9 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define CLOCKWORK_ARMOR_COOLDOWN 1800 //The cooldown period between summoning suits of clockwork armor
#define RATVARIAN_SPEAR_COOLDOWN 300 //The cooldown period between summoning another Ratvarian spear
#define MARAUDER_SCRIPTURE_SCALING_THRESHOLD 200 //The amount of deciseconds that must pass before marauder scripture will not gain a recital penalty
#define MARAUDER_SCRIPTURE_SCALING_TIME 50 //The amount of extra deciseconds tacked on to the marauder scripture recital time per recent marauder
#define MARAUDER_SCRIPTURE_SCALING_MAX 300 //The maximum extra time applied to the marauder scripture
+1
View File
@@ -38,6 +38,7 @@
#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size)
#define COMSIG_ATOM_SET_LIGHT "atom_set_light" //from base of atom/set_light(): (l_range, l_power, l_color)
#define COMSIG_ATOM_ROTATE "atom_rotate" //from base of atom/shuttleRotate(): (rotation, params)
#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params)
#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob)
+1 -1
View File
@@ -28,7 +28,7 @@
#define BAN_CHAPEL "chapel"
#define BAN_HURTPRIEST "hurtpriest"
#define BAN_AVOIDWATER "avoidwater"
#define BAN_STRIKEUNCONCIOUS "strikeunconcious"
#define BAN_STRIKEUNCONSCIOUS "strikeunconscious"
#define BAN_HURTLIZARD "hurtlizard"
#define BAN_HURTANIMAL "hurtanimal"
+2 -1
View File
@@ -74,7 +74,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define PASSGRILLE 4
#define PASSBLOB 8
#define PASSMOB 16
#define LETPASSTHROW 32
#define PASSCLOSEDTURF 32
#define LETPASSTHROW 64
//Movement Types
+41
View File
@@ -0,0 +1,41 @@
#define IC_INPUT "input"
#define IC_OUTPUT "output"
#define IC_ACTIVATOR "activator"
// Pin functionality.
#define DATA_CHANNEL "data channel"
#define PULSE_CHANNEL "pulse channel"
// Methods of obtaining a circuit.
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
// Displayed along with the pin name to show what type of pin it is.
#define IC_FORMAT_ANY "\<ANY\>"
#define IC_FORMAT_STRING "\<TEXT\>"
#define IC_FORMAT_CHAR "\<CHAR\>"
#define IC_FORMAT_COLOR "\<COLOR\>"
#define IC_FORMAT_NUMBER "\<NUM\>"
#define IC_FORMAT_DIR "\<DIR\>"
#define IC_FORMAT_BOOLEAN "\<BOOL\>"
#define IC_FORMAT_REF "\<REF\>"
#define IC_FORMAT_LIST "\<LIST\>"
#define IC_FORMAT_PULSE "\<PULSE\>"
// Used inside input/output list to tell the constructor what pin to make.
#define IC_PINTYPE_ANY /datum/integrated_io
#define IC_PINTYPE_STRING /datum/integrated_io/string
#define IC_PINTYPE_CHAR /datum/integrated_io/char
#define IC_PINTYPE_COLOR /datum/integrated_io/color
#define IC_PINTYPE_NUMBER /datum/integrated_io/number
#define IC_PINTYPE_DIR /datum/integrated_io/dir
#define IC_PINTYPE_BOOLEAN /datum/integrated_io/boolean
#define IC_PINTYPE_REF /datum/integrated_io/ref
#define IC_PINTYPE_LIST /datum/integrated_io/lists
#define IC_PINTYPE_PULSE_IN /datum/integrated_io/activate
#define IC_PINTYPE_PULSE_OUT /datum/integrated_io/activate/out
// Data limits.
#define IC_MAX_LIST_LENGTH 500
+67
View File
@@ -161,3 +161,70 @@
#define TINT_DARKENED 2 //Threshold of tint level to apply weld mask overlay
#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully
//Allowed equipment lists for security vests and hardsuits.
GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list(
/obj/item/ammo_box,
/obj/item/ammo_casing,
/obj/item/device/flashlight,
/obj/item/gun,
/obj/item/melee/baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/tank/internals)))
GLOBAL_LIST_INIT(security_hardsuit_allowed, typecacheof(list(
/obj/item/ammo_box,
/obj/item/ammo_casing,
/obj/item/device/flashlight,
/obj/item/gun/ballistic,
/obj/item/gun/energy,
/obj/item/melee/baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/tank/internals)))
GLOBAL_LIST_INIT(detective_vest_allowed, typecacheof(list(
/obj/item/ammo_box,
/obj/item/ammo_casing,
/obj/item/device/detective_scanner,
/obj/item/device/flashlight,
/obj/item/device/taperecorder,
/obj/item/gun/ballistic,
/obj/item/gun/energy,
/obj/item/lighter,
/obj/item/melee/baton,
/obj/item/melee/classic_baton,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/storage/fancy/cigarettes,
/obj/item/tank/internals/emergency_oxygen)))
GLOBAL_LIST_INIT(security_vest_allowed, typecacheof(list(
/obj/item/ammo_box,
/obj/item/ammo_casing,
/obj/item/device/flashlight,
/obj/item/gun/ballistic,
/obj/item/gun/energy,
/obj/item/kitchen/knife/combat,
/obj/item/melee/baton,
/obj/item/melee/classic_baton/telescopic,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/tank/internals/emergency_oxygen)))
GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list(
/obj/item/ammo_box,
/obj/item/ammo_casing,
/obj/item/device/flashlight,
/obj/item/storage/fancy/cigarettes,
/obj/item/gun/ballistic,
/obj/item/gun/energy,
/obj/item/lighter,
/obj/item/melee/baton,
/obj/item/melee/classic_baton/telescopic,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/tank/internals/emergency_oxygen,
/obj/item/toy)))
+4 -2
View File
@@ -8,7 +8,9 @@
#define ismovableatom(A) (istype(A, /atom/movable))
#define isatom(A) (istype(A, /atom))
#define isatom(A) (isloc(A))
#define isweakref(D) (istype(D, /datum/weakref))
//Turfs
//#define isturf(A) (istype(A, /turf)) This is actually a byond built-in. Added here for completeness sake.
@@ -183,4 +185,4 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
/obj/item/stack/sheet/plasmaglass,
/obj/item/stack/sheet/plasmarglass)))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
+1 -1
View File
@@ -13,6 +13,7 @@
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
#define MID_TURF_LAYER 2.02
#define HIGH_TURF_LAYER 2.03
#define TURF_DECAL_LAYER 2.039 //Makes turf decals appear in DM how they will look inworld.
#define ABOVE_OPEN_TURF_LAYER 2.04
#define CLOSED_TURF_LAYER 2.05
#define BULLET_HOLE_LAYER 2.06
@@ -20,7 +21,6 @@
#define LATTICE_LAYER 2.2
#define DISPOSAL_PIPE_LAYER 2.3
#define GAS_PIPE_HIDDEN_LAYER 2.35
#define TURF_DECAL_LAYER 2.39
#define WIRE_LAYER 2.4
#define WIRE_TERMINAL_LAYER 2.45
#define GAS_SCRUBBER_LAYER 2.46
+18 -16
View File
@@ -1,20 +1,22 @@
//Investigate logging defines
#define INVESTIGATE_ATMOS "atmos"
#define INVESTIGATE_BOTANY "botany"
#define INVESTIGATE_CARGO "cargo"
#define INVESTIGATE_EXPERIMENTOR "experimentor"
#define INVESTIGATE_GRAVITY "gravity"
#define INVESTIGATE_RECORDS "records"
#define INVESTIGATE_SINGULO "singulo"
#define INVESTIGATE_SUPERMATTER "supermatter"
#define INVESTIGATE_TELESCI "telesci"
#define INVESTIGATE_WIRES "wires"
#define INVESTIGATE_ATMOS "atmos"
#define INVESTIGATE_BOTANY "botany"
#define INVESTIGATE_CARGO "cargo"
#define INVESTIGATE_EXPERIMENTOR "experimentor"
#define INVESTIGATE_GRAVITY "gravity"
#define INVESTIGATE_RECORDS "records"
#define INVESTIGATE_SINGULO "singulo"
#define INVESTIGATE_SUPERMATTER "supermatter"
#define INVESTIGATE_TELESCI "telesci"
#define INVESTIGATE_WIRES "wires"
#define INVESTIGATE_PORTAL "portals"
#define INVESTIGATE_HALLUCINATIONS "hallucinations"
#define INVESTIGATE_HALLUCINATIONS "hallucinations"
#define INVESTIGATE_RADIATION "radiation"
#define INVESTIGATE_EXONET "exonet"
//Individual logging defines
#define INDIVIDUAL_ATTACK_LOG "Attack log"
#define INDIVIDUAL_SAY_LOG "Say log"
#define INDIVIDUAL_EMOTE_LOG "Emote log"
#define INDIVIDUAL_OOC_LOG "OOC log"
#define INDIVIDUAL_SHOW_ALL_LOG "All logs"
#define INDIVIDUAL_ATTACK_LOG "Attack log"
#define INDIVIDUAL_SAY_LOG "Say log"
#define INDIVIDUAL_EMOTE_LOG "Emote log"
#define INDIVIDUAL_OOC_LOG "OOC log"
#define INDIVIDUAL_SHOW_ALL_LOG "All logs"
+3
View File
@@ -84,3 +84,6 @@
#define SUPERMATTER_DANGER 4 // Integrity < 50%
#define SUPERMATTER_EMERGENCY 5 // Integrity < 25%
#define SUPERMATTER_DELAMINATING 6 // Pretty obvious.
//R&D Snowflakes
#define RD_CONSOLE_LOCKED_SCREEN 0.2
+7 -1
View File
@@ -466,9 +466,15 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
//Dummy mob reserve slots
#define DUMMY_HUMAN_SLOT_PREFERENCES "dummy_preference_preview"
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
//This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
#define MAX_PROC_DEPTH 195 // 200 proc calls deep and shit breaks, this is a bit lower to give some safety room
#define MAX_PROC_DEPTH 195 // 200 proc calls deep and shit breaks, this is a bit lower to give some safety room
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
#define SYRINGE_DRAW 0
#define SYRINGE_INJECT 1
+8 -14
View File
@@ -1,23 +1,17 @@
//Construction Categories
#define PIPE_BINARY 0 //2 directions: N/S, E/W
#define PIPE_STRAIGHT 0 //2 directions: N/S, E/W
#define PIPE_BENDABLE 1 //6 directions: N/S, E/W, N/E, N/W, S/E, S/W
#define PIPE_TRINARY 2 //4 directions: N/E/S, E/S/W, S/W/N, W/N/E
#define PIPE_TRIN_M 3 //8 directions: N->S+E, S->N+E, N->S+W, S->N+W, E->W+S, W->E+S, E->W+N, W->E+N
#define PIPE_UNARY 4 //4 directions: N, S, E, W
#define PIPE_QUAD 5 //1 directions: N/S/E/W
#define PIPE_ONEDIR 5 //1 direction: N/S/E/W
//Disposal piping numbers - do NOT hardcode these, use the defines
#define DISP_PIPE_STRAIGHT 0
#define DISP_PIPE_BENT 1
#define DISP_JUNCTION 2
#define DISP_JUNCTION_FLIP 3
#define DISP_YJUNCTION 4
#define DISP_END_TRUNK 5
#define DISP_END_BIN 6
#define DISP_END_OUTLET 7
#define DISP_END_CHUTE 8
#define DISP_SORTJUNCTION 9
#define DISP_SORTJUNCTION_FLIP 10
//Disposal pipe relative connection directions
#define DISP_DIR_BASE 0
#define DISP_DIR_LEFT 1
#define DISP_DIR_RIGHT 2
#define DISP_DIR_FLIP 4
#define DISP_DIR_NONE 8
//Transit tubes
#define TRANSIT_TUBE_STRAIGHT 0
+3 -3
View File
@@ -37,9 +37,9 @@
#define EAVESDROP_EXTRA_RANGE 1 //how much past the specified message_range does the message get starred, whispering only
// A link given to ghost alice to follow bob
#define FOLLOW_LINK(alice, bob) "<a href=?src=\ref[alice];follow=\ref[bob]>(F)</a>"
#define TURF_LINK(alice, turfy) "<a href=?src=\ref[alice];x=[turfy.x];y=[turfy.y];z=[turfy.z]>(T)</a>"
#define FOLLOW_OR_TURF_LINK(alice, bob, turfy) "<a href=?src=\ref[alice];follow=\ref[bob];x=[turfy.x];y=[turfy.y];z=[turfy.z]>(F)</a>"
#define FOLLOW_LINK(alice, bob) "<a href=?src=[REF(alice)];follow=[REF(bob)]>(F)</a>"
#define TURF_LINK(alice, turfy) "<a href=?src=[REF(alice)];x=[turfy.x];y=[turfy.y];z=[turfy.z]>(T)</a>"
#define FOLLOW_OR_TURF_LINK(alice, bob, turfy) "<a href=?src=[REF(alice)];follow=[REF(bob)];x=[turfy.x];y=[turfy.y];z=[turfy.z]>(F)</a>"
#define LOGSAY "say"
#define LOGWHISPER "whisper"
+6 -1
View File
@@ -65,4 +65,9 @@
//Docking turf movements
#define MOVE_TURF 1
#define MOVE_AREA 2
#define MOVE_CONTENTS 4
#define MOVE_CONTENTS 4
//Rotation params
#define ROTATE_DIR 1
#define ROTATE_SMOOTH 2
#define ROTATE_OFFSET 4
+71 -23
View File
@@ -1,23 +1,71 @@
//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on
#define CHANNEL_LOBBYMUSIC 1024
#define CHANNEL_ADMIN 1023
#define CHANNEL_VOX 1022
#define CHANNEL_JUKEBOX 1021
#define CHANNEL_JUSTICAR_ARK 1020
#define CHANNEL_HEARTBEAT 1019 //sound channel for heartbeats
#define CHANNEL_AMBIENCE 1018
#define CHANNEL_BUZZ 1017
#define CHANNEL_BICYCLE 1016
//Citadel code
#define CHANNEL_PRED 1015
#define CHANNEL_PREYLOOP 1014
//THIS SHOULD ALWAYS BE THE LOWEST ONE!
//KEEP IT UPDATED
#define CHANNEL_HIGHEST_AVAILABLE 1013
#define CHANNEL_HIGHEST_AVAILABLE 1017
#define SOUND_MINIMUM_PRESSURE 10
#define FALLOFF_SOUNDS 0.5
//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on
#define CHANNEL_LOBBYMUSIC 1024
#define CHANNEL_ADMIN 1023
#define CHANNEL_VOX 1022
#define CHANNEL_JUKEBOX 1021
#define CHANNEL_JUSTICAR_ARK 1020
#define CHANNEL_HEARTBEAT 1019 //sound channel for heartbeats
#define CHANNEL_AMBIENCE 1018
#define CHANNEL_BUZZ 1017
#define CHANNEL_BICYCLE 1016
//Citadel code
#define CHANNEL_PRED 1015
#define CHANNEL_PREYLOOP 1014
//THIS SHOULD ALWAYS BE THE LOWEST ONE!
//KEEP IT UPDATED
#define CHANNEL_HIGHEST_AVAILABLE 1013
#define SOUND_MINIMUM_PRESSURE 10
#define FALLOFF_SOUNDS 0.5
//Ambience types
#define GENERIC list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg',\
'sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg',\
'sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg',\
'sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg',\
'sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg',\
'sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg','sound/ambience/ambigen15.ogg')
#define HOLY list('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg',\
'sound/ambience/ambicha4.ogg', 'sound/ambience/ambiholy.ogg', 'sound/ambience/ambiholy2.ogg',\
'sound/ambience/ambiholy3.ogg')
#define HIGHSEC list('sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg')
#define RUINS list('sound/ambience/ambimine.ogg', 'sound/ambience/ambicave.ogg', 'sound/ambience/ambiruin.ogg',\
'sound/ambience/ambiruin2.ogg', 'sound/ambience/ambiruin3.ogg', 'sound/ambience/ambiruin4.ogg',\
'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\
'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambitech3.ogg',\
'sound/ambience/ambimystery.ogg', 'sound/ambience/ambimaint1.ogg')
#define ENGINEERING list('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg', 'sound/ambience/ambieng1.ogg',\
'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg', 'sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambitech3.ogg')
#define MINING list('sound/ambience/ambimine.ogg', 'sound/ambience/ambicave.ogg', 'sound/ambience/ambiruin.ogg',\
'sound/ambience/ambiruin2.ogg', 'sound/ambience/ambiruin3.ogg', 'sound/ambience/ambiruin4.ogg',\
'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\
'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambimaint1.ogg', 'sound/ambience/ambilava.ogg')
#define MEDICAL list('sound/ambience/ambinice.ogg')
#define SPOOKY list('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/ambience/ambiruin7.ogg','sound/ambience/ambiruin6.ogg',\
'sound/ambience/ambiodd.ogg', 'sound/ambience/ambimystery.ogg')
#define SPACE list('sound/ambience/ambispace.ogg', 'sound/ambience/ambispace2.ogg', 'sound/ambience/title2.ogg', 'sound/ambience/ambiatmos.ogg')
#define MAINTENANCE list('sound/ambience/ambimaint1.ogg', 'sound/ambience/ambimaint2.ogg', 'sound/ambience/ambimaint3.ogg', 'sound/ambience/ambimaint4.ogg',\
'sound/ambience/ambimaint5.ogg', 'sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg', 'sound/ambience/ambitech2.ogg' )
#define AWAY_MISSION list('sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambiruin.ogg',\
'sound/ambience/ambiruin2.ogg', 'sound/ambience/ambiruin3.ogg', 'sound/ambience/ambiruin4.ogg',\
'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\
'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambimaint.ogg',\
'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg', 'sound/ambience/ambiodd.ogg')
#define REEBE list('sound/ambience/ambireebe1.ogg', 'sound/ambience/ambireebe2.ogg', 'sound/ambience/ambireebe3.ogg')
+17
View File
@@ -0,0 +1,17 @@
#define STAT_ENTRY_TIME 1
#define STAT_ENTRY_COUNT 2
#define STAT_ENTRY_LENGTH 2
#define STAT_START_STOPWATCH var/STAT_STOP_WATCH = TICK_USAGE
#define STAT_STOP_STOPWATCH var/STAT_TIME = TICK_USAGE_TO_MS(STAT_STOP_WATCH)
#define STAT_LOG_ENTRY(entrylist, entryname) \
var/list/STAT_ENTRY = entrylist[entryname] || (entrylist[entryname] = new /list(STAT_ENTRY_LENGTH));\
STAT_ENTRY[STAT_ENTRY_TIME] += STAT_TIME;\
var/STAT_INCR_AMOUNT = min(1, 2**round((STAT_ENTRY[STAT_ENTRY_COUNT] || 0)/SHORT_REAL_LIMIT));\
if (STAT_INCR_AMOUNT == 1 || prob(100/STAT_INCR_AMOUNT)) {\
STAT_ENTRY[STAT_ENTRY_COUNT] += STAT_INCR_AMOUNT;\
};\
+25
View File
@@ -53,6 +53,7 @@
#define INIT_ORDER_ATOMS 11
#define INIT_ORDER_LANGUAGE 10
#define INIT_ORDER_MACHINES 9
#define INIT_ORDER_CIRCUIT 8
#define INIT_ORDER_TIMER 1
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_AIR -1
@@ -76,3 +77,27 @@
#define RUNLEVEL_POSTGAME 8
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
var/list/oo = A.our_overlays;\
var/list/po = A.priority_overlays;\
if(LAZYLEN(po)){\
if(LAZYLEN(oo)){\
A.overlays = oo + po;\
}\
else{\
A.overlays = po;\
}\
}\
else if(LAZYLEN(oo)){\
A.overlays = oo;\
}\
else{\
A.overlays.Cut();\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
}
+6
View File
@@ -0,0 +1,6 @@
#define TOOL_NONE 0
#define TOOL_CROWBAR 1
#define TOOL_MULTITOOL 2
#define TOOL_SCREWDRIVER 3
#define TOOL_WIRECUTTER 4
#define TOOL_WRENCH 5
+2
View File
@@ -0,0 +1,2 @@
#define WALL_DENT_HIT 1
#define WALL_DENT_SHOT 2
+93
View File
@@ -0,0 +1,93 @@
#define BP_MAX_ROOM_SIZE 300
// Gets an atmos isolated contained space
// Returns an associative list of turf|dirs pairs
// The dirs are connected turfs in the same space
// break_if_found is a typecache of turf types to return false if found
/proc/detect_room(turf/origin, list/break_if_found)
if(origin.blocks_air)
return list(origin)
. = list()
var/list/checked_turfs = list()
var/list/found_turfs = list(origin)
while(found_turfs.len)
var/turf/sourceT = found_turfs[1]
if(break_if_found[sourceT.type])
return FALSE
found_turfs.Cut(1, 2)
var/dir_flags = checked_turfs[sourceT]
for(var/dir in GLOB.alldirs)
if(dir_flags & dir) // This means we've checked this dir before, probably from the other turf
continue
var/turf/checkT = get_step(sourceT, dir)
if(!checkT)
continue
checked_turfs[sourceT] |= dir
checked_turfs[checkT] |= turn(dir, 180)
.[sourceT] |= dir
.[checkT] |= turn(dir, 180)
var/static/list/cardinal_cache = list("[NORTH]"=TRUE, "[EAST]"=TRUE, "[SOUTH]"=TRUE, "[WEST]"=TRUE)
if(!cardinal_cache["[dir]"] || checkT.blocks_air || !CANATMOSPASS(sourceT, checkT))
continue
found_turfs += checkT // Since checkT is connected, add it to the list to be processed
/proc/create_area(mob/creator)
var/static/blacklisted_turfs = typecacheof(/turf/open/space)
var/static/blacklisted_areas = typecacheof(/area/space)
var/list/turfs = detect_room(get_turf(creator), blacklisted_turfs)
if(!turfs)
to_chat(creator, "<span class='warning'>The new area must be completely airtight.</span>")
return
if(turfs.len > BP_MAX_ROOM_SIZE)
to_chat(creator, "<span class='warning'>The room you're in is too big. It is [((turfs.len / BP_MAX_ROOM_SIZE)-1)*100]% larger than allowed.</span>")
return
// This will fuck up shuttles that use the base area type but we need to fix those anyway
var/list/areas = list("New Area" = /area, "New Shuttle Area" = /area/shuttle/custom)
for(var/i in 1 to turfs.len)
var/area/place = get_area(turfs[i])
if(blacklisted_areas[place.type])
continue
areas[place.name] = place
var/area_choice = input(creator, "Choose an area to expand or make a new area.", "Area Expansion") as null|anything in areas
area_choice = areas[area_choice]
if(!area_choice)
to_chat(creator, "<span class='warning'>No choice selected. The area remains undefined.</span>")
return
var/area/newA
var/area/oldA = get_area(get_turf(creator))
if(!isarea(area_choice))
var/str = trim(stripped_input(creator,"New area name:", "Blueprint Editing", "", MAX_NAME_LEN))
if(!str || !length(str)) //cancel
return
if(length(str) > 50)
to_chat(creator, "<span class='warning'>The given name is too long. The area remains undefined.</span>")
return
newA = new area_choice
newA.setup(str)
newA.set_dynamic_lighting()
newA.has_gravity = oldA.has_gravity
else
newA = area_choice
for(var/i in 1 to turfs.len)
var/turf/thing = turfs[i]
var/area/old_area = thing.loc
newA.contents += thing
thing.change_area(old_area, newA)
var/list/related_areas = oldA.related
for(var/i in 1 to related_areas.len)
var/area/place = related_areas[i]
var/list/firedoors = place.firedoors
if(!LAZYLEN(firedoors))
continue
for(var/k in 1 to firedoors.len)
var/obj/machinery/door/firedoor/FD = firedoors[k]
FD.CalculateAffectingAreas()
to_chat(creator, "<span class='notice'>You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered.</span>")
return TRUE
#undef BP_MAX_ROOM_SIZE
+6 -1
View File
@@ -58,7 +58,12 @@ GLOBAL_VAR_INIT(cmp_field, "name")
. = B.failures - A.failures
if (!.)
. = B.qdels - A.qdels
/proc/cmp_generic_stat_item_time(list/A, list/B)
. = B[STAT_ENTRY_TIME] - A[STAT_ENTRY_TIME]
if (!.)
. = B[STAT_ENTRY_COUNT] - A[STAT_ENTRY_COUNT]
/proc/cmp_profile_avg_time_dsc(list/A, list/B)
return (B[PROFILE_ITEM_TIME]/(B[PROFILE_ITEM_COUNT] || 1)) - (A[PROFILE_ITEM_TIME]/(A[PROFILE_ITEM_COUNT] || 1))
+21 -9
View File
@@ -77,7 +77,7 @@
/proc/alone_in_area(area/the_area, mob/must_be_alone, check_type = /mob/living/carbon)
var/area/our_area = get_area(the_area)
for(var/C in GLOB.living_mob_list)
for(var/C in GLOB.alive_mob_list)
if(!istype(C, check_type))
continue
if(C == must_be_alone)
@@ -214,17 +214,28 @@
/proc/get_hearers_in_view(R, atom/source)
// Returns a list of hearers in view(R) from source (ignoring luminosity). Used in saycode.
var/turf/T = get_turf(source)
var/list/hear = list()
. = list()
if(!T)
return hear
return
var/list/range = get_hear(R, T)
for(var/atom/movable/A in range)
hear |= recursive_hear_check(A)
return hear
var/list/processing_list = list()
if (R == 0) // if the range is zero, we know exactly where to look for, we can skip view
processing_list += T.contents // We can shave off one iteration by assuming turfs cannot hear
else // A variation of get_hear inlined here to take advantage of the compiler's fastpath for obj/mob in view
var/lum = T.luminosity
T.luminosity = 6 // This is the maximum luminosity
processing_list = viewers(R, T)
for(var/obj/O in view(R, T))
processing_list += O
T.luminosity = lum
while(processing_list.len) // recursive_hear_check inlined here
var/atom/A = processing_list[1]
if(A.flags_1 & HEAR_1)
. += A
processing_list.Cut(1, 2)
processing_list += A.contents
/proc/get_mobs_in_radio_ranges(list/obj/item/device/radio/radios)
@@ -307,7 +318,8 @@
break
/proc/get_mob_by_key(key)
for(var/mob/M in GLOB.mob_list)
for(var/i in GLOB.player_list)
var/mob/M = i
if(M.ckey == lowertext(key))
return M
return null
+4
View File
@@ -179,6 +179,10 @@
underlay_appearance.icon_state = DEFAULT_UNDERLAY_ICON_STATE
underlays = U
// Drop posters which were previously placed on this wall.
for(var/obj/structure/sign/poster/P in src)
P.roll_and_drop(src)
/proc/cardinal_smooth(atom/A, adjacencies)
//NW CORNER
+7 -4
View File
@@ -178,7 +178,7 @@ mob
// Send the icon to src's local cache
src<<browse_rsc(I, iconName)
// Update the label to show it
winset(src,"imageLabel","image='\ref[I]'");
winset(src,"imageLabel","image='[REF(I)]'");
Add_Overlay()
set name = "4. Add Overlay"
@@ -849,7 +849,7 @@ The _flatIcons list is a cache for generated icon files.
if(A.alpha < 255)
flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
return icon(flat, "", SOUTH)
return icon(flat, "", curdir)
/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
@@ -1006,23 +1006,26 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
if(J)
J.equip(body, TRUE, FALSE)
SSoverlays.Flush()
var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing")
body.setDir(NORTH)
COMPILE_OVERLAYS(body)
var/icon/partial = getFlatIcon(body)
out_icon.Insert(partial,dir=NORTH)
body.setDir(SOUTH)
COMPILE_OVERLAYS(body)
partial = getFlatIcon(body)
out_icon.Insert(partial,dir=SOUTH)
body.setDir(WEST)
COMPILE_OVERLAYS(body)
partial = getFlatIcon(body)
out_icon.Insert(partial,dir=WEST)
body.setDir(EAST)
COMPILE_OVERLAYS(body)
partial = getFlatIcon(body)
out_icon.Insert(partial,dir=EAST)
@@ -1140,7 +1143,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0
// Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
var/atom/A = thing
var/key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]"
var/key = "[istype(A.icon, /icon) ? "[REF(A.icon)]" : A.icon]:[A.icon_state]"
if (!bicon_cache[key]) // Doesn't exist, make it.
+1 -1
View File
@@ -138,7 +138,7 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
var/t = round((val - min) / d)
return val - (t * d)
#define NORM_ROT(rot) ((((rot % 360) + (rot - round(rot, 1))) > 0) ? ((rot % 360) + (rot - round(rot, 1))) : (((rot % 360) + (rot - round(rot, 1))) + 360))
#define NORM_ROT(rot) ((((rot % 360) + (rot - round(rot, 1))) >= 0) ? ((rot % 360) + (rot - round(rot, 1))) : (((rot % 360) + (rot - round(rot, 1))) + 360))
/proc/get_angle_of_incidence(face_angle, angle_in, auto_normalize = TRUE)
+16 -14
View File
@@ -1,4 +1,4 @@
/proc/priority_announce(text, title = "", sound = 'sound/ai/attention.ogg', type)
/proc/priority_announce(text, title = "", sound = 'sound/ai/attention.ogg', type , sender_override)
if(!text)
return
@@ -13,13 +13,18 @@
GLOB.news_network.SubmitArticle(text, "Captain's Announcement", "Station Announcements", null)
else
announcement += "<h1 class='alert'>[command_name()] Update</h1>"
if(!sender_override)
announcement += "<h1 class='alert'>[command_name()] Update</h1>"
else
announcement += "<h1 class='alert'>[sender_override]</h1>"
if (title && length(title) > 0)
announcement += "<br><h2 class='alert'>[html_encode(title)]</h2>"
if(title == "")
GLOB.news_network.SubmitArticle(text, "Central Command Update", "Station Announcements", null)
else
GLOB.news_network.SubmitArticle(title + "<br><br>" + text, "Central Command", "Station Announcements", null)
if(!sender_override)
if(title == "")
GLOB.news_network.SubmitArticle(text, "Central Command Update", "Station Announcements", null)
else
GLOB.news_network.SubmitArticle(title + "<br><br>" + text, "Central Command", "Station Announcements", null)
announcement += "<br><span class='alert'>[html_encode(text)]</span><br>"
announcement += "<br>"
@@ -38,14 +43,11 @@
if(announce)
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg')
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && (C.z in GLOB.station_z_levels))
var/obj/item/paper/P = new /obj/item/paper(C.loc)
P.name = "paper - '[title]'"
P.info = text
C.messagetitle.Add("[title]")
C.messagetext.Add(text)
P.update_icon()
var/datum/comm_message/M = new
M.title = title
M.content = text
SScommunications.send_message(M)
/proc/minor_announce(message, title = "Attention:", alert)
if(!message)
+13
View File
@@ -0,0 +1,13 @@
/proc/render_stats(list/stats, user, sort = /proc/cmp_generic_stat_item_time)
sortTim(stats, sort, TRUE)
var/list/lines = list()
for (var/entry in stats)
var/list/data = stats[entry]
lines += "[entry] => [num2text(data[STAT_ENTRY_TIME], 10)]ms ([data[STAT_ENTRY_COUNT]]) (avg:[num2text(data[STAT_ENTRY_TIME]/(data[STAT_ENTRY_COUNT] || 1), 99)])"
if (user)
user << browse("<ol><li>[lines.Join("</li><li>")]</li></ol>", "window=[url_encode("stats:[REF(stats)]")]")
. = lines.Join("\n")
+1 -1
View File
@@ -654,7 +654,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
buffer = copytext(buffer, 1, cutoff) + punctbuffer
if(!findtext(buffer,alphanumeric))
continue
if(!buffer || lentext(buffer) > 140 || lentext(buffer) <= cullshort || buffer in accepted)
if(!buffer || lentext(buffer) > 280 || lentext(buffer) <= cullshort || buffer in accepted)
continue
accepted += buffer
+20
View File
@@ -578,3 +578,23 @@
return "turf"
else //regex everything else (works for /proc too)
return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
/proc/strtohex(str)
if(!istext(str)||!str)
return
var/r
var/c
for(var/i = 1 to length(str))
c= text2ascii(str,i)
r+= num2hex(c)
return r
/proc/hextostr(str)
if(!istext(str)||!str)
return
var/r
var/c
for(var/i = 1 to length(str)/2)
c= hex2num(copytext(str,i*2-1,i*2+1))
r+= ascii2text(c)
return r
+74 -4
View File
@@ -232,7 +232,7 @@ Turf and target are separate in case you want to teleport some distance from a t
//Returns a list of unslaved cyborgs
/proc/active_free_borgs()
. = list()
for(var/mob/living/silicon/robot/R in GLOB.living_mob_list)
for(var/mob/living/silicon/robot/R in GLOB.alive_mob_list)
if(R.connected_ai || R.shell)
continue
if(R.stat == DEAD)
@@ -244,7 +244,7 @@ Turf and target are separate in case you want to teleport some distance from a t
//Returns a list of AI's
/proc/active_ais(check_mind=0)
. = list()
for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list)
if(A.stat == DEAD)
continue
if(A.control_disabled == 1)
@@ -506,6 +506,7 @@ Turf and target are separate in case you want to teleport some distance from a t
/*
Gets all contents of contents and returns them all in a list.
*/
/atom/proc/GetAllContents()
var/list/processing_list = list(src)
var/list/assembled = list()
@@ -518,6 +519,19 @@ Turf and target are separate in case you want to teleport some distance from a t
assembled += A
return assembled
/atom/proc/GetAllContentsIgnoring(list/ignore_typecache)
if(!ignore_typecache)
return GetAllContents()
var/list/processing = list(src)
var/list/assembled = list()
while(processing.len)
var/atom/A = processing[1]
processing.Cut(1,2)
if(!ignore_typecache[A.type])
processing += A.contents
assembled += A
return assembled
//Step-towards method of determining whether one atom can see another. Similar to viewers()
/proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate.
var/turf/current = get_turf(source)
@@ -906,7 +920,7 @@ GLOBAL_LIST_INIT(WALLITEMS_INVERSE, typecacheof(list(
/proc/living_player_count()
var/living_player_count = 0
for(var/mob in GLOB.player_list)
if(mob in GLOB.living_mob_list)
if(mob in GLOB.alive_mob_list)
living_player_count += 1
return living_player_count
@@ -1343,6 +1357,9 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
anchored = TRUE
var/ready_to_die = FALSE
/mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists
return
/mob/dview/Destroy(force = FALSE)
if(!ready_to_die)
stack_trace("ALRIGHT WHICH FUCKER TRIED TO DELETE *MY* DVIEW?")
@@ -1412,6 +1429,46 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/proc/turf_z_is_planet(turf/T)
return GLOB.z_is_planet["[T.z]"]
//same as do_mob except for movables and it allows both to drift and doesn't draw progressbar
/proc/do_atom(atom/movable/user , atom/movable/target, time = 30, uninterruptible = 0,datum/callback/extra_checks = null)
if(!user || !target)
return TRUE
var/user_loc = user.loc
var/drifting = FALSE
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = TRUE
var/target_drifting = FALSE
if(!target.Process_Spacemove(0) && target.inertia_dir)
target_drifting = TRUE
var/target_loc = target.loc
var/endtime = world.time+time
// var/starttime = world.time
. = TRUE
while (world.time < endtime)
stoplag(1)
if(QDELETED(user) || QDELETED(target))
. = 0
break
if(uninterruptible)
continue
if(drifting && !user.inertia_dir)
drifting = FALSE
user_loc = user.loc
if(target_drifting && !target.inertia_dir)
target_drifting = FALSE
target_loc = target.loc
if((!drifting && user.loc != user_loc) || (!target_drifting && target.loc != target_loc) || (extra_checks && !extra_checks.Invoke()))
. = FALSE
break
//returns a GUID like identifier (using a mostly made up record format)
//guids are not on their own suitable for access or security tokens, as most of their bits are predictable.
// (But may make a nice salt to one)
@@ -1427,5 +1484,18 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
var/time_low = num2hex(world.time, 3)
var/time_clock = num2hex(TICK_DELTA_TO_MS(world.tick_usage), 3)
return "{[time_high]-[time_mid]-[GUID_VERSION][time_low]-[GUID_VARIANT][time_clock]-[node_id]}"
return "{[time_high]-[time_mid]-[GUID_VERSION][time_low]-[GUID_VARIANT][time_clock]-[node_id]}"
// \ref behaviour got changed in 512 so this is necesary to replicate old behaviour.
// If it ever becomes necesary to get a more performant REF(), this lies here in wait
// #define REF(thing) (thing && istype(thing, /datum) && thing:use_tag && thing:tag ? "[thing:tag]" : "\ref[thing]")
/proc/REF(input)
if(istype(input, /datum))
var/datum/thing = input
if(thing.use_tag)
if(!thing.tag)
WARNING("A ref was requested of an object with use_tag set but no tag: [thing]")
thing.use_tag = FALSE
else
return "\[[url_encode(thing.tag)]\]"
return "\ref[input]"
+4 -1
View File
@@ -12,10 +12,13 @@ GLOBAL_LIST_EMPTY(stealthminID) //reference list with IDs that store ckeys,
GLOBAL_LIST_EMPTY(player_list) //all mobs **with clients attached**. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(mob_list) //all mobs, including clientless
GLOBAL_LIST_EMPTY(mob_directory) //mob_id -> mob
GLOBAL_LIST_EMPTY(living_mob_list) //all alive mobs, including clientless. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(alive_mob_list) //all alive mobs, including clientless. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(drones_list)
GLOBAL_LIST_EMPTY(dead_mob_list) //all dead mobs, including clientless. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(joined_player_list) //all clients that have joined the game at round-start or as a latejoin.
GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs
GLOBAL_LIST_EMPTY(mob_living_list) //all instances of /mob/living and subtypes
GLOBAL_LIST_EMPTY(carbon_list) //all instances of /mob/living/carbon and subtypes, notably does not contain brains or simple animals
GLOBAL_LIST_EMPTY(ai_list)
GLOBAL_LIST_EMPTY(pai_list)
GLOBAL_LIST_EMPTY(available_ai_shells)
-1
View File
@@ -19,7 +19,6 @@ GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt")
GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt"))
GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt"))
GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt"))
GLOBAL_LIST_INIT(adjectives, world.file2list("strings/names/adjectives.txt"))
GLOBAL_LIST_INIT(dream_strings, world.file2list("strings/dreamstrings.txt"))
+2 -1
View File
@@ -36,4 +36,5 @@ GLOBAL_LIST_EMPTY(wire_name_directory)
GLOBAL_LIST_EMPTY(ai_status_displays)
GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects
GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects
GLOBAL_LIST_EMPTY(alert_consoles) // Station alert consoles, /obj/machinery/computer/station_alert
+1 -1
View File
@@ -25,7 +25,7 @@ GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
GLOBAL_LIST_EMPTY(admin_log)
GLOBAL_PROTECT(admin_log)
GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]"
GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used [REF(src)] @ location [src.loc]: [freq]/[code]"
GLOBAL_PROTECT(lastsignalers)
GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
GLOBAL_PROTECT(lawchanges)
+13 -12
View File
@@ -38,6 +38,8 @@
if(isnull(pixel_turf))
return
if(!can_see(A))
if(isturf(A)) //On unmodified clients clicking the static overlay clicks the turf underneath
return //So there's no point messaging admins
message_admins("[key_name_admin(src)] might be running a modified client! (failed can_see on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))")
var/message = "[key_name(src)] might be running a modified client! (failed can_see on AI click of [A]([COORD(pixel_turf)]))"
log_admin(message)
@@ -136,36 +138,35 @@
/obj/machinery/door/airlock/AICtrlClick() // Bolts doors
if(emagged)
return
if(locked)
Topic("aiEnable=4", list("aiEnable"="4"), 1)// 1 meaning no window (consistency!)
bolt_raise(usr)
else
Topic("aiDisable=4", list("aiDisable"="4"), 1)
bolt_drop(usr)
/obj/machinery/door/airlock/AIAltClick() // Eletrifies doors.
if(emagged)
return
if(!secondsElectrified)
// permanent shock
Topic("aiEnable=6", list("aiEnable"="6"), 1) // 1 meaning no window (consistency!)
shock_perm(usr)
else
// disable/6 is not in Topic; disable/5 disables both temporary and permenant shock
Topic("aiDisable=5", list("aiDisable"="5"), 1)
shock_restore(usr)
/obj/machinery/door/airlock/AIShiftClick() // Opens and closes doors!
if(emagged)
return
if(density)
Topic("aiEnable=7", list("aiEnable"="7"), 1) // 1 meaning no window (consistency!)
else
Topic("aiDisable=7", list("aiDisable"="7"), 1)
user_toggle_open(usr)
/obj/machinery/door/airlock/AICtrlShiftClick() // Sets/Unsets Emergency Access Override
if(emagged)
return
if(!emergency)
Topic("aiEnable=11", list("aiEnable"="11"), 1) // 1 meaning no window (consistency!)
emergency_on(usr)
else
Topic("aiDisable=11", list("aiDisable"="11"), 1)
emergency_off(usr)
/* APC */
/obj/machinery/power/apc/AICtrlClick() // turns off/on APCs.
+14 -10
View File
@@ -282,11 +282,13 @@
return
/mob/living/carbon/MiddleClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (iscarbon(A)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
swap_hand()
if(!stat && mind && iscarbon(A) && A != src)
var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling)
if(C && C.chosen_sting)
C.chosen_sting.try_to_sting(src,A)
next_click = world.time + 5
return
swap_hand()
/mob/living/simple_animal/drone/MiddleClickOn(atom/A)
swap_hand()
@@ -344,11 +346,13 @@
return
/mob/living/carbon/AltClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (iscarbon(A)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
..()
if(!stat && mind && iscarbon(A) && A != src)
var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling)
if(C && C.chosen_sting)
C.chosen_sting.try_to_sting(src,A)
next_click = world.time + 5
return
..()
/atom/proc/AltClick(mob/user)
SendSignal(COMSIG_CLICK_ALT, user)
+3 -3
View File
@@ -23,9 +23,6 @@
//Middle left indicators
#define ui_lingchemdisplay "WEST,CENTER-1:15"
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
#define ui_crafting "12:-10,1:5"
#define ui_building "12:-10,1:21"
#define ui_language_menu "11:6,2:-11"
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
@@ -85,6 +82,9 @@
#define ui_acti "EAST-3:24,SOUTH:5"
#define ui_zonesel "EAST-1:28,SOUTH:5"
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
#define ui_crafting "EAST-4:22,SOUTH:5"
#define ui_building "EAST-4:22,SOUTH:21"
#define ui_language_menu "EAST-4:6,SOUTH:21"
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
+2 -5
View File
@@ -390,7 +390,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
var/servants = 0
var/validservants = 0
var/list/textlist
for(var/mob/living/L in GLOB.living_mob_list)
for(var/mob/living/L in GLOB.alive_mob_list)
if(is_servant_of_ratvar(L))
servants++
if(ishuman(L) || issilicon(L))
@@ -407,16 +407,13 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
textlist += "[i] Scripture: <b>[SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G)
var/time_info
var/time_info = G.get_arrival_time(FALSE)
var/time_name
if(G.seconds_until_activation)
time_info = G.seconds_until_activation
time_name = "until the Ark activates"
else if(G.grace_period)
time_info = G.grace_period
time_name = "of grace period remaining"
else if(G.progress_in_seconds)
time_info = GATEWAY_RATVAR_ARRIVAL - G.progress_in_seconds
time_name = "until the Ark finishes summoning"
if(time_info)
textlist += "<b>[time_info / 60] minutes</b> [time_name].<br>"
+177 -175
View File
@@ -1,175 +1,177 @@
/mob
var/list/screens = list()
/mob/proc/overlay_fullscreen(category, type, severity)
var/obj/screen/fullscreen/screen
if(screens[category])
screen = screens[category]
if(screen.type != type)
clear_fullscreen(category, FALSE)
return .()
else if(!severity || severity == screen.severity)
return null
else
screen = new type()
screen.icon_state = "[initial(screen.icon_state)][severity]"
screen.severity = severity
screens[category] = screen
if(client && screen.should_show_to(src))
client.screen += screen
return screen
/mob/proc/clear_fullscreen(category, animated = 10)
var/obj/screen/fullscreen/screen = screens[category]
if(!screen)
return
screens -= category
if(animated)
animate(screen, alpha = 0, time = animated)
addtimer(CALLBACK(src, .proc/clear_fullscreen_after_animate, screen), animated, TIMER_CLIENT_TIME)
else
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreen_after_animate(obj/screen/fullscreen/screen)
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreens()
for(var/category in screens)
clear_fullscreen(category)
/mob/proc/hide_fullscreens()
if(client)
for(var/category in screens)
client.screen -= screens[category]
/mob/proc/reload_fullscreen()
if(client)
var/obj/screen/fullscreen/screen
for(var/category in screens)
screen = screens[category]
if(screen.should_show_to(src))
client.screen |= screen
else
client.screen -= screen
/obj/screen/fullscreen
icon = 'icons/mob/screen_full.dmi'
icon_state = "default"
screen_loc = "CENTER-7,CENTER-7"
layer = FULLSCREEN_LAYER
plane = FULLSCREEN_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/severity = 0
var/show_when_dead = FALSE
/obj/screen/fullscreen/proc/should_show_to(mob/mymob)
if(!show_when_dead && mymob.stat == DEAD)
return FALSE
return TRUE
/obj/screen/fullscreen/Destroy()
severity = 0
. = ..()
/obj/screen/fullscreen/brute
icon_state = "brutedamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/oxy
icon_state = "oxydamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit
icon_state = "passage"
layer = CRIT_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit/vision
icon_state = "oxydamageoverlay"
layer = BLIND_LAYER
/obj/screen/fullscreen/blind
icon_state = "blackimageoverlay"
layer = BLIND_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/curse
icon_state = "curse"
layer = CURSE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/impaired
icon_state = "impairedoverlay"
/obj/screen/fullscreen/blurry
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "blurry"
/obj/screen/fullscreen/flash
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
/obj/screen/fullscreen/flash/static
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "noise"
/obj/screen/fullscreen/high
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "druggy"
/obj/screen/fullscreen/color_vision
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
alpha = 80
/obj/screen/fullscreen/color_vision/green
color = "#00ff00"
/obj/screen/fullscreen/color_vision/red
color = "#ff0000"
/obj/screen/fullscreen/color_vision/blue
color = "#0000ff"
/obj/screen/fullscreen/lighting_backdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "flash"
transform = matrix(200, 0, 0, 0, 200, 0)
plane = LIGHTING_PLANE
blend_mode = BLEND_OVERLAY
show_when_dead = TRUE
//Provides darkness to the back of the lighting plane
/obj/screen/fullscreen/lighting_backdrop/lit
invisibility = INVISIBILITY_LIGHTING
layer = BACKGROUND_LAYER+21
color = "#000"
show_when_dead = TRUE
//Provides whiteness in case you don't see lights so everything is still visible
/obj/screen/fullscreen/lighting_backdrop/unlit
layer = BACKGROUND_LAYER+20
show_when_dead = TRUE
/obj/screen/fullscreen/see_through_darkness
icon_state = "nightvision"
plane = LIGHTING_PLANE
layer = LIGHTING_LAYER
blend_mode = BLEND_ADD
show_when_dead = TRUE
/mob
var/list/screens = list()
/mob/proc/overlay_fullscreen(category, type, severity)
var/obj/screen/fullscreen/screen = screens[category]
if (!screen || screen.type != type)
// needs to be recreated
clear_fullscreen(category, FALSE)
screens[category] = screen = new type()
else if ((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view))
// doesn't need to be updated
return screen
screen.icon_state = "[initial(screen.icon_state)][severity]"
screen.severity = severity
if (client && screen.should_show_to(src))
client.screen += screen
if (screen.screen_loc == "CENTER-7,CENTER-7" && screen.view != client.view)
var/scale = (1 + 2 * client.view) / 15
screen.view = client.view
screen.transform = matrix(scale, 0, 0, 0, scale, 0)
return screen
/mob/proc/clear_fullscreen(category, animated = 10)
var/obj/screen/fullscreen/screen = screens[category]
if(!screen)
return
screens -= category
if(animated)
animate(screen, alpha = 0, time = animated)
addtimer(CALLBACK(src, .proc/clear_fullscreen_after_animate, screen), animated, TIMER_CLIENT_TIME)
else
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreen_after_animate(obj/screen/fullscreen/screen)
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreens()
for(var/category in screens)
clear_fullscreen(category)
/mob/proc/hide_fullscreens()
if(client)
for(var/category in screens)
client.screen -= screens[category]
/mob/proc/reload_fullscreen()
if(client)
var/obj/screen/fullscreen/screen
for(var/category in screens)
screen = screens[category]
if(screen.should_show_to(src))
client.screen |= screen
else
client.screen -= screen
/obj/screen/fullscreen
icon = 'icons/mob/screen_full.dmi'
icon_state = "default"
screen_loc = "CENTER-7,CENTER-7"
layer = FULLSCREEN_LAYER
plane = FULLSCREEN_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/view = 7
var/severity = 0
var/show_when_dead = FALSE
/obj/screen/fullscreen/proc/should_show_to(mob/mymob)
if(!show_when_dead && mymob.stat == DEAD)
return FALSE
return TRUE
/obj/screen/fullscreen/Destroy()
severity = 0
. = ..()
/obj/screen/fullscreen/brute
icon_state = "brutedamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/oxy
icon_state = "oxydamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit
icon_state = "passage"
layer = CRIT_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit/vision
icon_state = "oxydamageoverlay"
layer = BLIND_LAYER
/obj/screen/fullscreen/blind
icon_state = "blackimageoverlay"
layer = BLIND_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/curse
icon_state = "curse"
layer = CURSE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/impaired
icon_state = "impairedoverlay"
/obj/screen/fullscreen/blurry
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "blurry"
/obj/screen/fullscreen/flash
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
/obj/screen/fullscreen/flash/static
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "noise"
/obj/screen/fullscreen/high
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "druggy"
/obj/screen/fullscreen/color_vision
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
alpha = 80
/obj/screen/fullscreen/color_vision/green
color = "#00ff00"
/obj/screen/fullscreen/color_vision/red
color = "#ff0000"
/obj/screen/fullscreen/color_vision/blue
color = "#0000ff"
/obj/screen/fullscreen/lighting_backdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "flash"
transform = matrix(200, 0, 0, 0, 200, 0)
plane = LIGHTING_PLANE
blend_mode = BLEND_OVERLAY
show_when_dead = TRUE
//Provides darkness to the back of the lighting plane
/obj/screen/fullscreen/lighting_backdrop/lit
invisibility = INVISIBILITY_LIGHTING
layer = BACKGROUND_LAYER+21
color = "#000"
show_when_dead = TRUE
//Provides whiteness in case you don't see lights so everything is still visible
/obj/screen/fullscreen/lighting_backdrop/unlit
layer = BACKGROUND_LAYER+20
show_when_dead = TRUE
/obj/screen/fullscreen/see_through_darkness
icon_state = "nightvision"
plane = LIGHTING_PLANE
layer = LIGHTING_LAYER
blend_mode = BLEND_ADD
show_when_dead = TRUE
+1 -1
View File
@@ -539,7 +539,7 @@
screen_loc = ui_healthdoll
/obj/screen/splash
icon = 'config/title_screens/images/title1.dmi'
icon = 'icons/blank_title.png'
icon_state = ""
screen_loc = "1,1"
layer = SPLASHSCREEN_LAYER
+19 -3
View File
@@ -1,12 +1,29 @@
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
if(pre_attackby(target, user, params))
if(!tool_check(user, target) && pre_attackby(target, user, params))
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = target.attackby(src, user, params)
if(!resolved && target && !QDELETED(src))
afterattack(target, user, 1, params) // 1: clicking something Adjacent
//Checks if the item can work as a tool, calling the appropriate tool behavior on the target
/obj/item/proc/tool_check(mob/user, atom/target)
switch(tool_behaviour)
if(TOOL_NONE)
return FALSE
if(TOOL_CROWBAR)
return target.crowbar_act(user, src)
if(TOOL_MULTITOOL)
return target.multitool_act(user, src)
if(TOOL_SCREWDRIVER)
return target.screwdriver_act(user, src)
if(TOOL_WRENCH)
return target.wrench_act(user, src)
if(TOOL_WIRECUTTER)
return target.wirecutter_act(user, src)
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
/obj/item/proc/attack_self(mob/user)
SendSignal(COMSIG_ITEM_ATTACK_SELF, user)
@@ -118,5 +135,4 @@
attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!"
visible_message("<span class='danger'>[attack_message]</span>", \
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
return 1
return 1
+7 -11
View File
@@ -53,23 +53,19 @@
if(user.client)
if(IsAdminGhost(user))
attack_ai(user)
if(user.client.prefs.inquisitive_ghost)
else if(user.client.prefs.inquisitive_ghost)
user.examinate(src)
/mob/living/attack_ghost(mob/dead/observer/user)
if(user.client && user.health_scan)
healthscan(user, src, 1, TRUE)
return
..()
// ---------------------------------------
// And here are some good things for free:
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
/obj/machinery/teleport/hub/attack_ghost(mob/user)
var/atom/l = loc
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
if(com && com.locked)
user.forceMove(get_turf(com.locked))
/obj/effect/portal/attack_ghost(mob/user)
if(linked)
user.forceMove(get_turf(linked))
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
if(awaygate)
user.forceMove(awaygate.loc)
+31
View File
@@ -0,0 +1,31 @@
/*/////////////////////////////////////////////////////////////////////////////////
/////// ///////
/////// Cit's exclusive jumpsuits, uniforms, etc. go here ///////
/////// ///////
*//////////////////////////////////////////////////////////////////////////////////
/obj/item/clothing/under/rank/security/skirt
name = "security skirt"
desc = "A tactical security skirt for officers complete with Nanotrasen belt buckle."
icon = 'icons/obj/clothing/cit_clothes.dmi'
icon_state = "secskirt"
icon_override = 'icons/mob/citadel/uniforms.dmi'
item_state = "r_suit"
item_color = "secskirt"
/obj/item/clothing/under/rank/head_of_security/skirt
name = "head of security's skirt"
desc = "A security skirt decorated for those few with the dedication to achieve the position of Head of Security."
icon = 'icons/obj/clothing/cit_clothes.dmi'
icon_state = "hosskirt"
icon_override = 'icons/mob/citadel/uniforms.dmi'
item_state = "gy_suit"
item_color = "hosskirt"
/obj/item/clothing/suit/armor/hos/trenchcoat/cloak
name = "armored trenchcloak"
desc = "A trenchcoat enchanced with a special lightweight kevlar. This one appears to be designed to be draped over one's shoulders rather than worn normally.."
alternate_worn_icon = 'icons/mob/citadel/suit.dmi'
icon_state = "hostrench"
item_state = "hostrench"
+5
View File
@@ -0,0 +1,5 @@
/obj/structure/displaycase/clown
desc = "In the event of clown, honk glass."
alert = 1
start_showpiece_type = /obj/item/bikehorn
req_access = list(ACCESS_CENT_GENERAL)
+45 -11
View File
@@ -180,6 +180,7 @@
icon_state = "toy9magazine"
max_ammo = 30
multiple_sprites = 2
materials = list(MAT_METAL = 200)
/obj/item/gun/ballistic/automatic/x9/toy
name = "\improper Foam Force X9"
@@ -193,6 +194,7 @@
spread = 90 //MAXIMUM XCOM MEMES (actually that'd be 180 spread)
w_class = WEIGHT_CLASS_BULKY
weapon_weight = WEAPON_HEAVY
origin_tech = "combat=1;magnets=1"
/datum/design/foam_x9
name = "Foam Force X9 Rifle"
@@ -213,6 +215,8 @@
damage = 15
armour_penetration = 10
light_range = 2
speed = 1.2
range = 25
light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/nlmags //non-lethal boolets
@@ -220,9 +224,11 @@
icon_state = "magjectile-nl"
damage = 1
knockdown = 0
stamina = 25
stamina = 30
armour_penetration = -10
light_range = 2
speed = 1.2
range = 25
light_color = LIGHT_COLOR_BLUE
@@ -289,6 +295,7 @@
/obj/item/gun/ballistic/automatic/pistol/mag/nopin
pin = null
spawnwithmagazine = FALSE
/datum/design/magpistol
name = "Magpistol"
@@ -347,6 +354,7 @@
fire_sound = 'sound/weapons/magpistol.ogg'
slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
origin_tech = "combat=1;magnets=1"
/obj/item/ammo_box/foambox/mag
name = "ammo box (Magnetic Foam Darts)"
@@ -378,19 +386,23 @@
/obj/item/projectile/bullet/magrifle
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "magjectile-large"
damage = 25
damage = 20
armour_penetration = 25
light_range = 3
speed = 1.2
range = 35
light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/nlmagrifle //non-lethal boolets
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "magjectile-large-nl"
damage = 2
damage = 1
knockdown = 0
stamina = 30
stamina = 35
armour_penetration = -10
light_range = 3
speed = 1.0
range = 35
light_color = LIGHT_COLOR_BLUE
///ammo casings///
@@ -451,6 +463,7 @@
/obj/item/gun/ballistic/automatic/magrifle/nopin
pin = null
spawnwithmagazine = FALSE
/datum/design/magrifle
name = "Magrifle"
@@ -489,15 +502,16 @@
max_ammo = 15
multiple_sprites = 2
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
materials = list(MAT_METAL = 200)
/obj/item/gun/ballistic/automatic/magrifle/toy
name = "foamag rifle"
desc = "A foam launching magnetic rifle. Ages 8 and up."
icon_state = "foamagrifle"
needs_permit = 0
needs_permit = FALSE
mag_type = /obj/item/ammo_box/magazine/toy/foamag
casing_ejector = FALSE
origin_tech = "combat=2;engineering=2;magnets=2"
origin_tech = "combat=1;engineering=1;magnets=1"
spread = 60
w_class = WEIGHT_CLASS_BULKY
weapon_weight = WEAPON_HEAVY
@@ -631,6 +645,7 @@
charge_delay = 2
recoil = 2
cell_type = /obj/item/stock_parts/cell/toymagburst
origin_tech = "combat=1;magnets=1"
/obj/item/stock_parts/cell/toymagburst
name = "toy mag burst rifle power supply"
@@ -687,6 +702,7 @@
fire_delay = 0
spread = 60
actions_types = list()
origin_tech = "combat=1;magnets=1"
/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_icon()
..()
@@ -913,6 +929,7 @@ obj/item/projectile/bullet/c10mm/soporific
desc = "A toy laser with a classic, retro feel and look. Compatible with existing laser tag systems."
ammo_type = list(/obj/item/ammo_casing/energy/laser/raytag)
selfcharge = TRUE
origin_tech = "combat=1;magnets=1"
/datum/design/toyray
name = "RayTag Gun"
@@ -1060,6 +1077,7 @@ obj/item/projectile/bullet/c10mm/soporific
if(arm_color_input)
arm_color = sanitize_hexcolor(arm_color_input, desired_format=6, include_crunch=1)
update_icon()
A.UpdateButtonIcon()
else
..()
@@ -1070,12 +1088,16 @@ obj/item/projectile/bullet/c10mm/soporific
name = "9mm frangible bullet"
damage = 15
stamina = 0
speed = 1.0
range = 20
armour_penetration = -25
/obj/item/projectile/bullet/c9mm/rubber
name = "9mm rubber bullet"
damage = 2
stamina = 25
damage = 5
stamina = 30
speed = 1.2
range = 14
knockdown = 0
/obj/item/ammo_casing/c9mm/frangible
@@ -1120,9 +1142,9 @@ obj/item/projectile/bullet/c10mm/soporific
name = "Box of 9mm Frangible Bullets"
id = "9mm_frag"
build_type = AUTOLATHE
materials = list(MAT_METAL = 30000)
materials = list(MAT_METAL = 25000)
build_path = /obj/item/ammo_box/c9mm/frangible
category = list("initial", "Security")
category = list("hacked", "Security")
/datum/design/c9mmrubber
name = "Box of 9mm Rubber Bullets"
@@ -1157,10 +1179,13 @@ obj/item/projectile/bullet/c10mm/soporific
name = "\improper Foam Force Mk.37F"
desc = "A licensed foam-firing reproduction of a handgun with a toggle-locking mechanism manufactured by CX Armories. This model is coated with a special polychromic material. Uses standard foam pistol magazines."
icon_state = "p37_foam"
pin = /obj/item/device/firing_pin
spawnwithmagazine = TRUE
needs_permit = FALSE
mag_type = /obj/item/ammo_box/magazine/toy/pistol
can_suppress = FALSE
actions_types = list(/datum/action/item_action/pick_color)
origin_tech = "combat=1;magnets=1"
/datum/design/foam_p37
name = "Foam Force Mk.37F"
@@ -1196,6 +1221,10 @@ obj/item/gun/energy/e_gun/cx/update_icon()
body_overlay.color = body_color
add_overlay(body_overlay)
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
obj/item/gun/energy/e_gun/cx/ui_action_click(mob/user, var/datum/action/A)
if(istype(A, /datum/action/item_action/pick_color))
if(alert("Are you sure you want to repaint your gun?", "Confirm Repaint", "Yes", "No") == "Yes")
@@ -1203,6 +1232,7 @@ obj/item/gun/energy/e_gun/cx/ui_action_click(mob/user, var/datum/action/A)
if(body_color_input)
body_color = sanitize_hexcolor(body_color_input, desired_format=6, include_crunch=1)
update_icon()
A.UpdateButtonIcon()
else
..()
@@ -1211,4 +1241,8 @@ obj/item/gun/energy/e_gun/cx/worn_overlays(isinhands, icon_file)
if(isinhands)
var/mutable_appearance/body_inhand = mutable_appearance(icon_file, "cxe_body")
body_inhand.color = body_color
. += body_inhand
. += body_inhand
/obj/item/ammo_box/magazine/toy/pistol //forcing this might be a bad idea, but it'll fix the foam gun infinite material exploit
..()
materials = list(MAT_METAL = 200)
+20 -6
View File
@@ -32,6 +32,10 @@
set_light(0)
update_icon()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
add_fingerprint(user)
/obj/item/toy/sword/cx/update_icon()
@@ -49,6 +53,10 @@
if(active)
add_overlay(blade_overlay)
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
/obj/item/toy/sword/cx/ui_action_click(mob/user, var/datum/action/A)
if(istype(A, /datum/action/item_action/pick_color))
if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
@@ -56,10 +64,8 @@
if(energy_color_input)
light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
update_icon()
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
update_light()
A.UpdateButtonIcon()
else
..()
@@ -72,6 +78,9 @@
blade_inhand.color = light_color
. += blade_inhand
/obj/item/toy/sword/cx/attackby(obj/item/W, mob/living/user, params)
return //NO MORE MAKING DUAL ESWORDS
/*///autolathe memes/// I really need to stop doing this and find a proper way of adding in my toys
/datum/design/toyneb
@@ -143,6 +152,9 @@
update_icon()
transform_messages(user, supress_message_text)
add_fingerprint(user)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
return TRUE
/obj/item/melee/transforming/energy/sword/cx/transform_messages(mob/living/user, supress_message_text)
@@ -165,6 +177,10 @@
if(active)
add_overlay(blade_overlay)
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
/obj/item/melee/transforming/energy/sword/cx/ui_action_click(mob/user, var/datum/action/A)
if(istype(A, /datum/action/item_action/pick_color))
if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
@@ -172,10 +188,8 @@
if(energy_color_input)
light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
update_icon()
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
update_light()
A.UpdateButtonIcon()
else
..()
@@ -15,7 +15,7 @@
/datum/objective/crew/cyborgs/check_completion()
var/borgcount = target_amount
for(var/mob/living/silicon/robot/R in GLOB.living_mob_list)
for(var/mob/living/silicon/robot/R in GLOB.alive_mob_list)
if(!(R.stat == DEAD))
borgcount--
if(borgcount <= 0)
@@ -42,4 +42,4 @@
if(S && S.files && S.files.known_designs)
if(targetdesign in S.files.known_designs)
return TRUE
return FALSE
return FALSE
@@ -51,6 +51,11 @@
return FALSE
return ..()
/datum/config_entry/proc/VASProcCallGuard(str_val)
. = !(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
if(!.)
log_admin_private("Config set of [type] to [str_val] attempted by [key_name(usr)]")
/datum/config_entry/proc/ValidateAndSet(str_val)
CRASH("Invalid config entry type!")
@@ -124,7 +124,7 @@ GLOBAL_PROTECT(config_dir)
stat("[name]:", statclick)
/datum/controller/configuration/proc/Get(entry_type)
if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "\ref[src]")
if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
return
var/datum/config_entry/E = entry_type
@@ -137,7 +137,7 @@ GLOBAL_PROTECT(config_dir)
return E.value
/datum/controller/configuration/proc/Set(entry_type, new_val)
if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Set" && GLOB.LastAdminCalledTargetRef == "\ref[src]")
if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Set" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
log_admin_private("Config rewrite of [entry_type] to [new_val] attempted by [key_name(usr)]")
return
var/datum/config_entry/E = entry_type
@@ -318,6 +318,8 @@ CONFIG_DEF(number/client_warn_version)
CONFIG_DEF(string/client_warn_message)
value = "Your version of byond may have issues or be blocked from accessing this server in the future."
CONFIG_DEF(flag/client_warn_popup)
CONFIG_DEF(number/client_error_version)
value = null
min_val = 500
@@ -372,3 +374,10 @@ CONFIG_TWEAK(number/mc_tick_rate/ValidateAndSet(str_val))
. = ..()
if (.)
Master.UpdateTickRate()
CONFIG_DEF(flag/resume_after_initializations)
CONFIG_TWEAK(flag/ValidateAndSet(str_val))
. = ..()
if(. && Master.current_runlevel)
world.sleep_offline = !value
@@ -163,9 +163,20 @@ CONFIG_DEF(flag/ooc_during_round)
CONFIG_DEF(flag/emojis)
CONFIG_DEF(number/run_delay) //Used for modifying movement speed for mobs.
var/static/value_cache = 0
CONFIG_TWEAK(number/run_delay/ValidateAndSet())
. = ..()
if(.)
value_cache = value
CONFIG_DEF(number/walk_delay)
var/static/value_cache = 0
CONFIG_TWEAK(number/walk_delay/ValidateAndSet())
. = ..()
if(.)
value_cache = value
CONFIG_DEF(number/human_delay) //Mob specific modifiers. NOTE: These will affect different mob types in different ways
CONFIG_DEF(number/robot_delay)
@@ -251,3 +262,5 @@ CONFIG_DEF(number/emergency_shuttle_autocall_threshold)
min_val = 0
max_val = 1
integer = FALSE
CONFIG_DEF(flag/ic_printing)
+3 -3
View File
@@ -40,18 +40,18 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
stat("Globals:", statclick.update("Edit"))
/datum/controller/global_vars/can_vv_get(var_name)
if(var_name in gvars_datum_protected_varlist)
if(gvars_datum_protected_varlist[var_name])
return FALSE
return ..()
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
if((var_name in gvars_datum_protected_varlist))
if(gvars_datum_protected_varlist[var_name])
return FALSE
return ..()
/datum/controller/global_vars/Initialize()
gvars_datum_init_order = list()
gvars_datum_protected_varlist = list("gvars_datum_protected_varlist")
gvars_datum_protected_varlist = list("gvars_datum_protected_varlist" = TRUE)
var/list/global_procs = typesof(/datum/controller/global_vars/proc)
var/expected_len = vars.len - gvars_datum_in_built_vars.len
if(global_procs.len != expected_len)
+3 -1
View File
@@ -189,10 +189,12 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
// Sort subsystems by display setting for easy access.
sortTim(subsystems, /proc/cmp_subsystem_display)
// Set world options.
world.sleep_offline = 1
world.sleep_offline = TRUE
world.fps = CONFIG_GET(number/fps)
var/initialized_tod = REALTIMEOFDAY
sleep(1)
if(CONFIG_GET(flag/resume_after_initializations))
world.sleep_offline = FALSE
initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10
// Loop.
Master.StartProcessing(0)
+11
View File
@@ -27,6 +27,7 @@ SUBSYSTEM_DEF(air)
var/list/hotspots = list()
var/list/networks = list()
var/list/obj/machinery/atmos_machinery = list()
var/list/pipe_init_dirs_cache = list()
@@ -376,6 +377,16 @@ SUBSYSTEM_DEF(air)
AM.build_network()
CHECK_TICK
/datum/controller/subsystem/air/proc/get_init_dirs(type, dir)
if(!pipe_init_dirs_cache[type])
pipe_init_dirs_cache[type] = list()
if(!pipe_init_dirs_cache[type]["[dir]"])
var/obj/machinery/atmospherics/temp = new type(null, FALSE, dir)
pipe_init_dirs_cache[type]["[dir]"] = temp.GetInitDirections()
qdel(temp)
return pipe_init_dirs_cache[type]["[dir]"]
#undef SSAIR_PIPENETS
#undef SSAIR_ATMOSMACHINERY
@@ -28,5 +28,19 @@ SUBSYSTEM_DEF(communications)
log_talk(user,"[key_name(user)] has made a priority announcement: [input]",LOGSAY)
message_admins("[key_name_admin(user)] has made a priority announcement.")
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && (C.z in GLOB.station_z_levels))
if(unique)
C.add_message(sending)
else //We copy the message for each console, answers and deletions won't be shared
var/datum/comm_message/M = new(sending.title,sending.content,sending.possible_answers.Copy())
C.add_message(M)
if(print)
var/obj/item/paper/P = new /obj/item/paper(C.loc)
P.name = "paper - '[sending.title]'"
P.info = sending.content
P.update_icon()
#undef COMMUNICATION_COOLDOWN
#undef COMMUNICATION_COOLDOWN_AI
+1 -1
View File
@@ -186,7 +186,7 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
/datum/DBQuery/proc/warn_execute()
. = Execute()
if(!.)
to_chat(usr, "<span class='danger'>A SQL error occured during this operation, check the server logs.</span>")
to_chat(usr, "<span class='danger'>A SQL error occurred during this operation, check the server logs.</span>")
/datum/DBQuery/proc/Execute(sql_query = sql, cursor_handler = default_cursor, log_error = TRUE)
Close()
+2 -2
View File
@@ -133,7 +133,7 @@ SUBSYSTEM_DEF(events)
var/magic = ""
var/holiday = ""
for(var/datum/round_event_control/E in SSevents.control)
dat = "<BR><A href='?src=\ref[src];[HrefToken()];forceevent=\ref[E]'>[E]</A>"
dat = "<BR><A href='?src=[REF(src)];[HrefToken()];forceevent=[REF(E)]'>[E]</A>"
if(E.holidayID)
holiday += dat
else if(E.wizardevent)
@@ -177,7 +177,7 @@ SUBSYSTEM_DEF(events)
var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
var/DDD = text2num(time2text(world.timeofday, "DDD")) // get the current weekday
var/DDD = time2text(world.timeofday, "DDD") // get the current weekday
var/W = weekdayofthemonth() // is this the first monday? second? etc.
for(var/H in subtypesof(/datum/holiday))
+3 -3
View File
@@ -164,7 +164,7 @@ SUBSYSTEM_DEF(garbage)
#endif
var/type = D.type
var/datum/qdel_item/I = items[type]
testing("GC: -- \ref[D] | [type] was unable to be GC'd --")
testing("GC: -- \ref[src] | [type] was unable to be GC'd --")
I.failures++
if (GC_QUEUE_HARDDELETE)
HardDelete(D)
@@ -263,7 +263,7 @@ SUBSYSTEM_DEF(garbage)
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(datum/D, force=FALSE)
/proc/qdel(datum/D, force=FALSE, ...)
if(!istype(D))
del(D)
return
@@ -278,7 +278,7 @@ SUBSYSTEM_DEF(garbage)
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
var/start_time = world.time
var/start_tick = world.tick_usage
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
if(world.time != start_time)
I.slept_destroy++
else
+6 -5
View File
@@ -575,7 +575,7 @@ SUBSYSTEM_DEF(job)
///////////////////////////////////
/datum/controller/subsystem/job/proc/get_living_heads()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
for(var/mob/living/carbon/human/player in GLOB.alive_mob_list)
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.command_positions))
. |= player.mind
@@ -585,7 +585,8 @@ SUBSYSTEM_DEF(job)
////////////////////////////
/datum/controller/subsystem/job/proc/get_all_heads()
. = list()
for(var/mob/player in GLOB.mob_list)
for(var/i in GLOB.mob_list)
var/mob/player = i
if(player.mind && (player.mind.assigned_role in GLOB.command_positions))
. |= player.mind
@@ -594,7 +595,7 @@ SUBSYSTEM_DEF(job)
//////////////////////////////////////////////
/datum/controller/subsystem/job/proc/get_living_sec()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
for(var/mob/living/carbon/human/player in GLOB.carbon_list)
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
@@ -603,6 +604,6 @@ SUBSYSTEM_DEF(job)
////////////////////////////////////////
/datum/controller/subsystem/job/proc/get_all_sec()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
for(var/mob/living/carbon/human/player in GLOB.carbon_list)
if(player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
. |= player.mind
+3 -1
View File
@@ -18,6 +18,8 @@ SUBSYSTEM_DEF(mapping)
var/list/shuttle_templates = list()
var/list/shelter_templates = list()
var/list/areas_in_z = list()
var/loading_ruins = FALSE
/datum/controller/subsystem/mapping/PreInit()
@@ -124,7 +126,7 @@ SUBSYSTEM_DEF(mapping)
query_round_map_name.Execute()
if(config.minetype != "lavaland")
INIT_ANNOUNCE("WARNING: A map without lavaland set as it's minetype was loaded! This is being ignored! Update the maploader code!")
INIT_ANNOUNCE("WARNING: A map without lavaland set as its minetype was loaded! This is being ignored! Update the maploader code!")
CreateSpace(ZLEVEL_SPACEMAX)
+5 -3
View File
@@ -7,13 +7,15 @@ SUBSYSTEM_DEF(mobs)
var/list/currentrun = list()
/datum/controller/subsystem/mobs/stat_entry()
..("P:[GLOB.mob_list.len]")
..("P:[GLOB.mob_living_list.len]")
/datum/controller/subsystem/mobs/fire(resumed = 0)
var/seconds = wait * 0.1
if (!resumed)
src.currentrun = GLOB.mob_list.Copy()
src.currentrun = GLOB.mob_living_list.Copy()
if (GLOB.overminds.len) // blob cameras need to Life()
src.currentrun += GLOB.overminds
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
@@ -24,6 +26,6 @@ SUBSYSTEM_DEF(mobs)
if(M)
M.Life(seconds, times_fired)
else
GLOB.mob_list.Remove(M)
GLOB.mob_living_list.Remove(M)
if (MC_TICK_CHECK)
return
@@ -1,4 +1,4 @@
PROCESSING_SUBSYSTEM_DEF(overlays)
SUBSYSTEM_DEF(overlays)
name = "Overlay"
flags = SS_TICKER
wait = 1
@@ -6,62 +6,63 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
init_order = INIT_ORDER_OVERLAY
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_SETUP
stat_tag = "Ov"
currentrun = null
var/list/queue
var/list/stats
var/list/overlay_icon_state_caches
var/list/overlay_icon_cache
var/initialized = FALSE
/datum/controller/subsystem/processing/overlays/PreInit()
LAZYINITLIST(overlay_icon_state_caches)
LAZYINITLIST(overlay_icon_cache)
/datum/controller/subsystem/overlays/PreInit()
overlay_icon_state_caches = list()
overlay_icon_cache = list()
queue = list()
stats = list()
/datum/controller/subsystem/processing/overlays/Initialize()
/datum/controller/subsystem/overlays/Initialize()
initialized = TRUE
Flush()
fire(mc_check = FALSE)
..()
/datum/controller/subsystem/processing/overlays/Recover()
/datum/controller/subsystem/overlays/stat_entry()
..("Ov:[length(queue)]")
/datum/controller/subsystem/overlays/Shutdown()
text2file("[GLOB.log_directory]/overlay.log", render_stats(stats))
/datum/controller/subsystem/overlays/Recover()
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
overlay_icon_cache = SSoverlays.overlay_icon_cache
processing = SSoverlays.processing
queue = SSoverlays.queue
#define COMPILE_OVERLAYS(A)\
var/list/oo = A.our_overlays;\
var/list/po = A.priority_overlays;\
if(LAZYLEN(po)){\
if(LAZYLEN(oo)){\
A.overlays = oo + po;\
}\
else{\
A.overlays = po;\
}\
}\
else if(LAZYLEN(oo)){\
A.overlays = oo;\
}\
else{\
A.overlays.Cut();\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1
/datum/controller/subsystem/processing/overlays/fire(resumed = FALSE, mc_check = TRUE)
var/list/processing = src.processing
while(processing.len)
var/atom/thing = processing[processing.len]
processing.len--
/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
var/list/queue = src.queue
var/static/count = 0
if (count)
var/c = count
count = 0 //so if we runtime on the Cut, we don't try again.
queue.Cut(1,c+1)
for (var/thing in queue)
count++
if(thing)
COMPILE_OVERLAYS(thing)
STAT_START_STOPWATCH
var/atom/A = thing
COMPILE_OVERLAYS(A)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(stats, A.type)
if(mc_check)
if(MC_TICK_CHECK)
break
else
CHECK_TICK
/datum/controller/subsystem/processing/overlays/proc/Flush()
if(processing.len)
testing("Flushing [processing.len] overlays")
fire(mc_check = FALSE) //pair this thread up with the MC to get extra compile time
if (count)
queue.Cut(1,count+1)
count = 0
/proc/iconstate2appearance(icon, iconstate)
var/static/image/stringbro = new()
@@ -102,6 +103,10 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
else if(isicon(overlay))
new_overlays += icon2appearance(overlay)
else
if(isloc(overlay))
var/atom/A = overlay
if (A.flags_1 & OVERLAY_QUEUED_1)
COMPILE_OVERLAYS(A)
appearance_bro.appearance = overlay //this works for images and atoms too!
if(!ispath(overlay))
var/image/I = overlay
@@ -110,7 +115,7 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
return new_overlays
#define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1))
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.processing += src;
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src;
/atom/proc/cut_overlays(priority = FALSE)
var/list/cached_overlays = our_overlays
var/list/cached_priority = priority_overlays
+8 -8
View File
@@ -109,23 +109,23 @@ SUBSYSTEM_DEF(pai)
dat += "<p class=\"top\">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>"
dat += "<table>"
dat += "<tr class=\"d0\"><td>Name:</td><td>[candidate.name]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=name;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=[REF(src)];option=name;new=1;candidate=[REF(candidate)]'>\[Edit\]</a></td><td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td></tr>"
dat += "<tr class=\"d0\"><td>Description:</td><td>[candidate.description]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=desc;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=[REF(src)];option=desc;new=1;candidate=[REF(candidate)]'>\[Edit\]</a></td><td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td></tr>"
dat += "<tr class=\"d0\"><td>Preferred Role:</td><td>[candidate.role]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=role;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=[REF(src)];option=role;new=1;candidate=[REF(candidate)]'>\[Edit\]</a></td><td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td></tr>"
dat += "<tr class=\"d0\"><td>OOC Comments:</td><td>[candidate.comments]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=ooc;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=[REF(src)];option=ooc;new=1;candidate=[REF(candidate)]'>\[Edit\]</a></td><td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td></tr>"
dat += "</table>"
dat += "<br>"
dat += "<h3><a href='byond://?src=\ref[src];option=submit;new=1;candidate=\ref[candidate]'>Submit Personality</a></h3><br>"
dat += "<a href='byond://?src=\ref[src];option=save;new=1;candidate=\ref[candidate]'>Save Personality</a><br>"
dat += "<a href='byond://?src=\ref[src];option=load;new=1;candidate=\ref[candidate]'>Load Personality</a><br>"
dat += "<h3><a href='byond://?src=[REF(src)];option=submit;new=1;candidate=[REF(candidate)]'>Submit Personality</a></h3><br>"
dat += "<a href='byond://?src=[REF(src)];option=save;new=1;candidate=[REF(candidate)]'>Save Personality</a><br>"
dat += "<a href='byond://?src=[REF(src)];option=load;new=1;candidate=[REF(candidate)]'>Load Personality</a><br>"
M << browse(dat, "window=paiRecruit")
@@ -182,7 +182,7 @@ SUBSYSTEM_DEF(pai)
dat += "<tr class=\"d1\"><td>Description:</td><td>[c.description]</td></tr>"
dat += "<tr class=\"d0\"><td>Preferred Role:</td><td>[c.role]</td></tr>"
dat += "<tr class=\"d1\"><td>OOC Comments:</td><td>[c.comments]</td></tr>"
dat += "<tr class=\"d2\"><td><a href='byond://?src=\ref[src];download=1;candidate=\ref[c];device=\ref[p]'>\[Download [c.name]\]</a></td><td></td></tr>"
dat += "<tr class=\"d2\"><td><a href='byond://?src=[REF(src)];download=1;candidate=[REF(c)];device=[REF(p)]'>\[Download [c.name]\]</a></td><td></td></tr>"
dat += "</table>"
+1 -1
View File
@@ -73,7 +73,7 @@ SUBSYSTEM_DEF(persistence)
break
/datum/controller/subsystem/persistence/proc/LoadPoly()
for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.living_mob_list)
for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list)
twitterize(P.speech_buffer, "polytalk")
break //Who's been duping the bird?!
@@ -0,0 +1,70 @@
PROCESSING_SUBSYSTEM_DEF(circuit)
name = "Circuit"
stat_tag = "CIR"
init_order = INIT_ORDER_CIRCUIT
flags = NONE
var/cipherkey
var/list/all_exonet_connections = list() //Address = connection datum.
var/list/obj/machinery/exonet_node/all_exonet_nodes = list()
var/list/all_circuits = list() // Associative list of [circuit_name]:[circuit_path] pairs
var/list/circuit_fabricator_recipe_list = list() // Associative list of [category_name]:[list_of_circuit_paths] pairs
/datum/controller/subsystem/processing/circuit/Initialize(start_timeofday)
SScircuit.cipherkey = random_string(2000+rand(0,10), GLOB.alphabet)
circuits_init()
return ..()
/datum/controller/subsystem/processing/circuit/proc/circuits_init()
//Cached lists for free performance
var/list/all_circuits = src.all_circuits
var/list/circuit_fabricator_recipe_list = src.circuit_fabricator_recipe_list
for(var/path in typesof(/obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = path
var/name = initial(IC.name)
all_circuits[name] = IC // Populating the complete list
if(!(initial(IC.spawn_flags) & (IC_SPAWN_DEFAULT | IC_SPAWN_RESEARCH)))
continue
var/category = initial(IC.category_text)
if(!circuit_fabricator_recipe_list[category])
circuit_fabricator_recipe_list[category] = list()
var/list/category_list = circuit_fabricator_recipe_list[category]
category_list += IC // Populating the fabricator categories
circuit_fabricator_recipe_list["Assemblies"] = list(
/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone
//new /obj/item/weapon/implant/integrated_circuit,
//new /obj/item/device/assembly/electronic_assembly
)
circuit_fabricator_recipe_list["Tools"] = list(
/obj/item/device/integrated_electronics/wirer,
/obj/item/device/integrated_electronics/debugger,
/obj/item/device/integrated_electronics/analyzer
)
/datum/controller/subsystem/processing/circuit/proc/get_exonet_node()
for(var/i in 1 to all_exonet_nodes.len)
var/obj/machinery/exonet_node/E = all_exonet_nodes[i]
if(E.is_operating())
return E
/datum/controller/subsystem/processing/circuit/proc/get_exonet_address(addr)
return all_exonet_connections[addr]
// Proc: get_atom_from_address()
// Parameters: 1 (target_address - the desired address to find)
// Description: Searches an address for the atom it is attached for, otherwise returns null.
/datum/controller/subsystem/processing/circuit/proc/get_atom_from_address(var/target_address)
var/datum/exonet_protocol/exonet = SScircuit.get_exonet_address(target_address)
if(exonet)
return exonet.holder
+8 -31
View File
@@ -4,38 +4,15 @@ PROCESSING_SUBSYSTEM_DEF(radiation)
priority = 25
var/list/warned_atoms = list()
var/list/next_warn = list()
var/last_warn = 0
/datum/controller/subsystem/processing/radiation/proc/warn(datum/component/radioactive)
if(!radioactive || QDELETED(radioactive))
/datum/controller/subsystem/processing/radiation/proc/warn(datum/component/radioactive/contamination)
if(!contamination || QDELETED(contamination))
return
if(warned_atoms["\ref[radioactive.parent]"])
var/ref = REF(contamination.parent)
if(warned_atoms[ref])
return
var/atom/master = radioactive.parent
warned_atoms[ref] = TRUE
var/atom/master = contamination.parent
SSblackbox.add_details("contaminated", "[master.type]")
next_warn["\ref[master]"] = "\ref[radioactive]"
var/wait_time = max(0, 500-(world.time-last_warn))+20 // wait at least 20 ticks, longer if we just messaged
addtimer(CALLBACK(src, .proc/send_warn), wait_time, TIMER_UNIQUE | TIMER_OVERRIDE)
/datum/controller/subsystem/processing/radiation/proc/send_warn()
var/msg = "Atom(s) have become contaminated by radiation and are strong enough they could pass it on:"
var/still_alive = FALSE
var/list/next_warn = src.next_warn // It's free performance!
for(var/i in next_warn)
var/atom/parent = locate(i)
var/datum/component/radioactive/radioactive = locate(next_warn[i])
if(!parent || !istype(parent) || !radioactive || !istype(radioactive))
continue
if(!still_alive)
msg += "\n"
still_alive = TRUE
else
msg += ", "
msg += "[parent][ADMIN_VV(parent)]source:[radioactive.source]"
if(!still_alive)
return
warned_atoms += next_warn
src.next_warn = list()
last_warn = world.time
message_admins(msg)
var/msg = "has become contamintaed with enough radiation to contaminate other objects. || Source: [contamination.source] || Strength: [contamination.strength]"
master.investigate_log(msg, INVESTIGATE_RADIATION)
+27 -1
View File
@@ -28,7 +28,9 @@ SUBSYSTEM_DEF(shuttle)
var/emergencyCallAmount = 0 //how many times the escape shuttle was called
var/emergencyNoEscape
var/emergencyNoRecall = FALSE
var/list/hostileEnvironments = list()
var/list/hostileEnvironments = list() //Things blocking escape shuttle from leaving
var/list/tradeBlockade = list() //Things blocking cargo from leaving.
var/supplyBlocked = FALSE
//supply shuttle stuff
var/obj/docking_port/mobile/supply/supply
@@ -335,6 +337,30 @@ SUBSYSTEM_DEF(shuttle)
hostileEnvironments -= bad
checkHostileEnvironment()
/datum/controller/subsystem/shuttle/proc/registerTradeBlockade(datum/bad)
tradeBlockade[bad] = TRUE
checkTradeBlockade()
/datum/controller/subsystem/shuttle/proc/clearTradeBlockade(datum/bad)
tradeBlockade -= bad
checkTradeBlockade()
/datum/controller/subsystem/shuttle/proc/checkTradeBlockade()
for(var/datum/d in tradeBlockade)
if(!istype(d) || QDELETED(d))
tradeBlockade -= d
supplyBlocked = tradeBlockade.len
if(supplyBlocked && (supply.mode == SHUTTLE_IGNITING))
supply.mode = SHUTTLE_STRANDED
supply.timer = null
//Make all cargo consoles speak up
if(!supplyBlocked && (supply.mode == SHUTTLE_STRANDED))
supply.mode = SHUTTLE_DOCKED
//Make all cargo consoles speak up
/datum/controller/subsystem/shuttle/proc/checkHostileEnvironment()
for(var/datum/d in hostileEnvironments)
if(!istype(d) || QDELETED(d))
+9 -9
View File
@@ -30,8 +30,7 @@ SUBSYSTEM_DEF(ticker)
var/list/availablefactions = list() //list of factions with openings
var/list/scripture_states = list(SCRIPTURE_DRIVER = TRUE, \
SCRIPTURE_SCRIPT = FALSE, \
SCRIPTURE_APPLICATION = FALSE, \
SCRIPTURE_JUDGEMENT = FALSE) //list of clockcult scripture states for announcements
SCRIPTURE_APPLICATION = FALSE) //list of clockcult scripture states for announcements
var/delay_end = 0 //if set true, the round will not restart on it's own
@@ -194,6 +193,7 @@ SUBSYSTEM_DEF(ticker)
if(!setup())
//setup failed
current_state = GAME_STATE_STARTUP
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
Master.SetRunLevel(RUNLEVEL_LOBBY)
if(GAME_STATE_PLAYING)
@@ -282,8 +282,6 @@ SUBSYSTEM_DEF(ticker)
collect_minds()
equip_characters()
SSoverlays.Flush() //Flush the majority of the shit
GLOB.data_core.manifest()
transfer_characters() //transfer keys to the new mobs
@@ -316,7 +314,7 @@ SUBSYSTEM_DEF(ticker)
set waitfor = FALSE
mode.post_setup()
GLOB.start_state = new /datum/station_state()
GLOB.start_state.count(1)
GLOB.start_state.count()
//Cleanup some stuff
for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
//Deleting Startpoints but we need the ai point to AI-ize people later
@@ -419,7 +417,8 @@ SUBSYSTEM_DEF(ticker)
C.playtitlemusic(40)*/
//Player status report
for(var/mob/Player in GLOB.mob_list)
for(var/i in GLOB.mob_list)
var/mob/Player = i
if(Player.mind && !isnewplayer(Player))
if(Player.stat != DEAD && !isbrain(Player))
num_survivors++
@@ -465,7 +464,8 @@ SUBSYSTEM_DEF(ticker)
CHECK_TICK
//Silicon laws report
for (var/mob/living/silicon/ai/aiPlayer in GLOB.mob_list)
for (var/i in GLOB.ai_list)
var/mob/living/silicon/ai/aiPlayer = i
if (aiPlayer.stat != DEAD && aiPlayer.mind)
to_chat(world, "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws at the end of the round were:</b>")
aiPlayer.show_laws(1)
@@ -484,7 +484,7 @@ SUBSYSTEM_DEF(ticker)
CHECK_TICK
for (var/mob/living/silicon/robot/robo in GLOB.mob_list)
for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs)
if (!robo.connected_ai && robo.mind)
if (robo.stat != DEAD)
to_chat(world, "<b>[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:</b>")
@@ -615,7 +615,7 @@ SUBSYSTEM_DEF(ticker)
if(5) //every 5 ticks check if there is a slot available
if(living_player_count() < hpc)
if(next_in_line && next_in_line.client)
to_chat(next_in_line, "<span class='userdanger'>A slot has opened! You have approximately 20 seconds to join. <a href='?src=\ref[next_in_line];late_join=override'>\>\>Join Game\<\<</a></span>")
to_chat(next_in_line, "<span class='userdanger'>A slot has opened! You have approximately 20 seconds to join. <a href='?src=[REF(next_in_line)];late_join=override'>\>\>Join Game\<\<</a></span>")
SEND_SOUND(next_in_line, sound('sound/misc/notice1.ogg'))
next_in_line.LateChoices()
return
+7 -7
View File
@@ -243,7 +243,7 @@ SUBSYSTEM_DEF(timer)
while(SStimer.timer_id_dict["timerid" + num2text(id, 8)])
SStimer.timer_id_dict["timerid" + num2text(id, 8)] = src
name = "Timer: " + num2text(id, 8) + ", TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
name = "Timer: " + num2text(id, 8) + ", TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: [REF(callBack)], callBack.object: [callBack.object][REF(callBack.object)]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
if (spent)
CRASH("HOLY JESUS. WHAT IS THAT? WHAT THE FUCK IS THAT?")
@@ -259,11 +259,11 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/Last = ctts[cttl]
if(Last.timeToRun >= timeToRun)
ctts += src
else if(cttl > 1)
for(var/I in cttl to 1)
var/datum/timedevent/E = ctts[I]
else
for(var/i in cttl to 1 step -1)
var/datum/timedevent/E = ctts[i]
if(E.timeToRun <= timeToRun)
ctts.Insert(src, I)
ctts.Insert(i, src)
break
else
ctts += src
@@ -362,9 +362,9 @@ SUBSYSTEM_DEF(timer)
if (flags & TIMER_UNIQUE)
var/list/hashlist
if(flags & TIMER_NO_HASH_WAIT)
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, flags & TIMER_CLIENT_TIME)
hashlist = list(callback.object, "([REF(callback.object)])", callback.delegate, flags & TIMER_CLIENT_TIME)
else
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
hashlist = list(callback.object, "([REF(callback.object)])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
hashlist += callback.arguments
hash = hashlist.Join("|||||||")
+9 -9
View File
@@ -199,7 +199,7 @@ SUBSYSTEM_DEF(vote)
text += "\n[question]"
log_vote(text)
var/vp = CONFIG_GET(number/vote_period)
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [DisplayTimeText(vp)] to vote.</font>")
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=[REF(src)]'>here</a> to place your votes.\nYou have [DisplayTimeText(vp)] to vote.</font>")
time_remaining = round(vp/10)
for(var/c in GLOB.clients)
var/client/C = c
@@ -232,36 +232,36 @@ SUBSYSTEM_DEF(vote)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</li>"
. += "<li><a href='?src=[REF(src)];vote=[i]'>[choices[i]]</a> ([votes] votes)</li>"
. += "</ul><hr>"
if(admin)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
. += "(<a href='?src=[REF(src)];vote=cancel'>Cancel Vote</a>) "
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
//restart
var/avr = CONFIG_GET(flag/allow_vote_restart)
if(trialmin || avr)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
. += "<a href='?src=[REF(src)];vote=restart'>Restart</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[avr ? "Allowed" : "Disallowed"]</a>)"
. += "\t(<a href='?src=[REF(src)];vote=toggle_restart'>[avr ? "Allowed" : "Disallowed"]</a>)"
. += "</li><li>"
//gamemode
var/avm = CONFIG_GET(flag/allow_vote_mode)
if(trialmin || avm)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
. += "<a href='?src=[REF(src)];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[avm ? "Allowed" : "Disallowed"]</a>)"
. += "\t(<a href='?src=[REF(src)];vote=toggle_gamemode'>[avm ? "Allowed" : "Disallowed"]</a>)"
. += "</li>"
//custom
if(trialmin)
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
. += "<li><a href='?src=[REF(src)];vote=custom'>Custom</a></li>"
. += "</ul><hr>"
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a>"
. += "<a href='?src=[REF(src)];vote=close' style='position:absolute;right:50px'>Close</a>"
return .
+2 -1
View File
@@ -13,7 +13,8 @@ SUBSYSTEM_DEF(weather)
var/datum/weather/W = V
if(W.aesthetic)
continue
for(var/mob/living/L in GLOB.mob_list)
for(var/i in GLOB.mob_living_list)
var/mob/living/L = i
if(W.can_weather_act(L))
W.weather_act(L)
for(var/Z in eligible_zlevels)
+113
View File
@@ -0,0 +1,113 @@
/*
Exonet Protocol Version 2
This is designed to be a fairly simple fake-networking system, allowing you to send and receive messages
between the exonet_protocol datums, and for atoms to react to those messages, based on the contents of the message.
Hopefully, this can evolve to be a more robust fake-networking system and allow for some devious network hacking in the future.
Version 1 never existed.
*Setting up*
To set up the exonet link, define a variable on your desired atom it is like this;
var/datum/exonet_protocol/exonet = null
Afterwards, before you want to do networking, call exonet = New(src), then exonet.make_address(string), and give it a string to hash into the new IP.
The reason it needs a string is so you can have the addresses be persistant, assuming no-one already took it first.
When you're no longer wanting to use the address and want to free it up, like when you want to Destroy() it, you need to call remove_address()
Destroy() also automatically calls remove_address().
*Sending messages*
To send a message to another datum, you need to know it's EPv2 (fake IP) address. Once you know that, call send_message(), place your
intended address in the first argument, then the message in the second. For example, send_message(exonet.address, "ping") will make you
ping yourself.
*Receiving messages*
You don't need to do anything special to receive the messages, other than give your target exonet datum an address as well. Once something hits
your datum with send_message(), receive_message() is called, and the default action is to call receive_exonet_message() on the datum's holder.
You'll want to override receive_exonet_message() on your atom, and define what will occur when the message is received.
The receiving atom will receive the origin atom (the atom that sent the message), the origin address, and finally the message itself.
It's suggested to start with an if or switch statement for the message, to determine what to do.
*/
/datum/exonet_protocol
var/address = "" //Resembles IPv6, but with only five 'groups', e.g. XXXX:XXXX:XXXX:XXXX:XXXX
var/atom/holder
/datum/exonet_protocol/New(var/atom/H)
holder = H
/datum/exonet_protocol/Destroy()
remove_address()
holder = null
return ..()
// Proc: make_address()
// Parameters: 1 (string - used to make into a hash that will be part of the new address)
// Description: Allocates a new address based on the string supplied. It results in consistant addresses for each round assuming it is not already taken..
/datum/exonet_protocol/proc/make_address(var/string)
if(!string)
return
var/hex = copytext(md5(string),1,25)
if(!hex)
return
var/addr_1 = copytext(hex,1,5)
var/addr_2 = copytext(hex,5,9)
var/addr_3 = copytext(hex,9,13)
var/addr_4 = copytext(hex,13,17)
address = "fc00:[addr_1]:[addr_2]:[addr_3]:[addr_4]"
if(SScircuit.all_exonet_connections[address])
stack_trace("WARNING: Exonet address collision in make_address. Holder type if applicable is [holder? holder.type : "NO HOLDER"]!")
SScircuit.all_exonet_connections[address] = src
// Proc: make_arbitrary_address()
// Parameters: 1 (new_address - the desired address)
// Description: Allocates that specific address, if it is available.
/datum/exonet_protocol/proc/make_arbitrary_address(var/new_address)
if(new_address)
if(new_address == SScircuit.get_exonet_address(new_address) ) //Collision test.
return FALSE
address = new_address
SScircuit.all_exonet_connections[address] = src
return TRUE
// Proc: remove_address()
// Parameters: None
// Description: Deallocates the address, freeing it for use.
/datum/exonet_protocol/proc/remove_address()
SScircuit.all_exonet_connections -= address
address = ""
// Proc: send_message()
// Parameters: 3 (target_address - the desired address to send the message to, data_type - text stating what the content is meant to be used for,
// content - the actual 'message' being sent to the address)
// Description: Sends the message to target_address, by calling receive_message() on the desired datum. Returns true if the message is recieved.
/datum/exonet_protocol/proc/send_message(var/target_address, var/data_type, var/content)
if(!address)
return FALSE
var/obj/machinery/exonet_node/node = SScircuit.get_exonet_node()
if(!node) // Telecomms went boom, ion storm, etc.
return FALSE
var/datum/exonet_protocol/exonet = SScircuit.get_exonet_address(target_address)
if(exonet)
node.write_log(address, target_address, data_type, content)
return exonet.receive_message(holder, address, data_type, content)
// Proc: receive_message()
// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from,
// data_type - text stating what the content is meant to be used for, content - the actual 'message' being sent from origin_atom)
// Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom.
/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/data_type, var/content)
holder.receive_exonet_message(origin_atom, origin_address, data_type, content)
return TRUE // for send_message()
// Proc: receive_exonet_message()
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
// Description: Override this to make your atom do something when a message is received.
/atom/proc/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
return
+483
View File
@@ -0,0 +1,483 @@
#define LING_FAKEDEATH_TIME 400 //40 seconds
#define LING_DEAD_GENETICDAMAGE_HEAL_CAP 50 //The lowest value of geneticdamage handle_changeling() can take it to while dead.
#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
/datum/antagonist/changeling
name = "Changeling"
job_rank = ROLE_CHANGELING
var/you_are_greet = TRUE
var/give_objectives = TRUE
var/list/objectives = list()
var/team_mode = FALSE //Should assign team objectives ?
//Changeling Stuff
var/list/stored_profiles = list() //list of datum/changelingprofile
var/datum/changelingprofile/first_prof = null
//var/list/absorbed_dna = list()
//var/list/protected_dna = list() //dna that is not lost when capacity is otherwise full
var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation.
var/absorbedcount = 0
var/chem_charges = 20
var/chem_storage = 75
var/chem_recharge_rate = 1
var/chem_recharge_slowdown = 0
var/sting_range = 2
var/changelingID = "Changeling"
var/geneticdamage = 0
var/isabsorbing = 0
var/islinking = 0
var/geneticpoints = 10
var/purchasedpowers = list()
var/mimicing = ""
var/canrespec = 0
var/changeling_speak = 0
var/datum/dna/chosen_dna
var/obj/effect/proc_holder/changeling/sting/chosen_sting
var/datum/cellular_emporium/cellular_emporium
var/datum/action/innate/cellular_emporium/emporium_action
// wip stuff
var/static/list/all_powers = typecacheof(/obj/effect/proc_holder/changeling,TRUE)
/datum/antagonist/changeling/New()
. = ..()
generate_name()
create_actions()
/datum/antagonist/changeling/Destroy()
QDEL_NULL(cellular_emporium)
QDEL_NULL(emporium_action)
. = ..()
/datum/antagonist/changeling/proc/generate_name()
var/honorific
if(owner.current.gender == FEMALE)
honorific = "Ms."
else
honorific = "Mr."
if(GLOB.possible_changeling_IDs.len)
changelingID = pick(GLOB.possible_changeling_IDs)
GLOB.possible_changeling_IDs -= changelingID
changelingID = "[honorific] [changelingID]"
else
changelingID = "[honorific] [rand(1,999)]"
/datum/antagonist/changeling/proc/create_actions()
cellular_emporium = new(src)
emporium_action = new(cellular_emporium)
/datum/antagonist/changeling/on_gain()
reset_powers()
create_initial_profile()
if(give_objectives)
if(team_mode)
forge_team_objectives()
forge_objectives()
remove_clownmut()
. = ..()
/datum/antagonist/changeling/on_removal()
remove_changeling_powers(FALSE)
owner.objectives -= objectives
. = ..()
/datum/antagonist/changeling/proc/remove_clownmut()
if (owner)
var/mob/living/carbon/human/H = owner.current
if(istype(H) && owner.assigned_role == "Clown")
to_chat(H, "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself.")
H.dna.remove_mutation(CLOWNMUT)
/datum/antagonist/changeling/proc/reset_properties()
changeling_speak = 0
chosen_sting = null
geneticpoints = initial(geneticpoints)
sting_range = initial(sting_range)
chem_storage = initial(chem_storage)
chem_recharge_rate = initial(chem_recharge_rate)
chem_charges = min(chem_charges, chem_storage)
chem_recharge_slowdown = initial(chem_recharge_slowdown)
mimicing = ""
/datum/antagonist/changeling/proc/remove_changeling_powers(keep_free_powers=0)
if(ishuman(owner.current) || ismonkey(owner.current))
reset_properties()
for(var/obj/effect/proc_holder/changeling/p in purchasedpowers)
if((p.dna_cost == 0 && keep_free_powers) || p.always_keep)
continue
purchasedpowers -= p
p.on_refund(owner.current)
//MOVE THIS
if(owner.current.hud_used)
owner.current.hud_used.lingstingdisplay.icon_state = null
owner.current.hud_used.lingstingdisplay.invisibility = INVISIBILITY_ABSTRACT
/datum/antagonist/changeling/proc/reset_powers()
if(purchasedpowers)
remove_changeling_powers(TRUE)
//Purchase free powers.
for(var/path in all_powers)
var/obj/effect/proc_holder/changeling/S = new path()
if(!S.dna_cost)
if(!has_sting(S))
purchasedpowers+=S
S.on_purchase(owner.current,TRUE)
/datum/antagonist/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power)
for(var/obj/effect/proc_holder/changeling/P in purchasedpowers)
if(initial(power.name) == P.name)
return TRUE
return FALSE
/datum/antagonist/changeling/proc/purchase_power(sting_name)
var/obj/effect/proc_holder/changeling/thepower = null
for(var/path in all_powers)
var/obj/effect/proc_holder/changeling/S = path
if(initial(S.name) == sting_name)
thepower = new path()
break
if(!thepower)
to_chat(owner.current, "This is awkward. Changeling power purchase failed, please report this bug to a coder!")
return
if(absorbedcount < thepower.req_dna)
to_chat(owner.current, "We lack the energy to evolve this ability!")
return
if(has_sting(thepower))
to_chat(owner.current, "We have already evolved this ability!")
return
if(thepower.dna_cost < 0)
to_chat(owner.current, "We cannot evolve this ability.")
return
if(geneticpoints < thepower.dna_cost)
to_chat(owner.current, "We have reached our capacity for abilities.")
return
if(owner.current.status_flags & FAKEDEATH)//To avoid potential exploits by buying new powers while in stasis, which clears your verblist.
to_chat(owner.current, "We lack the energy to evolve new abilities right now.")
return
geneticpoints -= thepower.dna_cost
purchasedpowers += thepower
thepower.on_purchase(owner.current)
/datum/antagonist/changeling/proc/readapt()
if(!ishuman(owner.current))
to_chat(owner.current, "<span class='danger'>We can't remove our evolutions in this form!</span>")
return
if(canrespec)
to_chat(owner.current, "<span class='notice'>We have removed our evolutions from this form, and are now ready to readapt.</span>")
reset_powers()
canrespec = 0
SSblackbox.add_details("changeling_power_purchase","Readapt")
return 1
else
to_chat(owner.current, "<span class='danger'>You lack the power to readapt your evolutions!</span>")
return 0
//Called in life()
/datum/antagonist/changeling/proc/regenerate()
var/mob/living/carbon/the_ling = owner.current
if(istype(the_ling))
emporium_action.Grant(the_ling)
if(the_ling.stat == DEAD)
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), (chem_storage*0.5))
geneticdamage = max(LING_DEAD_GENETICDAMAGE_HEAL_CAP,geneticdamage-1)
else //not dead? no chem/geneticdamage caps.
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
geneticdamage = max(0, geneticdamage-1)
/datum/antagonist/changeling/proc/get_dna(dna_owner)
for(var/datum/changelingprofile/prof in stored_profiles)
if(dna_owner == prof.name)
return prof
/datum/antagonist/changeling/proc/has_dna(datum/dna/tDNA)
for(var/datum/changelingprofile/prof in stored_profiles)
if(tDNA.is_same_as(prof.dna))
return TRUE
return FALSE
/datum/antagonist/changeling/proc/can_absorb_dna(mob/living/carbon/human/target, var/verbose=1)
var/mob/living/carbon/user = owner.current
if(!istype(user))
return
if(stored_profiles.len)
var/datum/changelingprofile/prof = stored_profiles[1]
if(prof.dna == user.dna && stored_profiles.len >= dna_max)//If our current DNA is the stalest, we gotta ditch it.
if(verbose)
to_chat(user, "<span class='warning'>We have reached our capacity to store genetic information! We must transform before absorbing more.</span>")
return
if(!target)
return
if(NO_DNA_COPY in target.dna.species.species_traits)
if(verbose)
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
return
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
if(verbose)
to_chat(user, "<span class='warning'>DNA of [target] is ruined beyond usability!</span>")
return
if(!ishuman(target))//Absorbing monkeys is entirely possible, but it can cause issues with transforming. That's what lesser form is for anyway!
if(verbose)
to_chat(user, "<span class='warning'>We could gain no benefit from absorbing a lesser creature.</span>")
return
if(has_dna(target.dna))
if(verbose)
to_chat(user, "<span class='warning'>We already have this DNA in storage!</span>")
return
if(!target.has_dna())
if(verbose)
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
return
return 1
/datum/antagonist/changeling/proc/create_profile(mob/living/carbon/human/H, protect = 0)
var/datum/changelingprofile/prof = new
H.dna.real_name = H.real_name //Set this again, just to be sure that it's properly set.
var/datum/dna/new_dna = new H.dna.type
H.dna.copy_dna(new_dna)
prof.dna = new_dna
prof.name = H.real_name
prof.protected = protect
prof.underwear = H.underwear
prof.undershirt = H.undershirt
prof.socks = H.socks
var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")
for(var/slot in slots)
if(slot in H.vars)
var/obj/item/I = H.vars[slot]
if(!I)
continue
prof.name_list[slot] = I.name
prof.appearance_list[slot] = I.appearance
prof.flags_cover_list[slot] = I.flags_cover
prof.item_color_list[slot] = I.item_color
prof.item_state_list[slot] = I.item_state
prof.exists_list[slot] = 1
else
continue
return prof
/datum/antagonist/changeling/proc/add_profile(datum/changelingprofile/prof)
if(stored_profiles.len > dna_max)
if(!push_out_profile())
return
if(!first_prof)
first_prof = prof
stored_profiles += prof
absorbedcount++
/datum/antagonist/changeling/proc/add_new_profile(mob/living/carbon/human/H, protect = 0)
var/datum/changelingprofile/prof = create_profile(H, protect)
add_profile(prof)
return prof
/datum/antagonist/changeling/proc/remove_profile(mob/living/carbon/human/H, force = 0)
for(var/datum/changelingprofile/prof in stored_profiles)
if(H.real_name == prof.name)
if(prof.protected && !force)
continue
stored_profiles -= prof
qdel(prof)
/datum/antagonist/changeling/proc/get_profile_to_remove()
for(var/datum/changelingprofile/prof in stored_profiles)
if(!prof.protected)
return prof
/datum/antagonist/changeling/proc/push_out_profile()
var/datum/changelingprofile/removeprofile = get_profile_to_remove()
if(removeprofile)
stored_profiles -= removeprofile
return 1
return 0
/datum/antagonist/changeling/proc/create_initial_profile()
var/mob/living/carbon/C = owner.current //only carbons have dna now, so we have to typecaste
if(ishuman(C))
add_new_profile(C)
/datum/antagonist/changeling/apply_innate_effects()
//Brains optional.
var/mob/living/carbon/C = owner.current
if(istype(C))
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
if(B)
B.vital = FALSE
B.decoy_override = TRUE
update_changeling_icons_added()
return
/datum/antagonist/changeling/remove_innate_effects()
update_changeling_icons_removed()
return
/datum/antagonist/changeling/greet()
if (you_are_greet)
to_chat(owner.current, "<span class='boldannounce'>You are [changelingID], a changeling! You have absorbed and taken the form of a human.</span>")
to_chat(owner.current, "<span class='boldannounce'>Use say \":g message\" to communicate with your fellow changelings.</span>")
to_chat(owner.current, "<b>You must complete the following tasks:</b>")
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ling_aler.ogg', 100, FALSE, pressure_affected = FALSE)
owner.announce_objectives()
/datum/antagonist/changeling/proc/forge_team_objectives()
if(GLOB.changeling_team_objective_type)
var/datum/objective/changeling_team_objective/team_objective = new GLOB.changeling_team_objective_type
team_objective.owner = owner
objectives += team_objective
return
/datum/antagonist/changeling/proc/forge_objectives()
//OBJECTIVES - random traitor objectives. Unique objectives "steal brain" and "identity theft".
//No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting
//If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone
var/escape_objective_possible = TRUE
//if there's a team objective, check if it's compatible with escape objectives
for(var/datum/objective/changeling_team_objective/CTO in objectives)
if(!CTO.escape_objective_compatible)
escape_objective_possible = FALSE
break
var/datum/objective/absorb/absorb_objective = new
absorb_objective.owner = owner
absorb_objective.gen_amount_goal(6, 8)
objectives += absorb_objective
if(prob(60))
if(prob(85))
var/datum/objective/steal/steal_objective = new
steal_objective.owner = owner
steal_objective.find_target()
objectives += steal_objective
else
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
objectives += download_objective
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = owner
destroy_objective.find_target()
objectives += destroy_objective
else
if(prob(70))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
if(team_mode) //No backstabbing while in a team
kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
kill_objective.find_target()
objectives += kill_objective
else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = owner
if(team_mode)
maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
maroon_objective.find_target()
objectives += maroon_objective
if (!(locate(/datum/objective/escape) in objectives) && escape_objective_possible)
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = owner
identity_theft.target = maroon_objective.target
identity_theft.update_explanation_text()
objectives += identity_theft
escape_objective_possible = FALSE
if (!(locate(/datum/objective/escape) in objectives) && escape_objective_possible)
if(prob(50))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
objectives += escape_objective
else
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = owner
if(team_mode)
identity_theft.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
identity_theft.find_target()
objectives += identity_theft
escape_objective_possible = FALSE
owner.objectives |= objectives
/datum/antagonist/changeling/proc/update_changeling_icons_added()
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
hud.join_hud(owner.current)
set_antag_hud(owner.current, "changling")
/datum/antagonist/changeling/proc/update_changeling_icons_removed()
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
hud.leave_hud(owner.current)
set_antag_hud(owner.current, null)
// Profile
/datum/changelingprofile
var/name = "a bug"
var/protected = 0
var/datum/dna/dna = null
var/list/name_list = list() //associative list of slotname = itemname
var/list/appearance_list = list()
var/list/flags_cover_list = list()
var/list/exists_list = list()
var/list/item_color_list = list()
var/list/item_state_list = list()
var/underwear
var/undershirt
var/socks
/datum/changelingprofile/Destroy()
qdel(dna)
. = ..()
/datum/changelingprofile/proc/copy_profile(datum/changelingprofile/newprofile)
newprofile.name = name
newprofile.protected = protected
newprofile.dna = new dna.type
dna.copy_dna(newprofile.dna)
newprofile.name_list = name_list.Copy()
newprofile.appearance_list = appearance_list.Copy()
newprofile.flags_cover_list = flags_cover_list.Copy()
newprofile.exists_list = exists_list.Copy()
newprofile.item_color_list = item_color_list.Copy()
newprofile.item_state_list = item_state_list.Copy()
newprofile.underwear = underwear
newprofile.undershirt = undershirt
newprofile.socks = socks
/datum/antagonist/changeling/xenobio
name = "Xenobio Changeling"
give_objectives = FALSE
you_are_greet = FALSE
+3 -3
View File
@@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(lawlorify, list (
BAN_CHAPEL = "This devil avoids holy ground.",
BAN_HURTPRIEST = "The annointed clergy appear to be immune to his powers.",
BAN_AVOIDWATER = "The devil seems to have some sort of aversion to water, though it does not appear to harm him.",
BAN_STRIKEUNCONCIOUS = "This devil only shows interest in those who are awake.",
BAN_STRIKEUNCONSCIOUS = "This devil only shows interest in those who are awake.",
BAN_HURTLIZARD = "This devil will not strike a lizardman first.",
BAN_HURTANIMAL = "This devil avoids hurting animals.",
BANISH_WATER = "To banish the devil, you must infuse its body with holy water.",
@@ -59,7 +59,7 @@ GLOBAL_LIST_INIT(lawlorify, list (
BAN_CHAPEL = "You must never attempt to enter the chapel.",
BAN_HURTPRIEST = "You must never attack a priest.",
BAN_AVOIDWATER = "You must never willingly touch a wet surface.",
BAN_STRIKEUNCONCIOUS = "You must never strike an unconscious person.",
BAN_STRIKEUNCONSCIOUS = "You must never strike an unconscious person.",
BAN_HURTLIZARD = "You must never harm a lizardman outside of self defense.",
BAN_HURTANIMAL = "You must never harm a non-sentient creature or robot outside of self defense.",
BANE_SILVER = "Silver, in all of its forms shall be your downfall.",
@@ -148,7 +148,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
return pick(OBLIGATION_FOOD, OBLIGATION_FIDDLE, OBLIGATION_DANCEOFF, OBLIGATION_GREET, OBLIGATION_PRESENCEKNOWN, OBLIGATION_SAYNAME, OBLIGATION_ANNOUNCEKILL, OBLIGATION_ANSWERTONAME)
/proc/randomdevilban()
return pick(BAN_HURTWOMAN, BAN_CHAPEL, BAN_HURTPRIEST, BAN_AVOIDWATER, BAN_STRIKEUNCONCIOUS, BAN_HURTLIZARD, BAN_HURTANIMAL)
return pick(BAN_HURTWOMAN, BAN_CHAPEL, BAN_HURTPRIEST, BAN_AVOIDWATER, BAN_STRIKEUNCONSCIOUS, BAN_HURTLIZARD, BAN_HURTANIMAL)
/proc/randomdevilbane()
return pick(BANE_SALT, BANE_LIGHT, BANE_IRON, BANE_WHITECLOTHES, BANE_SILVER, BANE_HARVEST, BANE_TOOLBOX)
+135
View File
@@ -0,0 +1,135 @@
/datum/antagonist/pirate
name = "Space Pirate"
job_rank = ROLE_TRAITOR
var/datum/objective_team/pirate/crew
/datum/antagonist/pirate/greet()
to_chat(owner, "<span class='boldannounce'>You are a Space Pirate!</span>")
to_chat(owner, "<B>The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot.</B>")
owner.announce_objectives()
/datum/antagonist/pirate/get_team()
return crew
/datum/antagonist/pirate/create_team(datum/objective_team/pirate/new_team)
if(!new_team)
for(var/datum/antagonist/pirate/P in GLOB.antagonists)
if(P.crew)
new_team = P.crew
if(!new_team)
crew = new /datum/objective_team/pirate
crew.forge_objectives()
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
crew = new_team
/datum/antagonist/pirate/on_gain()
if(crew)
owner.objectives |= crew.objectives
. = ..()
/datum/antagonist/pirate/on_removal()
if(crew)
owner.objectives -= crew.objectives
. = ..()
/datum/objective_team/pirate
name = "Pirate crew"
var/list/objectives = list()
/datum/objective_team/pirate/proc/forge_objectives()
var/datum/objective/loot/getbooty = new()
getbooty.team = src
getbooty.storage_area = locate(/area/shuttle/pirate/vault) in GLOB.sortedAreas
getbooty.update_initial_value()
getbooty.update_explanation_text()
objectives += getbooty
for(var/datum/mind/M in members)
M.objectives |= objectives
GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
/obj/structure/reagent_dispensers/beerkeg,
/mob/living/simple_animal/parrot,
/obj/item/stack/sheet/mineral/gold,
/obj/item/stack/sheet/mineral/diamond,
/obj/item/stack/spacecash,
/obj/item/melee/sabre,)))
/datum/objective/loot
var/area/storage_area //Place where we we will look for the loot.
explanation_text = "Acquire valuable loot and store it in designated area."
var/target_value = 50000
var/initial_value = 0 //Things in the vault at spawn time do not count
/datum/objective/loot/update_explanation_text()
if(storage_area)
explanation_text = "Acquire loot and store [target_value] of credits worth in [storage_area.name]."
/datum/objective/loot/proc/loot_listing()
//Lists notable loot.
if(!storage_area)
return "Nothing"
var/list/loot_table = list()
for(var/atom/movable/AM in storage_area.GetAllContents())
if(is_type_in_typecache(AM,GLOB.pirate_loot_cache))
var/lootname = AM.name
var/count = 1
if(istype(AM,/obj/item/stack)) //Ugh.
var/obj/item/stack/S = AM
lootname = S.singular_name
count = S.amount
if(!loot_table[lootname])
loot_table[lootname] = count
else
loot_table[lootname] += count
var/text = ""
for(var/key in loot_table)
var/amount = loot_table[key]
text += "[amount] [key][amount > 1 ? "s":""], "
return text
/datum/objective/loot/proc/get_loot_value()
if(!storage_area)
return 0
var/value = 0
for(var/turf/T in storage_area.contents)
value += export_item_and_contents(T,TRUE, TRUE, dry_run = TRUE)
return value - initial_value
/datum/objective/loot/proc/update_initial_value()
initial_value = get_loot_value()
/datum/objective/loot/check_completion()
return ..() || get_loot_value() >= target_value
//These need removal ASAP as everything is converted to datum antags.
/datum/game_mode/proc/auto_declare_completion_pirates()
var/list/datum/mind/pirates = get_antagonists(/datum/antagonist/pirate)
var/datum/objective_team/pirate/crew
var/text = ""
if(pirates.len)
text += "<br><b>Space Pirates were:</b>"
for(var/datum/mind/M in pirates)
text += printplayer(M)
if(!crew)
var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
crew = P.crew
if(crew)
text += "<br>Loot stolen: "
var/datum/objective/loot/L = locate() in crew.objectives
text += L.loot_listing()
text += "<br>Total loot value : [L.get_loot_value()]/[L.target_value] credits"
var/all_dead = TRUE
for(var/datum/mind/M in crew.members)
if(considered_alive(M))
all_dead = FALSE
break
if(L.check_completion() && !all_dead)
text += "<br><font color='green'><b>The pirate crew was successful!</b></font>"
else
text += "<br><span class='boldannounce'>The pirate crew has failed.</span>"
to_chat(world, text)
+4 -4
View File
@@ -132,13 +132,13 @@
var/output = {"<center><b>[Message]</b></center><br />
<div style="text-align:center">
<a style="font-size:large;float:[( Button2 ? "left" : "right" )]" href="?src=\ref[src];button=1">[Button1]</a>"}
<a style="font-size:large;float:[( Button2 ? "left" : "right" )]" href="?src=[REF(src)];button=1">[Button1]</a>"}
if (Button2)
output += {"<a style="font-size:large;[( Button3 ? "" : "float:right" )]" href="?src=\ref[src];button=2">[Button2]</a>"}
output += {"<a style="font-size:large;[( Button3 ? "" : "float:right" )]" href="?src=[REF(src)];button=2">[Button2]</a>"}
if (Button3)
output += {"<a style="font-size:large;float:right" href="?src=\ref[src];button=3">[Button3]</a>"}
output += {"<a style="font-size:large;float:right" href="?src=[REF(src)];button=3">[Button3]</a>"}
output += {"</div>"}
@@ -253,7 +253,7 @@
return
var/param = "null"
if(ref)
param = "\ref[ref]"
param = "[REF(ref)]"
winset(user, windowid, "on-close=\".windowclose [param]\"")
+3 -1
View File
@@ -87,9 +87,11 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
* Signals will not be recieved while this function is running
* Component may be deleted after this function completes without being attached
* Do not call `qdel(src)` from this function
1. `/datum/component/Destroy()` (virtual, no-sleep)
1. `/datum/component/Destroy(force(bool), silent(bool))` (virtual, no-sleep)
* Sends the `COMSIG_COMPONENT_REMOVING` signal to the parent datum if the `parent` isn't being qdeleted
* Properly removes the component from `parent` and cleans up references
* Setting `force` makes it not check for and remove the component from the parent
* Setting `silent` deletes the component without sending a `COMSIG_COMPONENT_REMOVING` signal
1. `/datum/component/proc/InheritComponent(datum/component/C, i_am_original(boolean))` (abstract, no-sleep)
* Called on a component when a component of the same type was added to the same parent
* See `/datum/component/var/dupe_mode`
+36 -22
View File
@@ -6,12 +6,15 @@
var/datum/parent
/datum/component/New(datum/P, ...)
if(type == /datum/component)
qdel(src)
CRASH("[type] instantiated!")
parent = P
var/list/arguments = args.Copy()
arguments.Cut(1, 2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
parent = null
qdel(src)
qdel(src, TRUE, TRUE)
return
_CheckDupesAndJoinParent(P)
@@ -32,13 +35,11 @@
switch(dm)
if(COMPONENT_DUPE_UNIQUE)
old.InheritComponent(src, TRUE)
parent = null //prevent COMPONENT_REMOVING signal, no _RemoveFromParent because we aren't in their list yet
qdel(src)
qdel(src, TRUE, TRUE)
return
if(COMPONENT_DUPE_HIGHLANDER)
InheritComponent(old, FALSE)
old._RemoveFromParent()
qdel(old)
qdel(old, FALSE, TRUE)
//provided we didn't eat someone
if(!old)
@@ -56,7 +57,7 @@
var/test = dc[I]
if(test) //already another component of this type here
var/list/components_of_type
if(!islist(test))
if(!length(test))
components_of_type = list(test)
dc[I] = components_of_type
else
@@ -79,22 +80,23 @@
/datum/component/proc/Initialize(...)
return
/datum/component/Destroy()
/datum/component/Destroy(force=FALSE, silent=FALSE)
enabled = FALSE
var/datum/P = parent
if(P)
if(!force)
_RemoveFromParent()
if(!silent)
P.SendSignal(COMSIG_COMPONENT_REMOVING, src)
parent = null
LAZYCLEARLIST(signal_procs)
return ..()
/datum/component/proc/_RemoveFromParent()
var/datum/P = parent
var/list/dc = P.datum_components
var/our_type = type
for(var/I in _GetInverseTypeList(our_type))
for(var/I in _GetInverseTypeList())
var/list/components_of_type = dc[I]
if(islist(components_of_type)) //
if(length(components_of_type)) //
var/list/subtracted = components_of_type - src
if(subtracted.len == 1) //only 1 guy left
dc[I] = subtracted[1] //make him special
@@ -104,9 +106,8 @@
dc -= I
if(!dc.len)
P.datum_components = null
parent = null
/datum/component/proc/RegisterSignal(sig_type_or_types, proc_on_self, override = FALSE)
/datum/component/proc/RegisterSignal(sig_type_or_types, proc_or_callback, override = FALSE)
if(QDELETED(src))
return
var/list/procs = signal_procs
@@ -120,8 +121,10 @@
. = procs[sig_type]
if(.)
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
procs[sig_type] = CALLBACK(src, proc_on_self)
if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now
proc_or_callback = CALLBACK(src, proc_or_callback)
procs[sig_type] = proc_or_callback
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
return
@@ -133,8 +136,19 @@
set waitfor = FALSE
return
/datum/component/proc/_GetInverseTypeList(current_type)
. = list(current_type)
/datum/component/proc/_GetInverseTypeList(our_type = type)
#if DM_VERSION >= 513
#warning 512 is definitely stable now, remove the old code
#endif
#if DM_VERSION < 512
//remove this when we use 512 full time
set invisibility = 101
#endif
//we can do this one simple trick
var/current_type = parent_type
. = list(our_type, current_type)
//and since most components are root level + 1, this won't even have to run
while (current_type != /datum/component)
current_type = type2parent(current_type)
. += current_type
@@ -146,7 +160,7 @@
var/list/arguments = args.Copy()
arguments.Cut(1, 2)
var/target = comps[/datum/component]
if(!islist(target))
if(!length(target))
var/datum/component/C = target
if(!C.enabled)
return FALSE
@@ -182,7 +196,7 @@
if(!dc)
return null
. = dc[c_type]
if(islist(.))
if(length(.))
return .[1]
/datum/proc/GetExactComponent(c_type)
@@ -191,7 +205,7 @@
return null
var/datum/component/C = dc[c_type]
if(C)
if(islist(C))
if(length(C))
C = C[1]
if(C.type == c_type)
return C
@@ -202,7 +216,7 @@
if(!dc)
return null
. = dc[c_type]
if(!islist(.))
if(!length(.))
return list(.)
/datum/proc/AddComponent(new_type, ...)
+60
View File
@@ -0,0 +1,60 @@
/datum/component/decal
dupe_mode = COMPONENT_DUPE_ALLOWED
var/cleanable
var/description
var/mutable_appearance/pic
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description)
if(!isatom(parent) || !_icon || !_icon_state)
. = COMPONENT_INCOMPATIBLE
CRASH("A turf decal was applied incorrectly to [parent.type]: icon:[_icon ? _icon : "none"] icon_state:[_icon_state ? _icon_state : "none"]")
// It has to be made from an image or dir breaks because of a byond bug
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
pic = new(temp_image)
pic.color = _color
cleanable = _cleanable
description = _description
apply()
if(_dir) // If no dir is assigned at start then it follows the atom's dir
RegisterSignal(COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
if(_cleanable)
RegisterSignal(COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
if(_description)
RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/examine)
/datum/component/decal/Destroy()
remove()
return ..()
/datum/component/decal/OnTransfer(atom/thing)
remove()
remove(thing)
apply(thing)
/datum/component/decal/proc/apply(atom/thing)
var/atom/master = thing || parent
master.add_overlay(pic, TRUE)
/datum/component/decal/proc/remove(atom/thing)
var/atom/master = thing || parent
master.cut_overlay(pic, TRUE)
/datum/component/decal/proc/rotate_react(old_dir, new_dir)
if(old_dir == new_dir)
return
remove()
var/rotation = SimplifyDegrees(dir2angle(new_dir)-dir2angle(old_dir))
pic.dir = turn(pic.dir, rotation)
apply()
/datum/component/decal/proc/clean_react(strength)
if(strength >= cleanable)
qdel(src)
/datum/component/decal/proc/examine(mob/user)
to_chat(user, description)
+9 -5
View File
@@ -37,11 +37,15 @@
return ..()
/datum/component/radioactive/process()
if(hl3_release_date && prob(50))
radiation_pulse(parent, strength, RAD_DISTANCE_COEFFICIENT*2, FALSE, can_contaminate)
strength -= strength / hl3_release_date
if(strength <= RAD_BACKGROUND_RADIATION)
qdel(src)
if(!prob(50))
return
radiation_pulse(parent, strength, RAD_DISTANCE_COEFFICIENT*2, FALSE, can_contaminate)
if(!hl3_release_date)
return
strength -= strength / hl3_release_date
if(strength <= RAD_BACKGROUND_RADIATION)
return PROCESS_KILL
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original)
if(!i_am_original)
@@ -0,0 +1,9 @@
/datum/component/redirect
dupe_mode = COMPONENT_DUPE_ALLOWED
/datum/component/redirect/Initialize(list/signals, datum/callback/_callback)
//It's not our job to verify the right signals are registered here, just do it.
if(!LAZYLEN(signals) || !istype(_callback))
. = COMPONENT_INCOMPATIBLE
CRASH("A redirection component was initialized with incorrect args.")
RegisterSignal(signals, _callback)
+51
View File
@@ -0,0 +1,51 @@
/datum/component/turf_decal
var/dir
var/icon
var/icon_state
var/layer
var/group
/datum/component/turf_decal/Initialize(_dir, _icon, _icon_state, _layer=TURF_DECAL_LAYER, _group=TURF_DECAL_PAINT)
if(!isturf(parent) || !_icon || !_icon_state)
WARNING("A turf decal was applied incorrectly to [parent]: icon:[_icon ? _icon : "none"] icon_state:[_icon_state ? _icon_state : "none"]")
return COMPONENT_INCOMPATIBLE
dir = _dir
icon = _icon
icon_state = _icon_state
layer = _layer
group = _group
apply_decal()
RegisterSignal(COMSIG_ATOM_ROTATE, .proc/rotate_react)
RegisterSignal(COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
/datum/component/turf_decal/Destroy()
remove_decal()
return ..()
/datum/component/turf_decal/OnTransfer(turf/newT)
remove_decal()
remove_decal(newT)
apply_decal(newT)
/datum/component/turf_decal/proc/get_decal()
return image(icon, null, icon_state, layer, dir)
/datum/component/turf_decal/proc/apply_decal(turf/overT)
var/turf/master = overT || parent
master.add_decal(get_decal(), group)
/datum/component/turf_decal/proc/remove_decal(turf/overT)
var/turf/master = overT || parent
master.remove_decal(group)
/datum/component/turf_decal/proc/rotate_react(rotation, params)
if(params & ROTATE_DIR)
dir = angle2dir(rotation+dir2angle(dir))
remove_decal()
apply_decal()
/datum/component/turf_decal/proc/clean_react(strength)
if(strength >= CLEAN_IMPRESSIVE)
qdel(src)
+7 -6
View File
@@ -3,6 +3,8 @@
var/list/active_timers //for SStimer
var/list/datum_components //for /datum/components
var/ui_screen = "home" //for tgui
var/use_tag = FALSE
var/datum/weakref/weak_reference
#ifdef TESTING
var/running_find_references
@@ -12,8 +14,9 @@
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
/datum/proc/Destroy(force=FALSE)
/datum/proc/Destroy(force=FALSE, ...)
tag = null
weak_reference = null //ensure prompt GCing of weakref.
var/list/timers = active_timers
active_timers = null
for(var/thing in timers)
@@ -24,14 +27,12 @@
var/list/dc = datum_components
if(dc)
var/all_components = dc[/datum/component]
if(islist(all_components))
if(length(all_components))
for(var/I in all_components)
var/datum/component/C = I
C._RemoveFromParent()
qdel(C)
qdel(C, FALSE, TRUE)
else
var/datum/component/C = all_components
C._RemoveFromParent()
qdel(C)
qdel(C, FALSE, TRUE)
dc.Cut()
return QDEL_HINT_QUEUE
+23 -18
View File
@@ -25,10 +25,10 @@
/datum/proc/vv_get_dropdown()
. = list()
. += "---"
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=\ref[src]"
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=\ref[src]"
.["Delete"] = "?_src_=vars;[HrefToken()];delete=\ref[src]"
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=\ref[src]"
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=[REF(src)]"
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=[REF(src)]"
.["Delete"] = "?_src_=vars;[HrefToken()];delete=[REF(src)]"
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=[REF(src)]"
/datum/proc/on_reagent_change()
@@ -53,7 +53,7 @@
return
var/title = ""
var/refid = "\ref[D]"
var/refid = REF(D)
var/icon/sprite
var/hash
@@ -71,7 +71,7 @@
hash = md5(hash + AT.icon_state)
src << browse_rsc(sprite, "vv[hash].png")
title = "[D] (\ref[D]) = [type]"
title = "[D] ([REF(D)]) = [type]"
var/sprite_text
if(sprite)
@@ -394,9 +394,9 @@
name = DA[name] //name is really the index until this line
else
value = DA[name]
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=\ref[DA];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=\ref[DA];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=\ref[DA];index=[index]'>-</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=[REF(DA)];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=[REF(DA)];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=[REF(DA)];index=[index]'>-</a>) "
else
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=[REF(DA)];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=[REF(DA)];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=[REF(DA)];varnamemass=[name]'>M</a>) "
else
header = "<li>"
@@ -411,7 +411,7 @@
#ifdef VARSICON
var/icon/I = new/icon(value)
var/rnd = rand(1,10000)
var/rname = "tmp\ref[I][rnd].png"
var/rname = "tmp[REF(I)][rnd].png"
usr << browse_rsc(I, rname)
item = "[VV_HTML_ENCODE(name)] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
#else
@@ -423,8 +423,8 @@
var/rnd = rand(1, 10000)
var/image/I = value
src << browse_rsc(I.icon, "tmp\ref[value][rnd].png")
html += "[name] = <img src=\"tmp\ref[value][rnd].png\">"
src << browse_rsc(I.icon, "tmp[REF(value)][rnd].png")
html += "[name] = <img src=\"tmp[REF(value)][rnd].png\">"
#else
html += "[name] = /image (<span class='value'>[value]</span>)"
#endif
@@ -434,14 +434,14 @@
//else if (istype(value, /client))
// var/client/C = value
// item = "<a href='?_src_=vars;Vars=\ref[value]'>[VV_HTML_ENCODE(name)] \ref[value]</a> = [C] [C.type]"
// item = "<a href='?_src_=vars;Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [C] [C.type]"
else if (istype(value, /datum))
var/datum/D = value
if ("[D]" != "[D.type]") //if the thing as a name var, lets use it.
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] \ref[value]</a> = [D] [D.type]"
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
else
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] \ref[value]</a> = [D.type]"
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
else if (islist(value))
var/list/L = value
@@ -453,15 +453,15 @@
var/val
if (IS_NORMAL_LIST(L) && !isnum(key))
val = L[key]
if (!val)
if (isnull(val)) // we still want to display non-null false values, such as 0 or ""
val = key
key = i
items += debug_variable(key, val, level + 1, sanitize = sanitize)
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
else
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
else
item = "[VV_HTML_ENCODE(name)] = <span class='value'>[VV_HTML_ENCODE(value)]</span>"
@@ -537,6 +537,11 @@
admin_delete(D)
href_list["datumrefresh"] = href_list["delete"]
else if(href_list["osay"])
if(!check_rights(R_FUN, 0))
return
usr.client.object_say(locate(href_list["osay"]))
else if(href_list["regenerateicons"])
if(!check_rights(0))
return
@@ -561,7 +566,7 @@
var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anything nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No")
if (prompt != "Yes" || !usr.client)
return
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=\ref[thing]'>VV window</a>")
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=[REF(thing)]'>VV window</a>")
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [thing]")
to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
C.debug_variables(thing)
+1 -1
View File
@@ -416,7 +416,7 @@
for(var/datum/disease/advance/AD in SSdisease.active_diseases)
AD.Refresh()
for(var/mob/living/carbon/human/H in shuffle(GLOB.living_mob_list))
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
if(!(H.z in GLOB.station_z_levels))
continue
if(!H.HasDisease(D))
+19 -17
View File
@@ -1,5 +1,6 @@
#define EXPLOSION_THROW_SPEED 4
#define REEBE_HUGBOX_COEFFICIENT 0.5
#define CITYOFCOGS_CAP_MULTIPLIER 0.5
#define MINING_CAP_MULTIPLIER 3
GLOBAL_LIST_EMPTY(explosions)
//Against my better judgement, I will return the explosion datum
@@ -53,21 +54,21 @@ GLOBAL_LIST_EMPTY(explosions)
var/orig_dev_range = devastation_range
var/orig_heavy_range = heavy_impact_range
var/orig_light_range = light_impact_range
if(!ignorecap && epicenter.z != ZLEVEL_MINING)
//Clamp all values to MAX_EXPLOSION_RANGE
devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE, devastation_range)
heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE, heavy_impact_range)
light_impact_range = min(GLOB.MAX_EX_LIGHT_RANGE, light_impact_range)
flash_range = min(GLOB.MAX_EX_FLASH_RANGE, flash_range)
flame_range = min(GLOB.MAX_EX_FLAME_RANGE, flame_range)
if(!ignorecap && epicenter.z == ZLEVEL_CITYOFCOGS)
devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE * REEBE_HUGBOX_COEFFICIENT, devastation_range)
heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE * REEBE_HUGBOX_COEFFICIENT, heavy_impact_range)
light_impact_range = min(GLOB.MAX_EX_LIGHT_RANGE * REEBE_HUGBOX_COEFFICIENT, light_impact_range)
flash_range = min(GLOB.MAX_EX_FLASH_RANGE * REEBE_HUGBOX_COEFFICIENT, flash_range)
flame_range = min(GLOB.MAX_EX_FLAME_RANGE * REEBE_HUGBOX_COEFFICIENT, flame_range)
//Zlevel specific bomb cap multiplier
var/cap_multiplier = 1
switch(epicenter.z)
if(ZLEVEL_CITYOFCOGS)
cap_multiplier = CITYOFCOGS_CAP_MULTIPLIER
if(ZLEVEL_MINING)
cap_multiplier = MINING_CAP_MULTIPLIER
if(!ignorecap)
devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, devastation_range)
heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, heavy_impact_range)
light_impact_range = min(GLOB.MAX_EX_LIGHT_RANGE * cap_multiplier, light_impact_range)
flash_range = min(GLOB.MAX_EX_FLASH_RANGE * cap_multiplier, flash_range)
flame_range = min(GLOB.MAX_EX_FLAME_RANGE * cap_multiplier, flame_range)
//DO NOT REMOVE THIS STOPLAG, IT BREAKS THINGS
//not sleeping causes us to ex_act() the thing that triggered the explosion
@@ -397,4 +398,5 @@ GLOBAL_LIST_EMPTY(explosions)
// 5 explosion power is a (0, 1, 3) explosion.
// 1 explosion power is a (0, 0, 1) explosion.
#undef REEBE_HUGBOX_COEFFICIENT
#undef CITYOFCOGS_CAP_MULTIPLIER
#undef MINING_CAP_MULTIPLIER
+3
View File
@@ -55,6 +55,9 @@
to_chat(src, "[prefix]<a href=\"[CONFIG_GET(string/githuburl)]/commit/[pc]\">[copytext(pc, 1, min(length(pc), 7))]</a>")
else
to_chat(src, "Revision unknown")
if(SERVER_TOOLS_PRESENT)
to_chat(src, "Server tools version: [SERVER_TOOLS_VERSION]")
to_chat(src, "Server tools API version: [SERVER_TOOLS_API_VERSION]")
to_chat(src, "<b>Current Informational Settings:</b>")
to_chat(src, "Protect Authority Roles From Traitor: [CONFIG_GET(flag/protect_roles_from_antagonist)]")
to_chat(src, "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]")
+3 -2
View File
@@ -152,13 +152,14 @@
if(istype(teleatom, /obj/item/storage/backpack/holding))
precision = rand(1,100)
var/list/bagholding = teleatom.search_contents_for(/obj/item/storage/backpack/holding)
var/static/list/bag_cache = typecacheof(/obj/item/storage/backpack/holding)
var/list/bagholding = typecache_filter_list(teleatom.GetAllContents(), bag_cache)
if(bagholding.len)
precision = max(rand(1,100)*bagholding.len,100)
if(isliving(teleatom))
var/mob/living/MM = teleatom
to_chat(MM, "<span class='warning'>The bluespace interface on your bag of holding interferes with the teleport!</span>")
return 1
return TRUE
// Safe location finder
+13 -10
View File
@@ -29,13 +29,12 @@ GLOBAL_LIST_INIT(huds, list(
var/list/hud_icons = list() //these will be the indexes for the atom's hud_list
/datum/atom_hud/proc/remove_hud_from(mob/M)
if(!M)
if(!M || !hudusers[M])
return
if(src in M.permanent_huds)
return
for(var/atom/A in hudatoms)
remove_from_single_hud(M, A)
hudusers -= M
if (!--hudusers[M])
hudusers -= M
for(var/atom/A in hudatoms)
remove_from_single_hud(M, A)
/datum/atom_hud/proc/remove_from_hud(atom/A)
if(!A)
@@ -54,9 +53,12 @@ GLOBAL_LIST_INIT(huds, list(
/datum/atom_hud/proc/add_hud_to(mob/M)
if(!M)
return
hudusers[M] = TRUE
for(var/atom/A in hudatoms)
add_to_single_hud(M, A)
if (!hudusers[M])
hudusers[M] = 1
for(var/atom/A in hudatoms)
add_to_single_hud(M, A)
else
hudusers[M]++
/datum/atom_hud/proc/add_to_hud(atom/A)
if(!A)
@@ -77,7 +79,8 @@ GLOBAL_LIST_INIT(huds, list(
/mob/proc/reload_huds()
for(var/datum/atom_hud/hud in (GLOB.huds|GLOB.active_alternate_appearances))
if(hud && hud.hudusers[src])
hud.add_hud_to(src)
for(var/atom/A in hud.hudatoms)
hud.add_to_single_hud(src, A)
/mob/dead/new_player/reload_huds()
return
+22 -1
View File
@@ -21,4 +21,25 @@
mid_sounds = list('sound/machines/generator/generator_mid1.ogg'=1, 'sound/machines/generator/generator_mid2.ogg'=1, 'sound/machines/generator/generator_mid3.ogg'=1)
mid_length = 4
end_sound = 'sound/machines/generator/generator_end.ogg'
volume = 40
volume = 40
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/deep_fryer
start_sound = 'sound/machines/fryer/deep_fryer_immerse.ogg' //my immersions
start_length = 10
mid_sounds = list('sound/machines/fryer/deep_fryer_1.ogg' = 1, 'sound/machines/fryer/deep_fryer_2.ogg' = 1)
mid_length = 2
end_sound = 'sound/machines/fryer/deep_fryer_emerge.ogg'
volume = 25
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/microwave
start_sound = 'sound/machines/microwave/microwave-start.ogg'
start_length = 10
mid_sounds = list('sound/machines/microwave/microwave-mid1.ogg'=10, 'sound/machines/microwave/microwave-mid2.ogg'=1)
mid_length = 10
end_sound = 'sound/machines/microwave/microwave-end.ogg'
volume = 90
+47
View File
@@ -0,0 +1,47 @@
/datum/looping_sound/active_outside_ashstorm
mid_sounds = list(
'sound/weather/ashstorm/outside/active_mid1.ogg'=1,
'sound/weather/ashstorm/outside/active_mid1.ogg'=1,
'sound/weather/ashstorm/outside/active_mid1.ogg'=1
)
mid_length = 80
start_sound = 'sound/weather/ashstorm/outside/active_start.ogg'
start_length = 130
end_sound = 'sound/weather/ashstorm/outside/active_end.ogg'
volume = 80
/datum/looping_sound/active_inside_ashstorm
mid_sounds = list(
'sound/weather/ashstorm/inside/active_mid1.ogg'=1,
'sound/weather/ashstorm/inside/active_mid2.ogg'=1,
'sound/weather/ashstorm/inside/active_mid3.ogg'=1
)
mid_length = 80
start_sound = 'sound/weather/ashstorm/inside/active_start.ogg'
start_length = 130
end_sound = 'sound/weather/ashstorm/inside/active_end.ogg'
volume = 80
/datum/looping_sound/weak_outside_ashstorm
mid_sounds = list(
'sound/weather/ashstorm/outside/weak_mid1.ogg'=1,
'sound/weather/ashstorm/outside/weak_mid2.ogg'=1,
'sound/weather/ashstorm/outside/weak_mid3.ogg'=1
)
mid_length = 80
start_sound = 'sound/weather/ashstorm/outside/weak_start.ogg'
start_length = 130
end_sound = 'sound/weather/ashstorm/outside/weak_end.ogg'
volume = 50
/datum/looping_sound/weak_inside_ashstorm
mid_sounds = list(
'sound/weather/ashstorm/inside/weak_mid1.ogg'=1,
'sound/weather/ashstorm/inside/weak_mid2.ogg'=1,
'sound/weather/ashstorm/inside/weak_mid3.ogg'=1
)
mid_length = 80
start_sound = 'sound/weather/ashstorm/inside/weak_start.ogg'
start_length = 130
end_sound = 'sound/weather/ashstorm/inside/weak_end.ogg'
volume = 50
+2 -2
View File
@@ -29,7 +29,7 @@
var/config_max_users = 0
var/config_min_users = 0
var/voteweight = 1
var/allow_custom_shuttles = "yes"
var/allow_custom_shuttles = TRUE
/datum/map_config/New(filename = "data/next_map.json", default_to_box, delete_after)
if(default_to_box)
@@ -69,7 +69,7 @@
map_file = json["map_file"]
minetype = json["minetype"] || minetype
allow_custom_shuttles = json["allow_custom_shuttles"] == TRUE
allow_custom_shuttles = json["allow_custom_shuttles"] != FALSE
var/jtcl = json["transition_config"]
if(jtcl && jtcl != "default")
+77 -91
View File
@@ -192,15 +192,10 @@
qdel(O)
/datum/mind/proc/remove_changeling()
if(src in SSticker.mode.changelings)
SSticker.mode.changelings -= src
current.remove_changeling_powers()
if(changeling)
qdel(changeling)
changeling = null
special_role = null
remove_antag_equip()
SSticker.mode.update_changeling_icons_removed(src)
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
if(C)
remove_antag_datum(/datum/antagonist/changeling)
special_role = null
/datum/mind/proc/remove_traitor()
if(src in SSticker.mode.traitors)
@@ -255,7 +250,6 @@
remove_wizard()
remove_cultist()
remove_rev()
SSticker.mode.update_changeling_icons_removed(src)
SSticker.mode.update_traitor_icons_removed(src)
SSticker.mode.update_cult_icons_removed(src)
@@ -388,7 +382,7 @@
var/out = "<B>[name]</B>[(current&&(current.real_name!=name))?" (as [current.real_name])":""]<br>"
out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]<br>"
out += "Assigned role: [assigned_role]. <a href='?src=\ref[src];role_edit=1'>Edit</a><br>"
out += "Assigned role: [assigned_role]. <a href='?src=[REF(src)];role_edit=1'>Edit</a><br>"
out += "Faction and special role: <b><font color='red'>[special_role]</font></b><br>"
var/list/sections = list(
@@ -412,11 +406,11 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if (src in SSticker.mode.traitors)
text += "<b>TRAITOR</b> | <a href='?src=\ref[src];traitor=clear'>loyal</a>"
text += "<b>TRAITOR</b> | <a href='?src=[REF(src)];traitor=clear'>loyal</a>"
if (objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=\ref[src];traitor=autoobjectives'>Randomize</a>!"
text += "<br>Objectives are empty! <a href='?src=[REF(src)];traitor=autoobjectives'>Randomize</a>!"
else
text += "<a href='?src=\ref[src];traitor=traitor'>traitor</a> | <b>LOYAL</b>"
text += "<a href='?src=[REF(src)];traitor=traitor'>traitor</a> | <b>LOYAL</b>"
if(current && current.client && (ROLE_TRAITOR in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -434,7 +428,7 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in SSticker.mode.brothers)
text += "<b>Brother</b> | <a href='?src=\ref[src];brother=clear'>no</a>"
text += "<b>Brother</b> | <a href='?src=[REF(src)];brother=clear'>no</a>"
if(current && current.client && (ROLE_BROTHER in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -448,20 +442,15 @@
if (SSticker.mode.config_tag=="changeling" || SSticker.mode.config_tag=="traitorchan")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if ((src in SSticker.mode.changelings) && special_role)
text += "<b>YES</b> | <a href='?src=\ref[src];changeling=clear'>no</a>"
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
if(C)
text += "<b>[C.name]</b> | <a href='?src=[REF(src)];changeling=clear'>No</a>"
if (objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=\ref[src];changeling=autoobjectives'>Randomize!</a>"
if(changeling && changeling.stored_profiles.len && (current.real_name != changeling.first_prof.name) )
text += "<br><a href='?src=\ref[src];changeling=initialdna'>Transform to initial appearance.</a>"
else if(src in SSticker.mode.changelings) //Station Aligned Changeling
text += "<b>YES (but not an antag)</b> | <a href='?src=\ref[src];changeling=clear'>no</a>"
if (objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=\ref[src];changeling=autoobjectives'>Randomize!</a>"
if(changeling && changeling.stored_profiles.len && (current.real_name != changeling.first_prof.name) )
text += "<br><a href='?src=\ref[src];changeling=initialdna'>Transform to initial appearance.</a>"
text += "<br>Objectives are empty! <a href='?src=[REF(src)];changeling=autoobjectives'>Randomize!</a>"
if(C.stored_profiles.len && (current.real_name != C.first_prof.name) )
text += "<br><a href='?src=[REF(src)];changeling=initialdna'>Transform to initial appearance.</a>"
else
text += "<a href='?src=\ref[src];changeling=changeling'>yes</a> | <b>NO</b>"
text += "<a href='?src=[REF(src)];changeling=changeling'>yes</a> | <b>NO</b>"
if(current && current.client && (ROLE_CHANGELING in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -477,7 +466,7 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if (ishuman(current))
text += "<a href='?src=\ref[src];monkey=healthy'>healthy</a> | <a href='?src=\ref[src];monkey=infected'>infected</a> | <b>HUMAN</b> | other"
text += "<a href='?src=[REF(src)];monkey=healthy'>healthy</a> | <a href='?src=[REF(src)];monkey=infected'>infected</a> | <b>HUMAN</b> | other"
else if(ismonkey(current))
var/found = FALSE
for(var/datum/disease/transformation/jungle_fever/JF in current.viruses)
@@ -485,9 +474,9 @@
break
if(found)
text += "<a href='?src=\ref[src];monkey=healthy'>healthy</a> | <b>INFECTED</b> | <a href='?src=\ref[src];monkey=human'>human</a> | other"
text += "<a href='?src=[REF(src)];monkey=healthy'>healthy</a> | <b>INFECTED</b> | <a href='?src=[REF(src)];monkey=human'>human</a> | other"
else
text += "<b>HEALTHY</b> | <a href='?src=\ref[src];monkey=infected'>infected</a> | <a href='?src=\ref[src];monkey=human'>human</a> | other"
text += "<b>HEALTHY</b> | <a href='?src=[REF(src)];monkey=infected'>infected</a> | <a href='?src=[REF(src)];monkey=human'>human</a> | other"
else
text += "healthy | infected | human | <b>OTHER</b>"
@@ -507,17 +496,17 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if (src in SSticker.mode.syndicates)
text += "<b>OPERATIVE</b> | <a href='?src=\ref[src];nuclear=clear'>nanotrasen</a>"
text += "<br><a href='?src=\ref[src];nuclear=lair'>To shuttle</a>, <a href='?src=\ref[src];common=undress'>undress</a>, <a href='?src=\ref[src];nuclear=dressup'>dress up</a>."
text += "<b>OPERATIVE</b> | <a href='?src=[REF(src)];nuclear=clear'>nanotrasen</a>"
text += "<br><a href='?src=[REF(src)];nuclear=lair'>To shuttle</a>, <a href='?src=[REF(src)];common=undress'>undress</a>, <a href='?src=[REF(src)];nuclear=dressup'>dress up</a>."
var/code
for (var/obj/machinery/nuclearbomb/bombue in GLOB.machines)
if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN")
code = bombue.r_code
break
if (code)
text += " Code is [code]. <a href='?src=\ref[src];nuclear=tellcode'>tell the code.</a>"
text += " Code is [code]. <a href='?src=[REF(src)];nuclear=tellcode'>tell the code.</a>"
else
text += "<a href='?src=\ref[src];nuclear=nuclear'>operative</a> | <b>NANOTRASEN</b>"
text += "<a href='?src=[REF(src)];nuclear=nuclear'>operative</a> | <b>NANOTRASEN</b>"
if(current && current.client && (ROLE_OPERATIVE in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -533,10 +522,10 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if (has_antag_datum(/datum/antagonist/wizard))
text += "<b>YES</b> | <a href='?src=\ref[src];wizard=clear'>no</a>"
text += "<br><a href='?src=\ref[src];wizard=lair'>To lair</a>, <a href='?src=\ref[src];common=undress'>undress</a>"
text += "<b>YES</b> | <a href='?src=[REF(src)];wizard=clear'>no</a>"
text += "<br><a href='?src=[REF(src)];wizard=lair'>To lair</a>, <a href='?src=[REF(src)];common=undress'>undress</a>"
else
text += "<a href='?src=\ref[src];wizard=wizard'>yes</a> | <b>NO</b>"
text += "<a href='?src=[REF(src)];wizard=wizard'>yes</a> | <b>NO</b>"
if(current && current.client && (ROLE_WIZARD in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -563,28 +552,28 @@
if(M && (M.z in GLOB.station_z_levels) && !M.stat)
last_healthy_headrev = FALSE
break
text += "head | not mindshielded | <a href='?src=\ref[src];revolution=clear'>employee</a> | <b>[last_healthy_headrev ? "<font color='red'>LAST </font> " : ""]HEADREV</b> | <a href='?src=\ref[src];revolution=rev'>rev</a>"
text += "<br>Flash: <a href='?src=\ref[src];revolution=flash'>give</a>"
text += "head | not mindshielded | <a href='?src=[REF(src)];revolution=clear'>employee</a> | <b>[last_healthy_headrev ? "<font color='red'>LAST </font> " : ""]HEADREV</b> | <a href='?src=[REF(src)];revolution=rev'>rev</a>"
text += "<br>Flash: <a href='?src=[REF(src)];revolution=flash'>give</a>"
var/list/L = current.get_contents()
var/obj/item/device/assembly/flash/flash = locate() in L
if (flash)
if(!flash.crit_fail)
text += " | <a href='?src=\ref[src];revolution=takeflash'>take</a>."
text += " | <a href='?src=[REF(src)];revolution=takeflash'>take</a>."
else
text += " | <a href='?src=\ref[src];revolution=takeflash'>take</a> | <a href='?src=\ref[src];revolution=repairflash'>repair</a>."
text += " | <a href='?src=[REF(src)];revolution=takeflash'>take</a> | <a href='?src=[REF(src)];revolution=repairflash'>repair</a>."
else
text += "."
text += " <a href='?src=\ref[src];revolution=reequip'>Reequip</a> (gives traitor uplink)."
text += " <a href='?src=[REF(src)];revolution=reequip'>Reequip</a> (gives traitor uplink)."
if (objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=\ref[src];revolution=autoobjectives'>Set to kill all heads</a>."
text += "<br>Objectives are empty! <a href='?src=[REF(src)];revolution=autoobjectives'>Set to kill all heads</a>."
else if(current.isloyal())
text += "head | <b>MINDSHIELDED</b> | employee | <a href='?src=\ref[src];revolution=headrev'>headrev</a> | rev"
text += "head | <b>MINDSHIELDED</b> | employee | <a href='?src=[REF(src)];revolution=headrev'>headrev</a> | rev"
else if (has_antag_datum(/datum/antagonist/rev))
text += "head | not mindshielded | <a href='?src=\ref[src];revolution=clear'>employee</a> | <a href='?src=\ref[src];revolution=headrev'>headrev</a> | <b>REV</b>"
text += "head | not mindshielded | <a href='?src=[REF(src)];revolution=clear'>employee</a> | <a href='?src=[REF(src)];revolution=headrev'>headrev</a> | <b>REV</b>"
else
text += "head | not mindshielded | <b>EMPLOYEE</b> | <a href='?src=\ref[src];revolution=headrev'>headrev</a> | <a href='?src=\ref[src];revolution=rev'>rev</a>"
text += "head | not mindshielded | <b>EMPLOYEE</b> | <a href='?src=[REF(src)];revolution=headrev'>headrev</a> | <a href='?src=[REF(src)];revolution=rev'>rev</a>"
if(current && current.client && (ROLE_REV in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -599,8 +588,8 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in SSticker.mode.abductors)
text += "<b>Abductor</b> | <a href='?src=\ref[src];abductor=clear'>human</a>"
text += " | <a href='?src=\ref[src];common=undress'>undress</a> | <a href='?src=\ref[src];abductor=equip'>equip</a>"
text += "<b>Abductor</b> | <a href='?src=[REF(src)];abductor=clear'>human</a>"
text += " | <a href='?src=[REF(src)];common=undress'>undress</a> | <a href='?src=[REF(src)];abductor=equip'>equip</a>"
if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -618,13 +607,13 @@
var/datum/antagonist/devil/devilinfo = has_antag_datum(ANTAG_DATUM_DEVIL)
if(devilinfo)
if(!devilinfo.ascendable)
text += "<b>DEVIL</b> | <a href='?src=\ref[src];devil=ascendable_devil'>ascendable devil</a> | sintouched | <a href='?src=\ref[src];devil=clear'>human</a>"
text += "<b>DEVIL</b> | <a href='?src=[REF(src)];devil=ascendable_devil'>ascendable devil</a> | sintouched | <a href='?src=[REF(src)];devil=clear'>human</a>"
else
text += "<a href='?src=\ref[src];devil=devil'>DEVIL</a> | <b>ASCENDABLE DEVIL</b> | sintouched | <a href='?src=\ref[src];devil=clear'>human</a>"
text += "<a href='?src=[REF(src)];devil=devil'>DEVIL</a> | <b>ASCENDABLE DEVIL</b> | sintouched | <a href='?src=[REF(src)];devil=clear'>human</a>"
else if(src in SSticker.mode.sintouched)
text += "devil | ascendable devil | <b>SINTOUCHED</b> | <a href='?src=\ref[src];devil=clear'>human</a>"
text += "devil | ascendable devil | <b>SINTOUCHED</b> | <a href='?src=[REF(src)];devil=clear'>human</a>"
else
text += "<a href='?src=\ref[src];devil=devil'>devil</a> | <a href='?src=\ref[src];devil=ascendable_devil'>ascendable devil</a> | <a href='?src=\ref[src];devil=sintouched'>sintouched</a> | <b>HUMAN</b>"
text += "<a href='?src=[REF(src)];devil=devil'>devil</a> | <a href='?src=[REF(src)];devil=ascendable_devil'>ascendable devil</a> | <a href='?src=[REF(src)];devil=sintouched'>sintouched</a> | <b>HUMAN</b>"
if(current && current.client && (ROLE_DEVIL in current.client.prefs.be_special))
text += " | Enabled in Prefs"
@@ -641,11 +630,11 @@
var/datum/antagonist/ninja/ninjainfo = has_antag_datum(ANTAG_DATUM_NINJA)
if(ninjainfo)
if(ninjainfo.helping_station)
text += "<a href='?src=\ref[src];ninja=clear'>employee</a> | syndicate | <b>NANOTRASEN</b> | <b><a href='?src=\ref[src];ninja=equip'>EQUIP</a></b>"
text += "<a href='?src=[REF(src)];ninja=clear'>employee</a> | syndicate | <b>NANOTRASEN</b> | <b><a href='?src=[REF(src)];ninja=equip'>EQUIP</a></b>"
else
text += "<a href='?src=\ref[src];ninja=clear'>employee</a> | <b>SYNDICATE</b> | nanotrasen | <b><a href='?src=\ref[src];ninja=equip'>EQUIP</a></b>"
text += "<a href='?src=[REF(src)];ninja=clear'>employee</a> | <b>SYNDICATE</b> | nanotrasen | <b><a href='?src=[REF(src)];ninja=equip'>EQUIP</a></b>"
else
text += "<b>EMPLOYEE</b> | <a href='?src=\ref[src];ninja=syndicate'>syndicate</a> | <a href='?src=\ref[src];ninja=nanotrasen'>nanotrasen</a> | <a href='?src=\ref[src];ninja=random'>random allegiance</a>"
text += "<b>EMPLOYEE</b> | <a href='?src=[REF(src)];ninja=syndicate'>syndicate</a> | <a href='?src=[REF(src)];ninja=nanotrasen'>nanotrasen</a> | <a href='?src=[REF(src)];ninja=random'>random allegiance</a>"
if(current && current.client && (ROLE_NINJA in current.client.prefs.be_special))
text += " | Enabled in Prefs"
else
@@ -660,10 +649,10 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(iscultist(current))
text += "not mindshielded | <a href='?src=\ref[src];cult=clear'>employee</a> | <b>CULTIST</b>"
text += "<br>Give <a href='?src=\ref[src];cult=tome'>tome</a> | <a href='?src=\ref[src];cult=amulet'>amulet</a>."
text += "not mindshielded | <a href='?src=[REF(src)];cult=clear'>employee</a> | <b>CULTIST</b>"
text += "<br>Give <a href='?src=[REF(src)];cult=tome'>tome</a> | <a href='?src=[REF(src)];cult=amulet'>amulet</a>."
else if(is_convertable_to_cult(current))
text += "not mindshielded | <b>EMPLOYEE</b> | <a href='?src=\ref[src];cult=cultist'>cultist</a>"
text += "not mindshielded | <b>EMPLOYEE</b> | <a href='?src=[REF(src)];cult=cultist'>cultist</a>"
else
text += "[!current.isloyal() ? "not mindshielded" : "<b>MINDSHIELDED</b>"] | <b>EMPLOYEE</b> | <i>cannot serve Nar-Sie</i>"
@@ -682,10 +671,10 @@
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(is_servant_of_ratvar(current))
text += "not mindshielded | <a href='?src=\ref[src];clockcult=clear'>employee</a> | <b>SERVANT</b>"
text += "<br><a href='?src=\ref[src];clockcult=slab'>Equip</a>"
text += "not mindshielded | <a href='?src=[REF(src)];clockcult=clear'>employee</a> | <b>SERVANT</b>"
text += "<br><a href='?src=[REF(src)];clockcult=slab'>Equip</a>"
else if(is_eligible_servant(current))
text += "not mindshielded | <b>EMPLOYEE</b> | <a href='?src=\ref[src];clockcult=servant'>servant</a>"
text += "not mindshielded | <b>EMPLOYEE</b> | <a href='?src=[REF(src)];clockcult=servant'>servant</a>"
else
text += "[!current.isloyal() ? "not mindshielded" : "<b>MINDSHIELDED</b>"] | <b>EMPLOYEE</b> | <i>cannot serve Ratvar</i>"
@@ -702,14 +691,14 @@
text = "silicon"
var/mob/living/silicon/robot/robot = current
if (istype(robot) && robot.emagged)
text += "<br>Cyborg: Is emagged! <a href='?src=\ref[src];silicon=unemag'>Unemag!</a><br>0th law: [robot.laws.zeroth]"
text += "<br>Cyborg: Is emagged! <a href='?src=[REF(src)];silicon=unemag'>Unemag!</a><br>0th law: [robot.laws.zeroth]"
var/mob/living/silicon/ai/ai = current
if (istype(ai) && ai.connected_robots.len)
var/n_e_robots = 0
for (var/mob/living/silicon/robot/R in ai.connected_robots)
if (R.emagged)
n_e_robots++
text += "<br>[n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. <a href='?src=\ref[src];silicon=unemagcyborgs'>Unemag</a>"
text += "<br>[n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. <a href='?src=[REF(src)];silicon=unemagcyborgs'>Unemag</a>"
if (SSticker.mode.config_tag == "traitorchan")
if (sections["traitor"])
out += sections["traitor"]+"<br>"
@@ -727,12 +716,12 @@
if(((src in SSticker.mode.traitors) || (src in SSticker.mode.syndicates)) && ishuman(current))
text = "Uplink: <a href='?src=\ref[src];common=uplink'>give</a>"
text = "Uplink: <a href='?src=[REF(src)];common=uplink'>give</a>"
var/obj/item/device/uplink/U = find_syndicate_uplink()
if(U)
text += " | <a href='?src=\ref[src];common=takeuplink'>take</a>"
text += " | <a href='?src=[REF(src)];common=takeuplink'>take</a>"
if (check_rights(R_FUN, 0))
text += ", <a href='?src=\ref[src];common=crystals'>[U.telecrystals]</a> TC"
text += ", <a href='?src=[REF(src)];common=crystals'>[U.telecrystals]</a> TC"
else
text += ", [U.telecrystals] TC"
text += "." //hiel grammar
@@ -742,18 +731,18 @@
out += "<b>Memory:</b><br>"
out += memory
out += "<br><a href='?src=\ref[src];memory_edit=1'>Edit memory</a><br>"
out += "<br><a href='?src=[REF(src)];memory_edit=1'>Edit memory</a><br>"
out += "Objectives:<br>"
if (objectives.len == 0)
out += "EMPTY<br>"
else
var/obj_count = 1
for(var/datum/objective/objective in objectives)
out += "<B>[obj_count]</B>: [objective.explanation_text] <a href='?src=\ref[src];obj_edit=\ref[objective]'>Edit</a> <a href='?src=\ref[src];obj_delete=\ref[objective]'>Delete</a> <a href='?src=\ref[src];obj_completed=\ref[objective]'><font color=[objective.completed ? "green" : "red"]>Toggle Completion</font></a><br>"
out += "<B>[obj_count]</B>: [objective.explanation_text] <a href='?src=[REF(src)];obj_edit=[REF(objective)]'>Edit</a> <a href='?src=[REF(src)];obj_delete=[REF(objective)]'>Delete</a> <a href='?src=[REF(src)];obj_completed=[REF(objective)]'><font color=[objective.completed ? "green" : "red"]>Toggle Completion</font></a><br>"
obj_count++
out += "<a href='?src=\ref[src];obj_add=1'>Add objective</a><br><br>"
out += "<a href='?src=[REF(src)];obj_add=1'>Add objective</a><br><br>"
out += "<a href='?src=\ref[src];obj_announce=1'>Announce objectives</a><br><br>"
out += "<a href='?src=[REF(src)];obj_announce=1'>Announce objectives</a><br><br>"
var/datum/browser/popup = new(usr, "edit_memory", "", 600, 600)
popup.set_content(out)
@@ -955,7 +944,7 @@
log_admin("[key_name(usr)] has rev'ed [current].")
else
return
if("headrev")
if(has_antag_datum(/datum/antagonist/rev))
var/datum/antagonist/rev/rev = has_antag_datum(/datum/antagonist/rev)
@@ -1050,30 +1039,29 @@
else if (href_list["changeling"])
switch(href_list["changeling"])
if("clear")
remove_changeling()
remove_antag_datum(/datum/antagonist/changeling)
special_role = null
to_chat(current, "<span class='userdanger'>You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!</span>")
message_admins("[key_name_admin(usr)] has de-changeling'ed [current].")
log_admin("[key_name(usr)] has de-changeling'ed [current].")
if("changeling")
if(!(src in SSticker.mode.changelings))
SSticker.mode.changelings += src
current.make_changeling()
special_role = "Changeling"
to_chat(current, "<span class='boldannounce'>Your powers are awoken. A flash of memory returns to us...we are [changeling.changelingID], a changeling!</span>")
message_admins("[key_name_admin(usr)] has changeling'ed [current].")
log_admin("[key_name(usr)] has changeling'ed [current].")
SSticker.mode.update_changeling_icons_added(src)
var/datum/antagonist/changeling/C = make_Changling()
to_chat(current, "<span class='boldannounce'>Our powers have awoken. A flash of memory returns to us...we are [C.changelingID], a changeling!</span>")
message_admins("[key_name_admin(usr)] has changeling'ed [current].")
log_admin("[key_name(usr)] has changeling'ed [current].")
if("autoobjectives")
SSticker.mode.forge_changeling_objectives(src)
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
if(C)
C.forge_objectives()
to_chat(usr, "<span class='notice'>The objectives for changeling [key] have been generated. You can edit them and anounce manually.</span>")
if("initialdna")
if( !changeling || !changeling.stored_profiles.len || !iscarbon(current))
var/datum/antagonist/changeling/ling = has_antag_datum(/datum/antagonist/changeling)
if( !ling || !ling.stored_profiles.len || !iscarbon(current))
to_chat(usr, "<span class='danger'>Resetting DNA failed!</span>")
else
var/mob/living/carbon/C = current
changeling.first_prof.dna.transfer_identity(C, transfer_SE=1)
C.real_name = changeling.first_prof.name
ling.first_prof.dna.transfer_identity(C, transfer_SE=1)
C.real_name = ling.first_prof.name
C.updateappearance(mutcolor_update=1)
C.domutcheck()
@@ -1408,13 +1396,11 @@
current.real_name = "[syndicate_name()] Operative #[SSticker.mode.syndicates.len-1]"
/datum/mind/proc/make_Changling()
if(!(src in SSticker.mode.changelings))
SSticker.mode.changelings += src
current.make_changeling()
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
if(!C)
C = add_antag_datum(/datum/antagonist/changeling)
special_role = "Changeling"
SSticker.mode.forge_changeling_objectives(src)
SSticker.mode.greet_changeling(src)
SSticker.mode.update_changeling_icons_added(src)
return C
/datum/mind/proc/make_Wizard()
if(!has_antag_datum(/datum/antagonist/wizard))
+2 -1
View File
@@ -98,7 +98,8 @@
/obj/structure/cable,
/obj/machinery/atmospherics,
/obj/item/ammo_casing,
/obj/item/implant
/obj/item/implant,
/obj/singularity
))
if(!can_contaminate || blacklisted[thing.type])
continue
+1 -1
View File
@@ -142,7 +142,7 @@
/datum/map_template/ruin/lavaland/ufo_crash
name = "UFO Crash"
id = "ufo-crash"
description = "Turns out that keeping your abductees unconcious is really important. Who knew?"
description = "Turns out that keeping your abductees unconscious is really important. Who knew?"
suffix = "lavaland_surface_ufo_crash.dmm"
cost = 5
+1 -1
View File
@@ -149,7 +149,7 @@
suffix = "mini"
name = "Ministation emergency shuttle"
credit_cost = 1000
description = "Despite it's namesake, this shuttle is actually only slightly smaller than standard, and still complete with a brig and medbay."
description = "Despite its namesake, this shuttle is actually only slightly smaller than standard, and still complete with a brig and medbay."
/datum/map_template/shuttle/emergency/scrapheap
suffix = "scrapheap"
+3 -1
View File
@@ -21,7 +21,7 @@
this["desc"] = ""
this["refs"] = list()
for(var/spawner_obj in GLOB.mob_spawners[spawner])
this["refs"] += "\ref[spawner_obj]"
this["refs"] += "[REF(spawner_obj)]"
if(!this["desc"])
if(istype(spawner_obj, /obj/effect/mob_spawn))
var/obj/effect/mob_spawn/MS = spawner_obj
@@ -40,6 +40,8 @@
var/spawner_ref = pick(GLOB.mob_spawners[params["name"]])
var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list
if(!MS)
return
switch(action)
if("jump")

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