Merge branch 'master' into theprthatbulliesjanitormains

This commit is contained in:
LetterJay
2017-12-22 02:56:10 -06:00
committed by GitHub
1414 changed files with 30231 additions and 17880 deletions
+14 -10
View File
@@ -24,7 +24,7 @@
#define MUT_MUTE "Mute"
#define SMILE "Smile"
#define STONER "Stoner"
#define UNINTELLIGABLE "Unintelligable"
#define UNINTELLIGIBLE "Unintelligible"
#define SWEDISH "Swedish"
#define CHAV "Chav"
#define ELVIS "Elvis"
@@ -82,7 +82,7 @@
#define DNA_MUTANTTAIL_BLOCK 17
#define DNA_MUTANTWING_BLOCK 18
#define DNA_WINGCOLOR_BLOCK 19
#define DNA_STRUC_ENZYMES_BLOCKS 19
#define DNA_STRUC_ENZYMES_BLOCKS 18
#define DNA_UNIQUE_ENZYMES_LEN 32
//Transformation proc stuff
@@ -127,15 +127,19 @@
#define TOXINLOVER 24
#define DIGITIGRADE 25 //Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi)
#define NO_UNDERWEAR 26
#define MUTCOLORS2 27
#define MUTCOLORS3 28
#define NOLIVER 29
#define NOSTOMACH 30
#define NOLIVER 27
#define NOSTOMACH 28
#define NO_DNA_COPY 29
#define DRINKSBLOOD 30
#define SPECIES_ORGANIC 31
#define SPECIES_INORGANIC 32
#define SPECIES_UNDEAD 33
#define SPECIES_ROBOTIC 34
//citadel code
#define NOAROUSAL 29 //Stops all arousal effects
#define NOGENITALS 30 //Cannot create, use, or otherwise have genitals
#define NO_DNA_COPY 31
#define DRINKSBLOOD 32
#define MUTCOLORS2 35
#define MUTCOLORS3 36
#define NOAROUSAL 37 //Stops all arousal effects
#define NOGENITALS 38 //Cannot create, use, or otherwise have genitals
#define ORGAN_SLOT_BRAIN "brain"
#define ORGAN_SLOT_APPENDIX "appendix"
+17 -13
View File
@@ -94,19 +94,22 @@
#define BANTYPE_ANY_JOB 9 //used to remove jobbans
//Admin Permissions
#define R_BUILDMODE 1
#define R_ADMIN 2
#define R_BAN 4
#define R_FUN 8
#define R_SERVER 16
#define R_DEBUG 32
#define R_POSSESS 64
#define R_PERMISSIONS 128
#define R_STEALTH 256
#define R_POLL 512
#define R_VAREDIT 1024
#define R_SOUNDS 2048
#define R_SPAWN 4096
#define R_BUILDMODE 0x1
#define R_ADMIN 0x2
#define R_BAN 0x4
#define R_FUN 0x8
#define R_SERVER 0x10
#define R_DEBUG 0x20
#define R_POSSESS 0x40
#define R_PERMISSIONS 0x80
#define R_STEALTH 0x100
#define R_POLL 0x200
#define R_VAREDIT 0x400
#define R_SOUNDS 0x800
#define R_SPAWN 0x1000
#define R_AUTOLOGIN 0x2000
#define R_DEFAULT R_AUTOLOGIN
#if DM_VERSION > 512
#error Remove the flag below , its been long enough
@@ -142,6 +145,7 @@
#define ADMIN_PUNISHMENT_GIB "Gib"
#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device"
#define ADMIN_PUNISHMENT_FIREBALL "Fireball"
#define ADMIN_PUNISHMENT_ROD "Immovable Rod"
#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
+71 -55
View File
@@ -1,14 +1,5 @@
#define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin (default 0.0215)
#define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage. (default 2.025)
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005)
#define O2STANDARD 0.21
#define N2STANDARD 0.79
#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%)
#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%)
//indices of values in gas lists. used by listmos.
//LISTMOS
//indices of values in gas lists.
#define MOLES 1
#define ARCHIVE 2
#define GAS_META 3
@@ -19,32 +10,41 @@
#define META_GAS_DANGER 5
#define META_GAS_ID 6
//stuff you should probably leave well alone!
//ATMOS
#define CELL_VOLUME 2500 //liters in a cell
#define BREATH_VOLUME 0.5 //liters in a normal breath
#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME) //Amount of air to take a from a tile
#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD*BREATH_PERCENTAGE*0.16) //Amount of air needed before pass out/suffocation commences
#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
#define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold
#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.1 //Ratio of air that must move to/from a tile to reset group processing
#define MINIMUM_AIR_RATIO_TO_MOVE 0.001 //Minimum ratio of air that must move to/from a tile
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Minimum amount of air that has to move before a group processing can be suspended
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_MOVE) //Either this must be active
#define EXCITED_GROUP_BREAKDOWN_CYCLES 4
#define EXCITED_GROUP_DISMANTLE_CYCLES 16
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100) //or this (or both, obviously)
#define MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND 0.012
//stuff you should probably leave well alone!
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa
#define T0C 273.15 // 0degC
#define T20C 293.15 // 20degC
#define TCMB 2.7 // -270.3degC
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity
#define O2STANDARD 0.21 //percentage of oxygen in a normal mixture of air
#define N2STANDARD 0.79 //same but for nitrogen
#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%)
#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%)
#define CELL_VOLUME 2500 //liters in a cell
#define BREATH_VOLUME 0.5 //liters in a normal breath
#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME) //Amount of air to take a from a tile
#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD*BREATH_PERCENTAGE*0.16) //Amount of air needed before pass out/suffocation commences
//EXCITED GROUPS
#define EXCITED_GROUP_BREAKDOWN_CYCLES 4 //number of FULL air controller ticks before an excited group breaks down (averages gas contents across turfs)
#define EXCITED_GROUP_DISMANTLE_CYCLES 16 //number of FULL air controller ticks before an excited group dismantles and removes its turfs from active
#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.1 //Ratio of air that must move to/from a tile to reset group processing
#define MINIMUM_AIR_RATIO_TO_MOVE 0.001 //Minimum ratio of air that must move to/from a tile
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Minimum amount of air that has to move before a group processing can be suspended
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_MOVE) //Either this must be active
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100) //or this (or both, obviously)
#define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4 //Minimum temperature difference before group processing is suspended
#define MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER 0.5 //Minimum temperature difference before the gas temperatures are just set to be equal
#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION T20C+10
#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION T20C+200
//HEAT TRANSFER COEFFICIENTS
//Must be between 0 and 1. Values closer to 1 equalize temperature faster
//Should not exceed 0.4 else strange heat flow occur
#define FLOOR_HEAT_TRANSFER_COEFFICIENT 0.4
#define WALL_HEAT_TRANSFER_COEFFICIENT 0.0
#define DOOR_HEAT_TRANSFER_COEFFICIENT 0.0
@@ -52,20 +52,31 @@
#define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4
#define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1 //a hack for now
#define HEAT_CAPACITY_VACUUM 7000 //a hack to help make vacuums "cold", sacrificing realism for gameplay
//Must be between 0 and 1. Values closer to 1 equalize temperature faster
//Should not exceed 0.4 else strange heat flow occur
//FIRE
#define FIRE_MINIMUM_TEMPERATURE_TO_SPREAD 150+T0C
#define FIRE_MINIMUM_TEMPERATURE_TO_EXIST 100+T0C
#define FIRE_SPREAD_RADIOSITY_SCALE 0.85
#define FIRE_GROWTH_RATE 40000 //For small fires
#define CARBON_LIFEFORM_FIRE_RESISTANCE 200+T0C //Resistance to fire damage
#define CARBON_LIFEFORM_FIRE_DAMAGE 4 //Fire damage
#define PLASMA_MINIMUM_BURN_TEMPERATURE 100+T0C
//GASES
#define MIN_TOXIC_GAS_DAMAGE 1
#define MAX_TOXIC_GAS_DAMAGE 10
#define MOLES_GAS_VISIBLE 0.5 //Moles in a standard cell after which gases are visible
#define STOP_REACTIONS 2
#define PLASMA_MINIMUM_BURN_TEMPERATURE 100+T0C
#define GAS_STIM_MINIMUM 0.002
//REACTIONS
//return values for reactions (bitflags)
#define NO_REACTION 0
#define REACTING 1
#define STOP_REACTIONS 2
//HUMANS
//Hurty numbers
#define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin
#define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage
// Pressure limits.
#define HAZARD_HIGH_PRESSURE 550 //This determins at what pressure the ultra-high pressure red icon is displayed. (This one is set as a constant)
@@ -107,65 +118,71 @@
#define SHOES_MIN_TEMP_PROTECT 2.0 //For gloves
#define SHOES_MAX_TEMP_PROTECT 1500 //For gloves
#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 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
// Atmos pipe limits
//PIPES
//Atmos pipe limits
#define MAX_OUTPUT_PRESSURE 4500 // (kPa) What pressure pumps and powered equipment max out at.
#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at.
//Atmos machinery pipenet stuff
// used for device_type vars; used by DEVICE_TYPE_LOOP
//used for device_type vars; used by DEVICE_TYPE_LOOP
#define UNARY 1
#define BINARY 2
#define TRINARY 3
#define QUATERNARY 4
// this is the standard for loop used by all sorts of atmos machinery procs
//TODO: finally remove this bullshit
//this is the standard for loop used by all sorts of atmos machinery procs
#define DEVICE_TYPE_LOOP var/I in 1 to device_type
// defines for the various machinery lists
// NODE_I, AIR_I, PARENT_I are used within DEVICE_TYPE_LOOP
//defines for the various machinery lists
//NODE_I, AIR_I, PARENT_I are used within DEVICE_TYPE_LOOP
// nodes list - all atmos machinery
//nodes list - all atmos machinery
#define NODE1 nodes[1]
#define NODE2 nodes[2]
#define NODE3 nodes[3]
#define NODE4 nodes[4]
#define NODE_I nodes[I]
// airs list - components only
//airs list - components only
#define AIR1 airs[1]
#define AIR2 airs[2]
#define AIR3 airs[3]
#define AIR_I airs[I]
// parents list - components only
//parents list - components only
#define PARENT1 parents[1]
#define PARENT2 parents[2]
#define PARENT3 parents[3]
#define PARENT_I parents[I]
//Tanks
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
#define TANK_MIN_RELEASE_PRESSURE 0
#define TANK_DEFAULT_RELEASE_PRESSURE 16
//TANKS
#define TANK_MELT_TEMPERATURE 1000000 //temperature in kelvins at which a tank will start to melt
#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
#define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
#define TANK_MIN_RELEASE_PRESSURE 0
#define TANK_DEFAULT_RELEASE_PRESSURE 16
//CANATMOSPASS
#define ATMOS_PASS_YES 1
#define ATMOS_PASS_NO 0
#define ATMOS_PASS_PROC -1 //ask CanAtmosPass()
#define ATMOS_PASS_DENSITY -2 //just check density
#define CANATMOSPASS(A, O) ( A.CanAtmosPass == ATMOS_PASS_PROC ? A.CanAtmosPass(O) : ( A.CanAtmosPass == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPass ) )
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300"
//MULTIPIPES
//IF YOU EVER CHANGE THESE CHANGE SPRITES TO MATCH.
#define PIPING_LAYER_MIN 1
#define PIPING_LAYER_MAX 3
@@ -179,11 +196,10 @@
#define PIPING_DEFAULT_LAYER_ONLY 4 //can only exist at PIPING_LAYER_DEFAULT
#define PIPING_CARDINAL_AUTONORMALIZE 8 //north/south east/west doesn't matter, auto normalize on build.
//HELPERS
#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity())
#define ADD_GAS(gas_id, out_list)\
var/list/tmp_gaslist = GLOB.gaslist_cache[gas_id]; out_list[gas_id] = tmp_gaslist.Copy();
//ASSERT_GAS(gas_id, gas_mixture) - used to guarantee that the gas list for this id exists in gas_mixture.gases.
//Must be used before adding to a gas. May be used before reading from a gas.
#define ASSERT_GAS(gas_id, gas_mixture) if (!gas_mixture.gases[gas_id]) { ADD_GAS(gas_id, gas_mixture.gases) };
+28 -20
View File
@@ -16,31 +16,39 @@
#define DIAG_BOT_HUD "12"// Bot HUDs
#define DIAG_TRACK_HUD "13"// Mech tracking beacon
#define DIAG_AIRLOCK_HUD "14"//Airlock shock overlay
#define DIAG_PATH_HUD "15"//Bot path indicators
#define GLAND_HUD "16"//Gland indicators for abductors
//for antag huds. these are used at the /mob level
#define ANTAG_HUD "15"
#define ANTAG_HUD "17"
//by default everything in the hud_list of an atom is an image
//a value in hud_list with one of these will change that behavior
#define HUD_LIST_LIST 1
//data HUD (medhud, sechud) defines
//Don't forget to update human/New() if you change these!
#define DATA_HUD_SECURITY_BASIC 1
#define DATA_HUD_SECURITY_ADVANCED 2
#define DATA_HUD_MEDICAL_BASIC 3
#define DATA_HUD_MEDICAL_ADVANCED 4
#define DATA_HUD_DIAGNOSTIC 5
#define DATA_HUD_SECURITY_BASIC 1
#define DATA_HUD_SECURITY_ADVANCED 2
#define DATA_HUD_MEDICAL_BASIC 3
#define DATA_HUD_MEDICAL_ADVANCED 4
#define DATA_HUD_DIAGNOSTIC_BASIC 5
#define DATA_HUD_DIAGNOSTIC_ADVANCED 6
#define DATA_HUD_ABDUCTOR 7
//antag HUD defines
#define ANTAG_HUD_CULT 6
#define ANTAG_HUD_REV 7
#define ANTAG_HUD_OPS 8
#define ANTAG_HUD_WIZ 9
#define ANTAG_HUD_SHADOW 10
#define ANTAG_HUD_TRAITOR 11
#define ANTAG_HUD_NINJA 12
#define ANTAG_HUD_CHANGELING 13
#define ANTAG_HUD_ABDUCTOR 14
#define ANTAG_HUD_DEVIL 15
#define ANTAG_HUD_SINTOUCHED 16
#define ANTAG_HUD_SOULLESS 17
#define ANTAG_HUD_CLOCKWORK 18
#define ANTAG_HUD_BROTHER 19
#define ANTAG_HUD_CULT 8
#define ANTAG_HUD_REV 9
#define ANTAG_HUD_OPS 10
#define ANTAG_HUD_WIZ 11
#define ANTAG_HUD_SHADOW 12
#define ANTAG_HUD_TRAITOR 13
#define ANTAG_HUD_NINJA 14
#define ANTAG_HUD_CHANGELING 15
#define ANTAG_HUD_ABDUCTOR 16
#define ANTAG_HUD_DEVIL 17
#define ANTAG_HUD_SINTOUCHED 18
#define ANTAG_HUD_SOULLESS 19
#define ANTAG_HUD_CLOCKWORK 20
#define ANTAG_HUD_BROTHER 21
// Notification action types
#define NOTIFY_JUMP "jump"
+10 -6
View File
@@ -1,12 +1,11 @@
//component id defines
#define BELLIGERENT_EYE "belligerent_eye"
#define VANGUARD_COGWHEEL "vanguard_cogwheel"
#define GEIS_CAPACITOR "geis_capacitor"
//component id defines; sometimes these may not make sense in regards to their use in scripture but important ones are bright
#define BELLIGERENT_EYE "belligerent_eye" //Use this for offensive and damaging scripture!
#define VANGUARD_COGWHEEL "vanguard_cogwheel" //Use this for defensive and healing scripture!
#define GEIS_CAPACITOR "geis_capacitor" //Use this for niche scripture!
#define REPLICANT_ALLOY "replicant_alloy"
#define HIEROPHANT_ANSIBLE "hierophant_ansible"
#define HIEROPHANT_ANSIBLE "hierophant_ansible" //Use this for construction-related scripture!
GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult
GLOBAL_VAR_INIT(clockwork_caches, 0) //How many clockwork caches exist in the world (not each individual)
GLOBAL_VAR_INIT(clockwork_vitality, 0) //How much Vitality is stored, total
GLOBAL_VAR_INIT(clockwork_power, 0) //How many watts of power are globally available to the clockwork cult
@@ -69,6 +68,9 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
//Objective text define
#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."
//Eminence defines
#define SUPERHEATED_CLOCKWORK_WALL_LIMIT 20 //How many walls can be superheated at once
//misc clockcult stuff
#define SIGIL_ACCESS_RANGE 2 //range at which transmission sigils can access power
@@ -86,3 +88,5 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#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
#define ARK_SCREAM_COOLDOWN 600 //This much time has to pass between instances of the Ark taking damage before it will "scream" again
+18 -4
View File
@@ -6,9 +6,10 @@
// How multiple components of the exact same type are handled in the same datum
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new
// All signals. Format:
// When the signal is called: (signal arguments)
@@ -23,6 +24,7 @@
// /atom signals
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
#define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob)
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (/atom/movable, /atom)
@@ -53,11 +55,15 @@
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)
#define COMSIG_MOVABLE_COLLIDE "movable_collide" //from base of atom/movable/Collide(): (/atom)
#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom, throwingdatum)
#define COMSIG_MOVABLE_BUCKLE "buckle" //from base of atom/movable/buckle_mob(): (mob, force)
#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" //from base of atom/movable/unbuckle_mob(): (mob, force)
// /obj/item signals
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob)
#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot)
#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (/mob/dropper)
// /obj/item/clothing signals
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
@@ -72,4 +78,12 @@
// /obj/machinery signals
#define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): ()
#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): ()
#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): ()
// /mob/living/carbon/human signals
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
#define CALTROP_BYPASS_SHOES 1
#define CALTROP_IGNORE_WALKERS 2
-2
View File
@@ -1,8 +1,6 @@
//config files
#define CONFIG_DEF(X) /datum/config_entry/##X { resident_file = CURRENT_RESIDENT_FILE }; /datum/config_entry/##X
#define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X)
#define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y)
#define CONFIG_TWEAK(X) /datum/config_entry/##X
#define CONFIG_MAPS_FILE "maps.txt"
+5
View File
@@ -23,6 +23,11 @@
#define WINDOW_IN_FRAME 1
#define WINDOW_SCREWED_TO_FRAME 2
//airlock assembly construction states
#define AIRLOCK_ASSEMBLY_NEEDS_WIRES 0
#define AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS 1
#define AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER 2
//plastic flaps construction states
#define PLASTIC_FLAPS_NORMAL 0
#define PLASTIC_FLAPS_DETACHED 1
+2
View File
@@ -20,6 +20,7 @@
#define IC_FORMAT_BOOLEAN "\<BOOL\>"
#define IC_FORMAT_REF "\<REF\>"
#define IC_FORMAT_LIST "\<LIST\>"
#define IC_FORMAT_INDEX "\<INDEX\>"
#define IC_FORMAT_PULSE "\<PULSE\>"
@@ -33,6 +34,7 @@
#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_INDEX /datum/integrated_io/index
#define IC_PINTYPE_PULSE_IN /datum/integrated_io/activate
#define IC_PINTYPE_PULSE_OUT /datum/integrated_io/activate/out
+4
View File
@@ -144,6 +144,8 @@
#define iscameramob(A) (istype(A, /mob/camera))
#define iseminence(A) (istype(A, /mob/camera/eminence))
//Objects
#define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs
@@ -189,3 +191,5 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
/obj/item/stack/sheet/plasmarglass)))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
#define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob))
+1
View File
@@ -10,6 +10,7 @@
#define INVESTIGATE_TELESCI "telesci"
#define INVESTIGATE_WIRES "wires"
#define INVESTIGATE_PORTAL "portals"
#define INVESTIGATE_RESEARCH "research"
#define INVESTIGATE_HALLUCINATIONS "hallucinations"
#define INVESTIGATE_RADIATION "radiation"
#define INVESTIGATE_EXONET "exonet"
+1 -1
View File
@@ -48,4 +48,4 @@ Last space-z level = empty
#define ZLEVEL_SPACEMIN 3
#define ZLEVEL_SPACEMAX 13
#define SPACERUIN_MAP_EDGE_PAD 15
#define SPACERUIN_MAP_EDGE_PAD 15
-27
View File
@@ -1,27 +0,0 @@
#define PI 3.1415
#define SPEED_OF_LIGHT 3e8 //not exact but hey!
#define SPEED_OF_LIGHT_SQ 9e+16
#define INFINITY 1e31 //closer then enough
//atmos
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa
#define T0C 273.15 // 0degC
#define T20C 293.15 // 20degC
#define TCMB 2.7 // -270.3degC
#define SHORT_REAL_LIMIT 16777216
//"fancy" math for calculating time in ms from tick_usage percentage and the length of ticks
//percent_of_tick_used * (ticklag * 100(to convert to ms)) / 100(percent ratio)
//collapsed to percent_of_tick_used * tick_lag
#define TICK_DELTA_TO_MS(percent_of_tick_used) ((percent_of_tick_used) * world.tick_lag)
#define TICK_USAGE_TO_MS(starting_tickusage) (TICK_DELTA_TO_MS(TICK_USAGE_REAL - starting_tickusage))
#define PERCENT(val) (round(val*100, 0.1))
#define CLAMP01(x) (Clamp(x, 0, 1))
//time of day but automatically adjusts to the server going into the next day within the same round.
//for when you need a reliable time number that doesn't depend on byond time.
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
#define MIDNIGHT_ROLLOVER_CHECK ( GLOB.rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : GLOB.midnight_rollovers )
+209
View File
@@ -0,0 +1,209 @@
// Credits to Nickr5 for the useful procs I've taken from his library resource.
// This file is quadruple wrapped for your pleasure
// (
#define NUM_E 2.71828183
#define NUM_SQRT2 1.41421356
#define PI 3.1415
#define SPEED_OF_LIGHT 3e8 //not exact but hey!
#define SPEED_OF_LIGHT_SQ 9e+16
#define INFINITY 1e31 //closer then enough
#define SHORT_REAL_LIMIT 16777216
//"fancy" math for calculating time in ms from tick_usage percentage and the length of ticks
//percent_of_tick_used * (ticklag * 100(to convert to ms)) / 100(percent ratio)
//collapsed to percent_of_tick_used * tick_lag
#define TICK_DELTA_TO_MS(percent_of_tick_used) ((percent_of_tick_used) * world.tick_lag)
#define TICK_USAGE_TO_MS(starting_tickusage) (TICK_DELTA_TO_MS(TICK_USAGE_REAL - starting_tickusage))
#define PERCENT(val) (round((val)*100, 0.1))
#define CLAMP01(x) (CLAMP(x, 0, 1))
//time of day but automatically adjusts to the server going into the next day within the same round.
//for when you need a reliable time number that doesn't depend on byond time.
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
#define MIDNIGHT_ROLLOVER_CHECK ( GLOB.rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : GLOB.midnight_rollovers )
#define SIGN(x) ( (x)!=0 ? (x) / abs(x) : 0 )
#define CEILING(x, y) ( -round(-(x) / (y)) * (y) )
// round() acts like floor(x, 1) by default but can't handle other values
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
#define CLAMP(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
#define WRAP(val, min, max) ( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) )
// Real modulus that handles decimals
#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
// Tangent
#define TAN(x) (sin(x) / cos(x))
// Cotangent
#define COT(x) (1 / TAN(x))
// Secant
#define SEC(x) (1 / cos(x))
// Cosecant
#define CSC(x) (1 / sin(x))
#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
// Greatest Common Divisor - Euclid's algorithm
/proc/Gcd(a, b)
return b ? Gcd(b, (a) % (b)) : a
// Least Common Multiple
#define Lcm(a, b) (abs(a) / Gcd(a, b) * abs(b))
#define INVERSE(x) ( 1/(x) )
// Used for calculating the radioactive strength falloff
#define INVERSE_SQUARE(initial_strength,cur_distance,initial_distance) ( (initial_strength)*((initial_distance)**2/(cur_distance)**2) )
#define ISABOUTEQUAL(a, b, deviation) (deviation ? abs((a) - (b)) <= deviation : abs((a) - (b)) <= 0.1)
#define ISEVEN(x) (x % 2 == 0)
#define ISODD(x) (x % 2 != 0)
// Returns true if val is from min to max, inclusive.
#define ISINRANGE(val, min, max) (min <= val && val <= max)
// Same as above, exclusive.
#define ISINRANGE_EX(val, min, max) (min < val && val > max)
#define ISINTEGER(x) (round(x) == x)
#define ISMULTIPLE(x, y) ((x) % (y) == 0)
// Performs a linear interpolation between a and b.
// Note that amount=0 returns a, amount=1 returns b, and
// amount=0.5 returns the mean of a and b.
#define LERP(a, b, amount) (amount ? ((a) + ((b) - (a)) * (amount)) : ((a) + ((b) - (a)) * 0.5)
// Returns the nth root of x.
#define ROOT(n, x) ((x) ** (1 / (n)))
// The quadratic formula. Returns a list with the solutions, or an empty list
// if they are imaginary.
/proc/SolveQuadratic(a, b, c)
ASSERT(a)
. = list()
var/d = b*b - 4 * a * c
var/bottom = 2 * a
if(d < 0)
return
var/root = sqrt(d)
. += (-b + root) / bottom
if(!d)
return
. += (-b - root) / bottom
#define TODEGREES(radians) ((radians) * 57.2957795)
#define TORADIANS(degrees) ((degrees) * 0.0174532925)
// Will filter out extra rotations and negative rotations
// E.g: 540 becomes 180. -180 becomes 180.
#define SIMPLIFY_DEGREES(degrees) (MODULUS((degrees), 360))
#define GET_ANGLE_OF_INCIDENCE(face, input) (MODULUS((face) - (input), 360))
//A logarithm that converts an integer to a number scaled between 0 and 1.
//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
#define TRANSFORM_USING_VARIABLE(input, max) ( sin((90*(input))/(max))**2 )
//converts a uniform distributed random number into a normal distributed one
//since this method produces two random numbers, one is saved for subsequent calls
//(making the cost negligble for every second call)
//This will return +/- decimals, situated about mean with standard deviation stddev
//68% chance that the number is within 1stddev
//95% chance that the number is within 2stddev
//98% chance that the number is within 3stddev...etc
#define ACCURACY 10000
/proc/gaussian(mean, stddev)
var/static/gaussian_next
var/R1;var/R2;var/working
if(gaussian_next != null)
R1 = gaussian_next
gaussian_next = null
else
do
R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
working = R1*R1 + R2*R2
while(working >= 1 || working==0)
working = sqrt(-2 * log(working) / working)
R1 *= working
gaussian_next = R2 * working
return (mean + stddev * R1)
#undef ACCURACY
/proc/mouse_angle_from_client(client/client)
var/list/mouse_control = params2list(client.mouseParams)
if(mouse_control["screen-loc"] && client)
var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",")
var/list/screen_loc_X = splittext(screen_loc_params[1],":")
var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
var/x = (text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32)
var/y = (text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32)
var/list/screenview = getviewsize(client.view)
var/screenviewX = screenview[1] * world.icon_size
var/screenviewY = screenview[2] * world.icon_size
var/ox = round(screenviewX/2) - client.pixel_x //"origin" x
var/oy = round(screenviewY/2) - client.pixel_y //"origin" y
var/angle = SIMPLIFY_DEGREES(ATAN2(y - oy, x - ox))
return angle
/proc/get_turf_in_angle(angle, turf/starting, increments)
var/pixel_x = 0
var/pixel_y = 0
for(var/i in 1 to increments)
pixel_x += sin(angle)+16*sin(angle)*2
pixel_y += cos(angle)+16*cos(angle)*2
var/new_x = starting.x
var/new_y = starting.y
while(pixel_x > 16)
pixel_x -= 32
new_x++
while(pixel_x < -16)
pixel_x += 32
new_x--
while(pixel_y > 16)
pixel_y -= 32
new_y++
while(pixel_y < -16)
pixel_y += 32
new_y--
new_x = CLAMP(new_x, 0, world.maxx)
new_y = CLAMP(new_y, 0, world.maxy)
return locate(new_x, new_y, starting.z)
// Returns a list where [1] is all x values and [2] is all y values that overlap between the given pair of rectangles
/proc/get_overlap(x1, y1, x2, y2, x3, y3, x4, y4)
var/list/region_x1 = list()
var/list/region_y1 = list()
var/list/region_x2 = list()
var/list/region_y2 = list()
// These loops create loops filled with x/y values that the boundaries inhabit
// ex: list(5, 6, 7, 8, 9)
for(var/i in min(x1, x2) to max(x1, x2))
region_x1["[i]"] = TRUE
for(var/i in min(y1, y2) to max(y1, y2))
region_y1["[i]"] = TRUE
for(var/i in min(x3, x4) to max(x3, x4))
region_x2["[i]"] = TRUE
for(var/i in min(y3, y4) to max(y3, y4))
region_y2["[i]"] = TRUE
return list(region_x1 & region_x2, region_y1 & region_y2)
// )
+17
View File
@@ -4,6 +4,11 @@
// #define EAST 4
// #define WEST 8
#define TEXT_NORTH "[NORTH]"
#define TEXT_SOUTH "[SOUTH]"
#define TEXT_EAST "[EAST]"
#define TEXT_WEST "[WEST]"
//These get to go at the top, because they're special
//You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects)
/* eg:
@@ -479,7 +484,19 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define SYRINGE_DRAW 0
#define SYRINGE_INJECT 1
#define RESEARCH_MATERIAL_RECLAMATION_ID "0"
//gold slime core spawning
#define NO_SPAWN 0
#define HOSTILE_SPAWN 1
#define FRIENDLY_SPAWN 2
#define RIDING_OFFSET_ALL "ALL"
//text files
#define BRAIN_DAMAGE_FILE "traumas.json"
//Fullscreen overlay resolution in tiles.
#define FULLSCREEN_OVERLAY_RESOLUTION_X 15
#define FULLSCREEN_OVERLAY_RESOLUTION_Y 15
+11
View File
@@ -51,6 +51,17 @@
#define DEVIL_BODYPART "devil"
/*see __DEFINES/inventory.dm for bodypart bitflag defines*/
//Brain Damage defines
#define BRAIN_DAMAGE_MILD 20
#define BRAIN_DAMAGE_SEVERE 100
#define BRAIN_DAMAGE_DEATH 200
#define BRAIN_TRAUMA_MILD /datum/brain_trauma/mild
#define BRAIN_TRAUMA_SEVERE /datum/brain_trauma/severe
#define BRAIN_TRAUMA_SPECIAL /datum/brain_trauma/special
#define BRAIN_DAMAGE_INTEGRITY_MULTIPLIER 0.5
//Health hud screws for carbon mobs
#define SCREWYHUD_NONE 0
#define SCREWYHUD_CRIT 1
+1 -1
View File
@@ -1 +1 @@
#define HID_RESTRICTED_END 101 //the first nonrestricted ID, automatically assigned on connection creation.
#define HID_RESTRICTED_END 101 //the first nonrestricted ID, automatically assigned on connection creation.
+26 -15
View File
@@ -1,19 +1,30 @@
#define SOLID 1
#define LIQUID 2
#define GAS 3
#define SOLID 1
#define LIQUID 2
#define GAS 3
#define INJECTABLE_1 1024 //Makes reagents addable through droppers and syringes
#define DRAWABLE_1 2048 //If a syringe can draw from it
#define OPENCONTAINER_1 4096 //Is an open container for chemistry purposes
#define TRANSPARENT_1 8192 //Used for non-open containers which you still want to be able to see the reagents off.
#define TOUCH 1 //splashing
#define INGEST 2 //ingestion
#define VAPOR 3 //foam, spray, blob attack
#define PATCH 4 //patches
#define INJECT 5 //injection
// container_type defines
#define INJECTABLE 1 // Makes it possible to add reagents through droppers and syringes.
#define DRAWABLE 2 // Makes it possible to remove reagents through syringes.
#define REFILLABLE 4 // Makes it possible to add reagents through any reagent container.
#define DRAINABLE 8 // Makes it possible to remove reagents through any reagent container.
#define TRANSPARENT 16 // Used on containers which you want to be able to see the reagents off.
#define AMOUNT_VISIBLE 32 // For non-transparent containers that still have the general amount of reagents in them visible.
// Is an open container for all intents and purposes.
#define OPENCONTAINER REFILLABLE | DRAINABLE | TRANSPARENT
#define TOUCH 1 // splashing
#define INGEST 2 // ingestion
#define VAPOR 3 // foam, spray, blob attack
#define PATCH 4 // patches
#define INJECT 5 // injection
//defines passed through to the on_reagent_change proc
#define DEL_REAGENT 1 //reagent deleted (fully cleared)
#define ADD_REAGENT 2 // reagent added
#define REM_REAGENT 3 // reagent removed (may still exist)
#define DEL_REAGENT 1 // reagent deleted (fully cleared)
#define ADD_REAGENT 2 // reagent added
#define REM_REAGENT 3 // reagent removed (may still exist)
+61
View File
@@ -0,0 +1,61 @@
//RDSCREEN screens
#define RDSCREEN_MENU 0
#define RDSCREEN_TECHDISK 1
#define RDSCREEN_DESIGNDISK 20
#define RDSCREEN_DESIGNDISK_UPLOAD 21
#define RDSCREEN_DECONSTRUCT 3
#define RDSCREEN_PROTOLATHE 40
#define RDSCREEN_PROTOLATHE_MATERIALS 41
#define RDSCREEN_PROTOLATHE_CHEMICALS 42
#define RDSCREEN_PROTOLATHE_CATEGORY_VIEW 43
#define RDSCREEN_PROTOLATHE_SEARCH 44
#define RDSCREEN_IMPRINTER 50
#define RDSCREEN_IMPRINTER_MATERIALS 51
#define RDSCREEN_IMPRINTER_CHEMICALS 52
#define RDSCREEN_IMPRINTER_CATEGORY_VIEW 53
#define RDSCREEN_IMPRINTER_SEARCH 54
#define RDSCREEN_SETTINGS 61
#define RDSCREEN_DEVICE_LINKING 62
#define RDSCREEN_TECHWEB 70
#define RDSCREEN_TECHWEB_NODEVIEW 71
#define RDSCREEN_TECHWEB_DESIGNVIEW 72
#define RDSCREEN_NOBREAK "<NO_HTML_BREAK>"
#define RDSCREEN_TEXT_NO_PROTOLATHE "<div><h3>No Protolathe Linked!</h3></div><br>"
#define RDSCREEN_TEXT_NO_IMPRINTER "<div><h3>No Circuit Imprinter Linked!</h3></div><br>"
#define RDSCREEN_TEXT_NO_DECONSTRUCT "<div><h3>No Deconstructive Analyzer Linked!</h3></div><br>"
#define RDSCREEN_TEXT_NO_TDISK "<div><h3>No Technology Disk Inserted!</h3></div><br>"
#define RDSCREEN_TEXT_NO_DDISK "<div><h3>No Design Disk Inserted!</h3></div><br>"
#define RDSCREEN_TEXT_NO_SNODE "<div><h3>No Technology Node Selected!</h3></div><br>"
#define RDSCREEN_TEXT_NO_SDESIGN "<div><h3>No Design Selected!</h3></div><br>"
#define RDSCREEN_UI_LATHE_CHECK if(!linked_lathe) { return RDSCREEN_TEXT_NO_PROTOLATHE }
#define RDSCREEN_UI_IMPRINTER_CHECK if(!linked_imprinter) { return RDSCREEN_TEXT_NO_IMPRINTER }
#define RDSCREEN_UI_DECONSTRUCT_CHECK if(!linked_destroy) { return RDSCREEN_TEXT_NO_DECONSTRUCT }
#define RDSCREEN_UI_TDISK_CHECK if(!t_disk) { return RDSCREEN_TEXT_NO_TDISK }
#define RDSCREEN_UI_DDISK_CHECK if(!d_disk) { return RDSCREEN_TEXT_NO_DDISK }
#define RDSCREEN_UI_SNODE_CHECK if(!selected_node) { return RDSCREEN_TEXT_NO_SNODE }
#define RDSCREEN_UI_SDESIGN_CHECK if(!selected_design) { return RDSCREEN_TEXT_NO_SDESIGN }
#define DEPLATHE_SCREEN_PRIMARY 1
#define DEPLATHE_SCREEN_SEARCH 2
#define DEPLATHE_SCREEN_MATERIALS 3
#define DEPLATHE_SCREEN_CHEMICALS 4
#define DEPPRINTER_SCREEN_PRIMARY 1
#define DEPPRINTER_SCREEN_SEARCH 2
#define DEPPRINTER_SCREEN_MATERIALS 3
#define DEPPRINTER_SCREEN_CHEMICALS 4
#define DEPARTMENTAL_FLAG_SECURITY 1
#define DEPARTMENTAL_FLAG_MEDICAL 2
#define DEPARTMENTAL_FLAG_CARGO 4
#define DEPARTMENTAL_FLAG_SCIENCE 8
#define DEPARTMENTAL_FLAG_ENGINEERING 16
#define DEPARTMENTAL_FLAG_SERVICE 32
#define DEPARTMENTAL_FLAG_ALL 64 //NO THIS DOESN'T ALLOW YOU TO PRINT EVERYTHING, IT'S FOR ALL DEPARTMENTS!
//#define DEPARTMENTAL_FLAG_MINING 128
#define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN"
+7 -1
View File
@@ -49,4 +49,10 @@
#define LOGCHAT "chat"
#define LOGASAY "adminsay"
#define LOGCOMMENT "comment"
#define LOGOOC "ooc"
#define LOGOOC "ooc"
#define LINGHIVE_NONE 0
#define LINGHIVE_OUTSIDER 1
#define LINGHIVE_LING 2
#define LINGHIVE_LINK 3
+8
View File
@@ -0,0 +1,8 @@
#define SERVER_TOOLS_EXTERNAL_CONFIGURATION
#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name)
#define SERVER_TOOLS_READ_GLOBAL(Name) GLOB.##Name
#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value
#define SERVER_TOOLS_WORLD_ANNOUNCE(message) to_chat(world, "<span class='boldannounce'>[html_encode(##message)]</span>")
#define SERVER_TOOLS_LOG(message) log_world("SERVICE: [##message]")
#define SERVER_TOOLS_NOTIFY_ADMINS(event) message_admins(##event)
#define SERVER_TOOLS_CLIENT_COUNT GLOB.clients.len
+14 -13
View File
@@ -1,4 +1,5 @@
// /tg/station 13 server tools API v3.1.0.2
// /tg/station 13 server tools API
#define SERVICE_API_VERSION_STRING "3.2.0.1"
//CONFIGURATION
//use this define if you want to do configuration outside of this file
@@ -10,19 +11,19 @@
//create a global variable named `Name` and set it to `Value`
//These globals must not be modifiable from anywhere outside of the server tools
#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name)
#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value)
//Read the value in the global variable `Name`
#define SERVER_TOOLS_READ_GLOBAL(Name) GLOB.##Name
#define SERVER_TOOLS_READ_GLOBAL(Name)
//Set the value in the global variable `Name` to `Value`
#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value
#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value)
//display an announcement `message` from the server to all players
#define SERVER_TOOLS_WORLD_ANNOUNCE(message) to_chat(world, "<span class='boldannounce'>[html_encode(##message)]</span>")
#define SERVER_TOOLS_WORLD_ANNOUNCE(message)
//Write a string `message` to a server log
#define SERVER_TOOLS_LOG(message) log_world("SERVICE: [##message]")
#define SERVER_TOOLS_LOG(message)
//Notify current in-game administrators of a string `event`
#define SERVER_TOOLS_NOTIFY_ADMINS(event) message_admins(##event)
#define SERVER_TOOLS_NOTIFY_ADMINS(event)
//The current amount of connected clients
#define SERVER_TOOLS_CLIENT_COUNT GLOB.clients.len
#define SERVER_TOOLS_CLIENT_COUNT
#endif
//Required hooks:
@@ -64,16 +65,15 @@
//IMPLEMENTATION
#define SERVICE_API_VERSION_STRING "3.1.0.2"
#define REBOOT_MODE_NORMAL 0
#define REBOOT_MODE_HARD 1
#define REBOOT_MODE_SHUTDOWN 2
#define SERVICE_WORLD_PARAM "server_service"
#define SERVICE_VERSION_PARAM "server_service_version"
#define SERVICE_INSTANCE_PARAM "server_instance"
#define SERVICE_PR_TEST_JSON "prtestjob.json"
#define SERVICE_INTERFACE_DLL "TGServiceInterface.dll"
#define SERVICE_INTERFACE_DLL "TGDreamDaemonBridge.dll"
#define SERVICE_INTERFACE_FUNCTION "DDEntryPoint"
#define SERVICE_CMD_HARD_REBOOT "hard_reboot"
@@ -98,11 +98,12 @@
#define SERVICE_REQUEST_WORLD_REBOOT "worldreboot"
#define SERVICE_REQUEST_API_VERSION "api_ver"
#define SERVICE_RETURN_SUCCESS "SUCCESS"
/*
The MIT License
Copyright (c) 2011 Dominic Tarr
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
+5 -1
View File
@@ -70,4 +70,8 @@
//Rotation params
#define ROTATE_DIR 1
#define ROTATE_SMOOTH 2
#define ROTATE_OFFSET 4
#define ROTATE_OFFSET 4
#define SHUTTLE_DOCKER_LANDING_CLEAR 1
#define SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT 2
#define SHUTTLE_DOCKER_BLOCKED 3
+1 -1
View File
@@ -20,7 +20,7 @@
#define SOUND_MINIMUM_PRESSURE 10
#define FALLOFF_SOUNDS 0.5
#define FALLOFF_SOUNDS 1
//Ambience types
+34 -31
View File
@@ -1,31 +1,34 @@
/*
Used with the various stat variables (mob, machines)
*/
//mob/var/stat things
#define CONSCIOUS 0
#define SOFT_CRIT 1
#define UNCONSCIOUS 2
#define DEAD 3
//mob disabilities stat
#define BLIND 1
#define MUTE 2
#define DEAF 4
#define NEARSIGHT 8
#define FAT 32
#define HUSK 64
#define NOCLONE 128
#define CLUMSY 256
// bitflags for machine stat variable
#define BROKEN 1
#define NOPOWER 2
#define MAINT 4 // under maintaince
#define EMPED 8 // temporary broken by EMP pulse
//ai power requirement defines
#define POWER_REQ_NONE 0
#define POWER_REQ_ALL 1
#define POWER_REQ_CLOCKCULT 2
/*
Used with the various stat variables (mob, machines)
*/
//mob/var/stat things
#define CONSCIOUS 0
#define SOFT_CRIT 1
#define UNCONSCIOUS 2
#define DEAD 3
//mob disabilities stat
#define BLIND 1
#define MUTE 2
#define DEAF 4
#define NEARSIGHT 8
#define FAT 32
#define HUSK 64
#define NOCLONE 128
#define CLUMSY 256
#define DUMB 512
#define MONKEYLIKE 1024 //sets IsAdvancedToolUser to FALSE
#define PACIFISM 2048
// bitflags for machine stat variable
#define BROKEN 1
#define NOPOWER 2
#define MAINT 4 // under maintaince
#define EMPED 8 // temporary broken by EMP pulse
//ai power requirement defines
#define POWER_REQ_NONE 0
#define POWER_REQ_ALL 1
#define POWER_REQ_CLOCKCULT 2
+12 -11
View File
@@ -23,8 +23,8 @@
#define FLIGHTSUIT_PROCESSING_FULL 1
#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize
#define INITIALIZATION_INNEW_MAPLOAD 1 //New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_REGULAR 2 //New should call Initialize(FALSE)
#define INITIALIZATION_INNEW_MAPLOAD 2 //New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_REGULAR 1 //New should call Initialize(FALSE)
#define INITIALIZE_HINT_NORMAL 0 //Nothing happens
#define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize
@@ -46,15 +46,16 @@
#define INIT_ORDER_DBCORE 18
#define INIT_ORDER_BLACKBOX 17
#define INIT_ORDER_SERVER_MAINT 16
#define INIT_ORDER_EVENTS 15
#define INIT_ORDER_JOBS 14
#define INIT_ORDER_TICKER 13
#define INIT_ORDER_MAPPING 12
#define INIT_ORDER_ATOMS 11
#define INIT_ORDER_NETWORKS 10
#define INIT_ORDER_LANGUAGE 9
#define INIT_ORDER_MACHINES 8
#define INIT_ORDER_CIRCUIT 7
#define INIT_ORDER_RESEARCH 15
#define INIT_ORDER_EVENTS 14
#define INIT_ORDER_JOBS 13
#define INIT_ORDER_TICKER 12
#define INIT_ORDER_MAPPING 11
#define INIT_ORDER_ATOMS 10
#define INIT_ORDER_NETWORKS 9
#define INIT_ORDER_LANGUAGE 8
#define INIT_ORDER_MACHINES 7
#define INIT_ORDER_CIRCUIT 6
#define INIT_ORDER_TIMER 1
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_AIR -1
+18 -18
View File
@@ -9,6 +9,16 @@
* Misc
*/
#define LAZYINITLIST(L) if (!L) L = list()
#define UNSETEMPTY(L) if (L && !L.len) L = null
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } }
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
#define LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
//Returns a list in plain english as a string
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
var/total = input.len
@@ -32,9 +42,9 @@
//Returns list element or null. Should prevent "index out of bounds" error.
/proc/listgetindex(list/L, index)
if(istype(L))
if(isnum(index) && IsInteger(index))
if(IsInRange(index,1,L.len))
if(LAZYLEN(L))
if(isnum(index) && ISINTEGER(index))
if(ISINRANGE(index,1,L.len))
return L[index]
else if(index in L)
return L[index]
@@ -42,7 +52,7 @@
//Return either pick(list) or null if list is not of type /list or is empty
/proc/safepick(list/L)
if(istype(L) && L.len)
if(LAZYLEN(L))
return pick(L)
//Checks if the list is empty
@@ -53,7 +63,7 @@
//Checks for specific types in a list
/proc/is_type_in_list(atom/A, list/L)
if(!L || !L.len || !A)
if(!LAZYLEN(L) || !A)
return FALSE
for(var/type in L)
if(istype(A, type))
@@ -62,7 +72,7 @@
//Checks for specific types in specifically structured (Assoc "type" = TRUE) lists ('typecaches')
/proc/is_type_in_typecache(atom/A, list/L)
if(!L || !L.len || !A)
if(!LAZYLEN(L) || !A)
return FALSE
if(ispath(A))
@@ -72,7 +82,7 @@
//Checks for a string in a list
/proc/is_string_in_list(string, list/L)
if(!L || !L.len || !string)
if(!LAZYLEN(L) || !string)
return
for(var/V in L)
if(string == V)
@@ -81,7 +91,7 @@
//Removes a string from a list
/proc/remove_strings_from_list(string, list/L)
if(!L || !L.len || !string)
if(!LAZYLEN(L) || !string)
return
for(var/V in L)
if(V == string)
@@ -486,16 +496,6 @@
//Picks from the list, with some safeties, and returns the "default" arg if it fails
#define DEFAULTPICK(L, default) ((islist(L) && length(L)) ? pick(L) : default)
#define LAZYINITLIST(L) if (!L) L = list()
#define UNSETEMPTY(L) if (L && !L.len) L = null
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } }
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
#define LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
/* Definining a counter as a series of key -> numeric value entries
* All these procs modify in place.
-19
View File
@@ -326,25 +326,6 @@
return M
return null
// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer.
/proc/get_candidates(be_special_type, afk_bracket = CONFIG_GET(number/inactivity_period), jobbanType)
var/list/candidates = list()
// Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000))
var/afk_period = CONFIG_GET(number/afk_period)
while(!candidates.len && afk_bracket < afk_period)
for(var/mob/dead/observer/G in GLOB.player_list)
if(G.client != null)
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
if(!G.client.is_afk(afk_bracket) && (be_special_type in G.client.prefs.be_special))
if (jobbanType)
if(!(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate")))
candidates += G.client
else
candidates += G.client
afk_bracket += 600 // Add a minute to the bracket, for every attempt
return candidates
/proc/considered_alive(datum/mind/M, enforce_human = TRUE)
if(M && M.current)
if(enforce_human)
-5
View File
@@ -72,11 +72,6 @@
var/datum/material/D = new path()
GLOB.materials_list[D.id] = D
//Techs
for(var/path in subtypesof(/datum/tech))
var/datum/tech/D = new path()
GLOB.tech_list[D.id] = D
//Emotes
for(var/path in subtypesof(/datum/emote))
var/datum/emote/E = new path()
-255
View File
@@ -1,255 +0,0 @@
// Credits to Nickr5 for the useful procs I've taken from his library resource.
GLOBAL_VAR_INIT(E, 2.71828183)
GLOBAL_VAR_INIT(Sqrt2, 1.41421356)
// List of square roots for the numbers 1-100.
GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10))
/proc/sign(x)
return x!=0?x/abs(x):0
/proc/Atan2(x, y)
if(!x && !y)
return 0
var/a = arccos(x / sqrt(x*x + y*y))
return y >= 0 ? a : -a
/proc/Ceiling(x, y=1)
return -round(-x / y) * y
/proc/Floor(x, y=1)
return round(x / y) * y
#define Clamp(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
/proc/Modulus(x, y) //Byond's modulus doesn't work with decimals.
return x - y * round(x / y)
// cotangent
/proc/Cot(x)
return 1 / Tan(x)
// cosecant
/proc/Csc(x)
return 1 / sin(x)
/proc/Default(a, b)
return a ? a : b
// Greatest Common Divisor - Euclid's algorithm
/proc/Gcd(a, b)
return b ? Gcd(b, a % b) : a
/proc/Inverse(x)
return 1 / x
#define InverseSquareLaw(initial_strength,cur_distance,initial_distance) (initial_strength*(initial_distance**2/cur_distance**2))
/proc/IsAboutEqual(a, b, deviation = 0.1)
return abs(a - b) <= deviation
/proc/IsEven(x)
return x % 2 == 0
// Returns true if val is from min to max, inclusive.
/proc/IsInRange(val, min, max)
return min <= val && val <= max
/proc/IsInteger(x)
return round(x) == x
/proc/IsOdd(x)
return !IsEven(x)
/proc/IsMultiple(x, y)
return x % y == 0
// Least Common Multiple
/proc/Lcm(a, b)
return abs(a) / Gcd(a, b) * abs(b)
// Performs a linear interpolation between a and b.
// Note that amount=0 returns a, amount=1 returns b, and
// amount=0.5 returns the mean of a and b.
/proc/Lerp(a, b, amount = 0.5)
return a + (b - a) * amount
//Calculates the sum of a list of numbers.
/proc/Sum(var/list/data)
. = 0
for(var/val in data)
.+= val
//Calculates the mean of a list of numbers.
/proc/Mean(var/list/data)
. = Sum(data) / (data.len)
// Returns the nth root of x.
/proc/Root(n, x)
return x ** (1 / n)
// secant
/proc/Sec(x)
return 1 / cos(x)
// The quadratic formula. Returns a list with the solutions, or an empty list
// if they are imaginary.
/proc/SolveQuadratic(a, b, c)
ASSERT(a)
. = list()
var/d = b*b - 4 * a * c
var/bottom = 2 * a
if(d < 0)
return
var/root = sqrt(d)
. += (-b + root) / bottom
if(!d)
return
. += (-b - root) / bottom
// tangent
/proc/Tan(x)
return sin(x) / cos(x)
/proc/ToDegrees(radians)
// 180 / Pi
return radians * 57.2957795
/proc/ToRadians(degrees)
// Pi / 180
return degrees * 0.0174532925
// Will filter out extra rotations and negative rotations
// E.g: 540 becomes 180. -180 becomes 180.
/proc/SimplifyDegrees(degrees)
degrees = degrees % 360
if(degrees < 0)
degrees += 360
return degrees
// min is inclusive, max is exclusive
/proc/Wrap(val, min, max)
var/d = max - min
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))
/proc/get_angle_of_incidence(face_angle, angle_in, auto_normalize = TRUE)
var/angle_in_s = NORM_ROT(angle_in)
var/face_angle_s = NORM_ROT(face_angle)
var/incidence = face_angle_s - angle_in_s
var/incidence_s = incidence
while(incidence_s < -90)
incidence_s += 180
while(incidence_s > 90)
incidence_s -= 180
if(auto_normalize)
return incidence_s
else
return incidence
//A logarithm that converts an integer to a number scaled between 0 and 1 (can be tweaked to be higher).
//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
/proc/TransformUsingVariable(input, inputmaximum, scaling_modifier = 0)
var/inputToDegrees = (input/inputmaximum)*180 //Converting from a 0 -> 100 scale to a 0 -> 180 scale. The 0 -> 180 scale corresponds to degrees
var/size_factor = ((-cos(inputToDegrees) +1) /2) //returns a value from 0 to 1
return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5
//converts a uniform distributed random number into a normal distributed one
//since this method produces two random numbers, one is saved for subsequent calls
//(making the cost negligble for every second call)
//This will return +/- decimals, situated about mean with standard deviation stddev
//68% chance that the number is within 1stddev
//95% chance that the number is within 2stddev
//98% chance that the number is within 3stddev...etc
#define ACCURACY 10000
/proc/gaussian(mean, stddev)
var/static/gaussian_next
var/R1;var/R2;var/working
if(gaussian_next != null)
R1 = gaussian_next
gaussian_next = null
else
do
R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
working = R1*R1 + R2*R2
while(working >= 1 || working==0)
working = sqrt(-2 * log(working) / working)
R1 *= working
gaussian_next = R2 * working
return (mean + stddev * R1)
#undef ACCURACY
/proc/mouse_angle_from_client(client/client)
var/list/mouse_control = params2list(client.mouseParams)
if(mouse_control["screen-loc"])
var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",")
var/list/screen_loc_X = splittext(screen_loc_params[1],":")
var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
var/x = (text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32)
var/y = (text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32)
var/screenview = (client.view * 2 + 1) * world.icon_size //Refer to http://www.byond.com/docs/ref/info.html#/client/var/view for mad maths
var/ox = round(screenview/2) - client.pixel_x //"origin" x
var/oy = round(screenview/2) - client.pixel_y //"origin" y
var/angle = NORM_ROT(Atan2(y - oy, x - ox))
return angle
/proc/get_turf_in_angle(angle, turf/starting, increments)
var/pixel_x = 0
var/pixel_y = 0
for(var/i in 1 to increments)
pixel_x += sin(angle)+16*sin(angle)*2
pixel_y += cos(angle)+16*cos(angle)*2
var/new_x = starting.x
var/new_y = starting.y
while(pixel_x > 16)
pixel_x -= 32
new_x++
while(pixel_x < -16)
pixel_x += 32
new_x--
while(pixel_y > 16)
pixel_y -= 32
new_y++
while(pixel_y < -16)
pixel_y += 32
new_y--
new_x = Clamp(new_x, 0, world.maxx)
new_y = Clamp(new_y, 0, world.maxy)
return locate(new_x, new_y, starting.z)
/proc/round_down(num)
if(round(num) != num)
return round(num--)
else return num
//proc/get_overlap()
// Returns a list where [1] is all x values and [2] is all y values that overlap between the given pair of rectangles
/proc/get_overlap(x1, y1, x2, y2, x3, y3, x4, y4)
var/list/region_x1 = list()
var/list/region_y1 = list()
var/list/region_x2 = list()
var/list/region_y2 = list()
// These loops create loops filled with x/y values that the boundaries inhabit
// ex: list(5, 6, 7, 8, 9)
for(var/i in min(x1, x2) to max(x1, x2))
region_x1["[i]"] = TRUE
for(var/i in min(y1, y2) to max(y1, y2))
region_y1["[i]"] = TRUE
for(var/i in min(x3, x4) to max(x3, x4))
region_x2["[i]"] = TRUE
for(var/i in min(y3, y4) to max(y3, y4))
region_y2["[i]"] = TRUE
return list(region_x1 & region_x2, region_y1 & region_y2)
+1 -1
View File
@@ -359,7 +359,7 @@ Proc for attack log creation, because really why not
if(!user)
return 0
var/atom/Tloc = null
if(target)
if(target && !isturf(target))
Tloc = target.loc
var/atom/Uloc = user.loc
+1 -5
View File
@@ -121,9 +121,6 @@ GLOBAL_VAR(command_name)
return new_station_name
/proc/syndicate_name()
var/static/syndicate_name
if (syndicate_name)
return syndicate_name
var/name = ""
@@ -146,8 +143,7 @@ GLOBAL_VAR(command_name)
else
name += pick("-", "*", "")
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive")
syndicate_name = name
return name
+14 -14
View File
@@ -1,14 +1,14 @@
// Ensure the frequency is within bounds of what it should be sending/recieving at
/proc/sanitize_frequency(frequency, free = FALSE)
. = round(frequency)
if(free)
. = Clamp(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ)
else
. = Clamp(frequency, MIN_FREQ, MAX_FREQ)
if(!(. % 2)) // Ensure the last digit is an odd number
. += 1
// Format frequency by moving the decimal.
/proc/format_frequency(frequency)
frequency = text2num(frequency)
return "[round(frequency / 10)].[frequency % 10]"
// Ensure the frequency is within bounds of what it should be sending/recieving at
/proc/sanitize_frequency(frequency, free = FALSE)
. = round(frequency)
if(free)
. = CLAMP(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ)
else
. = CLAMP(frequency, MIN_FREQ, MAX_FREQ)
if(!(. % 2)) // Ensure the last digit is an odd number
. += 1
// Format frequency by moving the decimal.
/proc/format_frequency(frequency)
frequency = text2num(frequency)
return "[round(frequency / 10)].[frequency % 10]"
+420
View File
@@ -0,0 +1,420 @@
/datum/controller/subsystem/ticker/proc/gather_roundend_feedback()
var/clients = GLOB.player_list.len
var/surviving_humans = 0
var/surviving_total = 0
var/ghosts = 0
var/escaped_humans = 0
var/escaped_total = 0
for(var/mob/M in GLOB.player_list)
if(ishuman(M))
if(!M.stat)
surviving_humans++
if(M.z == ZLEVEL_CENTCOM)
escaped_humans++
if(!M.stat)
surviving_total++
if(M.z == ZLEVEL_CENTCOM)
escaped_total++
if(isobserver(M))
ghosts++
if(clients)
SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients"))
if(ghosts)
SSblackbox.record_feedback("nested tally", "round_end_stats", ghosts, list("ghosts"))
if(surviving_humans)
SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_humans, list("survivors", "human"))
if(surviving_total)
SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_total, list("survivors", "total"))
if(escaped_humans)
SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_humans, list("escapees", "human"))
if(escaped_total)
SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_total, list("escapees", "total"))
gather_antag_success_rate()
/datum/controller/subsystem/ticker/proc/gather_antag_success_rate()
var/team_gid = 1
var/list/team_ids = list()
for(var/datum/antagonist/A in GLOB.antagonists)
var/list/antag_info = list()
antag_info["key"] = A.owner.key
antag_info["name"] = A.owner.name
antag_info["antagonist_type"] = A.type
antag_info["antagonist_name"] = A.name //For auto and custom roles
antag_info["objectives"] = list()
antag_info["team"] = list()
var/datum/team/T = A.get_team()
if(T)
antag_info["team"]["type"] = T.type
antag_info["team"]["name"] = T.name
if(!team_ids[T])
team_ids[T] = team_gid++
antag_info["team"]["id"] = team_ids[T]
if(!A.owner)
continue
if(A.objectives.len)
for(var/datum/objective/O in A.objectives)
var/result = O.check_completion() ? "SUCCESS" : "FAIL"
antag_info["objectives"] += list(list("objective_type"=O.type,"text"=O.explanation_text,"result"=result))
SSblackbox.record_feedback("associative", "antagonists", 1, antag_info)
/datum/controller/subsystem/ticker/proc/declare_completion()
set waitfor = FALSE
to_chat(world, "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>")
if(LAZYLEN(GLOB.round_end_notifiees))
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
/*for(var/client/C in GLOB.clients)
if(!C.credits)
C.RollCredits()
C.playtitlemusic(40)*/
display_report()
gather_roundend_feedback()
CHECK_TICK
// Add AntagHUD to everyone, see who was really evil the whole time!
for(var/datum/atom_hud/antag/H in GLOB.huds)
for(var/m in GLOB.player_list)
var/mob/M = m
H.add_hud_to(M)
CHECK_TICK
//Set news report and mode result
mode.set_round_result()
send2irc("Server", "Round just ended.")
if(CONFIG_GET(string/cross_server_address))
send_news_report()
CHECK_TICK
//These need update to actually reflect the real antagonists
//Print a list of antagonists to the server log
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
for(var/datum/mind/Mind in minds)
var/temprole = Mind.special_role
if(temprole) //if they are an antagonist of some sort.
if(temprole in total_antagonists) //If the role exists already, add the name to it
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
else
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
CHECK_TICK
//Now print them all into the log!
log_game("Antagonists at round end were...")
for(var/i in total_antagonists)
log_game("[i]s[total_antagonists[i]].")
CHECK_TICK
//Collects persistence features
if(mode.allow_persistence_save)
SSpersistence.CollectData()
//stop collecting feedback during grifftime
SSblackbox.Seal()
sleep(50)
ready_for_reboot = TRUE
standard_reboot()
/datum/controller/subsystem/ticker/proc/standard_reboot()
if(ready_for_reboot)
if(mode.station_was_nuked)
Reboot("Station destroyed by Nuclear Device.", "nuke")
else
Reboot("Round ended.", "proper completion")
else
CRASH("Attempted standard reboot without ticker roundend completion")
//Common part of the report
/datum/controller/subsystem/ticker/proc/build_roundend_report()
var/list/parts = list()
//Gamemode specific things. Should be empty most of the time.
parts += mode.special_report()
CHECK_TICK
//AI laws
parts += law_report()
CHECK_TICK
//Antagonists
parts += antag_report()
CHECK_TICK
//Medals
parts += medal_report()
//Station Goals
parts += goal_report()
listclearnulls(parts)
return parts.Join()
/datum/controller/subsystem/ticker/proc/survivor_report()
var/list/parts = list()
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
var/num_survivors = 0
var/num_escapees = 0
var/num_shuttle_escapees = 0
//Player status report
for(var/i in GLOB.mob_list)
var/mob/Player = i
if(Player.mind && !isnewplayer(Player))
if(Player.stat != DEAD && !isbrain(Player))
num_survivors++
if(station_evacuated) //If the shuttle has already left the station
var/list/area/shuttle_areas
if(SSshuttle && SSshuttle.emergency)
shuttle_areas = SSshuttle.emergency.shuttle_areas
if(Player.onCentCom() || Player.onSyndieBase())
num_escapees++
if(shuttle_areas[get_area(Player)])
num_shuttle_escapees++
//Round statistics report
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
parts += "[GLOB.TAB]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>"
parts += "[GLOB.TAB]Station Integrity: <B>[mode.station_was_nuked ? "<span class='redtext'>Destroyed</span>" : "[station_integrity]%"]</B>"
var/total_players = GLOB.joined_player_list.len
if(total_players)
parts+= "[GLOB.TAB]Total Population: <B>[total_players]</B>"
if(station_evacuated)
parts += "<BR>[GLOB.TAB]Evacuation Rate: <B>[num_escapees] ([PERCENT(num_escapees/total_players)]%)</B>"
parts += "[GLOB.TAB](on emergency shuttle): <B>[num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)</B>"
parts += "[GLOB.TAB]Survival Rate: <B>[num_survivors] ([PERCENT(num_survivors/total_players)]%)</B>"
return parts.Join("<br>")
/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report)
var/list/report_parts = list()
report_parts += personal_report(C)
report_parts += common_report
var/datum/browser/roundend_report = new(C, "roundend")
roundend_report.width = 800
roundend_report.height = 600
roundend_report.set_content(report_parts.Join())
roundend_report.stylesheets = list()
roundend_report.add_stylesheet("roundend",'html/browser/roundend.css')
roundend_report.open(0)
/datum/controller/subsystem/ticker/proc/personal_report(client/C)
var/list/parts = list()
var/mob/M = C.mob
if(M.mind && !isnewplayer(M))
if(M.stat != DEAD && !isbrain(M))
if(EMERGENCY_ESCAPED_OR_ENDGAMED)
if(!M.onCentCom() || !M.onSyndieBase())
parts += "<div class='panel stationborder'>"
parts += "<span class='marooned'>You managed to survive, but were marooned on [station_name()]...</span>"
else
parts += "<div class='panel greenborder'>"
parts += "<span class='greentext'>You managed to survive the events on [station_name()] as [M.real_name].</span>"
else
parts += "<div class='panel greenborder'>"
parts += "<span class='greentext'>You managed to survive the events on [station_name()] as [M.real_name].</span>"
else
parts += "<div class='panel redborder'>"
parts += "<span class='redtext'>You did not survive the events on [station_name()]...</span>"
else
parts += "<div class='panel stationborder'>"
parts += "<br>"
if(GLOB.survivor_report)
parts += GLOB.survivor_report
else
parts += survivor_report()
parts += "</div>"
return parts.Join()
/datum/controller/subsystem/ticker/proc/display_report()
GLOB.common_report = build_roundend_report()
for(var/client/C in GLOB.clients)
show_roundend_report(C,GLOB.common_report)
give_show_report_button(C)
CHECK_TICK
/datum/controller/subsystem/ticker/proc/law_report()
var/list/parts = list()
//Silicon laws report
for (var/i in GLOB.ai_list)
var/mob/living/silicon/ai/aiPlayer = i
if(aiPlayer.mind)
parts += "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws [aiPlayer.stat != DEAD ? "at the end of the round" : "when it was deactivated"] were:</b>"
parts += aiPlayer.laws.get_law_list(include_zeroth=TRUE)
parts += "<b>Total law changes: [aiPlayer.law_change_counter]</b>"
if (aiPlayer.connected_robots.len)
var/robolist = "<b>[aiPlayer.real_name]'s minions were:</b> "
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
if(robo.mind)
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]"
parts += "[robolist]"
for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs)
if (!robo.connected_ai && robo.mind)
if (robo.stat != DEAD)
parts += "<b>[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:</b>"
else
parts += "<b>[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:</b>"
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
parts += robo.laws.get_law_list(include_zeroth=TRUE)
if(parts.len)
return "<div class='panel stationborder'>[parts.Join("<br>")]</div>"
else
return ""
/datum/controller/subsystem/ticker/proc/goal_report()
var/list/parts = list()
if(mode.station_goals.len)
for(var/V in mode.station_goals)
var/datum/station_goal/G = V
parts += G.get_result()
return "<div class='panel stationborder'><ul>[parts.Join()]</ul></div>"
/datum/controller/subsystem/ticker/proc/medal_report()
if(GLOB.commendations.len)
var/list/parts = list()
parts += "<span class='header'>Medal Commendations:</span>"
for (var/com in GLOB.commendations)
parts += com
return "<div class='panel stationborder'>[parts.Join("<br>")]</div>"
return ""
/datum/controller/subsystem/ticker/proc/antag_report()
var/list/result = list()
var/list/all_teams = list()
var/list/all_antagonists = list()
for(var/datum/antagonist/A in GLOB.antagonists)
all_teams |= A.get_team()
all_antagonists += A
for(var/datum/team/T in all_teams)
result += T.roundend_report()
for(var/datum/antagonist/X in all_antagonists)
if(X.get_team() == T)
all_antagonists -= X
result += " "//newline between teams
var/currrent_category
var/datum/antagonist/previous_category
sortTim(all_antagonists, /proc/cmp_antag_category)
for(var/datum/antagonist/A in all_antagonists)
if(!A.show_in_roundend)
continue
if(A.roundend_category != currrent_category)
if(previous_category)
result += previous_category.roundend_report_footer()
result += "</div>"
result += "<div class='panel redborder'>"
result += A.roundend_report_header()
currrent_category = A.roundend_category
previous_category = A
result += A.roundend_report()
result += "<br>"
if(all_antagonists.len)
var/datum/antagonist/last = all_antagonists[all_antagonists.len]
result += last.roundend_report_footer()
result += "</div>"
return result.Join()
/proc/cmp_antag_category(datum/antagonist/A,datum/antagonist/B)
return sorttext(B.roundend_category,A.roundend_category)
/datum/controller/subsystem/ticker/proc/give_show_report_button(client/C)
var/datum/action/report/R = new
C.player_details.player_actions += R
R.Grant(C.mob)
to_chat(C,"<a href='?src=[REF(R)];report=1'>Show roundend report again</a>")
/datum/action/report
name = "Show roundend report"
button_icon_state = "vote"
/datum/action/report/Trigger()
if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED)
SSticker.show_roundend_report(owner.client,GLOB.common_report)
/datum/action/report/IsAvailable()
return 1
/datum/action/report/Topic(href,href_list)
if(usr != owner)
return
if(href_list["report"])
Trigger()
return
/proc/printplayer(datum/mind/ply, fleecheck)
var/text = "<b>[ply.key]</b> was <b>[ply.name]</b> the <b>[ply.assigned_role]</b> and"
if(ply.current)
if(ply.current.stat == DEAD)
text += " <span class='redtext'>died</span>"
else
text += " <span class='greentext'>survived</span>"
if(fleecheck)
var/turf/T = get_turf(ply.current)
if(!T || !(T.z in GLOB.station_z_levels))
text += " while <span class='redtext'>fleeing the station</span>"
if(ply.current.real_name != ply.name)
text += " as <b>[ply.current.real_name]</b>"
else
text += " <span class='redtext'>had their body destroyed</span>"
return text
/proc/printplayerlist(list/players,fleecheck)
var/list/parts = list()
parts += "<ul class='playerlist'>"
for(var/datum/mind/M in players)
parts += "<li>[printplayer(M,fleecheck)]</li>"
parts += "</ul>"
return parts.Join()
/proc/printobjectives(datum/mind/ply)
var/list/objective_parts = list()
var/count = 1
for(var/datum/objective/objective in ply.objectives)
if(objective.check_completion())
objective_parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</span>"
else
objective_parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
count++
return objective_parts.Join("<br>")
+3 -3
View File
@@ -60,7 +60,7 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
if(!second)
return "0 seconds"
if(second >= 60)
minute = round_down(second/60)
minute = FLOOR(second/60, 1)
second = round(second - (minute*60), 0.1)
second_rounded = TRUE
if(second) //check if we still have seconds remaining to format, or if everything went into minute.
@@ -91,7 +91,7 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
if(!minute)
return "[second]"
if(minute >= 60)
hour = round_down(minute/60,1)
hour = FLOOR(minute/60, 1)
minute = (minute - (hour*60))
if(minute) //alot simpler from here since you don't have to worry about fractions
if(minute != 1)
@@ -114,7 +114,7 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
if(!hour)
return "[minute][second]"
if(hour >= 24)
day = round_down(hour/24,1)
day = FLOOR(hour/24, 1)
hour = (hour - (day*24))
if(hour)
if(hour != 1)
+18 -25
View File
@@ -14,30 +14,23 @@
//breaks when hittin invalid characters thereafter
/proc/hex2num(hex)
. = 0
if(istext(hex))
var/negative = 0
var/len = length(hex)
for(var/i=1, i<=len, i++)
var/num = text2ascii(hex,i)
switch(num)
if(48 to 57)
num -= 48 //0-9
if(97 to 102)
num -= 87 //a-f
if(65 to 70)
num -= 55 //A-F
if(45)
negative = 1//-
else
if(num)
break
else
continue
. *= 16
. += num
if(negative)
. *= -1
return .
var/place = 1
for(var/i in length(hex) to 1 step -1)
var/num = text2ascii(hex, i)
switch(num)
if(48 to 57)
num -= 48 //0-9
if(97 to 102)
num -= 87 //a-f
if(65 to 70)
num -= 55 //A-F
if(45)
return . * -1 // -
else
CRASH("Malformed hex number")
. += num * place
place *= 16
//Returns the hex value of a decimal number
//len == length of returned string
@@ -124,7 +117,7 @@
//Converts an angle (degrees) into an ss13 direction
/proc/angle2dir(degree)
degree = SimplifyDegrees(degree)
degree = SIMPLIFY_DEGREES(degree)
switch(degree)
if(0 to 22.5) //north requires two angle ranges
return NORTH
+58 -12
View File
@@ -147,10 +147,10 @@ Turf and target are separate in case you want to teleport some distance from a t
var/line[] = list(locate(px,py,M.z))
var/dx=N.x-px //x distance
var/dy=N.y-py
var/dxabs=abs(dx)//Absolute value of x distance
var/dyabs=abs(dy)
var/sdx=sign(dx) //Sign of x distance (+ or -)
var/sdy=sign(dy)
var/dxabs = abs(dx)//Absolute value of x distance
var/dyabs = abs(dy)
var/sdx = SIGN(dx) //Sign of x distance (+ or -)
var/sdy = SIGN(dy)
var/x=dxabs>>1 //Counters for steps taken, setting to distance/2
var/y=dyabs>>1 //Bit-shifting makes me l33t. It also makes getline() unnessecarrily fast.
var/j //Generic integer for counting
@@ -353,9 +353,8 @@ Turf and target are separate in case you want to teleport some distance from a t
var/M = E/(SPEED_OF_LIGHT_SQ)
return M
//Takes the value of energy used/produced/ect.
//Returns a text value of that number in W, kW, MW, or GW.
/proc/DisplayPower(var/powerused)
// Format a power value in W, kW, MW, or GW.
/proc/DisplayPower(powerused)
if(powerused < 1000) //Less than a kW
return "[powerused] W"
else if(powerused < 1000000) //Less than a MW
@@ -364,6 +363,21 @@ Turf and target are separate in case you want to teleport some distance from a t
return "[round((powerused * 0.000001),0.001)] MW"
return "[round((powerused * 0.000000001),0.0001)] GW"
// Format an energy value in J, kJ, MJ, or GJ. 1W = 1J/s.
/proc/DisplayEnergy(units)
// APCs process every (SSmachines.wait * 0.1) seconds, and turn 1 W of
// excess power into GLOB.CELLRATE energy units when charging cells.
// With the current configuration of wait=20 and CELLRATE=0.002, this
// means that one unit is 1 kJ.
units *= SSmachines.wait * 0.1 / GLOB.CELLRATE
if (units < 1000) // Less than a kJ
return "[round(units, 0.1)] J"
else if (units < 1000000) // Less than a MJ
return "[round(units * 0.001, 0.01)] kJ"
else if (units < 1000000000) // Less than a GJ
return "[round(units * 0.000001, 0.001)] MJ"
return "[round(units * 0.000000001, 0.0001)] GJ"
/proc/key_name(whom, include_link = null, include_name = 1)
var/mob/M
var/client/C
@@ -939,8 +953,8 @@ GLOBAL_LIST_INIT(WALLITEMS_INVERSE, typecacheof(list(
tY = tY[1]
tX = splittext(tX[1], ":")
tX = tX[1]
tX = Clamp(origin.x + text2num(tX) - world.view - 1, 1, world.maxx)
tY = Clamp(origin.y + text2num(tY) - world.view - 1, 1, world.maxy)
tX = CLAMP(origin.x + text2num(tX) - world.view - 1, 1, world.maxx)
tY = CLAMP(origin.y + text2num(tY) - world.view - 1, 1, world.maxy)
return locate(tX, tY, tZ)
/proc/screen_loc2turf(text, turf/origin)
@@ -952,8 +966,8 @@ GLOBAL_LIST_INIT(WALLITEMS_INVERSE, typecacheof(list(
tX = splittext(tZ[2], "-")
tX = text2num(tX[2])
tZ = origin.z
tX = Clamp(origin.x + 7 - tX, 1, world.maxx)
tY = Clamp(origin.y + 7 - tY, 1, world.maxy)
tX = CLAMP(origin.x + 7 - tX, 1, world.maxx)
tY = CLAMP(origin.y + 7 - tY, 1, world.maxy)
return locate(tX, tY, tZ)
/proc/IsValidSrc(datum/D)
@@ -1258,7 +1272,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
. = 0
var/i = DS2TICKS(initial_delay)
do
. += Ceiling(i*DELTA_CALC)
. += CEILING(i*DELTA_CALC, 1)
sleep(i*world.tick_lag*DELTA_CALC)
i *= 2
while (TICK_USAGE > min(TICK_LIMIT_TO_RUN, Master.current_ticklimit))
@@ -1493,3 +1507,35 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
else
return "\[[url_encode(thing.tag)]\]"
return "\ref[input]"
// Makes a call in the context of a different usr
// Use sparingly
/world/proc/PushUsr(mob/M, datum/callback/CB)
var/temp = usr
usr = M
. = CB.Invoke()
usr = temp
//Returns a list of all servants of Ratvar and observers.
/proc/servants_and_ghosts()
. = list()
for(var/V in GLOB.player_list)
if(is_servant_of_ratvar(V) || isobserver(V))
. += V
//datum may be null, but it does need to be a typed var
#define NAMEOF(datum, X) (list(##datum.##X, #X)[2])
#define VARSET_LIST_CALLBACK(target, var_name, var_value) CALLBACK(GLOBAL_PROC, /proc/___callbackvarset, ##target, ##var_name, ##var_value)
//dupe code because dm can't handle 3 level deep macros
#define VARSET_CALLBACK(datum, var, var_value) CALLBACK(GLOBAL_PROC, /proc/___callbackvarset, ##datum, NAMEOF(##datum, ##var), ##var_value)
/proc/___callbackvarset(list_or_datum, var_name, var_value)
if(length(list_or_datum))
list_or_datum[var_name] = var_value
return
var/datum/D = list_or_datum
if(IsAdminAdvancedProcCall())
D.vv_edit_var(var_name, var_value) //same result generally, unless badmemes
else
D.vars[var_name] = var_value
+12
View File
@@ -0,0 +1,12 @@
/proc/getviewsize(view)
var/viewX
var/viewY
if(isnum(view))
var/totalviewrange = 1 + 2 * view
viewX = totalviewrange
viewY = totalviewrange
else
var/list/viewrangelist = splittext(view,"x")
viewX = text2num(viewrangelist[1])
viewY = text2num(viewrangelist[2])
return list(viewX, viewY)
-1
View File
@@ -35,4 +35,3 @@ GLOBAL_PROTECT(MAX_EX_FLASH_RANGE)
GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14)
GLOBAL_PROTECT(MAX_EX_FLAME_RANGE)
GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5)
+6 -12
View File
@@ -1,18 +1,12 @@
GLOBAL_VAR_INIT(master_mode, "traitor") //"extended"
GLOBAL_VAR_INIT(secret_force_mode, "secret") // if this is anything but "secret", the secret rotation will forceably choose this mode
GLOBAL_VAR(common_report) //Contains commmon part of roundend report
GLOBAL_VAR(survivor_report) //Contains shared surivor report for roundend report (part of personal report)
GLOBAL_VAR_INIT(wavesecret, 0) // meteor mode, delays wave progression, terrible name
GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report
// Cult, needs to be global so admin cultists are functional
GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master
GLOBAL_DATUM(blood_target_image, /image)
GLOBAL_VAR_INIT(blood_target_reset_timer, null)
GLOBAL_DATUM(sac_mind, /datum/mind)
GLOBAL_VAR_INIT(sac_image, null)
GLOBAL_VAR_INIT(cult_vote_called, FALSE)
GLOBAL_VAR_INIT(cult_mastered, FALSE)
GLOBAL_VAR_INIT(reckoning_complete, FALSE)
GLOBAL_VAR_INIT(sac_complete, FALSE)
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
GLOBAL_LIST_EMPTY(summon_spots)
//TODO clear this one up too
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
+1
View File
@@ -24,6 +24,7 @@ GLOBAL_LIST_EMPTY(pai_list)
GLOBAL_LIST_EMPTY(available_ai_shells)
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list())) // One for each AI_* status define
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
GLOBAL_LIST_EMPTY(bots_list)
GLOBAL_LIST_EMPTY(language_datum_instances)
GLOBAL_LIST_EMPTY(all_languages)
+1
View File
@@ -4,6 +4,7 @@ GLOBAL_LIST_EMPTY(airlocks) //list of all airlocks
GLOBAL_LIST_EMPTY(mechas_list) //list of all mechs. Used by hostile mobs target tracking.
GLOBAL_LIST_EMPTY(shuttle_caller_list) //list of all communication consoles and AIs, for automatic shuttle calls when there are none.
GLOBAL_LIST_EMPTY(machines) //NOTE: this is a list of ALL machines now. The processing machines list is SSmachine.processing !
GLOBAL_LIST_EMPTY(navigation_computers) //list of all /obj/machinery/computer/camera_advanced/shuttle_docker
GLOBAL_LIST_EMPTY(syndicate_shuttle_boards) //important to keep track of for managing nukeops war declarations.
GLOBAL_LIST_EMPTY(navbeacons) //list of all bot nagivation beacons, used for patrolling.
GLOBAL_LIST_EMPTY(teleportbeacons) //list of all tracking beacons used by teleporters
+2
View File
@@ -16,3 +16,5 @@ GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a perce
GLOBAL_LIST_EMPTY(powernets)
GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes
GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details
+28 -18
View File
@@ -285,7 +285,7 @@
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)
C.chosen_sting.try_to_sting(src,A)
next_click = world.time + 5
return
swap_hand()
@@ -349,7 +349,7 @@
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)
C.chosen_sting.try_to_sting(src,A)
next_click = world.time + 5
return
..()
@@ -433,28 +433,38 @@
else
setDir(WEST)
//debug
/obj/screen/proc/scale_to(x1,y1)
if(!y1)
y1 = x1
var/matrix/M = new
M.Scale(x1,y1)
transform = M
/obj/screen/click_catcher
icon = 'icons/mob/screen_gen.dmi'
icon_state = "flash"
icon_state = "catcher"
plane = CLICKCATCHER_PLANE
mouse_opacity = MOUSE_OPACITY_OPAQUE
screen_loc = "CENTER"
/obj/screen/click_catcher/proc/UpdateGreed(view_size_x = 7, view_size_y = 7)
var/icon/newicon = icon('icons/mob/screen_gen.dmi', "flash")
if(view_size_x > 16 || view_size_y > 16)
newicon.Scale((16 * 2 + 1) * world.icon_size,(16 * 2 + 1) * world.icon_size)
icon = newicon
var/tx = view_size_x/16
var/ty = view_size_y/16
var/matrix/M = new
M.Scale(tx, ty)
transform = M
screen_loc = "CENTER-16,CENTER-16"
else
screen_loc = "CENTER-[view_size_x],CENTER-[view_size_y]"
newicon.Scale((view_size_x * 2 + 1) * world.icon_size,(view_size_y * 2 + 1) * world.icon_size)
icon = newicon
#define MAX_SAFE_BYOND_ICON_SCALE_TILES (MAX_SAFE_BYOND_ICON_SCALE_PX / world.icon_size)
#define MAX_SAFE_BYOND_ICON_SCALE_PX 33 * 32 //Not using world.icon_size on purpose.
/obj/screen/click_catcher/proc/UpdateGreed(view_size_x = 15, view_size_y = 15)
var/icon/newicon = icon('icons/mob/screen_gen.dmi', "catcher")
var/ox = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_x)
var/oy = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_y)
var/px = view_size_x * world.icon_size
var/py = view_size_y * world.icon_size
var/sx = min(MAX_SAFE_BYOND_ICON_SCALE_PX, px)
var/sy = min(MAX_SAFE_BYOND_ICON_SCALE_PX, py)
newicon.Scale(sx, sy)
icon = newicon
screen_loc = "CENTER-[(ox-1)*0.5],CENTER-[(oy-1)*0.5]"
var/matrix/M = new
M.Scale(px/sx, py/sy)
transform = M
/obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
+16
View File
@@ -8,15 +8,22 @@
var/button_icon_state
var/appearance_cache
var/id
/obj/screen/movable/action_button/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
if(locked)
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
return TRUE
moved = 0
usr.update_action_buttons() //redraw buttons that are no longer considered "moved"
return TRUE
if(modifiers["ctrl"])
locked = !locked
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
if(id && usr.client) //try to (un)remember position
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null
return TRUE
if(usr.next_click > world.time)
return
@@ -38,21 +45,30 @@
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
if(locked)
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
return TRUE
moved = FALSE
usr.update_action_buttons(TRUE)
return TRUE
if(modifiers["ctrl"])
locked = !locked
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
if(id && usr.client) //try to (un)remember position
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null
return TRUE
if(modifiers["alt"])
for(var/V in usr.actions)
var/datum/action/A = V
var/obj/screen/movable/action_button/B = A.button
B.moved = FALSE
if(B.id && usr.client)
usr.client.prefs.action_buttons_screen_locs["[B.name]_[B.id]"] = null
B.locked = usr.client.prefs.buttons_locked
locked = usr.client.prefs.buttons_locked
moved = FALSE
if(id && usr.client)
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = null
usr.update_action_buttons(TRUE)
to_chat(usr, "<span class='notice'>Action button positions have been reset.</span>")
return TRUE
+25 -22
View File
@@ -302,32 +302,41 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
/obj/screen/alert/bloodsense/process()
var/atom/blood_target
if(GLOB.blood_target)
if(!get_turf(GLOB.blood_target))
GLOB.blood_target = null
var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!antag)
return
var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives
if(antag.cult_team.blood_target)
if(!get_turf(antag.cult_team.blood_target))
antag.cult_team.blood_target = null
else
blood_target = GLOB.blood_target
blood_target = antag.cult_team.blood_target
if(Cviewer && Cviewer.seeking && Cviewer.master)
blood_target = Cviewer.master
desc = "Your blood sense is leading you to [Cviewer.master]"
if(!blood_target)
if(!GLOB.sac_complete)
if(sac_objective && !sac_objective.check_completion())
if(icon_state == "runed_sense0")
return
animate(src, transform = null, time = 1, loop = 0)
angle = 0
cut_overlays()
icon_state = "runed_sense0"
desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin."
add_overlay(GLOB.sac_image)
desc = "Nar-Sie demands that [sac_objective.target] be sacrificed before the summoning ritual can begin."
add_overlay(sac_objective.sac_image)
else
var/datum/objective/eldergod/summon_objective = locate() in antag.cult_team.objectives
if(!summon_objective)
return
if(icon_state == "runed_sense1")
return
animate(src, transform = null, time = 1, loop = 0)
angle = 0
cut_overlays()
icon_state = "runed_sense1"
desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(GLOB.summon_spots)]!"
desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(summon_objective.summon_spots)]!"
add_overlay(narnar)
return
var/turf/P = get_turf(blood_target)
@@ -388,23 +397,17 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
desc = "<font size=3><b>CHETR<br>NYY<br>HAGEHUGF-NAQ-UBABE<br>RATVAR.</b></font>"
else
var/servants = 0
var/validservants = 0
var/list/textlist
var/list/textlist = list()
for(var/mob/living/L in GLOB.alive_mob_list)
if(is_servant_of_ratvar(L))
servants++
if(ishuman(L) || issilicon(L))
validservants++
if(servants > 1)
if(validservants > 1)
textlist = list("<b>[servants]</b> Servants, <b>[validservants]</b> of which count towards scripture.<br>")
else
textlist = list("<b>[servants]</b> Servants, [validservants ? "<b>[validservants]</b> of which counts":"none of which count"] towards scripture.<br>")
else
textlist = list("<b>[servants]</b> Servant, who [validservants ? "counts":"does not count"] towards scripture.<br>")
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
textlist += "[i] Scripture: <b>[SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
var/datum/antagonist/clockcult/C = mob_viewer.mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
if(C && C.clock_team)
textlist += "[C.clock_team.eminence ? "There is an Eminence." : "<b>There is no Eminence! Get one ASAP!</b>"]<br>"
textlist += "There are currently <b>[servants]</b> servant[servants > 1 ? "s" : ""] of Ratvar.<br>"
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
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 = G.get_arrival_time(FALSE)
+2 -2
View File
@@ -16,9 +16,9 @@
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
var/list/actualview = getviewsize(client.view)
screen.view = client.view
screen.transform = matrix(scale, 0, 0, 0, scale, 0)
screen.transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
return screen
+6 -4
View File
@@ -255,11 +255,13 @@
/obj/screen/parallax_layer/proc/update_o(view)
if (!view)
view = world.view
var/count = Ceiling(view/(480/world.icon_size))+1
var/list/viewscales = getviewsize(view)
var/countx = CEILING((viewscales[1]/2)/(480/world.icon_size), 1)+1
var/county = CEILING((viewscales[2]/2)/(480/world.icon_size), 1)+1
var/list/new_overlays = new
for(var/x in -count to count)
for(var/y in -count to count)
for(var/x in -countx to countx)
for(var/y in -county to county)
if(x == 0 && y == 0)
continue
var/mutable_appearance/texture_overlay = mutable_appearance(icon, icon_state)
+277 -277
View File
@@ -1,277 +1,277 @@
/obj/screen/robot
icon = 'icons/mob/screen_cyborg.dmi'
/obj/screen/robot/module
name = "cyborg module"
icon_state = "nomod"
/obj/screen/robot/Click()
if(isobserver(usr))
return 1
/obj/screen/robot/module/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
if(R.module.type != /obj/item/robot_module)
R.hud_used.toggle_show_robot_modules()
return 1
R.pick_module()
/obj/screen/robot/module1
name = "module1"
icon_state = "inv1"
/obj/screen/robot/module1/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(1)
/obj/screen/robot/module2
name = "module2"
icon_state = "inv2"
/obj/screen/robot/module2/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(2)
/obj/screen/robot/module3
name = "module3"
icon_state = "inv3"
/obj/screen/robot/module3/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(3)
/obj/screen/robot/radio
name = "radio"
icon_state = "radio"
/obj/screen/robot/radio/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.radio.interact(R)
/obj/screen/robot/store
name = "store"
icon_state = "store"
/obj/screen/robot/store/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.uneq_active()
/obj/screen/robot/lamp
name = "headlamp"
icon_state = "lamp0"
/obj/screen/robot/lamp/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.control_headlamp()
/obj/screen/robot/thrusters
name = "ion thrusters"
icon_state = "ionpulse0"
/obj/screen/robot/thrusters/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_ionpulse()
/datum/hud/robot
ui_style_icon = 'icons/mob/screen_cyborg.dmi'
/datum/hud/robot/New(mob/owner, ui_style = 'icons/mob/screen_cyborg.dmi')
..()
var/mob/living/silicon/robot/mymobR = mymob
var/obj/screen/using
using = new/obj/screen/language_menu
using.screen_loc = ui_borg_language_menu
static_inventory += using
//Radio
using = new /obj/screen/robot/radio()
using.screen_loc = ui_borg_radio
static_inventory += using
//Module select
using = new /obj/screen/robot/module1()
using.screen_loc = ui_inv1
static_inventory += using
mymobR.inv1 = using
using = new /obj/screen/robot/module2()
using.screen_loc = ui_inv2
static_inventory += using
mymobR.inv2 = using
using = new /obj/screen/robot/module3()
using.screen_loc = ui_inv3
static_inventory += using
mymobR.inv3 = using
//End of module select
//Photography stuff
using = new /obj/screen/ai/image_take()
using.screen_loc = ui_borg_camera
static_inventory += using
using = new /obj/screen/ai/image_view()
using.screen_loc = ui_borg_album
static_inventory += using
//Sec/Med HUDs
using = new /obj/screen/ai/sensors()
using.screen_loc = ui_borg_sensor
static_inventory += using
//Headlamp control
using = new /obj/screen/robot/lamp()
using.screen_loc = ui_borg_lamp
static_inventory += using
mymobR.lamp_button = using
//Thrusters
using = new /obj/screen/robot/thrusters()
using.screen_loc = ui_borg_thrusters
static_inventory += using
mymobR.thruster_button = using
//Intent
action_intent = new /obj/screen/act_intent/robot()
action_intent.icon_state = mymob.a_intent
static_inventory += action_intent
//Health
healths = new /obj/screen/healths/robot()
infodisplay += healths
//Installed Module
mymobR.hands = new /obj/screen/robot/module()
mymobR.hands.screen_loc = ui_borg_module
static_inventory += mymobR.hands
//Store
module_store_icon = new /obj/screen/robot/store()
module_store_icon.screen_loc = ui_borg_store
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_borg_pull
hotkeybuttons += pull_icon
zone_select = new /obj/screen/zone_sel/robot()
zone_select.update_icon(mymob)
static_inventory += zone_select
/datum/hud/proc/toggle_show_robot_modules()
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
R.shown_robot_modules = !R.shown_robot_modules
update_robot_modules_display()
/datum/hud/proc/update_robot_modules_display(mob/viewer)
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(!R.module)
return
if(!R.client)
return
if(R.shown_robot_modules && screenmob.hud_used.hud_shown)
//Modules display is shown
screenmob.client.screen += module_store_icon //"store" icon
if(!R.module.modules)
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
return
if(!R.robot_modules_background)
return
var/display_rows = Ceiling(length(R.module.get_inactive_modules()) / 8)
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
screenmob.client.screen += R.robot_modules_background
var/x = -4 //Start at CENTER-4,SOUTH+1
var/y = 1
for(var/atom/movable/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen += A
if(x < 0)
A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7"
else
A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7"
A.layer = ABOVE_HUD_LAYER
A.plane = ABOVE_HUD_PLANE
x++
if(x == 4)
x = -4
y++
else
//Modules display is hidden
screenmob.client.screen -= module_store_icon //"store" icon
for(var/atom/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen -= A
R.shown_robot_modules = 0
screenmob.client.screen -= R.robot_modules_background
/mob/living/silicon/robot/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/robot(src)
/datum/hud/robot/persistent_inventory_update(mob/viewer)
if(!mymob)
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(screenmob.hud_used)
if(screenmob.hud_used.hud_shown)
for(var/i in 1 to R.held_items.len)
var/obj/item/I = R.held_items[i]
if(I)
switch(i)
if(1)
I.screen_loc = ui_inv1
if(2)
I.screen_loc = ui_inv2
if(3)
I.screen_loc = ui_inv3
else
return
screenmob.client.screen += I
else
for(var/obj/item/I in R.held_items)
screenmob.client.screen -= I
/obj/screen/robot
icon = 'icons/mob/screen_cyborg.dmi'
/obj/screen/robot/module
name = "cyborg module"
icon_state = "nomod"
/obj/screen/robot/Click()
if(isobserver(usr))
return 1
/obj/screen/robot/module/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
if(R.module.type != /obj/item/robot_module)
R.hud_used.toggle_show_robot_modules()
return 1
R.pick_module()
/obj/screen/robot/module1
name = "module1"
icon_state = "inv1"
/obj/screen/robot/module1/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(1)
/obj/screen/robot/module2
name = "module2"
icon_state = "inv2"
/obj/screen/robot/module2/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(2)
/obj/screen/robot/module3
name = "module3"
icon_state = "inv3"
/obj/screen/robot/module3/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(3)
/obj/screen/robot/radio
name = "radio"
icon_state = "radio"
/obj/screen/robot/radio/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.radio.interact(R)
/obj/screen/robot/store
name = "store"
icon_state = "store"
/obj/screen/robot/store/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.uneq_active()
/obj/screen/robot/lamp
name = "headlamp"
icon_state = "lamp0"
/obj/screen/robot/lamp/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.control_headlamp()
/obj/screen/robot/thrusters
name = "ion thrusters"
icon_state = "ionpulse0"
/obj/screen/robot/thrusters/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_ionpulse()
/datum/hud/robot
ui_style_icon = 'icons/mob/screen_cyborg.dmi'
/datum/hud/robot/New(mob/owner, ui_style = 'icons/mob/screen_cyborg.dmi')
..()
var/mob/living/silicon/robot/mymobR = mymob
var/obj/screen/using
using = new/obj/screen/language_menu
using.screen_loc = ui_borg_language_menu
static_inventory += using
//Radio
using = new /obj/screen/robot/radio()
using.screen_loc = ui_borg_radio
static_inventory += using
//Module select
using = new /obj/screen/robot/module1()
using.screen_loc = ui_inv1
static_inventory += using
mymobR.inv1 = using
using = new /obj/screen/robot/module2()
using.screen_loc = ui_inv2
static_inventory += using
mymobR.inv2 = using
using = new /obj/screen/robot/module3()
using.screen_loc = ui_inv3
static_inventory += using
mymobR.inv3 = using
//End of module select
//Photography stuff
using = new /obj/screen/ai/image_take()
using.screen_loc = ui_borg_camera
static_inventory += using
using = new /obj/screen/ai/image_view()
using.screen_loc = ui_borg_album
static_inventory += using
//Sec/Med HUDs
using = new /obj/screen/ai/sensors()
using.screen_loc = ui_borg_sensor
static_inventory += using
//Headlamp control
using = new /obj/screen/robot/lamp()
using.screen_loc = ui_borg_lamp
static_inventory += using
mymobR.lamp_button = using
//Thrusters
using = new /obj/screen/robot/thrusters()
using.screen_loc = ui_borg_thrusters
static_inventory += using
mymobR.thruster_button = using
//Intent
action_intent = new /obj/screen/act_intent/robot()
action_intent.icon_state = mymob.a_intent
static_inventory += action_intent
//Health
healths = new /obj/screen/healths/robot()
infodisplay += healths
//Installed Module
mymobR.hands = new /obj/screen/robot/module()
mymobR.hands.screen_loc = ui_borg_module
static_inventory += mymobR.hands
//Store
module_store_icon = new /obj/screen/robot/store()
module_store_icon.screen_loc = ui_borg_store
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_borg_pull
hotkeybuttons += pull_icon
zone_select = new /obj/screen/zone_sel/robot()
zone_select.update_icon(mymob)
static_inventory += zone_select
/datum/hud/proc/toggle_show_robot_modules()
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
R.shown_robot_modules = !R.shown_robot_modules
update_robot_modules_display()
/datum/hud/proc/update_robot_modules_display(mob/viewer)
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(!R.module)
return
if(!R.client)
return
if(R.shown_robot_modules && screenmob.hud_used.hud_shown)
//Modules display is shown
screenmob.client.screen += module_store_icon //"store" icon
if(!R.module.modules)
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
return
if(!R.robot_modules_background)
return
var/display_rows = CEILING(length(R.module.get_inactive_modules()) / 8, 1)
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
screenmob.client.screen += R.robot_modules_background
var/x = -4 //Start at CENTER-4,SOUTH+1
var/y = 1
for(var/atom/movable/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen += A
if(x < 0)
A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7"
else
A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7"
A.layer = ABOVE_HUD_LAYER
A.plane = ABOVE_HUD_PLANE
x++
if(x == 4)
x = -4
y++
else
//Modules display is hidden
screenmob.client.screen -= module_store_icon //"store" icon
for(var/atom/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen -= A
R.shown_robot_modules = 0
screenmob.client.screen -= R.robot_modules_background
/mob/living/silicon/robot/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/robot(src)
/datum/hud/robot/persistent_inventory_update(mob/viewer)
if(!mymob)
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(screenmob.hud_used)
if(screenmob.hud_used.hud_shown)
for(var/i in 1 to R.held_items.len)
var/obj/item/I = R.held_items[i]
if(I)
switch(i)
if(1)
I.screen_loc = ui_inv1
if(2)
I.screen_loc = ui_inv2
if(3)
I.screen_loc = ui_inv3
else
return
screenmob.client.screen += I
else
for(var/obj/item/I in R.held_items)
screenmob.client.screen -= I
+9 -5
View File
@@ -34,7 +34,9 @@
// No comment
/atom/proc/attackby(obj/item/W, mob/user, params)
return SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params)
if(SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
return TRUE
return FALSE
/obj/attackby(obj/item/I, mob/living/user, params)
return ..() || (can_be_hit && I.attack_obj(src, user))
@@ -56,6 +58,8 @@
SendSignal(COMSIG_ITEM_ATTACK, M, user)
if(flags_1 & NOBLUDGEON_1)
return
if(user.disabilities & PACIFISM)
return
if(!force)
playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), 1, -1)
else if(hitsound)
@@ -117,9 +121,9 @@
/obj/item/proc/get_clamped_volume()
if(w_class)
if(force)
return Clamp((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
return CLAMP((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
else
return Clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
return CLAMP(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
var/message_verb = "attacked"
@@ -133,6 +137,6 @@
var/attack_message = "[src] has been [message_verb][message_hit_area] with [I]."
if(user in viewers(src, null))
attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!"
visible_message("<span class='danger'>[attack_message]</span>", \
visible_message("<span class='danger'>[attack_message]</span>",\
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
return 1
return 1
+1 -1
View File
@@ -14,7 +14,7 @@
// Otherwise jump
else if(A.loc)
loc = get_turf(A)
forceMove(get_turf(A))
update_parallax_contents()
/mob/dead/observer/ClickOn(var/atom/A, var/params)
+3
View File
@@ -25,7 +25,9 @@
if(override)
return
SendSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A)
A.attack_hand(src)
SendSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY, src)
/atom/proc/attack_hand(mob/user)
return
@@ -61,6 +63,7 @@
/atom/proc/attack_animal(mob/user)
return
/mob/living/RestrainedClickOn(atom/A)
return
+2 -2
View File
@@ -62,14 +62,14 @@
/mob/living/proc/adjustArousalLoss(amount, updating_arousal=1)
if(status_flags & GODMODE || !canbearoused)
return 0
arousalloss = Clamp(arousalloss + amount, min_arousal, max_arousal)
arousalloss = CLAMP(arousalloss + amount, min_arousal, max_arousal)
if(updating_arousal)
updatearousal()
/mob/living/proc/setArousalLoss(amount, updating_arousal=1)
if(status_flags & GODMODE || !canbearoused)
return 0
arousalloss = Clamp(amount, min_arousal, max_arousal)
arousalloss = CLAMP(amount, min_arousal, max_arousal)
if(updating_arousal)
updatearousal()
-1
View File
@@ -8,7 +8,6 @@
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_TINY
origin_tech = "biotech=3"
var/applied_region = "chest"
var/list/add_mutations = list()
var/list/remove_mutations = list()
-30
View File
@@ -4,7 +4,6 @@
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "lasernew"
item_state = "laser"
origin_tech = "combat=4;magnets=4"
force = 10
throwforce = 10
ammo_type = list(/obj/item/ammo_casing/energy/lasergun)
@@ -22,7 +21,6 @@
name = "Laser Carbine"
desc = "Beefed up version of a standard laser gun."
id = "lasercarbine"
req_tech = list("combat" = 5, "magnets" = 5, "powerstorage" = 4)
build_type = PROTOLATHE
materials = list(MAT_GOLD = 2500, MAT_METAL = 5000, MAT_GLASS = 5000)
build_path = /obj/item/gun/energy/laser/carbine/nopin
@@ -40,7 +38,6 @@
mag_type = /obj/item/ammo_box/magazine/sniper_rounds
fire_delay = 50
burst_size = 1
origin_tech = "combat=7"
can_suppress = 0
w_class = WEIGHT_CLASS_NORMAL
actions_types = list()
@@ -60,7 +57,6 @@
name = "Syndicate Anti Tank Pistol"
desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate a variety of joints without proper bracing."
pin = /obj/item/device/firing_pin/implant/pindicate
origin_tech = "combat=7;syndicate=6"
/////////////spinfusor stuff////////////////
@@ -115,7 +111,6 @@
select = 0
actions_types = list()
casing_ejector = 0
origin_tech = "combat=6;magnets=6"
/obj/item/gun/ballistic/automatic/spinfusor/attackby(obj/item/A, mob/user, params)
var/num_loaded = magazine.attackby(A, user, params, 1)
@@ -163,7 +158,6 @@
icon_state = "x9"
item_state = "arg"
slot_flags = 0
origin_tech = "combat=7;engineering=7"
mag_type = /obj/item/ammo_box/magazine/m556 //Uses the m90gl's magazine, just like the NT-ARG
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = 0
@@ -194,7 +188,6 @@
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"
@@ -254,7 +247,6 @@
name = "magpistol magazine (non-lethal disabler)"
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "nlmagmag"
origin_tech = "magnets=5"
ammo_type = /obj/item/ammo_casing/caseless/anlmags
caliber = "mags"
max_ammo = 15
@@ -264,7 +256,6 @@
name = "magpistol magazine (lethal)"
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "smallmagmag"
origin_tech = "combat=5"
ammo_type = /obj/item/ammo_casing/caseless/amags
//////the gun itself//////
@@ -280,7 +271,6 @@
can_suppress = 0
casing_ejector = 0
fire_delay = 2
origin_tech = "combat=4;magnets=4"
/obj/item/gun/ballistic/automatic/pistol/mag/update_icon()
..()
@@ -301,7 +291,6 @@
name = "Magpistol"
desc = "A weapon which fires ferromagnetic slugs."
id = "magpisol"
req_tech = list("combat" = 5, "magnets" = 6, "powerstorage" = 5)
build_type = PROTOLATHE
materials = list(MAT_METAL = 7500, MAT_GLASS = 1000, MAT_URANIUM = 1000, MAT_TITANIUM = 5000, MAT_SILVER = 2000)
build_path = /obj/item/gun/ballistic/automatic/pistol/mag/nopin
@@ -311,7 +300,6 @@
name = "Magpistol Magazine"
desc = "A 7 round magazine for the Magpistol."
id = "mag_magpistol"
req_tech = list("combat" = 5, "magnets" = 6, "materials" = 5, "syndicate" = 3)
build_type = PROTOLATHE
materials = list(MAT_METAL = 4000, MAT_SILVER = 500)
build_path = /obj/item/ammo_box/magazine/mmag/small/lethal
@@ -321,7 +309,6 @@
name = "Magpistol Magazine (Non-Lethal)"
desc = "A 7 round non-lethal magazine for the Magpistol."
id = "mag_magpistol_nl"
req_tech = list("combat" = 5, "magnets" = 6, "materials" = 5)
materials = list(MAT_METAL = 3000, MAT_SILVER = 250, MAT_TITANIUM = 250)
build_path = /obj/item/ammo_box/magazine/mmag/small
@@ -354,7 +341,6 @@
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)"
@@ -427,7 +413,6 @@
name = "magrifle magazine (non-lethal disabler)"
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "mediummagmag"
origin_tech = "magnets=6"
ammo_type = /obj/item/ammo_casing/caseless/anlmagm
caliber = "magm"
max_ammo = 27
@@ -437,7 +422,6 @@
name = "magrifle magazine (lethal)"
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "mediummagmag"
origin_tech = "combat=6"
ammo_type = /obj/item/ammo_casing/caseless/amagm
max_ammo = 21
@@ -450,7 +434,6 @@
icon_state = "magrifle"
item_state = "arg"
slot_flags = 0
origin_tech = "combat=6;engineering=6;magnets=6"
mag_type = /obj/item/ammo_box/magazine/mmag
fire_sound = 'sound/weapons/magrifle.ogg'
can_suppress = 0
@@ -470,7 +453,6 @@
name = "Magrifle"
desc = "An upscaled Magpistol in rifle form."
id = "magrifle"
req_tech = list("combat" = 7, "magnets" = 7, "powerstorage" = 7)
build_type = PROTOLATHE
materials = list(MAT_METAL = 10000, MAT_GLASS = 2000, MAT_URANIUM = 2000, MAT_TITANIUM = 10000, MAT_SILVER = 4000, MAT_GOLD = 2000)
build_path = /obj/item/gun/ballistic/automatic/magrifle/nopin
@@ -480,7 +462,6 @@
name = "Magrifle Magazine (Lethal)"
desc = "A 15 round magazine for the Magrifle."
id = "mag_magrifle"
req_tech = list("combat" = 7, "magnets" = 7, "materials" = 5, "syndicate" = 4)
build_type = PROTOLATHE
materials = list(MAT_METAL = 8000, MAT_SILVER = 1000)
build_path = /obj/item/ammo_box/magazine/mmag/lethal
@@ -490,7 +471,6 @@
name = "Magrifle Magazine (Non-Lethal)"
desc = "A 15 round non-lethal magazine for the Magrifle."
id = "mag_magrifle_nl"
req_tech = list("combat" = 7, "magnets" = 7, "materials" = 5)
materials = list(MAT_METAL = 6000, MAT_SILVER = 500, MAT_TITANIUM = 500)
build_path = /obj/item/ammo_box/magazine/mmag
@@ -512,7 +492,6 @@
needs_permit = FALSE
mag_type = /obj/item/ammo_box/magazine/toy/foamag
casing_ejector = FALSE
origin_tech = "combat=1;engineering=1;magnets=1"
spread = 60
w_class = WEIGHT_CLASS_BULKY
weapon_weight = WEAPON_HEAVY
@@ -598,7 +577,6 @@
icon_state = "hyperburst"
item_state = "arg"
slot_flags = 0
origin_tech = "combat=6;engineering=6;magnets=6;syndicate=6"
mag_type = /obj/item/ammo_box/magazine/mhyper
fire_sound = 'sound/weapons/magburst.ogg'
can_suppress = 0
@@ -646,7 +624,6 @@
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"
@@ -669,7 +646,6 @@
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "stealthpistol"
w_class = WEIGHT_CLASS_SMALL
origin_tech = "combat=3;materials=3;syndicate=4"
mag_type = /obj/item/ammo_box/magazine/m10mm
can_suppress = 0
fire_sound = 'sound/weapons/gunshot_silenced.ogg'
@@ -703,7 +679,6 @@
fire_delay = 0
spread = 60
actions_types = list()
origin_tech = "combat=1;magnets=1"
/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_icon()
..()
@@ -805,7 +780,6 @@ obj/item/projectile/bullet/c10mm/soporific
name = "flechette magazine (armor piercing)"
icon = 'icons/obj/guns/cit_guns.dmi'
icon_state = "flechettemag"
origin_tech = "combat=5;syndicate=1"
ammo_type = /obj/item/ammo_casing/caseless/flechetteap
caliber = "flechette"
max_ammo = 40
@@ -826,7 +800,6 @@ obj/item/projectile/bullet/c10mm/soporific
w_class = WEIGHT_CLASS_NORMAL
slot_flags = 0
/obj/item/device/firing_pin/implant/pindicate
origin_tech = "combat=6;materials=2;syndicate=5"
mag_type = /obj/item/ammo_box/magazine/flechette/
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = 0
@@ -930,7 +903,6 @@ 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"
@@ -1186,7 +1158,6 @@ obj/item/projectile/bullet/c10mm/soporific
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"
@@ -1209,7 +1180,6 @@ obj/item/gun/energy/e_gun/cx
lefthand_file = 'icons/mob/citadel/guns_lefthand.dmi'
righthand_file = 'icons/mob/citadel/guns_righthand.dmi'
ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser)
origin_tech = "combat=4;magnets=3"
flight_x_offset = 15
flight_y_offset = 10
actions_types = list(/datum/action/item_action/pick_color)
-221
View File
@@ -1,221 +0,0 @@
/obj/item/toy/sword/cx
name = "\improper DX Non-Euplastic LightSword"
desc = "A deluxe toy replica of an energy sword. Realistic visuals and sounds! Ages 8 and up."
icon = 'icons/obj/cit_weapons.dmi'
icon_state = "cxsword_hilt"
item_state = "cxsword"
lefthand_file = 'icons/mob/citadel/melee_lefthand.dmi'
righthand_file = 'icons/mob/citadel/melee_righthand.dmi'
active = FALSE
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("poked", "jabbed", "hit")
light_color = "#37FFF7"
var/light_brightness = 3
actions_types = list(/datum/action/item_action/pick_color)
/obj/item/toy/sword/cx/attack_self(mob/user)
active = !( active )
if (active)
to_chat(user, "<span class='notice'>You activate the holographic blade with a press of a button.</span>")
playsound(user, 'sound/weapons/nebon.ogg', 50, 1)
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("slashed", "stabbed", "ravaged")
set_light(light_brightness)
update_icon()
else
to_chat(user, "<span class='notice'>You deactivate the holographic blade with a press of a button.</span>")
playsound(user, 'sound/weapons/neboff.ogg', 50, 1)
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("poked", "jabbed", "hit")
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()
var/mutable_appearance/blade_overlay = mutable_appearance('icons/obj/cit_weapons.dmi', "cxsword_blade")
var/mutable_appearance/gem_overlay = mutable_appearance('icons/obj/cit_weapons.dmi', "cxsword_gem")
if(light_color)
blade_overlay.color = light_color
gem_overlay.color = light_color
cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
add_overlay(gem_overlay)
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")
var/energy_color_input = input(usr,"Choose Energy Color") as color|null
if(energy_color_input)
light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
update_icon()
update_light()
A.UpdateButtonIcon()
else
..()
/obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file)
. = ..()
if(active)
if(isinhands)
var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
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
name = "Non-Euplastic Blade"
id = "toyneb"
build_type = AUTOLATHE
materials = list(MAT_METAL = 10000, MAT_GLASS = 1000)
build_path = /obj/item/toy/sword/cx
category = list("hacked", "Misc")
*/ // There, I stopped doing it
/datum/crafting_recipe/toyneb
name = "Non-Euplastic Blade"
reqs = list(/obj/item/light/bulb = 1, /obj/item/stack/cable_coil = 1, /obj/item/toy/sword = 1)
result = /obj/item/toy/sword/cx
category = CAT_MISC
/*/////////////////////////////////////////////////////////////////////////
///////////// The TRUE Energy Sword ///////////////////////////
*//////////////////////////////////////////////////////////////////////////
/obj/item/melee/transforming/energy/sword/cx
name = "non-eutactic blade"
desc = "The CX Armories Type-69 Non-Eutactic Blade utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable."
icon_state = "cxsword_hilt"
icon = 'icons/obj/cit_weapons.dmi'
item_state = "cxsword"
lefthand_file = 'icons/mob/citadel/melee_lefthand.dmi'
righthand_file = 'icons/mob/citadel/melee_righthand.dmi'
force = 3
throwforce = 5
hitsound = "swing_hit" //it starts deactivated
hitsound_on = 'sound/weapons/nebhit.ogg'
attack_verb_off = list("tapped", "poked")
throw_speed = 3
throw_range = 5
sharpness = IS_SHARP
embed_chance = 40
embedded_impact_pain_multiplier = 10
armour_penetration = 0
origin_tech = "combat=3;magnets=4"
block_chance = 60
light_color = "#37FFF7"
actions_types = list(/datum/action/item_action/pick_color)
/obj/item/melee/transforming/energy/sword/cx/transform_weapon(mob/living/user, supress_message_text)
active = !active //I'd use a ..() here but it'd inherit from the regular esword's proc instead, so SPAGHETTI CODE
if(active) //also I need to rip out the iconstate changing bits
force = force_on
throwforce = throwforce_on
hitsound = hitsound_on
throw_speed = 4
if(attack_verb_on.len)
attack_verb = attack_verb_on
w_class = w_class_on
START_PROCESSING(SSobj, src)
set_light(brightness_on)
update_icon()
else
force = initial(force)
throwforce = initial(throwforce)
hitsound = initial(hitsound)
throw_speed = initial(throw_speed)
if(attack_verb_off.len)
attack_verb = attack_verb_off
w_class = initial(w_class)
STOP_PROCESSING(SSobj, src)
set_light(0)
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)
playsound(user, active ? 'sound/weapons/nebon.ogg' : 'sound/weapons/neboff.ogg', 65, 1)
if(!supress_message_text)
to_chat(user, "<span class='notice'>[src] [active ? "is now active":"can now be concealed"].</span>")
/obj/item/melee/transforming/energy/sword/cx/update_icon()
var/mutable_appearance/blade_overlay = mutable_appearance('icons/obj/cit_weapons.dmi', "cxsword_blade")
var/mutable_appearance/gem_overlay = mutable_appearance('icons/obj/cit_weapons.dmi', "cxsword_gem")
if(light_color)
blade_overlay.color = light_color
gem_overlay.color = light_color
cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
add_overlay(gem_overlay)
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")
var/energy_color_input = input(usr,"Choose Energy Color") as color|null
if(energy_color_input)
light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
update_icon()
update_light()
A.UpdateButtonIcon()
else
..()
/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file)
. = ..()
if(active)
if(isinhands)
var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
blade_inhand.color = light_color
. += blade_inhand
/obj/item/melee/transforming/energy/sword/cx/traitor
name = "\improper Dragon's Tooth Sword"
desc = "The Dragon's Tooth sword is a blackmarket modification of the CX Armouries Type-69 NEB, \
which utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable. \
It appears to have a wooden grip and a shaved down guard."
icon_state = "cxsword_hilt_traitor"
armour_penetration = 35
embed_chance = 75
block_chance = 50
origin_tech = "combat=3;magnets=4;syndicate=4"
hitsound_on = 'sound/weapons/blade1.ogg'
light_color = "#37F0FF"
/obj/item/melee/transforming/energy/sword/cx/traitor/transform_messages(mob/living/user, supress_message_text)
playsound(user, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, 1)
if(!supress_message_text)
to_chat(user, "<span class='notice'>[src] [active ? "is now active":"can now be concealed"].</span>")
@@ -38,8 +38,8 @@
explanation_text = "Make sure the research required to produce a [initial(targetdesign.name)] is available on the R&D server by the end of the shift."
/datum/objective/crew/research/check_completion()
for(var/obj/machinery/r_n_d/server/S in GLOB.machines)
if(S && S.files && S.files.known_designs)
if(targetdesign in S.files.known_designs)
for(var/obj/machinery/rnd/server/S in GLOB.machines)
if(S && S.stored_research)
if(S.stored_research.researched_designs[initial(targetdesign.id)])
return TRUE
return FALSE
+46 -11
View File
@@ -16,8 +16,9 @@
/obj/item/clothing/neck/cloak/inferno
name = "Kiara's Cloak"
desc = "The design on this seems a little too familiar."
icon = 'icons/obj/clothing/cloaks.dmi'
icon = 'icons/obj/custom.dmi'
icon_state = "infcloak"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "infcloak"
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN|LEGS|ARMS
@@ -25,7 +26,9 @@
/obj/item/clothing/neck/petcollar/inferno
name = "Kiara's Collar"
desc = "A soft black collar that seems to stretch to fit whoever wears it."
icon = 'icons/obj/custom.dmi'
icon_state = "infcollar"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "infcollar"
item_color = null
tagname = null
@@ -43,7 +46,7 @@
/obj/item/lighter/gold
name = "\improper Engraved Zippo"
desc = "A shiny and relatively expensive zippo lighter. There's a small etched in verse on the bottom that reads, 'No Gods, No Masters, Only Man.'"
icon = 'icons/obj/cigarettes.dmi'
icon = 'icons/obj/custom.dmi'
icon_state = "gold_zippo"
item_state = "gold_zippo"
w_class = WEIGHT_CLASS_TINY
@@ -58,15 +61,19 @@
/obj/item/clothing/neck/scarf/zomb //Default white color, same functionality as beanies.
name = "A special scarf"
icon = 'icons/obj/custom.dmi'
icon_state = "zombscarf"
desc = "A fashionable collar"
icon_override = 'icons/mob/custom_w.dmi'
item_color = "zombscarf"
dog_fashion = /datum/dog_fashion/head
/obj/item/clothing/suit/toggle/labcoat/mad/red
name = "\improper The Mad's labcoat"
desc = "An oddly special looking coat."
icon = 'icons/obj/custom.dmi'
icon_state = "labred"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "labred"
@@ -86,8 +93,8 @@
/obj/item/clothing/neck/cloak/carrot
name = "carrot cloak"
desc = "A cloak in the shape and color of a carrot!"
icon = 'icons/obj/clothing/cloaks.dmi'
icon_override = 'icons/mob/citadel/suit.dmi'
icon = 'icons/obj/custom.dmi'
icon_override = 'icons/mob/custom_w.dmi'
icon_state = "carrotcloak"
item_state = "carrotcloak"
w_class = WEIGHT_CLASS_SMALL
@@ -96,7 +103,7 @@
/obj/item/toy/plush/tree
name = "christmass tree plushie"
desc = "A festive plush that squeeks when you squeeze it!"
icon = 'icons/obj/plushes.dmi'
icon = 'icons/obj/custom.dmi'
icon_state = "pine_c"
item_state = "pine_c"
w_class = WEIGHT_CLASS_SMALL
@@ -104,13 +111,24 @@
resistance_flags = FLAMMABLE
squeak_override = list('sound/misc/server-ready.ogg'= 1)
/obj/item/clothing/neck/cloak/festive
name = "Celebratory Cloak of Morozko"
desc = " It probably will protect from snow, charcoal or elves."
icon = 'icons/obj/custom.dmi'
icon_state = "festive"
item_state = "festive"
icon_override = 'icons/mob/custom_w.dmi'
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN|LEGS|ARMS
/*Zigfie*/
/obj/item/clothing/mask/luchador/zigfie
name = "Alboroto Rosa mask"
icon = 'icons/mob/mask.dmi'
icon = 'icons/obj/custom.dmi'
icon_state = "lucharzigfie"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "lucharzigfie"
@@ -149,7 +167,9 @@
/obj/item/clothing/suit/trenchcoat/green
name = "Reece's Great Coat"
desc = "You would swear this was in your nightmares after eating too many veggies."
icon = 'icons/obj/custom.dmi'
icon_state = "hos-g"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "hos-g"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
@@ -160,13 +180,14 @@
desc = "Every good russian spaceman knows it's a good idea to bring along a couple of pints of whiskey wherever they go."
icon = 'icons/obj/custom.dmi'
icon_state = "russianflask"
item_state = "russianflask"
volume = 60
/obj/item/clothing/mask/gas/stalker
name = "S.T.A.L.K.E.R. mask"
desc = "Smells like reactor four."
icon = 'icons/obj/custom.dmi'
item_state = "stalker"
icon_override = 'icons/mob/custom_w.dmi'
icon_state = "stalker"
@@ -176,7 +197,8 @@
desc = "It's a collar..."
icon = 'icons/obj/custom.dmi'
icon_state = "petcollar-stripe"
item_color = "petcollar-stripe"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "petcollar-stripe"
tagname = null
@@ -184,17 +206,30 @@
/obj/item/clothing/under/singery/custom
name = "bluish performer's outfit"
desc = "Just looking at this makes you want to sing."
icon_state = "ssing"
item_state = "ssing"
item_color = "ssing"
icon = 'icons/obj/custom.dmi'
icon_state = "singer"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "singer"
item_color = "singer"
fitted = NO_FEMALE_UNIFORM
alternate_worn_layer = ABOVE_SHOES_LAYER
can_adjust = 0
/obj/item/clothing/shoes/sneakers/pink
icon = 'icons/obj/custom.dmi'
icon_state = "pink"
icon_override = 'icons/mob/custom_w.dmi'
item_state = "pink"
/*Fractious*/
/obj/item/clothing/suit/vermillion
name = "vermillion clothing"
desc = "Some clothing."
icon_state = "vermillion"
item_state = "vermillion"
body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS
icon = 'icons/obj/custom.dmi'
icon_override = 'icons/mob/custom_w.dmi'
@@ -9,7 +9,7 @@
var/value
var/default //read-only, just set value directly
var/resident_file //the file which this belongs to, must be set
var/resident_file //the file which this was loaded from, if any
var/modified = FALSE //set to TRUE if the default has been overridden by a config entry
var/protection = NONE
@@ -18,8 +18,6 @@
var/dupes_allowed = FALSE
/datum/config_entry/New()
if(!resident_file)
CRASH("Config entry [type] has no resident_file set")
if(type == abstract_type)
CRASH("Abstract config entry [type] instatiated!")
name = lowertext(type2top(type))
@@ -110,7 +108,7 @@
/datum/config_entry/number/ValidateAndSet(str_val)
var/temp = text2num(trim(str_val))
if(!isnull(temp))
value = Clamp(integer ? round(temp) : temp, min_val, max_val)
value = CLAMP(integer ? round(temp) : temp, min_val, max_val)
if(value != temp && !var_edited)
log_config("Changing [name] from [temp] to [value]!")
return TRUE
+40 -16
View File
@@ -20,10 +20,13 @@ GLOBAL_PROTECT(config_dir)
/datum/controller/configuration/New()
config = src
var/list/config_files = InitEntries()
InitEntries()
LoadModes()
for(var/I in config_files)
LoadEntries(I)
if(LoadEntries("config.txt") <= 1)
log_config("No $include directives found in config.txt! Loading legacy game_options/dbconfig/comms files...")
LoadEntries("game_options.txt")
LoadEntries("dbconfig.txt")
LoadEntries("comms.txt")
loadmaplist(CONFIG_MAPS_FILE)
/datum/controller/configuration/Destroy()
@@ -42,8 +45,6 @@ GLOBAL_PROTECT(config_dir)
var/list/_entries_by_type = list()
entries_by_type = _entries_by_type
. = list()
for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case
var/datum/config_entry/E = I
if(initial(E.abstract_type) == I)
@@ -57,24 +58,30 @@ GLOBAL_PROTECT(config_dir)
continue
_entries[esname] = E
_entries_by_type[I] = E
.[E.resident_file] = TRUE
/datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE)
entries -= CE.name
entries_by_type -= CE.type
/datum/controller/configuration/proc/LoadEntries(filename)
/datum/controller/configuration/proc/LoadEntries(filename, list/stack = list())
var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename
if(filename_to_test in stack)
log_config("Warning: Config recursion detected ([english_list(stack)]), breaking!")
return
stack = stack + filename_to_test
log_config("Loading config file [filename]...")
var/list/lines = world.file2list("[GLOB.config_dir][filename]")
var/list/_entries = entries
for(var/L in lines)
if(!L)
continue
if(copytext(L, 1, 2) == "#")
var/firstchar = copytext(L, 1, 2)
if(firstchar == "#")
continue
var/lockthis = copytext(L, 1, 2) == "@"
var/lockthis = firstchar == "@"
if(lockthis)
L = copytext(L, 2)
@@ -90,15 +97,25 @@ GLOBAL_PROTECT(config_dir)
if(!entry)
continue
if(entry == "$include")
if(!value)
log_config("Warning: Invalid $include directive: [value]")
else
LoadEntries(value, stack)
++.
continue
if(entry == "$include")
if(!value)
log_config("Warning: Invalid $include directive: [value]")
else
LoadEntries(value, stack)
continue
var/datum/config_entry/E = _entries[entry]
if(!E)
log_config("Unknown setting in configuration: '[entry]'")
continue
if(filename != E.resident_file)
log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.")
continue
if(lockthis)
E.protection |= CONFIG_ENTRY_LOCKED
@@ -107,10 +124,14 @@ GLOBAL_PROTECT(config_dir)
if(!validated)
log_config("Failed to validate setting \"[value]\" for [entry]")
else if(E.modified && !E.dupes_allowed)
log_config("Duplicate setting for [entry] ([value]) detected! Using latest.")
log_config("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.")
E.resident_file = filename
if(validated)
E.modified = TRUE
++.
/datum/controller/configuration/can_vv_get(var_name)
return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..()
@@ -168,7 +189,10 @@ GLOBAL_PROTECT(config_dir)
mode_names[M.config_tag] = M.name
probabilities[M.config_tag] = M.probability
mode_reports[M.config_tag] = M.generate_report()
mode_false_report_weight[M.config_tag] = M.false_report_weight
if(M.probability)
mode_false_report_weight[M.config_tag] = M.false_report_weight
else
mode_false_report_weight[M.config_tag] = 1
if(M.votable)
votable_modes += M.config_tag
qdel(M)
@@ -1,22 +1,20 @@
#define CURRENT_RESIDENT_FILE "comms.txt"
CONFIG_DEF(string/comms_key)
/datum/config_entry/string/comms_key
protection = CONFIG_ENTRY_HIDDEN
/datum/config_entry/string/comms_key/ValidateAndSet(str_val)
return str_val != "default_pwd" && length(str_val) > 6 && ..()
CONFIG_DEF(string/cross_server_address)
/datum/config_entry/keyed_string_list/cross_server
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/string/cross_server_address/ValidateAndSet(str_val)
return str_val != "byond:\\address:port" && ..()
CONFIG_DEF(string/cross_comms_name)
/datum/config_entry/string/cross_comms_name
GLOBAL_VAR_INIT(medals_enabled, TRUE) //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls.
CONFIG_DEF(string/medal_hub_address)
/datum/config_entry/string/medal_hub_address
CONFIG_DEF(string/medal_hub_password)
protection = CONFIG_ENTRY_HIDDEN
/datum/config_entry/string/medal_hub_password
protection = CONFIG_ENTRY_HIDDEN
@@ -1,387 +0,0 @@
#define CURRENT_RESIDENT_FILE "config.txt"
CONFIG_DEF(flag/autoadmin) // if autoadmin is enabled
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/autoadmin_rank) // the rank for autoadmins
value = "Game Master"
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/servername) // server name (the name of the game window)
CONFIG_DEF(string/serversqlname) // short form server name used for the DB
CONFIG_DEF(string/stationname) // station name (the name of the station in-game)
CONFIG_DEF(number/lobby_countdown) // In between round countdown.
value = 120
min_val = 0
CONFIG_DEF(number/round_end_countdown) // Post round murder death kill countdown
value = 25
min_val = 0
CONFIG_DEF(flag/hub) // if the game appears on the hub or not
CONFIG_DEF(flag/log_ooc) // log OOC channel
CONFIG_DEF(flag/log_access) // log login/logout
CONFIG_DEF(flag/log_say) // log client say
CONFIG_DEF(flag/log_admin) // log admin actions
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_prayer) // log prayers
CONFIG_DEF(flag/log_law) // log lawchanges
CONFIG_DEF(flag/log_game) // log game events
CONFIG_DEF(flag/log_vote) // log voting
CONFIG_DEF(flag/log_whisper) // log client whisper
CONFIG_DEF(flag/log_attack) // log attack messages
CONFIG_DEF(flag/log_emote) // log emotes
CONFIG_DEF(flag/log_adminchat) // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_pda) // log pda messages
CONFIG_DEF(flag/log_twitter) // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
CONFIG_DEF(flag/log_world_topic) // log all world.Topic() calls
CONFIG_DEF(flag/log_manifest) // log crew manifest to seperate file
CONFIG_DEF(flag/allow_admin_ooccolor) // Allows admins with relevant permissions to have their own ooc colour
CONFIG_DEF(flag/allow_vote_restart) // allow votes to restart
CONFIG_DEF(flag/allow_vote_mode) // allow votes to change mode
CONFIG_DEF(number/vote_delay) // minimum time between voting sessions (deciseconds, 10 minute default)
value = 6000
min_val = 0
CONFIG_DEF(number/vote_period) // length of voting period (deciseconds, default 1 minute)
value = 600
min_val = 0
CONFIG_DEF(flag/default_no_vote) // vote does not default to nochange/norestart
CONFIG_DEF(flag/no_dead_vote) // dead people can't vote
CONFIG_DEF(flag/allow_metadata) // Metadata is supported.
CONFIG_DEF(flag/popup_admin_pm) // adminPMs to non-admins show in a pop-up 'reply' window when set
CONFIG_DEF(number/fps)
value = 20
min_val = 1
max_val = 100 //byond will start crapping out at 50, so this is just ridic
var/sync_validate = FALSE
/datum/config_entry/number/fps/ValidateAndSet(str_val)
. = ..()
if(.)
sync_validate = TRUE
var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
if(!TL.sync_validate)
TL.ValidateAndSet(10 / value)
sync_validate = FALSE
CONFIG_DEF(number/ticklag)
integer = FALSE
var/sync_validate = FALSE
/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
var/datum/config_entry/CE = /datum/config_entry/number/fps
value = 10 / initial(CE.value)
..()
/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
. = text2num(str_val) > 0 && ..()
if(.)
sync_validate = TRUE
var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
if(!FPS.sync_validate)
FPS.ValidateAndSet(10 / value)
sync_validate = FALSE
CONFIG_DEF(flag/allow_holidays)
CONFIG_DEF(number/tick_limit_mc_init) //SSinitialization throttling
value = TICK_LIMIT_MC_INIT_DEFAULT
min_val = 0 //oranges warned us
integer = FALSE
CONFIG_DEF(flag/admin_legacy_system) //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/hostedby)
CONFIG_DEF(flag/norespawn)
CONFIG_DEF(flag/guest_jobban)
CONFIG_DEF(flag/usewhitelist)
CONFIG_DEF(flag/ban_legacy_system) //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/use_age_restriction_for_jobs) //Do jobs use account age restrictions? --requires database
CONFIG_DEF(flag/use_account_age_for_jobs) //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
CONFIG_DEF(flag/use_exp_tracking)
CONFIG_DEF(flag/use_exp_restrictions_heads)
CONFIG_DEF(number/use_exp_restrictions_heads_hours)
value = 0
min_val = 0
CONFIG_DEF(flag/use_exp_restrictions_heads_department)
CONFIG_DEF(flag/use_exp_restrictions_other)
CONFIG_DEF(flag/use_exp_restrictions_admin_bypass)
CONFIG_DEF(string/server)
CONFIG_DEF(string/banappeals)
CONFIG_DEF(string/wikiurl)
value = "http://www.tgstation13.org/wiki"
CONFIG_DEF(string/forumurl)
value = "http://tgstation13.org/phpBB/index.php"
CONFIG_DEF(string/rulesurl)
value = "http://www.tgstation13.org/wiki/Rules"
CONFIG_DEF(string/githuburl)
value = "https://www.github.com/tgstation/-tg-station"
CONFIG_DEF(number/githubrepoid)
value = null
min_val = 0
CONFIG_DEF(flag/guest_ban)
CONFIG_DEF(number/id_console_jobslot_delay)
value = 30
min_val = 0
CONFIG_DEF(number/inactivity_period) //time in ds until a player is considered inactive)
value = 3000
min_val = 0
/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val)
. = ..()
if(.)
value *= 10 //documented as seconds in config.txt
CONFIG_DEF(number/afk_period) //time in ds until a player is considered inactive)
value = 3000
min_val = 0
/datum/config_entry/number/afk_period/ValidateAndSet(str_val)
. = ..()
if(.)
value *= 10 //documented as seconds in config.txt
CONFIG_DEF(flag/kick_inactive) //force disconnect for inactive players
CONFIG_DEF(flag/load_jobs_from_txt)
CONFIG_DEF(flag/forbid_singulo_possession)
CONFIG_DEF(flag/automute_on) //enables automuting/spam prevention
CONFIG_DEF(string/panic_server_name)
/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
return str_val != "\[Put the name here\]" && ..()
CONFIG_DEF(string/panic_address) //Reconnect a player this linked server if this server isn't accepting new players
/datum/config_entry/string/panic_address/ValidateAndSet(str_val)
return str_val != "byond://address:port" && ..()
CONFIG_DEF(string/invoke_youtubedl)
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
CONFIG_DEF(flag/show_irc_name)
CONFIG_DEF(flag/see_own_notes) //Can players see their own admin notes (read-only)?
CONFIG_DEF(number/note_fresh_days)
value = null
min_val = 0
integer = FALSE
CONFIG_DEF(number/note_stale_days)
value = null
min_val = 0
integer = FALSE
CONFIG_DEF(flag/maprotation)
CONFIG_DEF(number/maprotatechancedelta)
value = 0.75
min_val = 0
max_val = 1
integer = FALSE
CONFIG_DEF(number/soft_popcap)
value = null
min_val = 0
CONFIG_DEF(number/hard_popcap)
value = null
min_val = 0
CONFIG_DEF(number/extreme_popcap)
value = null
min_val = 0
CONFIG_DEF(string/soft_popcap_message)
value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
CONFIG_DEF(string/hard_popcap_message)
value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
CONFIG_DEF(string/extreme_popcap_message)
value = "The server is currently serving a high number of users, find alternative servers."
CONFIG_DEF(flag/panic_bunker) // prevents people the server hasn't seen before from connecting
CONFIG_DEF(number/notify_new_player_age) // how long do we notify admins of a new player
min_val = -1
CONFIG_DEF(number/notify_new_player_account_age) // how long do we notify admins of a new byond account
min_val = 0
CONFIG_DEF(flag/irc_first_connection_alert) // do we notify the irc channel when somebody is connecting for the first time?
CONFIG_DEF(flag/check_randomizer)
CONFIG_DEF(string/ipintel_email)
/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
return str_val != "ch@nge.me" && ..()
CONFIG_DEF(number/ipintel_rating_bad)
value = 1
integer = FALSE
min_val = 0
max_val = 1
CONFIG_DEF(number/ipintel_save_good)
value = 12
min_val = 0
CONFIG_DEF(number/ipintel_save_bad)
value = 1
min_val = 0
CONFIG_DEF(string/ipintel_domain)
value = "check.getipintel.net"
CONFIG_DEF(flag/aggressive_changelog)
CONFIG_DEF(flag/autoconvert_notes) //if all connecting player's notes should attempt to be converted to the database
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/allow_webclient)
CONFIG_DEF(flag/webclient_only_byond_members)
CONFIG_DEF(flag/announce_admin_logout)
CONFIG_DEF(flag/announce_admin_login)
CONFIG_DEF(flag/allow_map_voting)
CONFIG_DEF(flag/generate_minimaps)
CONFIG_DEF(number/client_warn_version)
value = null
min_val = 500
max_val = DM_VERSION - 1
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
max_val = DM_VERSION - 1
CONFIG_DEF(string/client_error_message)
value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
CONFIG_DEF(number/minute_topic_limit)
value = null
min_val = 0
CONFIG_DEF(number/second_topic_limit)
value = null
min_val = 0
CONFIG_DEF(number/error_cooldown) // The "cooldown" time for each occurrence of a unique error)
value = 600
min_val = 0
CONFIG_DEF(number/error_limit) // How many occurrences before the next will silence them
value = 50
CONFIG_DEF(number/error_silence_time) // How long a unique error will be silenced for
value = 6000
CONFIG_DEF(number/error_msg_delay) // How long to wait between messaging admins about occurrences of a unique error
value = 50
CONFIG_DEF(flag/irc_announce_new_game)
CONFIG_DEF(flag/debug_admin_hrefs)
CONFIG_DEF(number/mc_tick_rate/base_mc_tick_rate)
integer = FALSE
value = 1
CONFIG_DEF(number/mc_tick_rate/high_pop_mc_tick_rate)
integer = FALSE
value = 1.1
CONFIG_DEF(number/mc_tick_rate/high_pop_mc_mode_amount)
value = 65
CONFIG_DEF(number/mc_tick_rate/disable_high_pop_mc_mode_amount)
value = 60
CONFIG_TWEAK(number/mc_tick_rate)
abstract_type = /datum/config_entry/number/mc_tick_rate
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
CONFIG_DEF(number/rounds_until_hard_restart)
value = -1
min_val = 0
@@ -1,28 +1,26 @@
#define CURRENT_RESIDENT_FILE "dbconfig.txt"
CONFIG_DEF(flag/sql_enabled) // for sql switching
/datum/config_entry/flag/sql_enabled // for sql switching
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/address)
/datum/config_entry/string/address
value = "localhost"
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
CONFIG_DEF(number/port)
/datum/config_entry/number/port
value = 3306
min_val = 0
max_val = 65535
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
CONFIG_DEF(string/feedback_database)
/datum/config_entry/string/feedback_database
value = "test"
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
CONFIG_DEF(string/feedback_login)
/datum/config_entry/string/feedback_login
value = "root"
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
CONFIG_DEF(string/feedback_password)
/datum/config_entry/string/feedback_password
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
CONFIG_DEF(string/feedback_tableprefix)
/datum/config_entry/string/feedback_tableprefix
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
@@ -1,253 +1,255 @@
#define CURRENT_RESIDENT_FILE "game_options.txt"
/datum/config_entry/number_list/repeated_mode_adjust
CONFIG_DEF(number_list/repeated_mode_adjust)
CONFIG_DEF(keyed_number_list/probability)
/datum/config_entry/keyed_number_list/probability
/datum/config_entry/keyed_number_list/probability/ValidateKeyName(key_name)
return key_name in config.modes
CONFIG_DEF(keyed_number_list/max_pop)
/datum/config_entry/keyed_number_list/max_pop
/datum/config_entry/keyed_number_list/max_pop/ValidateKeyName(key_name)
return key_name in config.modes
CONFIG_DEF(keyed_number_list/min_pop)
/datum/config_entry/keyed_number_list/min_pop
/datum/config_entry/keyed_number_list/min_pop/ValidateKeyName(key_name)
return key_name in config.modes
CONFIG_DEF(keyed_flag_list/continuous) // which roundtypes continue if all antagonists die
/datum/config_entry/keyed_flag_list/continuous // which roundtypes continue if all antagonists die
/datum/config_entry/keyed_flag_list/continuous/ValidateKeyName(key_name)
return key_name in config.modes
CONFIG_DEF(keyed_flag_list/midround_antag) // which roundtypes use the midround antagonist system
/datum/config_entry/keyed_flag_list/midround_antag // which roundtypes use the midround antagonist system
/datum/config_entry/keyed_flag_list/midround_antag/ValidateKeyName(key_name)
return key_name in config.modes
CONFIG_DEF(keyed_string_list/policy)
/datum/config_entry/keyed_string_list/policy
CONFIG_DEF(number/damage_multiplier)
/datum/config_entry/number/damage_multiplier
value = 1
integer = FALSE
CONFIG_DEF(number/minimal_access_threshold) //If the number of players is larger than this threshold, minimal access will be turned on.
/datum/config_entry/number/minimal_access_threshold //If the number of players is larger than this threshold, minimal access will be turned on.
min_val = 0
CONFIG_DEF(flag/jobs_have_minimal_access) //determines whether jobs use minimal access or expanded access.
/datum/config_entry/flag/jobs_have_minimal_access //determines whether jobs use minimal access or expanded access.
CONFIG_DEF(flag/assistants_have_maint_access)
/datum/config_entry/flag/assistants_have_maint_access
CONFIG_DEF(flag/security_has_maint_access)
/datum/config_entry/flag/security_has_maint_access
CONFIG_DEF(flag/everyone_has_maint_access)
/datum/config_entry/flag/everyone_has_maint_access
CONFIG_DEF(flag/sec_start_brig) //makes sec start in brig instead of dept sec posts
/datum/config_entry/flag/sec_start_brig //makes sec start in brig instead of dept sec posts
CONFIG_DEF(flag/force_random_names)
/datum/config_entry/flag/force_random_names
CONFIG_DEF(flag/humans_need_surnames)
/datum/config_entry/flag/humans_need_surnames
CONFIG_DEF(flag/allow_ai) // allow ai job
/datum/config_entry/flag/allow_ai // allow ai job
CONFIG_DEF(flag/disable_secborg) // disallow secborg module to be chosen.
/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen.
CONFIG_DEF(flag/disable_peaceborg)
/datum/config_entry/flag/disable_peaceborg
CONFIG_DEF(number/traitor_scaling_coeff) //how much does the amount of players get divided by to determine traitors
/datum/config_entry/number/traitor_scaling_coeff //how much does the amount of players get divided by to determine traitors
value = 6
min_val = 1
CONFIG_DEF(number/brother_scaling_coeff) //how many players per brother team
/datum/config_entry/number/brother_scaling_coeff //how many players per brother team
value = 25
min_val = 1
CONFIG_DEF(number/changeling_scaling_coeff) //how much does the amount of players get divided by to determine changelings
/datum/config_entry/number/changeling_scaling_coeff //how much does the amount of players get divided by to determine changelings
value = 6
min_val = 1
CONFIG_DEF(number/security_scaling_coeff) //how much does the amount of players get divided by to determine open security officer positions
/datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions
value = 8
min_val = 1
CONFIG_DEF(number/abductor_scaling_coeff) //how many players per abductor team
/datum/config_entry/number/abductor_scaling_coeff //how many players per abductor team
value = 15
min_val = 1
CONFIG_DEF(number/traitor_objectives_amount)
/datum/config_entry/number/traitor_objectives_amount
value = 2
min_val = 0
CONFIG_DEF(number/brother_objectives_amount)
/datum/config_entry/number/brother_objectives_amount
value = 2
min_val = 0
CONFIG_DEF(flag/reactionary_explosions) //If we use reactionary explosions, explosions that react to walls and doors
/datum/config_entry/flag/reactionary_explosions //If we use reactionary explosions, explosions that react to walls and doors
CONFIG_DEF(flag/protect_roles_from_antagonist) //If security and such can be traitor/cult/other
/datum/config_entry/flag/protect_roles_from_antagonist //If security and such can be traitor/cult/other
CONFIG_DEF(flag/protect_assistant_from_antagonist) //If assistants can be traitor/cult/other
/datum/config_entry/flag/protect_assistant_from_antagonist //If assistants can be traitor/cult/other
CONFIG_DEF(flag/enforce_human_authority) //If non-human species are barred from joining as a head of staff
/datum/config_entry/flag/enforce_human_authority //If non-human species are barred from joining as a head of staff
CONFIG_DEF(flag/allow_latejoin_antagonists) // If late-joining players can be traitor/changeling
/datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling
CONFIG_DEF(number/midround_antag_time_check) // How late (in minutes) you want the midround antag system to stay on, setting this to 0 will disable the system
/datum/config_entry/number/midround_antag_time_check // How late (in minutes you want the midround antag system to stay on, setting this to 0 will disable the system)
value = 60
min_val = 0
CONFIG_DEF(number/midround_antag_life_check) // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
/datum/config_entry/number/midround_antag_life_check // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
value = 0.7
integer = FALSE
min_val = 0
max_val = 1
CONFIG_DEF(number/shuttle_refuel_delay)
/datum/config_entry/number/shuttle_refuel_delay
value = 12000
min_val = 0
CONFIG_DEF(flag/show_game_type_odds) //if set this allows players to see the odds of each roundtype on the get revision screen
/datum/config_entry/flag/show_game_type_odds //if set this allows players to see the odds of each roundtype on the get revision screen
CONFIG_DEF(keyed_flag_list/roundstart_races) //races you can play as from the get go.
/datum/config_entry/keyed_flag_list/roundstart_races //races you can play as from the get go.
CONFIG_DEF(flag/join_with_mutant_humans) //players can pick mutant bodyparts for humans before joining the game
/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
CONFIG_DEF(flag/no_summon_guns) //No
/datum/config_entry/flag/no_summon_guns //No
CONFIG_DEF(flag/no_summon_magic) //Fun
/datum/config_entry/flag/no_summon_magic //Fun
CONFIG_DEF(flag/no_summon_events) //Allowed
/datum/config_entry/flag/no_summon_events //Allowed
CONFIG_DEF(flag/no_intercept_report) //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes.
/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes.
CONFIG_DEF(number/arrivals_shuttle_dock_window) //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
value = 55
min_val = 30
CONFIG_DEF(flag/arrivals_shuttle_require_undocked) //Require the arrivals shuttle to be undocked before latejoiners can join
/datum/config_entry/flag/arrivals_shuttle_require_undocked //Require the arrivals shuttle to be undocked before latejoiners can join
CONFIG_DEF(flag/arrivals_shuttle_require_safe_latejoin) //Require the arrivals shuttle to be operational in order for latejoiners to join
/datum/config_entry/flag/arrivals_shuttle_require_safe_latejoin //Require the arrivals shuttle to be operational in order for latejoiners to join
CONFIG_DEF(string/alert_green)
/datum/config_entry/string/alert_green
value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
CONFIG_DEF(string/alert_blue_upto)
/datum/config_entry/string/alert_blue_upto
value = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted."
CONFIG_DEF(string/alert_blue_downto)
/datum/config_entry/string/alert_blue_downto
value = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed."
CONFIG_DEF(string/alert_red_upto)
/datum/config_entry/string/alert_red_upto
value = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
CONFIG_DEF(string/alert_red_downto)
/datum/config_entry/string/alert_red_downto
value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised."
CONFIG_DEF(string/alert_delta)
/datum/config_entry/string/alert_delta
value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
CONFIG_DEF(flag/revival_pod_plants)
/datum/config_entry/flag/revival_pod_plants
CONFIG_DEF(flag/revival_cloning)
/datum/config_entry/flag/revival_cloning
CONFIG_DEF(number/revival_brain_life)
/datum/config_entry/number/revival_brain_life
value = -1
min_val = -1
CONFIG_DEF(flag/rename_cyborg)
/datum/config_entry/flag/rename_cyborg
CONFIG_DEF(flag/ooc_during_round)
/datum/config_entry/flag/ooc_during_round
CONFIG_DEF(flag/emojis)
/datum/config_entry/flag/emojis
CONFIG_DEF(number/run_delay) //Used for modifying movement speed for mobs.
/datum/config_entry/number/run_delay //Used for modifying movement speed for mobs.
var/static/value_cache = 0
CONFIG_TWEAK(number/run_delay/ValidateAndSet())
/datum/config_entry/number/run_delay/ValidateAndSet()
. = ..()
if(.)
value_cache = value
CONFIG_DEF(number/walk_delay)
/datum/config_entry/number/walk_delay
var/static/value_cache = 0
CONFIG_TWEAK(number/walk_delay/ValidateAndSet())
/datum/config_entry/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)
CONFIG_DEF(number/monkey_delay)
CONFIG_DEF(number/alien_delay)
CONFIG_DEF(number/slime_delay)
CONFIG_DEF(number/animal_delay)
/datum/config_entry/number/human_delay //Mob specific modifiers. NOTE: These will affect different mob types in different ways
/datum/config_entry/number/robot_delay
/datum/config_entry/number/monkey_delay
/datum/config_entry/number/alien_delay
/datum/config_entry/number/slime_delay
/datum/config_entry/number/animal_delay
CONFIG_DEF(number/gateway_delay) //How long the gateway takes before it activates. Default is half an hour.
/datum/config_entry/number/gateway_delay //How long the gateway takes before it activates. Default is half an hour.
value = 18000
min_val = 0
CONFIG_DEF(flag/ghost_interaction)
/datum/config_entry/flag/ghost_interaction
CONFIG_DEF(flag/silent_ai)
CONFIG_DEF(flag/silent_borg)
/datum/config_entry/flag/silent_ai
/datum/config_entry/flag/silent_borg
CONFIG_DEF(flag/sandbox_autoclose) // close the sandbox panel after spawning an item, potentially reducing griff
/datum/config_entry/flag/sandbox_autoclose // close the sandbox panel after spawning an item, potentially reducing griff
CONFIG_DEF(number/default_laws) //Controls what laws the AI spawns with.
/datum/config_entry/number/default_laws //Controls what laws the AI spawns with.
value = 0
min_val = 0
max_val = 3
CONFIG_DEF(number/silicon_max_law_amount)
/datum/config_entry/number/silicon_max_law_amount
value = 12
min_val = 0
CONFIG_DEF(keyed_flag_list/random_laws)
/datum/config_entry/keyed_flag_list/random_laws
CONFIG_DEF(keyed_number_list/law_weight)
/datum/config_entry/keyed_number_list/law_weight
splitter = ","
CONFIG_DEF(number/assistant_cap)
/datum/config_entry/number/assistant_cap
value = -1
min_val = -1
CONFIG_DEF(flag/starlight)
CONFIG_DEF(flag/grey_assistants)
/datum/config_entry/flag/starlight
/datum/config_entry/flag/grey_assistants
CONFIG_DEF(number/lavaland_budget)
/datum/config_entry/number/lavaland_budget
value = 60
min_val = 0
CONFIG_DEF(number/space_budget)
/datum/config_entry/number/space_budget
value = 16
min_val = 0
CONFIG_DEF(flag/allow_random_events) // Enables random events mid-round when set
/datum/config_entry/flag/allow_random_events // Enables random events mid-round when set
CONFIG_DEF(number/events_min_time_mul) // Multipliers for random events minimal starting time and minimal players amounts
/datum/config_entry/number/events_min_time_mul // Multipliers for random events minimal starting time and minimal players amounts
value = 1
min_val = 0
integer = FALSE
CONFIG_DEF(number/events_min_players_mul)
/datum/config_entry/number/events_min_players_mul
value = 1
min_val = 0
integer = FALSE
CONFIG_DEF(number/mice_roundstart)
/datum/config_entry/number/mice_roundstart
value = 10
min_val = 0
CONFIG_DEF(number/bombcap)
/datum/config_entry/number/bombcap
value = 14
min_val = 4
CONFIG_DEF(flag/allow_crew_objectives)
CONFIG_DEF(flag/allow_miscreants)
CONFIG_DEF(flag/allow_extended_miscreants)
//Cit changes - Adds config options for crew objectives and miscreants
/datum/config_entry/flag/allow_crew_objectives
/datum/config_entry/flag/allow_miscreants
/datum/config_entry/flag/allow_extended_miscreants
//End of Cit changes
/datum/config_entry/number/bombcap/ValidateAndSet(str_val)
. = ..()
@@ -258,9 +260,9 @@ CONFIG_DEF(flag/allow_extended_miscreants)
GLOB.MAX_EX_FLASH_RANGE = value
GLOB.MAX_EX_FLAME_RANGE = value
CONFIG_DEF(number/emergency_shuttle_autocall_threshold)
/datum/config_entry/number/emergency_shuttle_autocall_threshold
min_val = 0
max_val = 1
integer = FALSE
CONFIG_DEF(flag/ic_printing)
/datum/config_entry/flag/ic_printing
@@ -0,0 +1,388 @@
/datum/config_entry/flag/autoadmin // if autoadmin is enabled
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/string/autoadmin_rank // the rank for autoadmins
value = "Game Master"
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/string/servername // server name (the name of the game window)
/datum/config_entry/string/serversqlname // short form server name used for the DB
/datum/config_entry/string/stationname // station name (the name of the station in-game)
/datum/config_entry/number/lobby_countdown // In between round countdown.
value = 120
min_val = 0
/datum/config_entry/number/round_end_countdown // Post round murder death kill countdown
value = 25
min_val = 0
/datum/config_entry/flag/hub // if the game appears on the hub or not
/datum/config_entry/flag/log_ooc // log OOC channel
/datum/config_entry/flag/log_access // log login/logout
/datum/config_entry/flag/log_say // log client say
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_prayer // log prayers
/datum/config_entry/flag/log_law // log lawchanges
/datum/config_entry/flag/log_game // log game events
/datum/config_entry/flag/log_vote // log voting
/datum/config_entry/flag/log_whisper // log client whisper
/datum/config_entry/flag/log_attack // log attack messages
/datum/config_entry/flag/log_emote // log emotes
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_pda // log pda messages
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
/datum/config_entry/flag/allow_vote_restart // allow votes to restart
/datum/config_entry/flag/allow_vote_mode // allow votes to change mode
/datum/config_entry/number/vote_delay // minimum time between voting sessions (deciseconds, 10 minute default)
value = 6000
min_val = 0
/datum/config_entry/number/vote_period // length of voting period (deciseconds, default 1 minute)
value = 600
min_val = 0
/datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart
/datum/config_entry/flag/no_dead_vote // dead people can't vote
/datum/config_entry/flag/allow_metadata // Metadata is supported.
/datum/config_entry/flag/popup_admin_pm // adminPMs to non-admins show in a pop-up 'reply' window when set
/datum/config_entry/number/fps
value = 20
min_val = 1
max_val = 100 //byond will start crapping out at 50, so this is just ridic
var/sync_validate = FALSE
/datum/config_entry/number/fps/ValidateAndSet(str_val)
. = ..()
if(.)
sync_validate = TRUE
var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
if(!TL.sync_validate)
TL.ValidateAndSet(10 / value)
sync_validate = FALSE
/datum/config_entry/number/ticklag
integer = FALSE
var/sync_validate = FALSE
/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
var/datum/config_entry/CE = /datum/config_entry/number/fps
value = 10 / initial(CE.value)
..()
/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
. = text2num(str_val) > 0 && ..()
if(.)
sync_validate = TRUE
var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
if(!FPS.sync_validate)
FPS.ValidateAndSet(10 / value)
sync_validate = FALSE
/datum/config_entry/flag/allow_holidays
/datum/config_entry/number/tick_limit_mc_init //SSinitialization throttling
value = TICK_LIMIT_MC_INIT_DEFAULT
min_val = 0 //oranges warned us
integer = FALSE
/datum/config_entry/flag/admin_legacy_system //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/string/hostedby
/datum/config_entry/flag/norespawn
/datum/config_entry/flag/guest_jobban
/datum/config_entry/flag/usewhitelist
/datum/config_entry/flag/ban_legacy_system //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/use_age_restriction_for_jobs //Do jobs use account age restrictions? --requires database
/datum/config_entry/flag/use_account_age_for_jobs //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
/datum/config_entry/flag/use_exp_tracking
/datum/config_entry/flag/use_exp_restrictions_heads
/datum/config_entry/number/use_exp_restrictions_heads_hours
value = 0
min_val = 0
/datum/config_entry/flag/use_exp_restrictions_heads_department
/datum/config_entry/flag/use_exp_restrictions_other
/datum/config_entry/flag/use_exp_restrictions_admin_bypass
/datum/config_entry/string/server
/datum/config_entry/string/banappeals
/datum/config_entry/string/wikiurl
value = "http://www.tgstation13.org/wiki"
/datum/config_entry/string/forumurl
value = "http://tgstation13.org/phpBB/index.php"
/datum/config_entry/string/rulesurl
value = "http://www.tgstation13.org/wiki/Rules"
/datum/config_entry/string/githuburl
value = "https://www.github.com/tgstation/-tg-station"
/datum/config_entry/number/githubrepoid
value = null
min_val = 0
/datum/config_entry/flag/guest_ban
/datum/config_entry/number/id_console_jobslot_delay
value = 30
min_val = 0
/datum/config_entry/number/inactivity_period //time in ds until a player is considered inactive
value = 3000
min_val = 0
/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val)
. = ..()
if(.)
value *= 10 //documented as seconds in config.txt
/datum/config_entry/number/afk_period //time in ds until a player is considered inactive
value = 3000
min_val = 0
/datum/config_entry/number/afk_period/ValidateAndSet(str_val)
. = ..()
if(.)
value *= 10 //documented as seconds in config.txt
/datum/config_entry/flag/kick_inactive //force disconnect for inactive players
/datum/config_entry/flag/load_jobs_from_txt
/datum/config_entry/flag/forbid_singulo_possession
/datum/config_entry/flag/automute_on //enables automuting/spam prevention
/datum/config_entry/string/panic_server_name
/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
return str_val != "\[Put the name here\]" && ..()
/datum/config_entry/string/panic_server_address //Reconnect a player this linked server if this server isn't accepting new players
/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val)
return str_val != "byond://address:port" && ..()
/datum/config_entry/string/invoke_youtubedl
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
/datum/config_entry/flag/show_irc_name
/datum/config_entry/flag/see_own_notes //Can players see their own admin notes
/datum/config_entry/number/note_fresh_days
value = null
min_val = 0
integer = FALSE
/datum/config_entry/number/note_stale_days
value = null
min_val = 0
integer = FALSE
/datum/config_entry/flag/maprotation
/datum/config_entry/number/maprotatechancedelta
value = 0.75
min_val = 0
max_val = 1
integer = FALSE
/datum/config_entry/number/soft_popcap
value = null
min_val = 0
/datum/config_entry/number/hard_popcap
value = null
min_val = 0
/datum/config_entry/number/extreme_popcap
value = null
min_val = 0
/datum/config_entry/string/soft_popcap_message
value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
/datum/config_entry/string/hard_popcap_message
value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
/datum/config_entry/string/extreme_popcap_message
value = "The server is currently serving a high number of users, find alternative servers."
/datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting
/datum/config_entry/number/notify_new_player_age // how long do we notify admins of a new player
min_val = -1
/datum/config_entry/number/notify_new_player_account_age // how long do we notify admins of a new byond account
min_val = 0
/datum/config_entry/flag/irc_first_connection_alert // do we notify the irc channel when somebody is connecting for the first time?
/datum/config_entry/flag/check_randomizer
/datum/config_entry/string/ipintel_email
/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
return str_val != "ch@nge.me" && ..()
/datum/config_entry/number/ipintel_rating_bad
value = 1
integer = FALSE
min_val = 0
max_val = 1
/datum/config_entry/number/ipintel_save_good
value = 12
min_val = 0
/datum/config_entry/number/ipintel_save_bad
value = 1
min_val = 0
/datum/config_entry/string/ipintel_domain
value = "check.getipintel.net"
/datum/config_entry/flag/aggressive_changelog
/datum/config_entry/flag/autoconvert_notes //if all connecting player's notes should attempt to be converted to the database
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/allow_webclient
/datum/config_entry/flag/webclient_only_byond_members
/datum/config_entry/flag/announce_admin_logout
/datum/config_entry/flag/announce_admin_login
/datum/config_entry/flag/allow_map_voting
/datum/config_entry/flag/generate_minimaps
/datum/config_entry/number/client_warn_version
value = null
min_val = 500
max_val = DM_VERSION - 1
/datum/config_entry/string/client_warn_message
value = "Your version of byond may have issues or be blocked from accessing this server in the future."
/datum/config_entry/flag/client_warn_popup
/datum/config_entry/number/client_error_version
value = null
min_val = 500
max_val = DM_VERSION - 1
/datum/config_entry/string/client_error_message
value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
/datum/config_entry/number/minute_topic_limit
value = null
min_val = 0
/datum/config_entry/number/second_topic_limit
value = null
min_val = 0
/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
value = 600
min_val = 0
/datum/config_entry/number/error_limit // How many occurrences before the next will silence them
value = 50
/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for
value = 6000
/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error
value = 50
/datum/config_entry/flag/irc_announce_new_game
/datum/config_entry/flag/debug_admin_hrefs
/datum/config_entry/number/mc_tick_rate/base_mc_tick_rate
integer = FALSE
value = 1
/datum/config_entry/number/mc_tick_rate/high_pop_mc_tick_rate
integer = FALSE
value = 1.1
/datum/config_entry/number/mc_tick_rate/high_pop_mc_mode_amount
value = 65
/datum/config_entry/number/mc_tick_rate/disable_high_pop_mc_mode_amount
value = 60
/datum/config_entry/number/mc_tick_rate
abstract_type = /datum/config_entry/number/mc_tick_rate
/datum/config_entry/number/mc_tick_rate/ValidateAndSet(str_val)
. = ..()
if (.)
Master.UpdateTickRate()
/datum/config_entry/flag/resume_after_initializations
/datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val)
. = ..()
if(. && Master.current_runlevel)
world.sleep_offline = !value
/datum/config_entry/number/rounds_until_hard_restart
value = -1
min_val = 0
/datum/config_entry/string/default_view
value = "15x15"
+1 -1
View File
@@ -301,7 +301,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
continue
//Byond resumed us late. assume it might have to do the same next tick
if (last_run + Ceiling(world.tick_lag * (processing * sleep_delta), world.tick_lag) < world.time)
if (last_run + CEILING(world.tick_lag * (processing * sleep_delta), world.tick_lag) < world.time)
sleep_delta += 1
sleep_delta = MC_AVERAGE_FAST(sleep_delta, 1) //decay sleep_delta
+3
View File
@@ -8,6 +8,8 @@
var/flags = 0 //see MC.dm in __DEFINES Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again)
var/initialized = FALSE //set to TRUE after it has been initialized, will obviously never be set if the subsystem doesn't initialize
//set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
// use the SS_NO_FIRE flag instead for systems that never fire to keep it from even being added to the list
var/can_fire = TRUE
@@ -156,6 +158,7 @@
//used to initialize the subsystem AFTER the map has loaded
/datum/controller/subsystem/Initialize(start_timeofday)
initialized = TRUE
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
to_chat(world, "<span class='boldannounce'>[msg]</span>")
-1
View File
@@ -8,7 +8,6 @@ SUBSYSTEM_DEF(atoms)
init_order = INIT_ORDER_ATOMS
flags = SS_NO_FIRE
var/initialized = INITIALIZATION_INSSATOMS
var/old_initialized
var/list/late_loaders
+20 -6
View File
@@ -10,7 +10,8 @@ SUBSYSTEM_DEF(blackbox)
var/sealed = FALSE //time to stop tracking stats?
var/list/research_levels = list() //list of highest tech levels attained that isn't lost lost by destruction of RD computers
var/list/versions = list("time_dilation_current" = 2,
"science_techweb_unlock" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
"science_techweb_unlock" = 2,
"antagonists" = 3) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
/datum/controller/subsystem/blackbox/Initialize()
@@ -39,13 +40,20 @@ SUBSYSTEM_DEF(blackbox)
sealed = SSblackbox.sealed
//no touchie
/datum/controller/subsystem/blackbox/can_vv_get(var_name)
/datum/controller/subsystem/blackbox/vv_get_var(var_name)
if(var_name == "feedback")
return FALSE
return debug_variable(var_name, deepCopyList(feedback), 0, src)
return ..()
/datum/controller/subsystem/blackbox/vv_edit_var(var_name, var_value)
return FALSE
switch(var_name)
if("feedback")
return FALSE
if("sealed")
if(var_value)
return Seal()
return FALSE
return ..()
/datum/controller/subsystem/blackbox/Shutdown()
sealed = FALSE
@@ -76,11 +84,12 @@ SUBSYSTEM_DEF(blackbox)
/datum/controller/subsystem/blackbox/proc/Seal()
if(sealed)
return
return FALSE
if(IsAdminAdvancedProcCall())
message_admins("[key_name_admin(usr)] sealed the blackbox!")
log_game("Blackbox sealed[IsAdminAdvancedProcCall() ? " by [key_name(usr)]" : ""].")
sealed = TRUE
return TRUE
/datum/controller/subsystem/blackbox/proc/log_research(tech, level)
if(!(tech in research_levels) || research_levels[tech] < level)
@@ -217,7 +226,12 @@ Versioning
var/pos = length(FV.json["data"]) + 1
FV.json["data"]["[pos]"] = list() //in 512 "pos" can be replaced with "[FV.json["data"].len+1]"
for(var/i in data)
FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" //and here with "[FV.json["data"].len]"
if(islist(data[i]))
FV.json["data"]["[pos]"]["[i]"] = data[i] //and here with "[FV.json["data"].len]"
else
FV.json["data"]["[pos]"]["[i]"] = "[data[i]]"
else
CRASH("Invalid feedback key_type: [key_type]")
/datum/controller/subsystem/blackbox/proc/record_feedback_recurse_list(list/L, list/key_list, increment, depth = 1)
if(depth == key_list.len)
+8 -1
View File
@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(disease)
name = "Disease"
flags = SS_NO_FIRE | SS_NO_INIT
flags = SS_NO_FIRE
var/list/active_diseases = list() //List of Active disease in all mobs; purely for quick referencing.
var/list/diseases
@@ -12,6 +12,13 @@ SUBSYSTEM_DEF(disease)
if(!diseases)
diseases = subtypesof(/datum/disease)
/datum/controller/subsystem/disease/Initialize(timeofday)
var/list/all_common_diseases = diseases - typesof(/datum/disease/advance)
for(var/common_disease_type in all_common_diseases)
var/datum/disease/prototype = new common_disease_type()
archive_diseases[prototype.GetDiseaseID()] = prototype
..()
/datum/controller/subsystem/disease/stat_entry(msg)
..("P:[active_diseases.len]")
+12
View File
@@ -0,0 +1,12 @@
SUBSYSTEM_DEF(input)
name = "Input"
wait = 1 //SS_TICKER means this runs every tick
flags = SS_TICKER | SS_NO_INIT
priority = 1000
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
/datum/controller/subsystem/input/fire()
var/list/clients = GLOB.clients // Let's sing the list cache song
for(var/i in 1 to clients.len)
var/client/C = clients[i]
C.keyLoop()
-2
View File
@@ -8,8 +8,6 @@ SUBSYSTEM_DEF(lighting)
init_order = INIT_ORDER_LIGHTING
flags = SS_TICKER
var/initialized = FALSE
/datum/controller/subsystem/lighting/stat_entry()
..("L:[GLOB.lighting_update_lights.len]|C:[GLOB.lighting_update_corners.len]|O:[GLOB.lighting_update_objects.len]")
+5 -1
View File
@@ -1,14 +1,18 @@
SUBSYSTEM_DEF(mobs)
name = "Mobs"
priority = 100
flags = SS_KEEP_TIMING|SS_NO_INIT
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/currentrun = list()
var/static/list/clients_by_zlevel[][]
/datum/controller/subsystem/mobs/stat_entry()
..("P:[GLOB.mob_living_list.len]")
/datum/controller/subsystem/mobs/Initialize(start_timeofday)
clients_by_zlevel = new /list(world.maxz,0)
return ..()
/datum/controller/subsystem/mobs/fire(resumed = 0)
var/seconds = wait * 0.1
-1
View File
@@ -10,7 +10,6 @@ SUBSYSTEM_DEF(overlays)
var/list/stats
var/list/overlay_icon_state_caches
var/list/overlay_icon_cache
var/initialized = FALSE
/datum/controller/subsystem/overlays/PreInit()
overlay_icon_state_caches = list()
@@ -44,10 +44,20 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
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
/obj/item/device/electronic_assembly/default,
/obj/item/device/electronic_assembly/calc,
/obj/item/device/electronic_assembly/clam,
/obj/item/device/electronic_assembly/simple,
/obj/item/device/electronic_assembly/medium/default,
/obj/item/device/electronic_assembly/medium/box,
/obj/item/device/electronic_assembly/medium/clam,
/obj/item/device/electronic_assembly/medium/medical,
/obj/item/device/electronic_assembly/large/default,
/obj/item/device/electronic_assembly/large/scope,
/obj/item/device/electronic_assembly/large/terminal,
/obj/item/device/electronic_assembly/large/arm,
/obj/item/device/electronic_assembly/drone/default,
/obj/item/device/electronic_assembly/drone/arms
///obj/item/weapon/implant/integrated_circuit
)
@@ -1,36 +1,36 @@
PROCESSING_SUBSYSTEM_DEF(networks)
name = "Networks"
priority = 80
wait = 1
stat_tag = "NET"
flags = SS_KEEP_TIMING
init_order = INIT_ORDER_NETWORKS
var/datum/ntnet/station/station_network
var/assignment_hardware_id = HID_RESTRICTED_END
var/list/networks_by_id = list() //id = network
var/list/interfaces_by_id = list() //hardware id = component interface
/datum/controller/subsystem/processing/networks/Initialize()
station_network = new
station_network.register_map_supremecy()
. = ..()
/datum/controller/subsystem/processing/networks/proc/register_network(datum/ntnet/network)
if(!networks_by_id[network.network_id])
networks_by_id[network.network_id] = network
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_network(datum/ntnet/network)
networks_by_id -= network.network_id
return TRUE
/datum/controller/subsystem/processing/networks/proc/register_interface(datum/component/ntnet_interface/D)
if(!interfaces_by_id[D.hardware_id])
interfaces_by_id[D.hardware_id] = D
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_interface(datum/component/ntnet_interface/D)
interfaces_by_id -= D.hardware_id
return TRUE
PROCESSING_SUBSYSTEM_DEF(networks)
name = "Networks"
priority = 80
wait = 1
stat_tag = "NET"
flags = SS_KEEP_TIMING
init_order = INIT_ORDER_NETWORKS
var/datum/ntnet/station/station_network
var/assignment_hardware_id = HID_RESTRICTED_END
var/list/networks_by_id = list() //id = network
var/list/interfaces_by_id = list() //hardware id = component interface
/datum/controller/subsystem/processing/networks/Initialize()
station_network = new
station_network.register_map_supremecy()
. = ..()
/datum/controller/subsystem/processing/networks/proc/register_network(datum/ntnet/network)
if(!networks_by_id[network.network_id])
networks_by_id[network.network_id] = network
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_network(datum/ntnet/network)
networks_by_id -= network.network_id
return TRUE
/datum/controller/subsystem/processing/networks/proc/register_interface(datum/component/ntnet_interface/D)
if(!interfaces_by_id[D.hardware_id])
interfaces_by_id[D.hardware_id] = D
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_interface(datum/component/ntnet_interface/D)
interfaces_by_id -= D.hardware_id
return TRUE
+7
View File
@@ -3,6 +3,13 @@ SUBSYSTEM_DEF(radio)
flags = SS_NO_FIRE|SS_NO_INIT
var/list/datum/radio_frequency/frequencies = list()
var/list/saymodes = list()
/datum/controller/subsystem/radio/PreInit(timeofday)
for(var/_SM in subtypesof(/datum/saymode))
var/datum/saymode/SM = new _SM()
saymodes[SM.key] = SM
return ..()
/datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency as num, filter = null as text|null)
var/f_text = num2text(new_frequency)
+75
View File
@@ -0,0 +1,75 @@
SUBSYSTEM_DEF(research)
name = "Research"
flags = SS_KEEP_TIMING
priority = 15 //My powergame is priority.
wait = 10
init_order = INIT_ORDER_RESEARCH
var/list/invalid_design_ids = list() //associative id = number of times
var/list/invalid_node_ids = list() //associative id = number of times
var/list/invalid_node_boost = list() //associative id = error message
var/list/obj/machinery/rnd/server/servers = list()
var/datum/techweb/science/science_tech
var/datum/techweb/admin/admin_tech
var/list/techweb_nodes = list() //associative id = node datum
var/list/techweb_categories = list() //category name = list(node.id = node)
var/list/techweb_designs = list() //associative id = node datum
var/list/techweb_nodes_starting = list() //associative id = node datum
var/list/techweb_boost_items = list() //associative double-layer path = list(id = point_discount)
var/list/techweb_nodes_hidden = list() //Nodes that should be hidden by default.
var/list/techweb_point_items = list() //path = value
var/list/errored_datums = list()
//----------------------------------------------
var/single_server_income = 40.7
var/multiserver_calculation = FALSE
var/last_income = 0
//^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^
//Aiming for 1.5 hours to max R&D
//[88nodes * 5000points/node] / [1.5hr * 90min/hr * 60s/min]
//Around 450000 points max???
var/bomb_research_point_scaling = 1800
/datum/controller/subsystem/research/Initialize()
initialize_all_techweb_designs()
initialize_all_techweb_nodes()
science_tech = new /datum/techweb/science
admin_tech = new /datum/techweb/admin
autosort_categories()
return ..()
/datum/controller/subsystem/research/fire()
handle_research_income()
/datum/controller/subsystem/research/proc/handle_research_income()
var/bitcoins = 0
if(multiserver_calculation)
var/eff = calculate_server_coefficient()
for(var/obj/machinery/rnd/server/miner in servers)
bitcoins += (miner.mine() * eff) //SLAVE AWAY, SLAVE.
else
for(var/obj/machinery/rnd/server/miner in servers)
if(miner.working)
bitcoins = single_server_income
break //Just need one to work.
var/income_time_difference = world.time - last_income
bitcoins *= income_time_difference / 10
science_tech.research_points += bitcoins
last_income = world.time
/datum/controller/subsystem/research/proc/calculate_server_coefficient() //Diminishing returns.
var/amt = servers.len
if(!amt)
return 0
var/coeff = 100
coeff = sqrt(coeff / amt)
return coeff
/datum/controller/subsystem/research/proc/autosort_categories()
for(var/i in techweb_nodes)
var/datum/techweb_node/I = techweb_nodes[i]
if(techweb_categories[I.category])
techweb_categories[I.category][I.id] = I
else
techweb_categories[I.category] = list(I.id = I)
@@ -55,5 +55,8 @@ SUBSYSTEM_DEF(server_maint)
co.ehjax_send(data = "roundrestart")
if(server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[server]")
if(SERVER_TOOLS_PRESENT)
SSblackbox.record_feedback("text", "server_tools", 1, SERVER_TOOLS_VERSION)
SSblackbox.record_feedback("text", "server_tools_api", 1, SERVER_TOOLS_API_VERSION)
#undef PING_BUFFER_TIME
+43 -1
View File
@@ -44,6 +44,9 @@ SUBSYSTEM_DEF(shuttle)
var/list/requestlist = list()
var/list/orderhistory = list()
var/list/hidden_shuttle_turfs = list() //all turfs hidden from navigation computers associated with a list containing the image hiding them and the type of the turf they are pretending to be
var/list/hidden_shuttle_turf_images = list() //only the images from the above list
var/datum/round_event/shuttle_loan/shuttle_loan
var/shuttle_purchased = FALSE //If the station has purchased a replacement escape shuttle this round
@@ -304,6 +307,9 @@ SUBSYSTEM_DEF(shuttle)
return 1
/datum/controller/subsystem/shuttle/proc/autoEvac()
if (!SSticker.IsRoundInProgress())
return
var/callShuttle = 1
for(var/thing in GLOB.shuttle_caller_list)
@@ -648,4 +654,40 @@ SUBSYSTEM_DEF(shuttle)
var/list/xs = overlap[1]
var/list/ys = overlap[2]
if(xs.len && ys.len)
.[port] = overlap
.[port] = overlap
/datum/controller/subsystem/shuttle/proc/update_hidden_docking_ports(list/remove_turfs, list/add_turfs)
var/list/remove_images = list()
var/list/add_images = list()
if(remove_turfs)
for(var/T in remove_turfs)
var/list/L = hidden_shuttle_turfs[T]
if(L)
remove_images += L[1]
hidden_shuttle_turfs -= remove_turfs
if(add_turfs)
for(var/V in add_turfs)
var/turf/T = V
var/image/I
if(remove_images.len)
//we can just reuse any images we are about to delete instead of making new ones
I = remove_images[1]
remove_images.Cut(1, 2)
I.loc = T
else
I = image(loc = T)
add_images += I
I.appearance = T.appearance
I.override = TRUE
hidden_shuttle_turfs[T] = list(I, T.type)
hidden_shuttle_turf_images -= remove_images
hidden_shuttle_turf_images += add_images
for(var/V in GLOB.navigation_computers)
var/obj/machinery/computer/camera_advanced/shuttle_docker/C = V
C.update_hidden_docking_ports(remove_images, add_images)
QDEL_LIST(remove_images)
+1 -1
View File
@@ -80,7 +80,7 @@ SUBSYSTEM_DEF(throwing)
last_move = world.time
//calculate how many tiles to move, making up for any missed ticks.
var/tilestomove = Ceiling(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait))
var/tilestomove = CEILING(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait), 1)
while (tilestomove-- > 0)
if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc))
finalize()
+1 -192
View File
@@ -33,8 +33,8 @@ SUBSYSTEM_DEF(ticker)
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
var/admin_delay_notice = "" //a message to display to anyone who tries to restart the world after a delay
var/ready_for_reboot = FALSE //all roundend preparation done with, all that's left is reboot
var/triai = 0 //Global holder for Triumvirate
var/tipped = 0 //Did we broadcast the tip of the day yet?
@@ -398,197 +398,6 @@ SUBSYSTEM_DEF(ticker)
var/mob/living/L = I
L.notransform = FALSE
/datum/controller/subsystem/ticker/proc/declare_completion()
set waitfor = FALSE
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
var/num_survivors = 0
var/num_escapees = 0
var/num_shuttle_escapees = 0
var/list/successfulCrew = list()
var/list/miscreants = list()
to_chat(world, "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>")
if(LAZYLEN(GLOB.round_end_notifiees))
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
/* var/nocredits = config.no_credits_round_end
for(var/client/C in GLOB.clients)
if(!C.credits && !nocredits)
C.RollCredits()
C.playtitlemusic(40)*/
//Player status report
for(var/i in GLOB.mob_list)
var/mob/Player = i
if(Player.mind && !isnewplayer(Player))
if(Player.stat != DEAD && !isbrain(Player))
num_survivors++
if(station_evacuated) //If the shuttle has already left the station
var/list/area/shuttle_areas
if(SSshuttle && SSshuttle.emergency)
shuttle_areas = SSshuttle.emergency.shuttle_areas
if(!Player.onCentCom() && !Player.onSyndieBase())
to_chat(Player, "<font color='blue'><b>You managed to survive, but were marooned on [station_name()]...</b></FONT>")
else
num_escapees++
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>")
if(shuttle_areas[get_area(Player)])
num_shuttle_escapees++
else
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>")
else
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></FONT>")
CHECK_TICK
//Round statistics report
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
to_chat(world, "<BR>[GLOB.TAB]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>")
to_chat(world, "<BR>[GLOB.TAB]Station Integrity: <B>[mode.station_was_nuked ? "<font color='red'>Destroyed</font>" : "[station_integrity]%"]</B>")
if(mode.station_was_nuked)
SSticker.news_report = STATION_DESTROYED_NUKE
var/total_players = GLOB.joined_player_list.len
if(total_players)
to_chat(world, "<BR>[GLOB.TAB]Total Population: <B>[total_players]</B>")
if(station_evacuated)
to_chat(world, "<BR>[GLOB.TAB]Evacuation Rate: <B>[num_escapees] ([PERCENT(num_escapees/total_players)]%)</B>")
to_chat(world, "<BR>[GLOB.TAB](on emergency shuttle): <B>[num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)</B>")
news_report = STATION_EVACUATED
if(SSshuttle.emergency.is_hijacked())
news_report = SHUTTLE_HIJACK
to_chat(world, "<BR>[GLOB.TAB]Survival Rate: <B>[num_survivors] ([PERCENT(num_survivors/total_players)]%)</B>")
to_chat(world, "<BR>")
CHECK_TICK
//Silicon laws report
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)
else if (aiPlayer.mind) //if the dead ai has a mind, use its key instead
to_chat(world, "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws when it was deactivated were:</b>")
aiPlayer.show_laws(1)
to_chat(world, "<b>Total law changes: [aiPlayer.law_change_counter]</b>")
if (aiPlayer.connected_robots.len)
var/robolist = "<b>[aiPlayer.real_name]'s minions were:</b> "
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
if(robo.mind)
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]"
to_chat(world, "[robolist]")
CHECK_TICK
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>")
else
to_chat(world, "<b>[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:</b>")
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
robo.laws.show_laws(world)
CHECK_TICK
mode.declare_completion()//To declare normal completion.
CHECK_TICK
//calls auto_declare_completion_* for all modes
for(var/handler in typesof(/datum/game_mode/proc))
if (findtext("[handler]","auto_declare_completion_"))
call(mode, handler)(force_ending)
CHECK_TICK
if(CONFIG_GET(string/cross_server_address))
send_news_report()
CHECK_TICK
//Print a list of antagonists to the server log
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
for(var/datum/mind/Mind in minds)
var/temprole = Mind.special_role
if(temprole) //if they are an antagonist of some sort.
if(temprole in total_antagonists) //If the role exists already, add the name to it
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
else
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
CHECK_TICK
//Now print them all into the log!
log_game("Antagonists at round end were...")
for(var/i in total_antagonists)
log_game("[i]s[total_antagonists[i]].")
CHECK_TICK
for(var/datum/mind/crewMind in minds)
if(!crewMind.current || !crewMind.objectives.len)
continue
for(var/datum/objective/miscreant/MO in crewMind.objectives)
miscreants += "<B>[crewMind.current.real_name]</B> (Played by: <B>[crewMind.key]</B>)<BR><B>Objective</B>: [MO.explanation_text] <font color='grey'>(Optional)</font>"
for(var/datum/objective/crew/CO in crewMind.objectives)
if(CO.check_completion())
to_chat(crewMind.current, "<br><B>Your optional objective</B>: [CO.explanation_text] <font color='green'><B>Success!</B></font>")
successfulCrew += "<B>[crewMind.current.real_name]</B> (Played by: <B>[crewMind.key]</B>)<BR><B>Objective</B>: [CO.explanation_text] <font color='green'><B>Success!</B></font> <font color='grey'>(Optional)</font>"
else
to_chat(crewMind.current, "<br><B>Your optional objective</B>: [CO.explanation_text] <font color='red'><B>Failed.</B></font>")
if (successfulCrew.len)
var/completedObjectives = "<B>The following crew members completed their Crew Objectives:</B><BR>"
for(var/i in successfulCrew)
completedObjectives += "[i]<BR>"
to_chat(world, "[completedObjectives]<BR>")
else
if(CONFIG_GET(flag/allow_crew_objectives))
to_chat(world, "<B>Nobody completed their Crew Objectives!</B><BR>")
CHECK_TICK
if (miscreants.len)
var/miscreantObjectives = "<B>The following crew members were miscreants:</B><BR>"
for(var/i in miscreants)
miscreantObjectives += "[i]<BR>"
to_chat(world, "[miscreantObjectives]<BR>")
CHECK_TICK
mode.declare_station_goal_completion()
CHECK_TICK
//medals, placed far down so that people can actually see the commendations.
if(GLOB.commendations.len)
to_chat(world, "<b><font size=3>Medal Commendations:</font></b>")
for (var/com in GLOB.commendations)
to_chat(world, com)
CHECK_TICK
//Collects persistence features
if(mode.allow_persistence_save)
SSpersistence.CollectData()
//stop collecting feedback during grifftime
SSblackbox.Seal()
sleep(50)
if(mode.station_was_nuked)
Reboot("Station destroyed by Nuclear Device.", "nuke")
else
Reboot("Round ended.", "proper completion")
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
var/m
if(selected_tip)
+3
View File
@@ -357,6 +357,9 @@ SUBSYSTEM_DEF(timer)
wait = max(wait, 0)
if(wait >= INFINITY)
CRASH("Attempted to create timer with INFINITY delay")
var/hash
if (flags & TIMER_UNIQUE)
+52
View File
@@ -0,0 +1,52 @@
SUBSYSTEM_DEF(traumas)
name = "Traumas"
flags = SS_NO_FIRE
var/list/phobia_types
var/list/phobia_words
var/list/phobia_mobs
var/list/phobia_objs
var/list/phobia_turfs
var/list/phobia_species
#define PHOBIA_FILE "phobia.json"
/datum/controller/subsystem/traumas/Initialize()
phobia_types = list("spiders", "space", "security", "clowns", "greytide", "lizards", "skeletons")
phobia_words = list("spiders" = strings(PHOBIA_FILE, "spiders"),
"space" = strings(PHOBIA_FILE, "space"),
"security" = strings(PHOBIA_FILE, "security"),
"clowns" = strings(PHOBIA_FILE, "clowns"),
"greytide" = strings(PHOBIA_FILE, "greytide"),
"lizards" = strings(PHOBIA_FILE, "lizards"),
"skeletons" = strings(PHOBIA_FILE, "skeletons"),
)
phobia_mobs = list("spiders" = typecacheof(list(/mob/living/simple_animal/hostile/poison/giant_spider)),
"security" = typecacheof(list(/mob/living/simple_animal/bot/secbot)),
"lizards" = typecacheof(list(/mob/living/simple_animal/hostile/lizard))
)
phobia_objs = list("spiders" = typecacheof(list(/obj/structure/spider)),
"security" = typecacheof(list(/obj/item/clothing/under/rank/security, /obj/item/clothing/under/rank/warden,
/obj/item/clothing/under/rank/head_of_security, /obj/item/clothing/under/rank/det,
/obj/item/melee/baton, /obj/item/gun/energy/taser, /obj/item/restraints/handcuffs,
/obj/machinery/door/airlock/security)),
"clowns" = typecacheof(list(/obj/item/clothing/under/rank/clown, /obj/item/clothing/shoes/clown_shoes,
/obj/item/clothing/mask/gas/clown_hat, /obj/item/device/instrument/bikehorn,
/obj/item/device/pda/clown, /obj/item/grown/bananapeel)),
"greytide" = typecacheof(list(/obj/item/clothing/under/color/grey, /obj/item/melee/baton/cattleprod,
/obj/item/twohanded/spear, /obj/item/clothing/mask/gas)),
"lizards" = typecacheof(list(/obj/item/toy/plush/lizardplushie, /obj/item/reagent_containers/food/snacks/kebab/tail,
/obj/item/organ/tail/lizard, /obj/item/reagent_containers/food/drinks/bottle/lizardwine)),
"skeletons" = typecacheof(list(/obj/item/organ/tongue/bone, /obj/item/clothing/suit/armor/bone, /obj/item/stack/sheet/bone,
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton,
/obj/effect/decal/remains/human))
)
phobia_turfs = list("space" = typecacheof(list(/turf/open/space, /turf/open/floor/holofloor/space, /turf/open/floor/fakespace)))
phobia_species = list("lizards" = typecacheof(list(/datum/species/lizard)),
"skeletons" = typecacheof(list(/datum/species/skeleton, /datum/species/plasmaman))
)
#undef PHOBIA_FILE
+12 -1
View File
@@ -165,7 +165,7 @@ SUBSYSTEM_DEF(vote)
var/admin = FALSE
var/ckey = ckey(initiator_key)
if((GLOB.admin_datums[ckey]) || (ckey in GLOB.deadmins))
if(GLOB.admin_datums[ckey])
admin = TRUE
if(next_allowed_time > world.time && !admin)
@@ -206,6 +206,7 @@ SUBSYSTEM_DEF(vote)
var/datum/action/vote/V = new
if(question)
V.name = "Vote: [question]"
C.player_details.player_actions += V
V.Grant(C.mob)
generated_actions += V
return 1
@@ -299,6 +300,7 @@ SUBSYSTEM_DEF(vote)
for(var/v in generated_actions)
var/datum/action/vote/V = v
if(!QDELETED(V))
V.remove_from_client()
V.Remove(V.owner)
generated_actions = list()
@@ -318,7 +320,16 @@ SUBSYSTEM_DEF(vote)
/datum/action/vote/Trigger()
if(owner)
owner.vote()
remove_from_client()
Remove(owner)
/datum/action/vote/IsAvailable()
return 1
/datum/action/vote/proc/remove_from_client()
if(owner.client)
owner.client.player_details.player_actions -= src
else if(owner.ckey)
var/datum/player_details/P = GLOB.player_details[owner.ckey]
if(P)
P.player_actions -= src
+9
View File
@@ -41,5 +41,14 @@ SUBSYSTEM_DEF(weather)
if(W.name == weather_name && W.target_z == Z)
W.telegraph()
/datum/controller/subsystem/weather/proc/is_weather_affecting_area(area/A, weather_datum_type)
for(var/V in processing)
var/datum/weather/W = V
if(!istype(W, weather_datum_type))
continue
if(A in W.impacted_areas)
return TRUE
return FALSE
/datum/controller/subsystem/weather/proc/make_z_eligible(zlevel)
eligible_zlevels |= zlevel
+19 -1
View File
@@ -43,10 +43,27 @@
return
Remove(owner)
owner = M
//button id generation
var/counter = 0
var/bitfield = 0
for(var/datum/action/A in M.actions)
if(A.name == name && A.button.id)
counter += 1
bitfield |= A.button.id
bitfield = ~bitfield
var/bitflag = 1
for(var/i in 1 to (counter + 1))
if(bitfield & bitflag)
button.id = bitflag
break
bitflag *= 2
M.actions += src
if(M.client)
M.client.screen += button
button.locked = M.client.prefs.buttons_locked
button.locked = M.client.prefs.buttons_locked || button.id ? M.client.prefs.action_buttons_screen_locs["[name]_[button.id]"] : FALSE //even if it's not defaultly locked we should remember we locked it before
button.moved = button.id ? M.client.prefs.action_buttons_screen_locs["[name]_[button.id]"] : FALSE
M.update_action_buttons()
else
Remove(owner)
@@ -60,6 +77,7 @@
owner = null
button.moved = FALSE //so the button appears in its normal position when given to another owner.
button.locked = FALSE
button.id = null
/datum/action/proc/Trigger()
if(!IsAvailable())
+3 -26
View File
@@ -373,32 +373,9 @@
ion = list()
/datum/ai_laws/proc/show_laws(who)
if (devillaws && devillaws.len) //Yes, devil laws go in FRONT of zeroth laws, as the devil must still obey it's ban/obligation.
for(var/i in devillaws)
to_chat(who, "666. [i]")
if (zeroth)
to_chat(who, "0. [zeroth]")
for (var/index = 1, index <= ion.len, index++)
var/law = ion[index]
var/num = ionnum()
to_chat(who, "[num]. [law]")
var/number = 1
for (var/index = 1, index <= inherent.len, index++)
var/law = inherent[index]
if (length(law) > 0)
to_chat(who, "[number]. [law]")
number++
for (var/index = 1, index <= supplied.len, index++)
var/law = supplied[index]
if (length(law) > 0)
to_chat(who, "[number]. [law]")
number++
var/list/printable_laws = get_law_list(include_zeroth = TRUE)
for(var/law in printable_laws)
to_chat(who,law)
/datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1
if(force)
+65 -2
View File
@@ -1,7 +1,8 @@
/datum/antagonist/abductor
name = "Abductor"
roundend_category = "abductors"
job_rank = ROLE_ABDUCTOR
var/datum/objective_team/abductor_team/team
var/datum/team/abductor_team/team
var/sub_role
var/outfit
var/landmark_type
@@ -19,7 +20,7 @@
landmark_type = /obj/effect/landmark/abductor/scientist
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
/datum/antagonist/abductor/create_team(datum/objective_team/abductor_team/new_team)
/datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team)
if(!new_team)
return
if(!istype(new_team))
@@ -70,3 +71,65 @@
var/mob/living/carbon/human/H = owner.current
var/datum/species/abductor/A = H.dna.species
A.scientist = TRUE
/datum/team/abductor_team
member_name = "abductor"
var/team_number
var/list/datum/mind/abductees = list()
/datum/team/abductor_team/is_solo()
return FALSE
/datum/team/abductor_team/proc/add_objective(datum/objective/O)
O.team = src
O.update_explanation_text()
objectives += O
/datum/team/abductor_team/roundend_report()
var/list/result = list()
var/won = TRUE
for(var/datum/objective/O in objectives)
if(!O.check_completion())
won = FALSE
if(won)
result += "<span class='greentext big'>[name] team fulfilled its mission!</span>"
else
result += "<span class='redtext big'>[name] team failed its mission.</span>"
result += "<span class='header'>The abductors of [name] were:</span>"
for(var/datum/mind/abductor_mind in members)
result += printplayer(abductor_mind)
result += printobjectives(abductor_mind)
return result.Join("<br>")
/datum/antagonist/abductee
name = "Abductee"
roundend_category = "abductees"
/datum/antagonist/abductee/on_gain()
give_objective()
. = ..()
/datum/antagonist/abductee/greet()
to_chat(owner, "<span class='warning'><b>Your mind snaps!</b></span>")
to_chat(owner, "<big><span class='warning'><b>You can't remember how you got here...</b></span></big>")
owner.announce_objectives()
/datum/antagonist/abductee/proc/give_objective()
var/mob/living/carbon/human/H = owner.current
if(istype(H))
H.gain_trauma_type(BRAIN_TRAUMA_MILD)
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
var/datum/objective/abductee/O = new objtype()
objectives += O
owner.objectives += objectives
/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override)
SSticker.mode.update_abductor_icons_added(mob_override ? mob_override.mind : owner)
/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override)
SSticker.mode.update_abductor_icons_removed(mob_override ? mob_override.mind : owner)
+59 -3
View File
@@ -2,6 +2,8 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist
var/name = "Antagonist"
var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section
var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report
var/datum/mind/owner //Mind that owns this datum
var/silent = FALSE //Silent will prevent the gain/lose texts to show
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
@@ -9,6 +11,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/delete_on_mind_deletion = TRUE
var/job_rank
var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
var/list/objectives = list()
/datum/antagonist/New(datum/mind/new_owner)
GLOB.antagonists += src
@@ -46,7 +49,7 @@ GLOBAL_LIST_EMPTY(antagonists)
return
//Assign default team and creates one for one of a kind team antagonists
/datum/antagonist/proc/create_team(datum/objective_team/team)
/datum/antagonist/proc/create_team(datum/team/team)
return
//Proc called when the datum is given to a mind.
@@ -81,7 +84,7 @@ GLOBAL_LIST_EMPTY(antagonists)
LAZYREMOVE(owner.antag_datums, src)
if(!silent && owner.current)
farewell()
var/datum/objective_team/team = get_team()
var/datum/team/team = get_team()
if(team)
team.remove_member(owner)
qdel(src)
@@ -96,9 +99,62 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/get_team()
return
//Individual roundend report
/datum/antagonist/proc/roundend_report()
var/list/report = list()
if(!owner)
CRASH("antagonist datum without owner")
report += printplayer(owner)
var/objectives_complete = TRUE
if(owner.objectives.len)
report += printobjectives(owner)
for(var/datum/objective/objective in owner.objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
if(owner.objectives.len == 0 || objectives_complete)
report += "<span class='greentext big'>The [name] was successful!</span>"
else
report += "<span class='redtext big'>The [name] has failed!</span>"
return report.Join("<br>")
//Displayed at the start of roundend_category section, default to roundend_category header
/datum/antagonist/proc/roundend_report_header()
return "<span class='header'>The [roundend_category] were:</span><br>"
//Displayed at the end of roundend_category section
/datum/antagonist/proc/roundend_report_footer()
return
//Should probably be on ticker or job ss ?
/proc/get_antagonists(antag_type,specific = FALSE)
. = list()
for(var/datum/antagonist/A in GLOB.antagonists)
if(!specific && istype(A,antag_type) || specific && A.type == antag_type)
. += A.owner
. += A.owner
//This datum will autofill the name with special_role
//Used as placeholder for minor antagonists, please create proper datums for these
/datum/antagonist/auto_custom
/datum/antagonist/auto_custom/on_gain()
..()
name = owner.special_role
//Add all objectives not already owned by other datums to this one.
var/list/already_registered_objectives = list()
for(var/datum/antagonist/A in owner.antag_datums)
if(A == src)
continue
else
already_registered_objectives |= A.objectives
objectives = owner.objectives - already_registered_objectives
//This one is created by admin tools for custom objectives
/datum/antagonist/custom
+70 -2
View File
@@ -2,12 +2,12 @@
name = "Brother"
job_rank = ROLE_BROTHER
var/special_role = "blood brother"
var/datum/objective_team/brother_team/team
var/datum/team/brother_team/team
/datum/antagonist/brother/New(datum/mind/new_owner)
return ..()
/datum/antagonist/brother/create_team(datum/objective_team/brother_team/new_team)
/datum/antagonist/brother/create_team(datum/team/brother_team/new_team)
if(!new_team)
return
if(!istype(new_team))
@@ -55,3 +55,71 @@
/datum/antagonist/brother/proc/finalize_brother()
SSticker.mode.update_brother_icons_added(owner)
/datum/team/brother_team
name = "brotherhood"
member_name = "blood brother"
var/meeting_area
/datum/team/brother_team/is_solo()
return FALSE
/datum/team/brother_team/proc/update_name()
var/list/last_names = list()
for(var/datum/mind/M in members)
var/list/split_name = splittext(M.name," ")
last_names += split_name[split_name.len]
name = last_names.Join(" & ")
/datum/team/brother_team/roundend_report()
var/list/parts = list()
parts += "<span class='header'>The blood brothers of [name] were:</span>"
for(var/datum/mind/M in members)
parts += printplayer(M)
var/win = TRUE
var/objective_count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
objective_count++
if(win)
parts += "<span class='greentext'>The blood brothers were successful!</span>"
else
parts += "<span class='redtext'>The blood brothers have failed!</span>"
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
/datum/team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE)
O.team = src
if(needs_target)
O.find_target()
O.update_explanation_text()
objectives += O
/datum/team/brother_team/proc/forge_brother_objectives()
objectives = list()
var/is_hijacker = prob(10)
for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker))
forge_single_objective()
if(is_hijacker)
if(!locate(/datum/objective/hijack) in objectives)
add_objective(new/datum/objective/hijack)
else if(!locate(/datum/objective/escape) in objectives)
add_objective(new/datum/objective/escape)
/datum/team/brother_team/proc/forge_single_objective()
if(prob(50))
if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len))
add_objective(new/datum/objective/destroy, TRUE)
else if(prob(30))
add_objective(new/datum/objective/maroon, TRUE)
else
add_objective(new/datum/objective/assassinate, TRUE)
else
add_objective(new/datum/objective/steal, TRUE)
+32 -1
View File
@@ -4,11 +4,11 @@
/datum/antagonist/changeling
name = "Changeling"
roundend_category = "changelings"
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
@@ -478,4 +478,35 @@
/datum/antagonist/changeling/xenobio
name = "Xenobio Changeling"
give_objectives = FALSE
show_in_roundend = FALSE //These are here for admin tracking purposes only
you_are_greet = FALSE
/datum/antagonist/changeling/roundend_report()
var/list/parts = list()
var/changelingwin = 1
if(!owner.current)
changelingwin = 0
parts += printplayer(owner)
//Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed.
parts += "<b>Changeling ID:</b> [changelingID]."
parts += "<b>Genomes Extracted:</b> [absorbedcount]"
parts += " "
if(objectives.len)
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</b></span>"
else
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
changelingwin = 0
count++
if(changelingwin)
parts += "<span class='greentext'>The changeling was successful!</span>"
else
parts += "<span class='redtext'>The changeling has failed.</span>"
return parts.Join("<br>")
+53 -2
View File
@@ -1,8 +1,11 @@
//CLOCKCULT PROOF OF CONCEPT
/datum/antagonist/clockcult
name = "Clock Cultist"
var/datum/action/innate/hierophant/hierophant_network = new()
roundend_category = "clock cultists"
job_rank = ROLE_SERVANT_OF_RATVAR
var/datum/action/innate/hierophant/hierophant_network = new()
var/datum/team/clockcult/clock_team
var/make_team = TRUE //This should be only false for tutorial scarabs
/datum/antagonist/clockcult/silent
silent = TRUE
@@ -11,6 +14,22 @@
qdel(hierophant_network)
return ..()
/datum/antagonist/clockcult/get_team()
return clock_team
/datum/antagonist/clockcult/create_team(datum/team/clockcult/new_team)
if(!new_team && make_team)
//TODO blah blah same as the others, allow multiple
for(var/datum/antagonist/clockcult/H in GLOB.antagonists)
if(H.clock_team)
clock_team = H.clock_team
return
clock_team = new /datum/team/clockcult
return
if(make_team && !istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
clock_team = new_team
/datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner)
. = ..()
if(.)
@@ -156,7 +175,7 @@
SSticker.mode.servants_of_ratvar -= owner
SSticker.mode.update_servant_icons_removed(owner)
if(!silent)
owner.current.visible_message("<span class='big'>[owner] seems to have remembered their true allegiance!</span>", ignored_mob = owner.current)
owner.current.visible_message("<span class='deconversion_message'>[owner] seems to have remembered their true allegiance!</span>", ignored_mob = owner.current)
to_chat(owner, "<span class='userdanger'>A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.</span>")
owner.current.log_message("<font color=#BE8700>Has renounced the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
owner.wipe_memory()
@@ -164,3 +183,35 @@
if(iscyborg(owner.current))
to_chat(owner.current, "<span class='warning'>Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.</span>")
. = ..()
/datum/team/clockcult
name = "Clockcult"
var/list/objective
var/datum/mind/eminence
/datum/team/clockcult/proc/check_clockwork_victory()
if(GLOB.clockwork_gateway_activated)
return TRUE
return FALSE
/datum/team/clockcult/roundend_report()
var/list/parts = list()
if(check_clockwork_victory())
parts += "<span class='greentext big'>Ratvar's servants defended the Ark until its activation!</span>"
else
parts += "<span class='redtext big'>The Ark was destroyed! Ratvar will rust away for all eternity!</span>"
parts += " "
parts += "<b>The servants' objective was:</b> [CLOCKCULT_OBJECTIVE]."
parts += "<b>Construction Value(CV)</b> was: <b>[GLOB.clockwork_construction_value]</b>"
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER)
parts += "<b>[i] scripture</b> was: <b>[SSticker.scripture_states[i] ? "UN":""]LOCKED</b>"
if(eminence)
parts += "<span class='header'>The Eminence was:</span> [printplayer(eminence)]"
if(members.len)
parts += "<span class='header'>Ratvar's servants were:</span>"
parts += printplayerlist(members - eminence)
return "<div class='panel clockborder'>[parts.Join("<br>")]</div>"
+197 -62
View File
@@ -2,84 +2,103 @@
/datum/antagonist/cult
name = "Cultist"
roundend_category = "cultists"
var/datum/action/innate/cult/comm/communion = new
var/datum/action/innate/cult/mastervote/vote = new
job_rank = ROLE_CULTIST
var/ignore_implant = FALSE
var/give_equipment = FALSE
var/datum/team/cult/cult_team
/datum/antagonist/cult/get_team()
return cult_team
/datum/antagonist/cult/create_team(datum/team/cult/new_team)
if(!new_team)
//todo remove this and allow admin buttons to create more than one cult
for(var/datum/antagonist/cult/H in GLOB.antagonists)
if(H.cult_team)
cult_team = H.cult_team
return
cult_team = new /datum/team/cult
cult_team.setup_objectives()
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
cult_team = new_team
/datum/antagonist/cult/proc/add_objectives()
objectives |= cult_team.objectives
owner.objectives |= objectives
/datum/antagonist/cult/proc/remove_objectives()
owner.objectives -= objectives
/datum/antagonist/cult/Destroy()
QDEL_NULL(communion)
QDEL_NULL(vote)
return ..()
/datum/antagonist/cult/proc/add_objectives()
var/list/target_candidates = list()
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && (player != owner) && player.stat != DEAD)
target_candidates += player.mind
if(target_candidates.len == 0)
message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && (player != owner) && player.stat != DEAD)
target_candidates += player.mind
listclearnulls(target_candidates)
if(LAZYLEN(target_candidates))
GLOB.sac_mind = pick(target_candidates)
if(!GLOB.sac_mind)
message_admins("Cult Sacrifice: ERROR - Null target chosen!")
else
var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role)
var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
reshape.Shift(SOUTH, 4)
reshape.Shift(EAST, 1)
reshape.Crop(7,4,26,31)
reshape.Crop(-5,-3,26,30)
GLOB.sac_image = reshape
else
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
GLOB.sac_complete = TRUE
SSticker.mode.cult_objectives += "sacrifice"
if(!GLOB.summon_spots.len)
while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots)
if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory)
GLOB.summon_spots += summon
SSticker.mode.cult_objectives += "eldergod"
/datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind)
var/mob/living/current = cult_mind.current
for(var/obj_count = 1,obj_count <= SSticker.mode.cult_objectives.len,obj_count++)
var/explanation
switch(SSticker.mode.cult_objectives[obj_count])
if("sacrifice")
if(GLOB.sac_mind)
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
else
explanation = "The veil has already been weakened here, proceed to the final objective."
GLOB.sac_complete = TRUE
if("eldergod")
explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. <b>The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin.</b>"
if(!silent)
to_chat(current, "<B>Objective #[obj_count]</B>: [explanation]")
cult_mind.memory += "<B>Objective #[obj_count]</B>: [explanation]<BR>"
/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
. = ..()
if(. && !ignore_implant)
. = is_convertable_to_cult(new_owner.current)
. = is_convertable_to_cult(new_owner.current,cult_team)
/datum/antagonist/cult/greet()
to_chat(owner, "<span class='userdanger'>You are a member of the cult!</span>")
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
owner.announce_objectives()
/datum/antagonist/cult/on_gain()
. = ..()
var/mob/living/current = owner.current
if(!LAZYLEN(SSticker.mode.cult_objectives))
add_objectives()
add_objectives()
if(give_equipment)
equip_cultist()
SSticker.mode.cult += owner // Only add after they've been given objectives
cult_memorization(owner)
SSticker.mode.update_cult_icons_added(owner)
current.log_message("<font color=#960000>Has been converted to the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
if(GLOB.blood_target && GLOB.blood_target_image && current.client)
current.client.images += GLOB.blood_target_image
if(cult_team.blood_target && cult_team.blood_target_image && current.client)
current.client.images += cult_team.blood_target_image
/datum/antagonist/cult/proc/equip_cultist(tome=FALSE)
var/mob/living/carbon/H = owner.current
if(!istype(H))
return
if (owner.assigned_role == "Clown")
to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
H.dna.remove_mutation(CLOWNMUT)
if(tome)
. += cult_give_item(/obj/item/tome, H)
else
. += cult_give_item(/obj/item/paper/talisman/supply, H)
to_chat(owner, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.</span>")
/datum/antagonist/cult/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob)
var/list/slots = list(
"backpack" = slot_in_backpack,
"left pocket" = slot_l_store,
"right pocket" = slot_r_store
)
var/T = new item_path(mob)
var/item_name = initial(item_path.name)
var/where = mob.equip_in_one_of_slots(T, slots)
if(!where)
to_chat(mob, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
return 0
else
to_chat(mob, "<span class='danger'>You have a [item_name] in your [where].</span>")
if(where == "backpack")
var/obj/item/storage/B = mob.back
B.orient2hud(mob)
B.show_to(mob)
return 1
/datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
. = ..()
@@ -89,7 +108,7 @@
current.faction |= "cult"
current.grant_language(/datum/language/narsie)
current.verbs += /mob/living/proc/cult_help
if(!GLOB.cult_mastered)
if(!cult_team.cult_mastered)
vote.Grant(current)
communion.Grant(current)
current.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
@@ -107,6 +126,7 @@
current.clear_alert("bloodsense")
/datum/antagonist/cult/on_removal()
remove_objectives()
owner.wipe_memory()
SSticker.mode.cult -= owner
SSticker.mode.update_cult_icons_removed(owner)
@@ -114,8 +134,8 @@
owner.current.visible_message("<span class='big'>[owner.current] looks like [owner.current.p_they()] just reverted to their old faith!</span>", ignored_mob = owner.current)
to_chat(owner.current, "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.</span>")
owner.current.log_message("<font color=#960000>Has renounced the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
if(GLOB.blood_target && GLOB.blood_target_image && owner.current.client)
owner.current.client.images -= GLOB.blood_target_image
if(cult_team.blood_target && cult_team.blood_target_image && owner.current.client)
owner.current.client.images -= cult_team.blood_target_image
. = ..()
/datum/antagonist/cult/master
@@ -145,7 +165,7 @@
var/mob/living/current = owner.current
if(mob_override)
current = mob_override
if(!GLOB.reckoning_complete)
if(!cult_team.reckoning_complete)
reckoning.Grant(current)
bloodmark.Grant(current)
throwing.Grant(current)
@@ -162,3 +182,118 @@
throwing.Remove(current)
current.update_action_buttons_icon()
current.remove_status_effect(/datum/status_effect/cult_master)
/datum/team/cult
name = "Cult"
var/blood_target
var/image/blood_target_image
var/blood_target_reset_timer
var/cult_vote_called = FALSE
var/cult_mastered = FALSE
var/reckoning_complete = FALSE
/datum/team/cult/proc/setup_objectives()
//SAC OBJECTIVE , todo: move this to objective internals
var/list/target_candidates = list()
var/datum/objective/sacrifice/sac_objective = new
sac_objective.team = src
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && player.stat != DEAD)
target_candidates += player.mind
if(target_candidates.len == 0)
message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && player.stat != DEAD)
target_candidates += player.mind
listclearnulls(target_candidates)
if(LAZYLEN(target_candidates))
sac_objective.target = pick(target_candidates)
sac_objective.update_explanation_text()
var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role)
var/datum/preferences/sacface = sac_objective.target.current.client.prefs
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
reshape.Shift(SOUTH, 4)
reshape.Shift(EAST, 1)
reshape.Crop(7,4,26,31)
reshape.Crop(-5,-3,26,30)
sac_objective.sac_image = reshape
objectives += sac_objective
else
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
//SUMMON OBJECTIVE
var/datum/objective/eldergod/summon_objective = new()
summon_objective.team = src
objectives += summon_objective
/datum/objective/sacrifice
var/sacced = FALSE
var/sac_image
/datum/objective/sacrifice/check_completion()
return sacced || completed
/datum/objective/sacrifice/update_explanation_text()
if(target && !sacced)
explanation_text = "Sacrifice [target], the [target.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
else
explanation_text = "The veil has already been weakened here, proceed to the final objective."
/datum/objective/eldergod
var/summoned = FALSE
var/list/summon_spots = list()
/datum/objective/eldergod/New()
..()
var/sanity = 0
while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
var/area/summon = pick(GLOB.sortedAreas - summon_spots)
if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory)
summon_spots += summon
sanity++
update_explanation_text()
/datum/objective/eldergod/update_explanation_text()
explanation_text = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. <b>The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin.</b>"
/datum/objective/eldergod/check_completion()
return summoned || completed
/datum/team/cult/proc/check_cult_victory()
for(var/datum/objective/O in objectives)
if(!O.check_completion())
return FALSE
return TRUE
/datum/team/cult/roundend_report()
var/list/parts = list()
if(check_cult_victory())
parts += "<span class='greentext big'>The cult has succeeded! Nar-sie has snuffed out another torch in the void!</span>"
else
parts += "<span class='redtext big'>The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!</span>"
if(objectives.len)
parts += "<b>The cultists' objectives were:</b>"
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</span>"
else
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
count++
if(members.len)
parts += "<span class='header'>The cultists were:</span>"
parts += printplayerlist(members)
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
+55 -5
View File
@@ -1,5 +1,6 @@
/datum/antagonist/traitor
name = "Traitor"
roundend_category = "traitors"
job_rank = ROLE_TRAITOR
var/should_specialise = FALSE //do we split into AI and human, set to true on inital assignment only
var/ai_datum = ANTAG_DATUM_TRAITOR_AI
@@ -8,7 +9,6 @@
var/employer = "The Syndicate"
var/give_objectives = TRUE
var/should_give_codewords = TRUE
var/list/objectives_given = list()
/datum/antagonist/traitor/human
var/should_equip = TRUE
@@ -52,9 +52,9 @@
if(should_specialise)
return ..()//we never did any of this anyway
SSticker.mode.traitors -= owner
for(var/O in objectives_given)
for(var/O in objectives)
owner.objectives -= O
objectives_given = list()
objectives = list()
if(!silent && owner.current)
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
owner.special_role = null
@@ -71,11 +71,11 @@
/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O)
owner.objectives += O
objectives_given += O
objectives += O
/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O)
owner.objectives -= O
objectives_given -= O
objectives -= O
/datum/antagonist/traitor/proc/forge_traitor_objectives()
return
@@ -294,3 +294,53 @@
where = "In your [equipped_slot]"
to_chat(mob, "<BR><BR><span class='info'>[where] is a folder containing <b>secret documents</b> that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.</span><BR>")
//TODO Collate
/datum/antagonist/traitor/roundend_report()
var/list/result = list()
var/traitorwin = TRUE
result += printplayer(owner)
var/TC_uses = 0
var/uplink_true = FALSE
var/purchases = ""
for(var/datum/component/uplink/H in GLOB.uplinks)
if(H && H.owner && H.owner == owner.key)
TC_uses += H.spent_telecrystals
uplink_true = TRUE
purchases += H.purchase_log.generate_render(FALSE)
var/objectives_text = ""
if(objectives.len)//If the traitor had no objectives, don't need to process this.
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
traitorwin = FALSE
count++
if(uplink_true)
var/uplink_text = "(used [TC_uses] TC) [purchases]"
if(TC_uses==0 && traitorwin)
var/static/icon/badass = icon('icons/badass.dmi', "badass")
uplink_text += "<BIG>[icon2html(badass, world)]</BIG>"
result += uplink_text
result += objectives_text
var/special_role_text = lowertext(name)
if(traitorwin)
result += "<span class='greentext'>The [special_role_text] was successful!</span>"
else
result += "<span class='redtext'>The [special_role_text] has failed!</span>"
SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
return result.Join("<br>")
/datum/antagonist/traitor/roundend_report_footer()
return "<br><b>The code phrases were:</b> <span class='codephrase'>[GLOB.syndicate_code_phrase]</span><br>\
<b>The code responses were:</b> <span class='codephrase'>[GLOB.syndicate_code_response]</span><br>"
+30
View File
@@ -86,6 +86,7 @@ GLOBAL_LIST_INIT(devil_syllable, list("hal", "ve", "odr", "neit", "ci", "quon",
GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", ", the Lord of all things", ", Jr."))
/datum/antagonist/devil
name = "Devil"
roundend_category = "devils"
job_rank = ROLE_DEVIL
//Don't delete upon mind destruction, otherwise soul re-selling will break.
delete_on_mind_deletion = FALSE
@@ -508,6 +509,35 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
owner.RemoveSpell(S)
.=..()
/datum/antagonist/devil/proc/printdevilinfo()
var/list/parts = list()
parts += "The devil's true name is: [truename]"
parts += "The devil's bans were:"
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][ban]]"
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][bane]]"
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][obligation]]"
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][banish]]"
return parts.Join("<br>")
/datum/antagonist/devil/roundend_report()
var/list/parts = list()
parts += printplayer(owner)
parts += printdevilinfo()
parts += printobjectives(owner)
return parts.Join("<br>")
/datum/antagonist/devil/roundend_report_footer()
//sintouched go here for now as a hack , TODO proper antag datum for these
var/list/parts = list()
if(SSticker.mode.sintouched.len)
parts += "<span class='header'>The sintouched were:</span>"
var/list/sintouchedUnique = uniqueList(SSticker.mode.sintouched)
for(var/S in sintouchedUnique)
var/datum/mind/sintouched_mind = S
parts += printplayer(sintouched_mind)
parts += printobjectives(sintouched_mind)
return parts.Join("<br>")
//A simple super light weight datum for the codex gigas.
/datum/fakeDevil
var/truename
+11 -10
View File
@@ -37,19 +37,20 @@
else if(M.assigned_role in GLOB.command_positions)
possible_targets[M] = 1 //good-guy
var/list/objectives = list(1,2,3,4)
while(owner.objectives.len < quantity)
switch(pick_n_take(objectives))
var/list/possible_objectives = list(1,2,3,4)
while(objectives.len < quantity)
switch(pick_n_take(possible_objectives))
if(1) //research
var/datum/objective/download/O = new /datum/objective/download()
O.owner = owner
O.gen_amount_goal()
owner.objectives += O
objectives += O
if(2) //steal
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
O.owner = owner
owner.objectives += O
objectives += O
if(3) //protect/kill
if(!possible_targets.len) continue
@@ -63,13 +64,13 @@
O.owner = owner
O.target = M
O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]."
owner.objectives += O
objectives += O
else //protect
var/datum/objective/protect/O = new /datum/objective/protect()
O.owner = owner
O.target = M
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
owner.objectives += O
objectives += O
if(4) //debrain/capture
if(!possible_targets.len) continue
var/selected = rand(1,possible_targets.len)
@@ -82,17 +83,17 @@
O.owner = owner
O.target = M
O.explanation_text = "Steal the brain of [M.current.real_name]."
owner.objectives += O
objectives += O
else //capture
var/datum/objective/capture/O = new /datum/objective/capture()
O.owner = owner
O.gen_amount_goal()
owner.objectives += O
objectives += O
else
break
var/datum/objective/O = new /datum/objective/survive()
O.owner = owner
owner.objectives += O
owner.objectives |= objectives
/proc/remove_ninja(mob/living/L)
+322
View File
@@ -0,0 +1,322 @@
#define NUKE_RESULT_FLUKE 0
#define NUKE_RESULT_NUKE_WIN 1
#define NUKE_RESULT_CREW_WIN 2
#define NUKE_RESULT_CREW_WIN_SYNDIES_DEAD 3
#define NUKE_RESULT_DISK_LOST 4
#define NUKE_RESULT_DISK_STOLEN 5
#define NUKE_RESULT_NOSURVIVORS 6
#define NUKE_RESULT_WRONG_STATION 7
#define NUKE_RESULT_WRONG_STATION_DEAD 8
/datum/antagonist/nukeop
name = "Nuclear Operative"
roundend_category = "syndicate operatives" //just in case
job_rank = ROLE_OPERATIVE
var/datum/team/nuclear/nuke_team
var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
var/nukeop_outfit = /datum/outfit/syndicate
/datum/antagonist/nukeop/proc/update_synd_icons_added(mob/living/M)
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
opshud.join_hud(M)
set_antag_hud(M, "synd")
/datum/antagonist/nukeop/proc/update_synd_icons_removed(mob/living/M)
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
opshud.leave_hud(M)
set_antag_hud(M, null)
/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_synd_icons_added(M)
/datum/antagonist/nukeop/remove_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_synd_icons_removed(M)
/datum/antagonist/nukeop/proc/equip_op()
if(!ishuman(owner.current))
return
var/mob/living/carbon/human/H = owner.current
H.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs
H.equipOutfit(nukeop_outfit)
return TRUE
/datum/antagonist/nukeop/greet()
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
to_chat(owner, "<span class='notice'>You are a [nuke_team ? nuke_team.syndicate_name : "syndicate"] agent!</span>")
owner.announce_objectives()
return
/datum/antagonist/nukeop/on_gain()
give_alias()
forge_objectives()
. = ..()
equip_op()
memorize_code()
if(send_to_spawnpoint)
move_to_spawnpoint()
/datum/antagonist/nukeop/get_team()
return nuke_team
/datum/antagonist/nukeop/proc/assign_nuke()
if(nuke_team && !nuke_team.tracked_nuke)
nuke_team.memorized_code = random_nukecode()
var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list
if(nuke)
nuke_team.tracked_nuke = nuke
if(nuke.r_code == "ADMIN")
nuke.r_code = nuke_team.memorized_code
else //Already set by admins/something else?
nuke_team.memorized_code = nuke.r_code
else
stack_trace("Syndicate nuke not found during nuke team creation.")
nuke_team.memorized_code = null
/datum/antagonist/nukeop/proc/give_alias()
if(nuke_team && nuke_team.syndicate_name)
var/number = 1
number = nuke_team.members.Find(owner)
owner.current.real_name = "[nuke_team.syndicate_name] Operative #[number]"
/datum/antagonist/nukeop/proc/memorize_code()
if(nuke_team && nuke_team.tracked_nuke && nuke_team.memorized_code)
owner.store_memory("<B>[nuke_team.tracked_nuke] Code</B>: [nuke_team.memorized_code]", 0, 0)
to_chat(owner, "The nuclear authorization code is: <B>[nuke_team.memorized_code]</B>")
else
to_chat(owner, "Unfortunately the syndicate was unable to provide you with nuclear authorization code.")
/datum/antagonist/nukeop/proc/forge_objectives()
if(nuke_team)
owner.objectives |= nuke_team.objectives
/datum/antagonist/nukeop/proc/move_to_spawnpoint()
var/team_number = 1
if(nuke_team)
team_number = nuke_team.members.Find(owner)
owner.current.forceMove(GLOB.nukeop_start[((team_number - 1) % GLOB.nukeop_start.len) + 1])
/datum/antagonist/nukeop/leader/move_to_spawnpoint()
owner.current.forceMove(pick(GLOB.nukeop_leader_start))
/datum/antagonist/nukeop/create_team(datum/team/nuclear/new_team)
if(!new_team)
if(!always_new_team)
for(var/datum/antagonist/nukeop/N in GLOB.antagonists)
if(N.nuke_team)
nuke_team = N.nuke_team
return
nuke_team = new /datum/team/nuclear
nuke_team.update_objectives()
assign_nuke() //This is bit ugly
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
nuke_team = new_team
/datum/antagonist/nukeop/leader
name = "Nuclear Operative Leader"
nukeop_outfit = /datum/outfit/syndicate/leader
always_new_team = TRUE
var/title
/datum/antagonist/nukeop/leader/memorize_code()
..()
if(nuke_team && nuke_team.memorized_code)
var/obj/item/paper/P = new
P.info = "The nuclear authorization code is: <b>[nuke_team.memorized_code]</b>"
P.name = "nuclear bomb code"
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
P.forceMove(get_turf(H))
else
H.put_in_hands(P, TRUE)
H.update_icons()
/datum/antagonist/nukeop/leader/give_alias()
title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
if(nuke_team && nuke_team.syndicate_name)
owner.current.real_name = "[nuke_team.syndicate_name] [title]"
else
owner.current.real_name = "Syndicate [title]"
/datum/antagonist/nukeop/leader/greet()
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
to_chat(owner, "<B>You are the Syndicate [title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.</B>")
to_chat(owner, "<B>If you feel you are not up to this task, give your ID to another operative.</B>")
to_chat(owner, "<B>In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.</B>")
owner.announce_objectives()
addtimer(CALLBACK(src, .proc/nuketeam_name_assign), 1)
/datum/antagonist/nukeop/leader/proc/nuketeam_name_assign()
if(!nuke_team)
return
nuke_team.rename_team(ask_name())
/datum/team/nuclear/proc/rename_team(new_name)
syndicate_name = new_name
name = "[syndicate_name] Team"
for(var/I in members)
var/datum/mind/synd_mind = I
var/mob/living/carbon/human/H = synd_mind.current
if(!istype(H))
continue
var/chosen_name = H.dna.species.random_name(H.gender,0,syndicate_name)
H.fully_replace_character_name(H.real_name,chosen_name)
/datum/antagonist/nukeop/leader/proc/ask_name()
var/randomname = pick(GLOB.last_names)
var/newname = stripped_input(owner.current,"You are the nuke operative [title]. Please choose a last name for your family.", "Name change",randomname)
if (!newname)
newname = randomname
else
newname = reject_bad_name(newname)
if(!newname)
newname = randomname
return capitalize(newname)
/datum/antagonist/nukeop/lone
name = "Lone Operative"
always_new_team = TRUE
send_to_spawnpoint = FALSE //Handled by event
nukeop_outfit = /datum/outfit/syndicate/full
/datum/antagonist/nukeop/lone/assign_nuke()
if(nuke_team && !nuke_team.tracked_nuke)
nuke_team.memorized_code = random_nukecode()
var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.nuke_list
if(nuke)
nuke_team.tracked_nuke = nuke
if(nuke.r_code == "ADMIN")
nuke.r_code = nuke_team.memorized_code
else //Already set by admins/something else?
nuke_team.memorized_code = nuke.r_code
else
stack_trace("Station self destruct ot found during lone op team creation.")
nuke_team.memorized_code = null
/datum/team/nuclear
var/syndicate_name
var/obj/machinery/nuclearbomb/tracked_nuke
var/core_objective = /datum/objective/nuclear
var/memorized_code
/datum/team/nuclear/New()
..()
syndicate_name = syndicate_name()
/datum/team/nuclear/proc/update_objectives()
if(core_objective)
var/datum/objective/O = new core_objective
O.team = src
objectives += O
/datum/team/nuclear/proc/disk_rescued()
for(var/obj/item/disk/nuclear/D in GLOB.poi_list)
if(!D.onCentCom())
return FALSE
return TRUE
/datum/team/nuclear/proc/operatives_dead()
for(var/I in members)
var/datum/mind/operative_mind = I
if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD))
return FALSE
return TRUE
/datum/team/nuclear/proc/syndies_escaped()
var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate")
return (S && (S.z == ZLEVEL_CENTCOM || S.z == ZLEVEL_TRANSIT))
/datum/team/nuclear/proc/get_result()
var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME
var/disk_rescued = disk_rescued()
var/syndies_didnt_escape = !syndies_escaped()
var/station_was_nuked = SSticker.mode.station_was_nuked
var/nuke_off_station = SSticker.mode.nuke_off_station
if(nuke_off_station == NUKE_SYNDICATE_BASE)
return NUKE_RESULT_FLUKE
else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
return NUKE_RESULT_NUKE_WIN
else if (!disk_rescued && station_was_nuked && syndies_didnt_escape)
return NUKE_RESULT_NOSURVIVORS
else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape)
return NUKE_RESULT_WRONG_STATION
else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
return NUKE_RESULT_WRONG_STATION_DEAD
else if ((disk_rescued || evacuation) && operatives_dead())
return NUKE_RESULT_CREW_WIN_SYNDIES_DEAD
else if (disk_rescued)
return NUKE_RESULT_CREW_WIN
else if (!disk_rescued && operatives_dead())
return NUKE_RESULT_DISK_LOST
else if (!disk_rescued && evacuation)
return NUKE_RESULT_DISK_STOLEN
else
return //Undefined result
/datum/team/nuclear/roundend_report()
var/list/parts = list()
parts += "<span class='header'>[syndicate_name] Operatives:</span>"
switch(get_result())
if(NUKE_RESULT_FLUKE)
parts += "<span class='redtext big'>Humiliating Syndicate Defeat</span>"
parts += "<B>The crew of [station_name()] gave [syndicate_name] operatives back their bomb! The syndicate base was destroyed!</B> Next time, don't lose the nuke!"
if(NUKE_RESULT_NUKE_WIN)
parts += "<span class='greentext big'>Syndicate Major Victory!</span>"
parts += "<B>[syndicate_name] operatives have destroyed [station_name()]!</B>"
if(NUKE_RESULT_NOSURVIVORS)
parts += "<span class='neutraltext big'>Total Annihilation</span>"
parts += "<B>[syndicate_name] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion.</B> Next time, don't lose the disk!"
if(NUKE_RESULT_WRONG_STATION)
parts += "<span class='redtext big'>Crew Minor Victory</span>"
parts += "<B>[syndicate_name] operatives secured the authentication disk but blew up something that wasn't [station_name()].</B> Next time, don't do that!"
if(NUKE_RESULT_WRONG_STATION_DEAD)
parts += "<span class='redtext big'>[syndicate_name] operatives have earned Darwin Award!</span>"
parts += "<B>[syndicate_name] operatives blew up something that wasn't [station_name()] and got caught in the explosion.</B> Next time, don't do that!"
if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD)
parts += "<span class='redtext big'>Crew Major Victory!</span>"
parts += "<B>The Research Staff has saved the disk and killed the [syndicate_name] Operatives</B>"
if(NUKE_RESULT_CREW_WIN)
parts += "<span class='redtext big'>Crew Major Victory</span>"
parts += "<B>The Research Staff has saved the disk and stopped the [syndicate_name] Operatives!</B>"
if(NUKE_RESULT_DISK_LOST)
parts += "<span class='neutraltext big'>Neutral Victory!</span>"
parts += "<B>The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name] Operatives!</B>"
if(NUKE_RESULT_DISK_STOLEN)
parts += "<span class='greentext big'>Syndicate Minor Victory!</span>"
parts += "<B>[syndicate_name] operatives survived the assault but did not achieve the destruction of [station_name()].</B> Next time, don't lose the disk!"
else
parts += "<span class='neutraltext big'>Neutral Victory</span>"
parts += "<B>Mission aborted!</B>"
var/text = "<br><span class='header'>The syndicate operatives were:</span>"
var/purchases = ""
var/TC_uses = 0
for(var/I in members)
var/datum/mind/syndicate = I
for(var/U in GLOB.uplinks)
var/datum/component/uplink/H = U
if(H.owner == syndicate.key)
TC_uses += H.purchase_log.total_spent
if(H.purchase_log)
purchases += H.purchase_log.generate_render(show_key = FALSE)
else
stack_trace("WARNING: Nuke Op uplink with no purchase_log Owner: [H.owner]")
text += printplayerlist(members)
text += "<br>"
text += "(Syndicates used [TC_uses] TC) [purchases]"
if(TC_uses == 0 && SSticker.mode.station_was_nuked && !operatives_dead())
text += "<BIG>[icon2html('icons/badass.dmi', world, "badass")]</BIG>"
parts += text
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
+32 -38
View File
@@ -1,7 +1,8 @@
/datum/antagonist/pirate
name = "Space Pirate"
job_rank = ROLE_TRAITOR
var/datum/objective_team/pirate/crew
roundend_category = "space pirates"
var/datum/team/pirate/crew
/datum/antagonist/pirate/greet()
to_chat(owner, "<span class='boldannounce'>You are a Space Pirate!</span>")
@@ -11,15 +12,16 @@
/datum/antagonist/pirate/get_team()
return crew
/datum/antagonist/pirate/create_team(datum/objective_team/pirate/new_team)
/datum/antagonist/pirate/create_team(datum/team/pirate/new_team)
if(!new_team)
for(var/datum/antagonist/pirate/P in GLOB.antagonists)
if(P.crew)
new_team = P.crew
crew = P.crew
return
if(!new_team)
crew = new /datum/objective_team/pirate
crew = new /datum/team/pirate
crew.forge_objectives()
return
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
crew = new_team
@@ -34,11 +36,10 @@
owner.objectives -= crew.objectives
. = ..()
/datum/objective_team/pirate
/datum/team/pirate
name = "Pirate crew"
var/list/objectives = list()
/datum/objective_team/pirate/proc/forge_objectives()
/datum/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
@@ -84,11 +85,11 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
loot_table[lootname] = count
else
loot_table[lootname] += count
var/text = ""
var/list/loot_texts = list()
for(var/key in loot_table)
var/amount = loot_table[key]
text += "[amount] [key][amount > 1 ? "s":""], "
return text
loot_texts += "[amount] [key][amount > 1 ? "s":""]"
return loot_texts.Join(", ")
/datum/objective/loot/proc/get_loot_value()
if(!storage_area)
@@ -104,32 +105,25 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
/datum/objective/loot/check_completion()
return ..() || get_loot_value() >= target_value
/datum/team/pirate/roundend_report()
var/list/parts = list()
//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"
parts += "<span class='header'>Space Pirates were:</span>"
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)
var/all_dead = TRUE
for(var/datum/mind/M in members)
if(considered_alive(M))
all_dead = FALSE
parts += printplayerlist(members)
parts += "Loot stolen: "
var/datum/objective/loot/L = locate() in objectives
parts += L.loot_listing()
parts += "Total loot value : [L.get_loot_value()]/[L.target_value] credits"
if(L.check_completion() && !all_dead)
parts += "<span class='greentext big'>The pirate crew was successful!</span>"
else
parts += "<span class='redtext big'>The pirate crew has failed.</span>"
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
+71 -18
View File
@@ -3,9 +3,10 @@
/datum/antagonist/rev
name = "Revolutionary"
roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen
job_rank = ROLE_REV
var/hud_type = "rev"
var/datum/objective_team/revolution/rev_team
var/datum/team/revolution/rev_team
/datum/antagonist/rev/can_be_owned(datum/mind/new_owner)
. = ..()
@@ -39,17 +40,17 @@
. = ..()
/datum/antagonist/rev/greet()
to_chat(owner, "<span class='danger'><FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</FONT></span>")
to_chat(owner, "<span class='userdanger'>You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</span>")
owner.announce_objectives()
/datum/antagonist/rev/create_team(datum/objective_team/revolution/new_team)
/datum/antagonist/rev/create_team(datum/team/revolution/new_team)
if(!new_team)
//For now only one revolution at a time
for(var/datum/antagonist/rev/head/H in GLOB.antagonists)
if(H.rev_team)
rev_team = H.rev_team
return
rev_team = new /datum/objective_team/revolution
rev_team = new /datum/team/revolution
rev_team.update_objectives()
rev_team.update_heads()
return
@@ -77,7 +78,7 @@
old_owner.add_antag_datum(new_revhead,old_team)
new_revhead.silent = FALSE
to_chat(old_owner, "<span class='userdanger'>You have proved your devotion to revolution! You are a head revolutionary now!</span>")
/datum/antagonist/rev/head
name = "Head Revolutionary"
@@ -131,14 +132,14 @@
old_owner.add_antag_datum(new_rev,old_team)
new_rev.silent = FALSE
to_chat(old_owner, "<span class='userdanger'>Revolution has been disappointed of your leader traits! You are a regular revolutionary now!</span>")
/datum/antagonist/rev/farewell()
if(ishuman(owner.current))
owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!", \
"<span class='userdanger'><FONT size = 3>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</FONT></span>")
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like they just remembered their real allegiance!</span>", ignored_mob = owner.current)
to_chat(owner, "<span class='userdanger'>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</span>")
else if(issilicon(owner.current))
owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.", \
"<span class='userdanger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</FONT></span>")
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.</span>", ignored_mob = owner.current)
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</span>")
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
log_attack("[owner.current] (Key: [key_name(owner.current)]) has been deconverted from the revolution by [deconverter] (Key: [key_name(deconverter)])!")
@@ -163,7 +164,7 @@
if(remove_clumsy && owner.assigned_role == "Clown")
to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
H.dna.remove_mutation(CLOWNMUT)
if(give_flash)
var/obj/item/device/assembly/flash/T = new(H)
var/list/slots = list (
@@ -176,18 +177,17 @@
to_chat(H, "The Syndicate were unfortunately unable to get you a flash.")
else
to_chat(H, "The flash in your [where] will help you to persuade the crew to join your cause.")
if(give_hud)
var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = new(H)
S.Insert(H, special = FALSE, drop_if_replaced = FALSE)
to_chat(H, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.")
/datum/objective_team/revolution
/datum/team/revolution
name = "Revolution"
var/list/objectives = list()
var/max_headrevs = 3
/datum/objective_team/revolution/proc/update_objectives(initial = FALSE)
/datum/team/revolution/proc/update_objectives(initial = FALSE)
var/untracked_heads = SSjob.get_all_heads()
for(var/datum/objective/mutiny/O in objectives)
untracked_heads -= O.target
@@ -199,16 +199,16 @@
objectives += new_target
for(var/datum/mind/M in members)
M.objectives |= objectives
addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
/datum/objective_team/revolution/proc/head_revolutionaries()
/datum/team/revolution/proc/head_revolutionaries()
. = list()
for(var/datum/mind/M in members)
if(M.has_antag_datum(/datum/antagonist/rev/head))
. += M
/datum/objective_team/revolution/proc/update_heads()
/datum/team/revolution/proc/update_heads()
if(SSticker.HasRoundStarted())
var/list/datum/mind/head_revolutionaries = head_revolutionaries()
var/list/datum/mind/heads = SSjob.get_all_heads()
@@ -227,3 +227,56 @@
rev.promote()
addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
/datum/team/revolution/roundend_report()
if(!members.len)
return
var/list/result = list()
result += "<div class='panel redborder'>"
var/num_revs = 0
var/num_survivors = 0
for(var/mob/living/carbon/survivor in GLOB.alive_mob_list)
if(survivor.ckey)
num_survivors++
if(survivor.mind)
if(is_revolutionary(survivor))
num_revs++
if(num_survivors)
result += "Command's Approval Rating: <B>[100 - round((num_revs/num_survivors)*100, 0.1)]%</B><br>"
var/list/targets = list()
var/list/datum/mind/headrevs = get_antagonists(/datum/antagonist/rev/head)
var/list/datum/mind/revs = get_antagonists(/datum/antagonist/rev,TRUE)
if(headrevs.len)
var/list/headrev_part = list()
headrev_part += "<span class='header'>The head revolutionaries were:</span>"
headrev_part += printplayerlist(headrevs,TRUE)
result += headrev_part.Join("<br>")
if(revs.len)
var/list/rev_part = list()
rev_part += "<span class='header'>The revolutionaries were:</span>"
rev_part += printplayerlist(revs,TRUE)
result += rev_part.Join("<br>")
var/list/heads = SSjob.get_all_heads()
if(heads.len)
var/head_text = "<span class='header'>The heads of staff were:</span>"
head_text += "<ul class='playerlist'>"
for(var/datum/mind/head in heads)
var/target = (head in targets)
head_text += "<li>"
if(target)
head_text += "<span class='redtext'>Target</span>"
head_text += "[printplayer(head, 1)]</li>"
head_text += "</ul><br>"
result += head_text
result += "</div>"
return result.Join()

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