Merge remote-tracking branch 'citadel/master' into combat_rework

This commit is contained in:
kevinz000
2020-04-08 04:04:45 -07:00
919 changed files with 148968 additions and 10144 deletions
+9 -12
View File
@@ -2,18 +2,6 @@
//Be sure to update the min/max of these if you do change them.
//Measurements are in imperial units. Inches, feet, yards, miles. Tsp, tbsp, cups, quarts, gallons, etc
//HUD stuff
#define ui_arousal "EAST-1:28,CENTER-4:8"//Below the health doll
#define ui_stamina "EAST-1:28,CENTER:17" // replacing internals button
#define ui_overridden_resist "EAST-3:24,SOUTH+1:7"
#define ui_combat_toggle "EAST-4:22,SOUTH:5"
//1:1 HUD layout stuff
#define ui_boxcraft "EAST-4:22,SOUTH+1:6"
#define ui_boxarea "EAST-4:6,SOUTH+1:6"
#define ui_boxlang "EAST-5:22,SOUTH+1:6"
#define ui_boxvore "EAST-5:22,SOUTH+1:6"
//Filters
#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, color="#04080F")
@@ -35,6 +23,9 @@
#define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ
#define CAN_CLIMAX_WITH (1<<7)
#define GENITAL_CAN_AROUSE (1<<8)
#define GENITAL_UNDIES_HIDDEN (1<<9)
#define UPDATE_OWNER_APPEARANCE (1<<10)
#define GENITAL_CAN_TAUR (1<<11)
#define DEF_VAGINA_SHAPE "Human"
@@ -71,6 +62,12 @@
#define MILK_RATE_MULT 1
#define MILK_EFFICIENCY 1
//visibility toggles defines to avoid errors typos code errors.
#define GEN_VISIBLE_ALWAYS "Always visible"
#define GEN_VISIBLE_NO_CLOTHES "Hidden by clothes"
#define GEN_VISIBLE_NO_UNDIES "Hidden by underwear"
#define GEN_VISIBLE_NEVER "Always hidden"
//Individual logging define
#define INDIVIDUAL_LOOC_LOG "LOOC log"
+1
View File
@@ -82,6 +82,7 @@
#define CANUNCONSCIOUS (1<<2)
#define CANPUSH (1<<3)
#define GODMODE (1<<4)
#define CANSTAGGER (1<<5)
//Health Defines
#define HEALTH_THRESHOLD_CRIT 0
+14
View File
@@ -39,3 +39,17 @@
//Ouch my toes!
#define CALTROP_BYPASS_SHOES 1
#define CALTROP_IGNORE_WALKERS 2
#define SPELL_SKIP_ALL_REQS (1<<0)
#define SPELL_SKIP_CENTCOM (1<<1)
#define SPELL_SKIP_STAT (1<<2)
#define SPELL_SKIP_CLOTHES (1<<3)
#define SPELL_SKIP_ANTIMAGIC (1<<4)
#define SPELL_SKIP_VOCAL (1<<5)
#define SPELL_SKIP_MOBTYPE (1<<6)
#define SPELL_WIZARD_HAT (1<<7)
#define SPELL_WIZARD_ROBE (1<<8)
#define SPELL_CULT_HELMET (1<<9)
#define SPELL_CULT_ARMOR (1<<10)
#define SPELL_WIZARD_GARB (SPELL_WIZARD_HAT|SPELL_WIZARD_ROBE)
#define SPELL_CULT_GARB (SPELL_CULT_HELMET|SPELL_CULT_ARMOR)
+7 -1
View File
@@ -149,7 +149,9 @@
#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
#define COMPONENT_BLOCK_DEATH_BROADCAST 1 //stops the death from being broadcasted in deadchat.
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize(): (can_reenter_corpse, special, penalize)
#define COMPONENT_BLOCK_GHOSTING 1
#define COMPONENT_BLOCK_GHOSTING (1<<0)
#define COMPONENT_DO_NOT_PENALIZE_GHOSTING (1<<1)
#define COMPONENT_FREE_GHOSTING (1<<2)
#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
#define COMPONENT_BLOCK_MAGIC 1
@@ -175,6 +177,9 @@
#define SPEECH_LANGUAGE 5
// #define SPEECH_IGNORE_SPAM 6
// #define SPEECH_FORCED 7
#define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum)
#define COMSIG_MOB_SPELL_CAST_CHECK "mob_spell_cast_check" //called from base of /obj/effect/proc_holder/spell/cast_check(): (spell)
// /mob/living signals
#define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs)
@@ -185,6 +190,7 @@
#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
#define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive)
#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" //sent when a mob/login() finishes: (client)
#define COMSIG_MOB_CLIENT_MOVE "comsig_mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc)
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
// This returns flags as defined for block in __DEFINES/combat.dm!
#define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
+1
View File
@@ -6,6 +6,7 @@
#define NO_ASSASSIN (1<<0)
#define WAROPS_ALWAYS_ALLOWED (1<<1)
#define USE_PREF_WEIGHTS (1<<2)
#define FORCE_IF_WON (1<<3)
#define ONLY_RULESET (1<<0)
#define HIGHLANDER_RULESET (1<<1)
+29
View File
@@ -0,0 +1,29 @@
#define INSTRUMENT_MIN_OCTAVE 1
#define INSTRUMENT_MAX_OCTAVE 9
#define INSTRUMENT_MIN_KEY 0
#define INSTRUMENT_MAX_KEY 127
/// Max number of playing notes per instrument.
#define CHANNELS_PER_INSTRUMENT 128
/// Distance multiplier that makes us not be impacted by 3d sound as much. This is a multiplier so lower it is the closer we will pretend to be to people.
#define INSTRUMENT_DISTANCE_FALLOFF_BUFF 0.2
/// How many tiles instruments have no falloff for
#define INSTRUMENT_DISTANCE_NO_FALLOFF 3
/// Maximum length a note should ever go for
#define INSTRUMENT_MAX_TOTAL_SUSTAIN (5 SECONDS)
/// These are per decisecond.
#define INSTRUMENT_EXP_FALLOFF_MIN 1.025 //100/(1.025^50) calculated for [INSTRUMENT_MIN_SUSTAIN_DROPOFF] to be 30.
#define INSTRUMENT_EXP_FALLOFF_MAX 10
/// Minimum volume for when the sound is considered dead.
#define INSTRUMENT_MIN_SUSTAIN_DROPOFF 30
#define SUSTAIN_LINEAR 1
#define SUSTAIN_EXPONENTIAL 2
// /datum/instrument instrument_flags
#define INSTRUMENT_LEGACY (1<<0) //Legacy instrument. Implies INSTRUMENT_DO_NOT_AUTOSAMPLE
#define INSTRUMENT_DO_NOT_AUTOSAMPLE (1<<1) //Do not automatically sample
+28
View File
@@ -4,11 +4,16 @@
#define CLICKCATCHER_PLANE -99
#define PLANE_SPACE -95
#define PLANE_SPACE_RENDER_TARGET "PLANE_SPACE"
#define PLANE_SPACE_PARALLAX -90
#define PLANE_SPACE_PARALLAX_RENDER_TARGET "PLANE_SPACE_PARALLAX"
#define FLOOR_PLANE -2
#define FLOOR_PLANE_RENDER_TARGET "FLOOR_PLANE"
#define GAME_PLANE -1
#define GAME_PLANE_RENDER_TARGET "GAME_PLANE"
#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
#define BLACKNESS_PLANE_RENDER_TARGET "BLACKNESS_PLANE"
#define SPACE_LAYER 1.8
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
@@ -78,20 +83,38 @@
#define MASSIVE_OBJ_LAYER 11
#define POINT_LAYER 12
#define EMISSIVE_BLOCKER_PLANE 12
#define EMISSIVE_BLOCKER_LAYER 12
#define EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE"
#define EMISSIVE_PLANE 13
#define EMISSIVE_LAYER 13
#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE"
#define EMISSIVE_UNBLOCKABLE_PLANE 14
#define EMISSIVE_UNBLOCKABLE_LAYER 14
#define EMISSIVE_UNBLOCKABLE_RENDER_TARGET "*EMISSIVE_UNBLOCKABLE_PLANE"
#define LIGHTING_PLANE 15
#define LIGHTING_LAYER 15
#define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
#define ABOVE_LIGHTING_PLANE 16
#define ABOVE_LIGHTING_LAYER 16
#define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE"
#define FLOOR_OPENSPACE_PLANE 17
#define OPENSPACE_LAYER 17
#define OPENSPACE_RENDER_TARGET "OPENSPACE_PLANE"
#define BYOND_LIGHTING_PLANE 18
#define BYOND_LIGHTING_LAYER 18
#define BYOND_LIGHTING_RENDER_TARGET "BYOND_LIGHTING_PLANE"
#define CAMERA_STATIC_PLANE 19
#define CAMERA_STATIC_LAYER 19
#define CAMERA_STATIC_RENDER_TARGET "CAMERA_STATIC_PLANE"
//HUD layer defines
#define FULLSCREEN_PLANE 20
@@ -101,11 +124,16 @@
#define BLIND_LAYER 20.3
#define CRIT_LAYER 20.4
#define CURSE_LAYER 20.5
#define FULLSCREEN_RENDER_TARGET "FULLSCREEN_PLANE"
#define HUD_PLANE 21
#define HUD_LAYER 21
#define HUD_RENDER_TARGET "HUD_PLANE"
#define ABOVE_HUD_PLANE 22
#define ABOVE_HUD_LAYER 22
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
#define SPLASHSCREEN_LAYER 23
#define SPLASHSCREEN_PLANE 23
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
+5
View File
@@ -83,3 +83,8 @@
#define FLASH_LIGHT_DURATION 2
#define FLASH_LIGHT_POWER 3
#define FLASH_LIGHT_RANGE 3.8
/// Uses vis_overlays to leverage caching so that very few new items need to be made for the overlay. For anything that doesn't change outline or opaque area much or at all.
#define EMISSIVE_BLOCK_GENERIC 1
/// Uses a dedicated render_target object to copy the entire appearance in real time to the blocking layer. For things that can change in appearance a lot from the base state, like humans.
#define EMISSIVE_BLOCK_UNIQUE 2
+3 -1
View File
@@ -30,7 +30,7 @@
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
// 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))) )
#define WRAP(val, min, max) CLAMP(( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) ),min,max-1)
// Real modulus that handles decimals
#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
@@ -203,5 +203,7 @@
#define MANHATTAN_DISTANCE(a, b) (abs(a.x - b.x) + abs(a.y - b.y))
#define LOGISTIC_FUNCTION(L,k,x,x_0) (L/(1+(NUM_E**(-k*(x-x_0)))))
/// Make sure something is a boolean TRUE/FALSE 1/0 value, since things like bitfield & bitflag doesn't always give 1s and 0s.
#define FORCE_BOOLEAN(x) ((x)? TRUE : FALSE)
+4 -5
View File
@@ -345,11 +345,10 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are.
//Endgame Results
#define NUKE_NEAR_MISS 1
#define NUKE_MISS_STATION 2
#define NUKE_SYNDICATE_BASE 3
#define STATION_DESTROYED_NUKE 4
#define STATION_EVACUATED 5
#define NUKE_MISS_STATION 1
#define NUKE_SYNDICATE_BASE 2
#define STATION_DESTROYED_NUKE 3
#define STATION_EVACUATED 4
#define BLOB_WIN 8
#define BLOB_NUKE 9
#define BLOB_DESTROYED 10
+2 -1
View File
@@ -289,4 +289,5 @@
#define HUMAN_FIRE_STACK_ICON_NUM 3
#define PULL_PRONE_SLOWDOWN 0.6
#define HUMAN_CARRY_SLOWDOWN 0
#define FIREMAN_CARRY_SLOWDOWN 0
#define PIGGYBACK_CARRY_SLOWDOWN 1
+1
View File
@@ -20,6 +20,7 @@
#define CHANNEL_HIGHEST_AVAILABLE 1008 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS
#define MAX_INSTRUMENT_CHANNELS (128 * 6)
#define SOUND_MINIMUM_PRESSURE 10
#define FALLOFF_SOUNDS 1
+8 -5
View File
@@ -50,17 +50,19 @@
#define INIT_ORDER_PROFILER 100
#define INIT_ORDER_FAIL2TOPIC 99
#define INIT_ORDER_TITLE 98
#define INIT_ORDER_GARBAGE 97
#define INIT_ORDER_DBCORE 95
#define INIT_ORDER_BLACKBOX 94
#define INIT_ORDER_SERVER_MAINT 93
#define INIT_ORDER_INPUT 85
#define INIT_ORDER_GARBAGE 95
#define INIT_ORDER_DBCORE 93
#define INIT_ORDER_BLACKBOX 92
#define INIT_ORDER_SERVER_MAINT 91
#define INIT_ORDER_INPUT 90
#define INIT_ORDER_SOUNDS 85
#define INIT_ORDER_VIS 80
#define INIT_ORDER_RESEARCH 75
#define INIT_ORDER_EVENTS 70
#define INIT_ORDER_JOBS 65
#define INIT_ORDER_QUIRKS 60
#define INIT_ORDER_TICKER 55
#define INIT_ORDER_INSTRUMENTS 53
#define INIT_ORDER_MAPPING 50
#define INIT_ORDER_NETWORKS 45
#define INIT_ORDER_ATOMS 30
@@ -100,6 +102,7 @@
#define FIRE_PRIORITY_PROCESS 25
#define FIRE_PRIORITY_THROWING 25
#define FIRE_PRIORITY_SPACEDRIFT 30
#define FIRE_PRIORITY_INSTRUMENTS 30
#define FIRE_PRIORITY_FIELDS 30
#define FIRE_PRIOTITY_SMOOTHING 35
#define FIRE_PRIORITY_NETWORKS 40
+6
View File
@@ -147,6 +147,7 @@
#define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat.
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
#define TRAIT_NO_MIDROUND_ANTAG "no-midround-antag" //can't be turned into an antag by random events
#define TRAIT_PASSTABLE "passtable"
// mobility flag traits
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
@@ -173,6 +174,9 @@
//non-mob traits
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
#define VEHICLE_TRAIT "vehicle" // inherited from riding vehicles
#define INNATE_TRAIT "innate"
// item traits
#define TRAIT_NODROP "nodrop"
@@ -212,6 +216,7 @@
#define TRAIT_NO_TELEPORT "no-teleport" //you just can't
#define TRAIT_NO_INTERNALS "no-internals"
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
#define TRAIT_MUTATION_STASIS "mutation_stasis" //Prevents processed genetics mutations from processing.
// common trait sources
#define TRAIT_GENERIC "generic"
@@ -236,6 +241,7 @@
#define APHRO_TRAIT "aphro"
#define BLOODSUCKER_TRAIT "bloodsucker"
#define CLOTHING_TRAIT "clothing" //used for quirky carrygloves
#define SHOES_TRAIT "shoes" //inherited from your sweet kicks
// unique trait sources, still defines
#define STATUE_MUTE "statue"
+12
View File
@@ -5,6 +5,11 @@
#define MAJORITY_JUDGEMENT_VOTING 4
#define INSTANT_RUNOFF_VOTING 5
#define SHOW_RESULTS (1<<0)
#define SHOW_VOTES (1<<1)
#define SHOW_WINNER (1<<2)
#define SHOW_ABSTENTION (1<<3)
GLOBAL_LIST_INIT(vote_score_options,list("Bad","Poor","Acceptable","Good","Great"))
GLOBAL_LIST_INIT(vote_type_names,list(\
@@ -15,3 +20,10 @@ GLOBAL_LIST_INIT(vote_type_names,list(\
"Raw Score (returns results from 0 to 1, winner is 1)" = SCORE_VOTING,\
"Majority Judgement (single-winner score voting)" = MAJORITY_JUDGEMENT_VOTING,\
))
GLOBAL_LIST_INIT(display_vote_settings, list(\
"Results" = SHOW_RESULTS,
"Ongoing Votes" = SHOW_VOTES,
"Winner" = SHOW_WINNER,
"Abstainers" = SHOW_ABSTENTION
))
+102
View File
@@ -19,3 +19,105 @@
#define VV_RESTORE_DEFAULT "Restore to Default"
#define VV_MARKED_DATUM "Marked Datum"
#define VV_BITFIELD "Bitfield"
#define VV_TEXT_LOCATE "Custom Reference Locate"
#define VV_PROCCALL_RETVAL "Return Value of Proccall"
#define VV_MSG_MARKED "<br><font size='1' color='red'><b>Marked Object</b></font>"
#define VV_MSG_EDITED "<br><font size='1' color='red'><b>Var Edited</b></font>"
#define VV_MSG_DELETED "<br><font size='1' color='red'><b>Deleted</b></font>"
#define VV_NORMAL_LIST_NO_EXPAND_THRESHOLD 50
#define VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD 150
//#define IS_VALID_ASSOC_KEY(V) (istext(V) || ispath(V) || isdatum(V) || islist(V))
#define IS_VALID_ASSOC_KEY(V) (!isnum(V)) //hhmmm..
//General helpers
#define VV_HREF_TARGET_INTERNAL(target, href_key) "?_src_=vars;[HrefToken()];[href_key]=TRUE;[VV_HK_TARGET]=[REF(target)]"
#define VV_HREF_TARGETREF_INTERNAL(targetref, href_key) "?_src_=vars;[HrefToken()];[href_key]=TRUE;[VV_HK_TARGET]=[targetref]"
#define VV_HREF_TARGET(target, href_key, text) "<a href='[VV_HREF_TARGET_INTERNAL(target, href_key)]'>[text]</a>"
#define VV_HREF_TARGETREF(targetref, href_key, text) "<a href='[VV_HREF_TARGETREF_INTERNAL(targetref, href_key)]'>[text]</a>"
#define VV_HREF_TARGET_1V(target, href_key, text, varname) "<a href='[VV_HREF_TARGET_INTERNAL(target, href_key)];[VV_HK_VARNAME]=[varname]'>[text]</a>" //for stuff like basic varedits, one variable
#define VV_HREF_TARGETREF_1V(targetref, href_key, text, varname) "<a href='[VV_HREF_TARGETREF_INTERNAL(targetref, href_key)];[VV_HK_VARNAME]=[varname]'>[text]</a>"
#define GET_VV_TARGET locate(href_list[VV_HK_TARGET])
#define GET_VV_VAR_TARGET href_list[VV_HK_VARNAME]
//Helper for getting something to vv_do_topic in general
#define VV_TOPIC_LINK(datum, href_key, text) "<a href='?_src_=vars;[HrefToken()];[href_key]=TRUE;target=[REF(datum)]'>text</a>"
//Helpers for vv_get_dropdown()
#define VV_DROPDOWN_OPTION(href_key, name) . += "<option value='?_src_=vars;[HrefToken()];[href_key]=TRUE;target=[REF(src)]'>[name]</option>"
// VV HREF KEYS
#define VV_HK_TARGET "target"
#define VV_HK_VARNAME "targetvar" //name or index of var for 1 variable targetting hrefs.
// vv_do_list() keys
#define VV_HK_LIST_ADD "listadd"
#define VV_HK_LIST_EDIT "listedit"
#define VV_HK_LIST_CHANGE "listchange"
#define VV_HK_LIST_REMOVE "listremove"
#define VV_HK_LIST_ERASE_NULLS "listnulls"
#define VV_HK_LIST_ERASE_DUPES "listdupes"
#define VV_HK_LIST_SHUFFLE "listshuffle"
#define VV_HK_LIST_SET_LENGTH "listlen"
// vv_do_basic() keys
#define VV_HK_BASIC_EDIT "datumedit"
#define VV_HK_BASIC_CHANGE "datumchange"
#define VV_HK_BASIC_MASSEDIT "massedit"
// /datum
#define VV_HK_DELETE "delete"
#define VV_HK_EXPOSE "expose"
#define VV_HK_CALLPROC "proc_call"
#define VV_HK_MARK "mark"
#define VV_HK_MODIFY_TRAITS "modtraits"
// /atom
#define VV_HK_MODIFY_TRANSFORM "atom_transform"
#define VV_HK_ADD_REAGENT "addreagent"
#define VV_HK_TRIGGER_EMP "empulse"
#define VV_HK_TRIGGER_EXPLOSION "explode"
#define VV_HK_AUTO_RENAME "auto_rename"
// /obj
#define VV_HK_OSAY "osay"
#define VV_HK_MASS_DEL_TYPE "mass_delete_type"
#define VV_HK_ARMOR_MOD "mod_obj_armor"
// /mob
#define VV_HK_GIB "gib"
#define VV_HK_GIVE_SPELL "give_spell"
#define VV_HK_REMOVE_SPELL "remove_spell"
#define VV_HK_GIVE_DISEASE "give_disease"
#define VV_HK_GODMODE "godmode"
#define VV_HK_DROP_ALL "dropall"
#define VV_HK_REGEN_ICONS "regen_icons"
#define VV_HK_PLAYER_PANEL "player_panel"
#define VV_HK_BUILDMODE "buildmode"
#define VV_HK_DIRECT_CONTROL "direct_control"
#define VV_HK_OFFER_GHOSTS "offer_ghosts"
// /mob/living/carbon
#define VV_HK_MAKE_AI "aiify"
#define VV_HK_MODIFY_BODYPART "mod_bodypart"
#define VV_HK_MODIFY_ORGANS "organs_modify"
#define VV_HK_HALLUCINATION "force_hallucinate"
#define VV_HK_MARTIAL_ART "give_martial_art"
#define VV_HK_GIVE_TRAUMA "give_trauma"
#define VV_HK_CURE_TRAUMA "cure_trauma"
// /mob/living/carbon/human
#define VV_HK_COPY_OUTFIT "copy_outfit"
#define VV_HK_MOD_QUIRKS "quirkmod"
#define VV_HK_MAKE_MONKEY "human_monkify"
#define VV_HK_MAKE_CYBORG "human_cyborgify"
#define VV_HK_MAKE_SLIME "human_slimeify"
#define VV_HK_MAKE_ALIEN "human_alienify"
#define VV_HK_SET_SPECIES "setspecies"
#define VV_HK_PURRBATION "purrbation"
// misc
#define VV_HK_SPACEVINE_PURGE "spacevine_purge"
+4 -5
View File
@@ -58,14 +58,13 @@ GLOBAL_LIST_EMPTY(ipc_antennas_list)
//Genitals and Arousal Lists
GLOBAL_LIST_EMPTY(genitals_list)
GLOBAL_LIST_EMPTY(cock_shapes_list)
GLOBAL_LIST_EMPTY(gentlemans_organ_names)
GLOBAL_LIST_EMPTY(balls_shapes_list)
GLOBAL_LIST_EMPTY(breasts_shapes_list)
GLOBAL_LIST_EMPTY(vagina_shapes_list)
GLOBAL_LIST_INIT(cum_into_containers_list, list(/obj/item/reagent_containers/food/snacks/pie)) //Yer fuggin snowflake name list jfc
GLOBAL_LIST_INIT(dick_nouns, list("dick","cock","member","shaft"))
GLOBAL_LIST_INIT(cum_id_list,"semen")
GLOBAL_LIST_INIT(milk_id_list,"milk")
//longcat memes.
GLOBAL_LIST_INIT(dick_nouns, list("phallus", "willy", "dick", "prick", "member", "tool", "gentleman's organ", "cock", "wang", "knob", "dong", "joystick", "pecker", "johnson", "weenie", "tadger", "schlong", "thirsty ferret", "One eyed trouser trout", "Ding dong", "ankle spanker", "Pork sword", "engine cranker", "Harry hot dog", "Davy Crockett", "Kidney cracker", "Heat seeking moisture missile", "Giggle stick", "love whistle", "Tube steak", "Uncle Dick", "Purple helmet warrior"))
GLOBAL_LIST_INIT(genitals_visibility_toggles, list(GEN_VISIBLE_ALWAYS, GEN_VISIBLE_NO_CLOTHES, GEN_VISIBLE_NO_UNDIES, GEN_VISIBLE_NEVER))
GLOBAL_LIST_INIT(dildo_shapes, list(
"Human" = "human",
-5
View File
@@ -54,11 +54,6 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list)
GLOB.gentlemans_organ_names = list("phallus", "willy", "dick", "prick", "member", "tool", "gentleman's organ",
"cock", "wang", "knob", "dong", "joystick", "pecker", "johnson", "weenie", "tadger", "schlong", "thirsty ferret",
"baloney pony", "schlanger", "Mutton dagger", "old blind bob","Hanging Johnny", "fishing rod", "Tally whacker", "polly rocket",
"One eyed trouser trout", "Ding dong", "ankle spanker", "Pork sword", "engine cranker", "Harry hot dog", "Davy Crockett",
"Kidney cracker", "Heat seeking moisture missile", "Giggle stick", "love whistle", "Tube steak", "Uncle Dick", "Purple helmet warrior")
for(var/gpath in subtypesof(/obj/item/organ/genital))
var/obj/item/organ/genital/G = gpath
+18 -7
View File
@@ -184,8 +184,8 @@
"cock_length" = COCK_SIZE_DEF,
"cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF,
"cock_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"cock_taur" = FALSE,
"has_balls" = FALSE,
"balls_internal" = FALSE,
"balls_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"balls_size" = BALLS_SIZE_DEF,
"balls_shape" = DEF_BALLS_SHAPE,
@@ -200,13 +200,11 @@
"has_vag" = FALSE,
"vag_shape" = pick(GLOB.vagina_shapes_list),
"vag_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"vag_clits" = 1,
"vag_clit_diam" = 0.25,
"vag_clit_len" = 0.25,
"has_womb" = FALSE,
"womb_cum_rate" = CUM_RATE,
"womb_cum_mult" = CUM_RATE_MULT,
"womb_efficiency" = CUM_EFFICIENCY,
"balls_visibility" = GEN_VISIBLE_NO_UNDIES,
"breasts_visibility"= GEN_VISIBLE_NO_UNDIES,
"cock_visibility" = GEN_VISIBLE_NO_UNDIES,
"vag_visibility" = GEN_VISIBLE_NO_UNDIES,
"ipc_screen" = snowflake_ipc_antenna_list ? pick(snowflake_ipc_antenna_list) : "None",
"ipc_antenna" = "None",
"flavor_text" = "",
@@ -582,3 +580,16 @@ GLOBAL_LIST_EMPTY(species_list)
chosen = pick(mob_spawn_meancritters)
var/mob/living/simple_animal/C = new chosen(spawn_location)
return C
/proc/passtable_on(target, source)
var/mob/living/L = target
if(!HAS_TRAIT(L, TRAIT_PASSTABLE) && L.pass_flags & PASSTABLE)
ADD_TRAIT(L, TRAIT_PASSTABLE, INNATE_TRAIT)
ADD_TRAIT(L, TRAIT_PASSTABLE, source)
L.pass_flags |= PASSTABLE
/proc/passtable_off(target, source)
var/mob/living/L = target
REMOVE_TRAIT(L, TRAIT_PASSTABLE, source)
if(!HAS_TRAIT(L, TRAIT_PASSTABLE))
L.pass_flags &= ~PASSTABLE
+3 -3
View File
@@ -320,8 +320,8 @@
parts += "[FOURSPACES]<i>Nobody died this shift!</i>"
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
parts += "[FOURSPACES]Threat level: [mode.threat_level]"
parts += "[FOURSPACES]Threat left: [mode.threat]"
parts += "[FOURSPACES]Final threat level: [mode.threat_level]"
parts += "[FOURSPACES]Final threat: [mode.threat]"
parts += "[FOURSPACES]Executed rules:"
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat"
@@ -331,7 +331,7 @@
for(var/entry in mode.threat_tallies)
parts += "[FOURSPACES][FOURSPACES][entry] added [mode.threat_tallies[entry]]"
SSblackbox.record_feedback("tally","dynamic_threat",mode.threat_level,"Final threat level")
SSblackbox.record_feedback("tally","dynamic_threat",mode.threat,"Threat left")
SSblackbox.record_feedback("tally","dynamic_threat",mode.threat,"Final Threat")
return parts.Join("<br>")
/client/proc/roundend_report_file()
+2 -1
View File
@@ -25,7 +25,8 @@ GLOBAL_VAR_INIT(midnight_rollovers, 0)
GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
/proc/update_midnight_rollover()
if (world.timeofday < GLOB.rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS!
return GLOB.midnight_rollovers++
GLOB.midnight_rollovers++
GLOB.rollovercheck_last_timeofday = world.timeofday
return GLOB.midnight_rollovers
/proc/weekdayofthemonth()
+60
View File
@@ -0,0 +1,60 @@
/proc/make_types_fancy(var/list/types)
if (ispath(types))
types = list(types)
. = list()
for(var/type in types)
var/typename = "[type]"
var/static/list/TYPES_SHORTCUTS = list(
/obj/effect/decal/cleanable = "CLEANABLE",
/obj/item/radio/headset = "HEADSET",
/obj/item/clothing/head/helmet/space = "SPESSHELMET",
/obj/item/book/manual = "MANUAL",
/obj/item/reagent_containers/food/drinks = "DRINK", //longest paths comes first
/obj/item/reagent_containers/food = "FOOD",
/obj/item/reagent_containers = "REAGENT_CONTAINERS",
/obj/machinery/atmospherics = "ATMOS_MECH",
/obj/machinery/portable_atmospherics = "PORT_ATMOS",
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack = "MECHA_MISSILE_RACK",
/obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP",
/obj/item/organ = "ORGAN",
/obj/item = "ITEM",
/obj/machinery = "MACHINERY",
/obj/effect = "EFFECT",
/obj = "O",
/datum = "D",
/turf/open = "OPEN",
/turf/closed = "CLOSED",
/turf = "T",
/mob/living/carbon = "CARBON",
/mob/living/simple_animal = "SIMPLE",
/mob/living = "LIVING",
/mob = "M"
)
for (var/tn in TYPES_SHORTCUTS)
if (copytext(typename,1, length("[tn]/")+1)=="[tn]/" /*findtextEx(typename,"[tn]/",1,2)*/ )
typename = TYPES_SHORTCUTS[tn]+copytext(typename,length("[tn]/"))
break
.[typename] = type
/proc/get_fancy_list_of_atom_types()
var/static/list/pre_generated_list
if (!pre_generated_list) //init
pre_generated_list = make_types_fancy(typesof(/atom))
return pre_generated_list
/proc/get_fancy_list_of_datum_types()
var/static/list/pre_generated_list
if (!pre_generated_list) //init
pre_generated_list = make_types_fancy(sortList(typesof(/datum) - typesof(/atom)))
return pre_generated_list
/proc/filter_fancy_list(list/L, filter as text)
var/list/matches = new
for(var/key in L)
var/value = L[key]
if(findtext("[key]", filter) || findtext("[value]", filter))
matches[key] = value
return matches
+1 -1
View File
@@ -14,7 +14,7 @@ GLOBAL_VAR_INIT(fileaccess_timer, 0)
GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
GLOBAL_VAR_INIT(CELLRATE, 0.002) // conversion ratio between a watt-tick and kilojoule
GLOBAL_VAR_INIT(CELLRATE, 0.002) // conversion ratio between a watt-tick and kilojoule, dimensionless, kilojoules/watt-tick
GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second)
GLOBAL_LIST_EMPTY(powernets)
+1
View File
@@ -49,6 +49,7 @@
message_admins("[ADMIN_LOOKUPFLW(src)] might be running a modified client! (failed can_see on AI click of [A] (Turf Loc: [ADMIN_VERBOSEJMP(pixel_turf)]))")
var/message = "[key_name(src)] might be running a modified client! (failed can_see on AI click of [A] (Turf Loc: [AREACOORD(pixel_turf)]))"
log_admin(message)
to_chat(src, "<span class='warning'>You're experiencing a bug. Reconnect immediately to fix it. Admins have been notified.</span>")
if(REALTIMEOFDAY >= chnotify + 9000)
chnotify = REALTIMEOFDAY
send2irc_adminless_only("NOCHEAT", message)
+2 -2
View File
@@ -155,10 +155,10 @@
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A,1)
UnarmedAttack(A, 1)
else
if(W)
W.afterattack(A,src,0,params)
W.ranged_attack_chain(src, A, params)
else
RangedAttack(A,params)
+11
View File
@@ -163,3 +163,14 @@
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24"
#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
#define ui_ghost_pai "SOUTH: 6, CENTER+2:24"
//UI position overrides for 1:1 screen layout. (default is 7:5)
#define ui_stamina "EAST-1:28,CENTER:17" // replacing internals button
#define ui_overridden_resist "EAST-3:24,SOUTH+1:7"
#define ui_combat_toggle "EAST-4:22,SOUTH:5"
#define ui_boxcraft "EAST-4:22,SOUTH+1:6"
#define ui_boxarea "EAST-4:6,SOUTH+1:6"
#define ui_boxlang "EAST-5:22,SOUTH+1:6"
#define ui_boxvore "EAST-5:22,SOUTH+1:6"
+51
View File
@@ -16,6 +16,7 @@
//Trust me, you need one. Period. If you don't think you do, you're doing something extremely wrong.
/obj/screen/plane_master/proc/backdrop(mob/mymob)
///Things rendered on "openspace"; holes in multi-z
/obj/screen/plane_master/openspace
name = "open space plane master"
plane = FLOOR_OPENSPACE_PLANE
@@ -38,12 +39,14 @@
/obj/screen/plane_master/proc/clear_filters()
filters = list()
///Contains just the floor
/obj/screen/plane_master/floor
name = "floor plane master"
plane = FLOOR_PLANE
appearance_flags = PLANE_MASTER
blend_mode = BLEND_OVERLAY
///Contains most things in the game world
/obj/screen/plane_master/game_world
name = "game world plane master"
plane = GAME_PLANE
@@ -57,12 +60,60 @@
remove_filter("ambient_occlusion")
update_filters()
///Contains all lighting objects
/obj/screen/plane_master/lighting
name = "lighting plane master"
plane = LIGHTING_PLANE
blend_mode = BLEND_MULTIPLY
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/screen/plane_master/lighting/Initialize()
. = ..()
filters += filter(type="alpha", render_source=EMISSIVE_RENDER_TARGET, flags=MASK_INVERSE)
filters += filter(type="alpha", render_source=EMISSIVE_UNBLOCKABLE_RENDER_TARGET, flags=MASK_INVERSE)
/**
* Things placed on this mask the lighting plane. Doesn't render directly.
*
* Gets masked by blocking plane. Use for things that you want blocked by
* mobs, items, etc.
*/
/obj/screen/plane_master/emissive
name = "emissive plane master"
plane = EMISSIVE_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
render_target = EMISSIVE_RENDER_TARGET
/obj/screen/plane_master/emissive/Initialize()
. = ..()
filters += filter(type="alpha", render_source=EMISSIVE_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE)
/**
* Things placed on this always mask the lighting plane. Doesn't render directly.
*
* Always masks the light plane, isn't blocked by anything. Use for on mob glows,
* magic stuff, etc.
*/
/obj/screen/plane_master/emissive_unblockable
name = "unblockable emissive plane master"
plane = EMISSIVE_UNBLOCKABLE_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
render_target = EMISSIVE_UNBLOCKABLE_RENDER_TARGET
/**
* Things placed on this layer mask the emissive layer. Doesn't render directly
*
* You really shouldn't be directly using this, use atom helpers instead
*/
/obj/screen/plane_master/emissive_unblockable
name = "emissive mob plane master"
plane = EMISSIVE_BLOCKER_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
render_target = EMISSIVE_BLOCKER_RENDER_TARGET
///Contains space parallax
/obj/screen/plane_master/parallax
name = "parallax plane master"
plane = PLANE_SPACE_PARALLAX
+44 -4
View File
@@ -8,12 +8,15 @@
*afterattack. The return value does not matter.
*/
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT)
if(isliving(user))
var/mob/living/L = user
if(isliving(user))
var/mob/living/L = user
if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT)
if(IS_STAMCRIT(L))
to_chat(L, "<span class='warning'>You are too exhausted to swing [src]!</span>")
return
if(!CHECK_MOBILITY(L, MOBILITY_USE))
to_chat(L, "<span class='warning'>You are unable to swing [src] right now!</span>")
return
if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
return
if(pre_attack(target, user, params))
@@ -24,6 +27,15 @@
return
afterattack(target, user, TRUE, params)
/// Like melee_attack_chain but for ranged.
/obj/item/proc/ranged_attack_chain(mob/user, atom/target, params)
if(isliving(user))
var/mob/living/L = user
if(!CHECK_MOBILITY(L, MOBILITY_USE))
to_chat(L, "<span class='warning'>You are unable to raise [src] right now!</span>")
return
afterattack(target, user, FALSE, params)
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
/obj/item/proc/attack_self(mob/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT)
@@ -50,7 +62,6 @@
user.changeNext_move(CLICK_CD_MELEE)
return I.attack(src, user)
/obj/item/proc/attack(mob/living/M, mob/living/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
return
@@ -117,6 +128,7 @@
if((user != src) && run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user) & BLOCK_SUCCESS)
return FALSE
send_item_attack_message(I, user)
I.do_stagger_action(src, user)
if(I.force)
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
@@ -166,5 +178,33 @@
playsound(src, 'sound/weapons/dink.ogg', 30, 1)
return 1
/// How much stamina this takes to swing this is not for realism purposes hecc off.
/obj/item/proc/getweight()
return total_mass || w_class * 1.25
/// How long this staggers for. 0 and negatives supported.
/obj/item/proc/melee_stagger_duration()
if(!isnull(stagger_force))
return stagger_force
/// totally not an untested, arbitrary equation.
return clamp((1.5 + (w_class/7.5)) * (force / 2), 0, 10 SECONDS)
/obj/item/proc/do_stagger_action(mob/living/target, mob/living/user)
if(!CHECK_BITFIELD(target.status_flags, CANSTAGGER))
return FALSE
if(target.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
target.do_staggered_animation()
var/duration = melee_stagger_duration()
if(!duration) //0
return FALSE
else if(duration > 0)
target.Stagger(duration)
else //negative
target.AdjustStaggered(duration)
return TRUE
/mob/proc/do_staggered_animation()
set waitfor = FALSE
animate(src, pixel_x = -2, pixel_y = -2, time = 1, flags = ANIMATION_RELATIVE | ANIMATION_PARALLEL)
animate(pixel_x = 4, pixel_y = 4, time = 1, flags = ANIMATION_RELATIVE)
animate(pixel_x = -2, pixel_y = -2, time = 0.5, flags = ANIMATION_RELATIVE)
@@ -368,12 +368,16 @@
var/list/datum/dynamic_storyteller/runnable_storytellers = new
var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight)
var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust)
var/list/min_player_counts = Get(/datum/config_entry/keyed_list/storyteller_min_players)
for(var/T in storyteller_cache)
var/datum/dynamic_storyteller/S = T
var/config_tag = initial(S.config_tag)
var/probability = (config_tag in probabilities) ? probabilities[config_tag] : initial(S.weight)
var/min_players = (config_tag in min_player_counts) ? min_player_counts[config_tag] : initial(S.min_players)
if(probability <= 0)
continue
if(length(GLOB.player_list) < min_players)
continue
if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len)
var/name = initial(S.name)
var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3)
@@ -92,3 +92,7 @@
/datum/config_entry/keyed_list/storyteller_weight
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/keyed_list/storyteller_min_players
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
@@ -396,6 +396,14 @@
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/keyed_list/job_threat
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/keyed_list/antag_threat
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/number/monkeycap
config_entry_value = 64
min_val = 0
@@ -436,3 +444,8 @@
/datum/config_entry/number/penis_max_inches_prefs
config_entry_value = 20
min_val = 0
/datum/config_entry/keyed_list/safe_visibility_toggles
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_FLAG
config_entry_value = list(GEN_VISIBLE_NO_CLOTHES, GEN_VISIBLE_NO_UNDIES, GEN_VISIBLE_NEVER) //refer to cit_helpers for all toggles.
+2 -1
View File
@@ -66,6 +66,7 @@ SUBSYSTEM_DEF(job)
/datum/controller/subsystem/job/proc/GetJob(rank)
RETURN_TYPE(/datum/job)
if(!occupations.len)
SetupOccupations()
return name_occupations[rank]
@@ -738,4 +739,4 @@ SUBSYSTEM_DEF(job)
. |= player.mind
/datum/controller/subsystem/job/proc/JobDebug(message)
log_job_debug(message)
log_job_debug(message)
@@ -1,5 +1,4 @@
PROCESSING_SUBSYSTEM_DEF(chemistry)
wait = 5
flags = SS_KEEP_TIMING
name = "Chemistry"
@@ -0,0 +1,43 @@
PROCESSING_SUBSYSTEM_DEF(instruments)
name = "Instruments"
wait = 0.5
init_order = INIT_ORDER_INSTRUMENTS
flags = SS_KEEP_TIMING
priority = FIRE_PRIORITY_INSTRUMENTS
var/static/list/datum/instrument/instrument_data = list() //id = datum
var/static/list/datum/song/songs = list()
var/static/musician_maxlines = 600
var/static/musician_maxlinechars = 300
var/static/musician_hearcheck_mindelay = 5
var/static/max_instrument_channels = MAX_INSTRUMENT_CHANNELS
var/static/current_instrument_channels = 0
/datum/controller/subsystem/processing/instruments/Initialize()
initialize_instrument_data()
return ..()
/datum/controller/subsystem/processing/instruments/proc/on_song_new(datum/song/S)
songs += S
/datum/controller/subsystem/processing/instruments/proc/on_song_del(datum/song/S)
songs -= S
/datum/controller/subsystem/processing/instruments/proc/initialize_instrument_data()
for(var/path in subtypesof(/datum/instrument))
var/datum/instrument/I = path
if(initial(I.abstract_type) == path)
continue
I = new path
I.Initialize()
instrument_data[I.id || "[I.type]"] = I
CHECK_TICK
/datum/controller/subsystem/processing/instruments/proc/get_instrument(id_or_path)
return instrument_data["[id_or_path]"]
/datum/controller/subsystem/processing/instruments/proc/reserve_instrument_channel(datum/instrument/I)
if(current_instrument_channels > max_instrument_channels)
return
. = SSsounds.reserve_sound_channel(I)
if(!isnull(.))
current_instrument_channels++
@@ -37,11 +37,11 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
if(job?.blacklisted_quirks)
cut = filter_quirks(my_quirks, job.blacklisted_quirks)
for(var/V in my_quirks)
var/datum/quirk/Q = quirks[V]
if(Q)
if(V in quirks)
var/datum/quirk/Q = quirks[V]
user.add_quirk(Q, spawn_effects)
else
stack_trace("Invalid quirk \"[V]\" in client [cli.ckey] preferences")
log_admin("Invalid quirk \"[V]\" in client [cli.ckey] preferences")
cli.prefs.all_quirks -= V
badquirk = TRUE
if(badquirk)
@@ -1,3 +1,4 @@
PROCESSING_SUBSYSTEM_DEF(status_effects)
wait = 1
flags = SS_TICKER
name = "Status Effects"
+91
View File
@@ -0,0 +1,91 @@
#define DATUMLESS "NO_DATUM"
SUBSYSTEM_DEF(sounds)
name = "Sounds"
flags = SS_NO_FIRE
init_order = INIT_ORDER_SOUNDS
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
// Hey uh these two needs to be initialized fast because the whole "things get deleted before init" thing.
/// Assoc list, "[channel]" = either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel
var/list/using_channels = list()
/// Assoc list datum = list(channel1, channel2, ...) for what channels something reserved.
var/list/using_channels_by_datum = list()
/// List of all available channels with associations set to TRUE for fast lookups/allocation.
var/list/available_channels
/datum/controller/subsystem/sounds/Initialize()
setup_available_channels()
return ..()
/datum/controller/subsystem/sounds/proc/setup_available_channels()
available_channels = list()
for(var/i in 1 to using_channels_max)
available_channels[num2text(i)] = TRUE
/// Removes a channel from using list.
/datum/controller/subsystem/sounds/proc/free_sound_channel(channel)
channel = num2text(channel)
var/using = using_channels[channel]
using_channels -= channel
if(using)
using_channels_by_datum[using] -= channel
if(!length(using_channels_by_datum[using]))
using_channels_by_datum -= using
available_channels[channel] = TRUE
/// Frees all the channels a datum is using.
/datum/controller/subsystem/sounds/proc/free_datum_channels(datum/D)
var/list/L = using_channels_by_datum[D]
if(!L)
return
for(var/channel in L)
using_channels -= channel
available_channels[channel] = TRUE
using_channels_by_datum -= D
/// Frees all datumless channels
/datum/controller/subsystem/sounds/proc/free_datumless_channels()
free_datum_channels(DATUMLESS)
/// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel.
/datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless()
var/channel = random_available_channel_text()
if(!channel) //oh no..
return FALSE
available_channels -= channel
using_channels[channel] = DATUMLESS
LAZYINITLIST(using_channels_by_datum[DATUMLESS])
using_channels_by_datum[DATUMLESS] += channel
return text2num(channel)
/// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel.
/datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D)
if(!D) //i don't like typechecks but someone will fuck it up
CRASH("Attempted to reserve sound channel without datum using the managed proc.")
var/channel = random_available_channel_text()
if(!channel)
return FALSE
available_channels -= channel
using_channels[channel] = D
LAZYINITLIST(using_channels_by_datum[D])
using_channels_by_datum[D] += channel
return text2num(channel)
/// Random available channel, returns text.
/datum/controller/subsystem/sounds/proc/random_available_channel_text()
return pick(available_channels)
/// Random available channel, returns number
/datum/controller/subsystem/sounds/proc/random_available_channel()
return text2num(pick(available_channels))
/// If a channel is available
/datum/controller/subsystem/sounds/proc/is_channel_available(channel)
return available_channels[num2text(channel)]
/// How many channels we have left.
/datum/controller/subsystem/sounds/proc/available_channels_left()
return length(available_channels)
#undef DATUMLESS
+7 -7
View File
@@ -479,15 +479,15 @@ SUBSYSTEM_DEF(ticker)
var/vote_type = CONFIG_GET(string/map_vote_type)
switch(vote_type)
if("PLURALITY")
SSvote.initiate_vote("map","server",hideresults=TRUE)
SSvote.initiate_vote("map","server", display = SHOW_RESULTS)
if("APPROVAL")
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = APPROVAL_VOTING)
SSvote.initiate_vote("map","server", display = SHOW_RESULTS, votesystem = APPROVAL_VOTING)
if("IRV")
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = INSTANT_RUNOFF_VOTING)
SSvote.initiate_vote("map","server", display = SHOW_RESULTS, votesystem = INSTANT_RUNOFF_VOTING)
if("SCORE")
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING)
SSvote.initiate_vote("map","server", display = SHOW_RESULTS, votesystem = MAJORITY_JUDGEMENT_VOTING)
else
SSvote.initiate_vote("map","server",hideresults=TRUE)
SSvote.initiate_vote("map","server", display = SHOW_RESULTS)
// fallback
/datum/controller/subsystem/ticker/proc/HasRoundStarted()
@@ -503,9 +503,9 @@ SUBSYSTEM_DEF(ticker)
SSticker.modevoted = TRUE
var/dynamic = CONFIG_GET(flag/dynamic_voting)
if(dynamic)
SSvote.initiate_vote("dynamic","server",hideresults=TRUE,votesystem=SCORE_VOTING,forced=TRUE,vote_time = 20 MINUTES)
SSvote.initiate_vote("dynamic", "server", display = NONE, votesystem = SCORE_VOTING, forced = TRUE,vote_time = 20 MINUTES)
else
SSvote.initiate_vote("roundtype","server",hideresults=TRUE,votesystem=PLURALITY_VOTING,forced=TRUE, \
SSvote.initiate_vote("roundtype", "server", display = NONE, votesystem = PLURALITY_VOTING, forced=TRUE, \
vote_time = (CONFIG_GET(flag/modetier_voting) ? 1 MINUTES : 20 MINUTES))
/datum/controller/subsystem/ticker/Recover()
+34 -15
View File
@@ -23,7 +23,7 @@ SUBSYSTEM_DEF(vote)
var/list/generated_actions = list()
var/next_pop = 0
var/obfuscated = FALSE//CIT CHANGE - adds obfuscated/admin-only votes
var/display_votes = SHOW_RESULTS|SHOW_VOTES|SHOW_WINNER|SHOW_ABSTENTION //CIT CHANGE - adds obfuscated/admin-only votes
var/list/stored_gamemode_votes = list() //Basically the last voted gamemode is stored here for end-of-round use.
@@ -59,7 +59,7 @@ SUBSYSTEM_DEF(vote)
voted.Cut()
voting.Cut()
scores.Cut()
obfuscated = FALSE //CIT CHANGE - obfuscated votes
display_votes = initial(display_votes) //CIT CHANGE - obfuscated votes
remove_action_buttons()
/datum/controller/subsystem/vote/proc/get_result()
@@ -250,7 +250,7 @@ SUBSYSTEM_DEF(vote)
if(winners.len > 0)
if(was_roundtype_vote)
stored_gamemode_votes = list()
if(!obfuscated)
if(display_votes & SHOW_RESULTS)
if(vote_system == SCHULZE_VOTING)
text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
if(vote_system == MAJORITY_JUDGEMENT_VOTING)
@@ -261,15 +261,15 @@ SUBSYSTEM_DEF(vote)
votes = 0
if(was_roundtype_vote)
stored_gamemode_votes[choices[i]] = votes
text += "\n<b>[choices[i]]:</b> [obfuscated ? "???" : votes]" //CIT CHANGE - adds obfuscated votes
text += "\n<b>[choices[i]]:</b> [display_votes & SHOW_RESULTS ? votes : "???"]" //CIT CHANGE - adds obfuscated votes
if(mode != "custom")
if(winners.len > 1 && !obfuscated) //CIT CHANGE - adds obfuscated votes
if(winners.len > 1 && display_votes & SHOW_WINNER) //CIT CHANGE - adds obfuscated votes
text = "\n<b>Vote Tied Between:</b>"
for(var/option in winners)
text += "\n\t[option]"
. = pick(winners)
text += "\n<b>Vote Result: [obfuscated ? "???" : .]</b>" //CIT CHANGE - adds obfuscated votes
else
text += "\n<b>Vote Result: [display_votes & SHOW_WINNER ? . : "???"]</b>" //CIT CHANGE - adds obfuscated votes
if(display_votes & SHOW_ABSTENTION)
text += "\n<b>Did not vote:</b> [GLOB.clients.len-voted.len]"
else if(vote_system == SCORE_VOTING)
for(var/score_name in scores)
@@ -278,7 +278,7 @@ SUBSYSTEM_DEF(vote)
score = 0
if(was_roundtype_vote)
stored_gamemode_votes[score_name] = score
text = "\n<b>[score_name]:</b> [obfuscated ? "???" : score]"
text = "\n<b>[score_name]:</b> [display_votes & SHOW_RESULTS ? score : "???"]"
. = 1
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
@@ -295,7 +295,7 @@ SUBSYSTEM_DEF(vote)
if(islist(myvote))
for(var/j=1,j<=myvote.len,j++)
SSblackbox.record_feedback("nested tally","voting",1,list(vote_title_text,"[j]\th",choices[myvote[j]]))
if(obfuscated) //CIT CHANGE - adds obfuscated votes. this messages admins with the vote's true results
if(!(display_votes & SHOW_RESULTS)) //CIT CHANGE - adds obfuscated votes. this messages admins with the vote's true results
var/admintext = "Obfuscated results"
if(vote_system != SCORE_VOTING)
if(vote_system == SCHULZE_VOTING)
@@ -327,7 +327,7 @@ SUBSYSTEM_DEF(vote)
if(CONFIG_GET(flag/modetier_voting))
reset()
started_time = 0
initiate_vote("mode tiers","server",hideresults=FALSE,votesystem=SCORE_VOTING,forced=TRUE, vote_time = 30 MINUTES)
initiate_vote("mode tiers","server", votesystem=SCORE_VOTING, forced=TRUE, vote_time = 30 MINUTES)
to_chat(world,"<b>The vote will end right as the round starts.</b>")
return .
if("restart")
@@ -354,11 +354,15 @@ SUBSYSTEM_DEF(vote)
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
GLOB.master_mode = "dynamic"
var/list/runnable_storytellers = config.get_runnable_storytellers()
var/datum/dynamic_storyteller/picked
for(var/T in runnable_storytellers)
var/datum/dynamic_storyteller/S = T
if(stored_gamemode_votes[initial(S.name)] == 1 && CHECK_BITFIELD(initial(S.flags), FORCE_IF_WON))
picked = S
runnable_storytellers[S] *= round(stored_gamemode_votes[initial(S.name)]*100000,1)
var/datum/dynamic_storyteller/S = pickweightAllowZero(runnable_storytellers)
GLOB.dynamic_storyteller_type = S
if(!picked)
picked = pickweightAllowZero(runnable_storytellers)
GLOB.dynamic_storyteller_type = picked
if("map")
var/datum/map_config/VM = config.maplist[.]
message_admins("The map has been voted for and will change to: [VM.map_name]")
@@ -432,7 +436,7 @@ SUBSYSTEM_DEF(vote)
saved -= usr.ckey
return 0
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY_VOTING, forced = FALSE,vote_time = -1)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, display = display_votes, votesystem = PLURALITY_VOTING, forced = FALSE,vote_time = -1)//CIT CHANGE - adds display argument to votes to allow for obfuscated votes
vote_system = votesystem
if(!mode)
if(started_time)
@@ -452,7 +456,7 @@ SUBSYSTEM_DEF(vote)
SEND_SOUND(world, sound('sound/misc/notice2.ogg'))
reset()
obfuscated = hideresults //CIT CHANGE - adds obfuscated votes
display_votes = display //CIT CHANGE - adds obfuscated votes
switch(vote_type)
if("restart")
choices.Add("Restart Round","Continue Playing")
@@ -503,6 +507,21 @@ SUBSYSTEM_DEF(vote)
if(!option || mode || !usr.client)
break
choices.Add(option)
var/keep_going = TRUE
var/toggles = SHOW_RESULTS|SHOW_VOTES|SHOW_WINNER
while(keep_going)
var/list/choices = list()
for(var/A in GLOB.display_vote_settings)
var/toggletext
var/bitflag = GLOB.display_vote_settings[A]
toggletext = "[toggles & bitflag ? "Show" : "Hide"] [A]"
choices[toggletext] = bitflag
var/chosen = input(usr, "Toggle vote display settings. Cancel to finalize.", toggles) as null|anything in choices
if(!chosen)
keep_going = FALSE
else
toggles ^= choices[chosen]
display_votes = toggles
else
return 0
mode = vote_type
@@ -573,7 +592,7 @@ SUBSYSTEM_DEF(vote)
ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey]))
if(!votes)
votes = 0
. += "<li>[ivotedforthis ? "<b>" : ""]<a href='?src=[REF(src)];vote=[i]'>[choices[i]]</a> ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "</b>" : ""]</li>" // CIT CHANGE - adds obfuscated votes
. += "<li>[ivotedforthis ? "<b>" : ""]<a href='?src=[REF(src)];vote=[i]'>[choices[i]]</a> ([display_votes & SHOW_VOTES ? votes : (admin ? "??? ([votes])" : "???")] votes)[ivotedforthis ? "</b>" : ""]</li>" // CIT CHANGE - adds obfuscated votes
if(choice_descs.len >= i)
. += "<li>[choice_descs[i]]</li>"
. += "</ul><hr>"
+1 -11
View File
@@ -302,16 +302,6 @@
name = "Toggle Friendly Fire \[ON\]"
..()
/datum/action/item_action/synthswitch
name = "Change Synthesizer Instrument"
desc = "Change the type of instrument your synthesizer is playing as."
/datum/action/item_action/synthswitch/Trigger()
if(istype(target, /obj/item/instrument/piano_synth))
var/obj/item/instrument/piano_synth/synth = target
return synth.selectInstrument()
return ..()
/datum/action/item_action/vortex_recall
name = "Vortex Recall"
desc = "Recall yourself, and anyone nearby, to an attuned hierophant beacon at any time.<br>If the beacon is still attached, will detach it."
@@ -659,7 +649,7 @@
return FALSE
var/obj/effect/proc_holder/spell/S = target
if(owner)
return S.can_cast(owner)
return S.can_cast(owner, FALSE, TRUE)
return FALSE
/datum/action/spell_action/alien
+17 -11
View File
@@ -9,8 +9,8 @@
var/max_distance = 0
var/sleep_time = 3
var/finished = 0
var/target_oldloc = null
var/origin_oldloc = null
var/turf/target_oldloc
var/turf/origin_oldloc
var/static_beam = 0
var/beam_type = /obj/effect/ebeam //must be subtype
var/timing_id = null
@@ -23,13 +23,13 @@
target_oldloc = get_turf(target)
sleep_time = beam_sleep_time
if(origin_oldloc == origin && target_oldloc == target)
static_beam = 1
static_beam = TRUE
max_distance = maxdistance
base_icon = new(beam_icon,beam_icon_state)
icon = beam_icon
icon_state = beam_icon_state
beam_type = btype
if(time < INFINITY)
if(time < INFINITY)
addtimer(CALLBACK(src,.proc/End), time)
/datum/beam/proc/Start()
@@ -42,10 +42,14 @@
return
recalculating = TRUE
timing_id = null
if(origin && target && get_dist(origin,target)<max_distance && origin.z == target.z)
var/origin_turf = get_turf(origin)
var/target_turf = get_turf(target)
if(!static_beam && (origin_turf != origin_oldloc || target_turf != target_oldloc))
var/turf/origin_turf
if(origin)
origin_turf = get_turf(origin)
var/turf/target_turf
if(target)
target_turf = get_turf(target)
if(origin_turf && target_turf && (get_dist(origin_turf, target_turf) < max_distance) && (origin_turf.z == target_turf.z))
if(!static_beam && ((origin_turf != origin_oldloc) || (target_turf != target_oldloc)))
origin_oldloc = origin_turf //so we don't keep checking against their initial positions, leading to endless Reset()+Draw() calls
target_oldloc = target_turf
Reset()
@@ -90,13 +94,15 @@
return ..()
/datum/beam/proc/Draw()
var/Angle = round(Get_Angle(origin,target))
if(!origin_oldloc || !target_oldloc)
return
var/Angle = round(Get_Angle(origin_oldloc,target_oldloc))
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(Angle)
//Translation vector for origin and target
var/DX = (32*target.x+target.pixel_x)-(32*origin.x+origin.pixel_x)
var/DY = (32*target.y+target.pixel_y)-(32*origin.y+origin.pixel_y)
var/DX = (32*target_oldloc.x+target_oldloc.pixel_x)-(32*origin_oldloc.x+origin_oldloc.pixel_x)
var/DY = (32*target_oldloc.y+target_oldloc.pixel_y)-(32*origin_oldloc.y+origin_oldloc.pixel_y)
var/N = 0
var/length = round(sqrt((DX)**2+(DY)**2)) //hypotenuse of the triangle formed by target and origin's displacement
+9 -12
View File
@@ -20,6 +20,7 @@
..()
make_backseats()
get_ghost()
RegisterSignal(M, COMSIG_MOB_DEATH, .proc/revert_to_normal)
/datum/brain_trauma/severe/split_personality/proc/make_backseats()
stranger_backseat = new(owner, src)
@@ -37,23 +38,23 @@
qdel(src)
/datum/brain_trauma/severe/split_personality/on_life()
if(owner.stat == DEAD)
if(current_controller != OWNER)
switch_personalities()
qdel(src)
else if(prob(3))
if(prob(3))
switch_personalities()
..()
/datum/brain_trauma/severe/split_personality/on_lose()
if(current_controller != OWNER) //it would be funny to cure a guy only to be left with the other personality, but it seems too cruel
switch_personalities()
switch_personalities(TRUE)
QDEL_NULL(stranger_backseat)
QDEL_NULL(owner_backseat)
UnregisterSignal(owner, COMSIG_MOB_DEATH)
..()
/datum/brain_trauma/severe/split_personality/proc/switch_personalities()
if(QDELETED(owner) || owner.stat == DEAD || QDELETED(stranger_backseat) || QDELETED(owner_backseat))
/datum/brain_trauma/severe/split_personality/proc/revert_to_normal()
qdel(src)
/datum/brain_trauma/severe/split_personality/proc/switch_personalities(forced = FALSE)
if(QDELETED(owner) || (owner.stat == DEAD && !forced) || QDELETED(stranger_backseat) || QDELETED(owner_backseat))
return
var/mob/living/split_personality/current_backseat
@@ -126,10 +127,6 @@
if(QDELETED(body))
qdel(src) //in case trauma deletion doesn't already do it
if((body.stat == DEAD && trauma.owner_backseat == src))
trauma.switch_personalities()
qdel(trauma)
//if one of the two ghosts, the other one stays permanently
if(!body.client && trauma.initialized)
trauma.switch_personalities()
+2 -2
View File
@@ -72,9 +72,9 @@
return {"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
[head_content]
</head>
<body scroll=auto>
+2
View File
@@ -8,6 +8,8 @@
var/obj/screen/craft/C = new()
C.icon = H.ui_style
H.static_inventory += C
if(!CL.prefs.widescreenpref)
C.screen_loc = ui_boxcraft
CL.screen += C
RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact)
@@ -33,6 +33,13 @@
/obj/item/organ/ears/cat = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/papermask
name = "Paper Mask"
result = /obj/item/clothing/mask/paper
time = 10
reqs = list(/obj/item/paper = 20)
category = CAT_CLOTHING
////////
//Huds//
////////
+12 -4
View File
@@ -191,20 +191,28 @@
///////Yes, I said humans. No, this won't end well...//////////
/datum/component/riding/human
var/fireman_carrying = FALSE
/datum/component/riding/human/Initialize()
. = ..()
RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE)
var/mob/living/carbon/human/H = parent
H.remove_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING)
. = ..()
var/mob/living/carbon/human/H = parent
if(!length(H.buckled_mobs))
H.remove_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING)
if(!fireman_carrying)
M.Daze(25)
REMOVE_TRAIT(M, TRAIT_MOBILITY_NOUSE, src)
/datum/component/riding/human/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE)
. = ..()
var/mob/living/carbon/human/H = parent
H.add_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING, multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN)
if(length(H.buckled_mobs))
H.add_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING, multiplicative_slowdown = fireman_carrying? FIREMAN_CARRY_SLOWDOWN : PIGGYBACK_CARRY_SLOWDOWN)
if(fireman_carrying)
ADD_TRAIT(M, TRAIT_MOBILITY_NOUSE, src)
/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
var/mob/living/carbon/human/H = parent
@@ -236,11 +244,11 @@
else
return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4))
/datum/component/riding/human/force_dismount(mob/living/user)
var/atom/movable/AM = parent
AM.unbuckle_mob(user)
user.DefaultCombatKnockdown(60)
user.Daze(50)
user.visible_message("<span class='warning'>[AM] pushes [user] off of [AM.p_them()]!</span>")
/datum/component/riding/cyborg
+17 -2
View File
@@ -27,6 +27,8 @@ GLOBAL_LIST_EMPTY(uplinks)
var/datum/ui_state/checkstate
var/compact_mode = FALSE
var/debug = FALSE
var/saved_player_population = 0
var/list/filters = list()
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class)
if(!isitem(parent))
@@ -47,7 +49,6 @@ GLOBAL_LIST_EMPTY(uplinks)
RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation)
GLOB.uplinks += src
var/list/filters = list()
if(istype(traitor_class))
filters = traitor_class.uplink_filters
starting_tc = traitor_class.TC
@@ -68,6 +69,7 @@ GLOBAL_LIST_EMPTY(uplinks)
if(!lockable)
active = TRUE
locked = FALSE
saved_player_population = GLOB.joined_player_list.len
/datum/component/uplink/InheritComponent(datum/component/uplink/U)
lockable |= U.lockable
@@ -117,7 +119,18 @@ GLOBAL_LIST_EMPTY(uplinks)
return
active = TRUE
if(user)
//update the saved population
var/previous_player_population = saved_player_population
saved_player_population = GLOB.joined_player_list.len
//if population has changed, update uplink items
if(saved_player_population != previous_player_population)
//make sure discounts are not rerolled
var/old_discounts = uplink_items["Discounted Gear"]
uplink_items = get_uplink_items(gamemode, FALSE, allow_restricted, filters)
if(old_discounts)
uplink_items["Discounted Gear"] = old_discounts
ui_interact(user)
// an unlocked uplink blocks also opening the PDA or headset menu
return COMPONENT_NO_INTERACT
@@ -190,7 +203,9 @@ GLOBAL_LIST_EMPTY(uplinks)
if(item in buyable_items)
var/datum/uplink_item/I = buyable_items[item]
MakePurchase(usr, I)
//check to make sure people cannot buy items when the player pop is below the requirement
if(GLOB.joined_player_list.len >= I.player_minimum)
MakePurchase(usr, I)
. = TRUE
if("lock")
active = FALSE
+2
View File
@@ -109,6 +109,8 @@
UnregisterSignal(target, signal_procs[target])
//END: ECS SHIT
SSsounds.free_datum_channels(src)
return QDEL_HINT_QUEUE
#ifdef DATUMVAR_DEBUGGING_MODE
+23 -1378
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -412,13 +412,13 @@
switch(deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 4))
if(G_MALE)
set_gender(MALE, TRUE)
set_gender(MALE, TRUE, forced = TRUE)
if(G_FEMALE)
set_gender(FEMALE, TRUE)
set_gender(FEMALE, TRUE, forced = TRUE)
if(G_PLURAL)
set_gender(PLURAL, TRUE)
set_gender(PLURAL, TRUE, forced = TRUE)
else
set_gender(NEUTER, TRUE)
set_gender(NEUTER, TRUE, forced = TRUE)
/mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
..()
+12 -2
View File
@@ -72,7 +72,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
var/atom/target = locate(href_list["show_flavor"])
var/text = texts_by_atom[target]
if(text)
usr << browse("<HTML><HEAD><TITLE>[target.name]</TITLE></HEAD><BODY><TT>[replacetext(texts_by_atom[target], "\n", "<BR>")]</TT></BODY></HTML>", "window=[target.name];size=500x200")
usr << browse("<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[target.name]</TITLE></HEAD><BODY><TT>[replacetext(texts_by_atom[target], "\n", "<BR>")]</TT></BODY></HTML>", "window=[target.name];size=500x200")
onclose(usr, "[target.name]")
return TRUE
@@ -114,6 +114,9 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
//subtypes with additional hooks for DNA and preferences.
/datum/element/flavor_text/carbon
//list of antagonists etcetera that should have nothing to do with people's snowflakes.
var/static/list/i_dont_even_know_who_you_are = typecacheof(list(/datum/antagonist/abductor, /datum/antagonist/ert,
/datum/antagonist/nukeop, /datum/antagonist/wizard))
/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE)
if(!iscarbon(target))
@@ -122,6 +125,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
if(. == ELEMENT_INCOMPATIBLE)
return
RegisterSignal(target, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, .proc/update_dna_flavor_text)
RegisterSignal(target, COMSIG_MOB_ANTAG_ON_GAIN, .proc/on_antag_gain)
if(ishuman(target))
RegisterSignal(target, COMSIG_HUMAN_PREFS_COPIED_TO, .proc/update_prefs_flavor_text)
RegisterSignal(target, COMSIG_HUMAN_HARDSET_DNA, .proc/update_dna_flavor_text)
@@ -129,7 +133,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
/datum/element/flavor_text/carbon/Detach(mob/living/carbon/C)
. = ..()
UnregisterSignal(C, list(COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, COMSIG_HUMAN_PREFS_COPIED_TO, COMSIG_HUMAN_HARDSET_DNA, COMSIG_HUMAN_ON_RANDOMIZE))
UnregisterSignal(C, list(COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, COMSIG_MOB_ANTAG_ON_GAIN, COMSIG_HUMAN_PREFS_COPIED_TO, COMSIG_HUMAN_HARDSET_DNA, COMSIG_HUMAN_ON_RANDOMIZE))
/datum/element/flavor_text/carbon/proc/update_dna_flavor_text(mob/living/carbon/C)
texts_by_atom[C] = C.dna.features["flavor_text"]
@@ -144,3 +148,9 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
/datum/element/flavor_text/carbon/proc/unset_flavor(mob/living/carbon/user)
texts_by_atom[user] = ""
/datum/element/flavor_text/carbon/proc/on_antag_gain(mob/living/carbon/user, datum/antagonist/antag)
if(is_type_in_typecache(antag, i_dont_even_know_who_you_are))
texts_by_atom[user] = ""
if(user.dna)
user.dna.features["flavor_text"] = ""
+17 -2
View File
@@ -1,15 +1,21 @@
/datum/element/ghost_role_eligibility
element_flags = ELEMENT_DETACH
element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE
id_arg_index = 3
var/list/timeouts = list()
var/list/mob/eligible_mobs = list()
var/penalizing = FALSE
var/free_ghost = FALSE
/datum/element/ghost_role_eligibility/Attach(datum/target,penalize = FALSE)
/datum/element/ghost_role_eligibility/Attach(datum/target,penalize = FALSE,free_ghosting = FALSE, penalize_on_ghost = FALSE)
. = ..()
if(!ismob(target))
return ELEMENT_INCOMPATIBLE
penalizing = penalize_on_ghost
free_ghost = free_ghosting
var/mob/M = target
if(!(M in eligible_mobs))
eligible_mobs += M
RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/get_ghost_flags)
if(penalize) //penalizing them from making a ghost role / midround antag comeback right away.
var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES
var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES
@@ -32,6 +38,7 @@
. = ..()
if(M in eligible_mobs)
eligible_mobs -= M
UnregisterSignal(M, COMSIG_MOB_GHOSTIZE)
/datum/element/ghost_role_eligibility/proc/get_all_ghost_role_eligible(silent = FALSE)
var/list/candidates = list()
@@ -56,3 +63,11 @@
if(!silent && M.client)
to_chat(M, "<span class='warning'>You are unable to reenter the round[timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(timeout - world.realtime)]" : ""].</span>")
return FALSE
/datum/element/ghost_role_eligibility/proc/get_ghost_flags()
. = 0
if(!penalizing)
. |= COMPONENT_DO_NOT_PENALIZE_GHOSTING
if(free_ghost)
. |= COMPONENT_FREE_GHOSTING
return .
+6
View File
@@ -76,6 +76,7 @@
lefthand_file = 'icons/mob/animals_held_lh.dmi'
icon_state = ""
w_class = WEIGHT_CLASS_BULKY
dynamic_hair_suffix = ""
var/mob/living/held_mob
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/target, worn_state, alt_worn, right_hand, left_hand, slots = NONE)
@@ -162,6 +163,11 @@
L.visible_message("<span class='warning'>[held_mob] escapes from [L]!</span>", "<span class='warning'>[held_mob] escapes your grip!</span>")
release()
/obj/item/clothing/head/mob_holder/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
if(!ishuman(M)) //monkeys holding monkeys holding monkeys...
return FALSE
return ..()
/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
var/atom/location = loc
if(!loc)
+54
View File
@@ -0,0 +1,54 @@
/datum/element/spellcasting //allows to cast certain spells or skip requirements.
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
var/cast_flags
var/cast_slots
var/list/users_by_item = list()
var/list/stacked_spellcasting_by_user = list()
/datum/element/spellcasting/Attach(datum/target, _flags, _slots)
. = ..()
if(isitem(target))
RegisterSignal(target, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(target, COMSIG_ITEM_DROPPED, .proc/on_drop)
else if(ismob(target))
RegisterSignal(target, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast)
stacked_spellcasting_by_user[target]++
else
return ELEMENT_INCOMPATIBLE
cast_flags = _flags
cast_slots = _slots
/datum/element/spellcasting/Detach(datum/target)
. = ..()
UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_MOB_SPELL_CAST_CHECK))
if(users_by_item[target])
var/mob/user = users_by_item[target]
stacked_spellcasting_by_user[user]--
if(!stacked_spellcasting_by_user[user])
stacked_spellcasting_by_user -= user
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
else if(ismob(target))
stacked_spellcasting_by_user[target]--
if(!stacked_spellcasting_by_user[target])
stacked_spellcasting_by_user -= target
/datum/element/spellcasting/proc/on_equip(datum/source, mob/equipper, slot)
if(!(slot in cast_slots))
return
users_by_item[source] = equipper
if(!stacked_spellcasting_by_user[equipper])
RegisterSignal(equipper, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast)
stacked_spellcasting_by_user[equipper]++
/datum/element/spellcasting/proc/on_drop(datum/source, mob/user)
if(!users_by_item[source])
return
users_by_item -= source
stacked_spellcasting_by_user[user]--
if(!stacked_spellcasting_by_user[user])
stacked_spellcasting_by_user -= user
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
/datum/element/spellcasting/proc/on_cast(mob/caster, obj/effect/proc_holder/spell)
return cast_flags
+1 -1
View File
@@ -15,4 +15,4 @@
/datum/element/sword_point/proc/point(datum/source, atom/target, mob/user, proximity_flag, params)
if(!proximity_flag && ismob(target))
user.visible_message("<span class='notice'>[user] points the tip of [source] at [target].</span>", "<span class='notice'>You point the tip of [src] at [target].</span>")
user.visible_message("<span class='notice'>[user] points the tip of [source] at [target].</span>", "<span class='notice'>You point the tip of [source] at [target].</span>")
+1 -1
View File
@@ -73,7 +73,7 @@
var/list/atoms_cache = output_atoms
var/sound/S = sound(soundfile)
if(direct)
S.channel = open_sound_channel()
S.channel = SSsounds.random_available_channel()
S.volume = volume
for(var/i in 1 to atoms_cache.len)
var/atom/thing = atoms_cache[i]
+1 -1
View File
@@ -37,7 +37,7 @@
D.apply_damage(damage, STAMINA, affecting, armor_block)
log_combat(A, D, "punched (boxing) ")
if(D.getStaminaLoss() > 100)
if(D.getStaminaLoss() > 100 && istype(D.mind?.martial_art, /datum/martial_art/boxing))
var/knockout_prob = (D.getStaminaLoss() + rand(-15,15))*0.75
if((D.stat != DEAD) && prob(knockout_prob))
D.visible_message("<span class='danger'>[A] has knocked [D] out with a haymaker!</span>", \
+2 -2
View File
@@ -63,11 +63,11 @@
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
if((D.mobility_flags & MOBILITY_STAND))
D.apply_damage(10, BRUTE, BODY_ZONE_HEAD)
D.DefaultCombatKnockdown(50)
D.DefaultCombatKnockdown(50, override_hardstun = 0.01, override_stamdmg = 0)
D.adjustStaminaLoss(40) //A cit specific change form the tg port to really punish anyone who tries to stand up
D.visible_message("<span class='warning'>[A] kicks [D] in the head, sending them face first into the floor!</span>", \
"<span class='userdanger'>You are kicked in the head by [A], sending you crashing to the floor!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
if(!(D.mobility_flags & MOBILITY_STAND))
else if(!(D.mobility_flags & MOBILITY_STAND))
D.apply_damage(5, BRUTE, BODY_ZONE_HEAD)
D.adjustStaminaLoss(40)
D.drop_all_held_items()
+20
View File
@@ -18,6 +18,8 @@
var/datum/action/drop/drop = new/datum/action/drop()
/datum/martial_art/wrestling/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(!can_use(A, D))
return 0
switch(streak)
if("drop")
streak = ""
@@ -448,6 +450,8 @@
/datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
if(!can_use(A,D))
return ..()
if(A.pulling == D || A == D) // don't stun grab yoursel
return FALSE
A.start_pulling(D)
@@ -476,3 +480,19 @@
if(H.get_item_by_slot(SLOT_BELT) == src)
style.remove(H)
return
//Subtype of wrestling, reserved for the wrestling belts found in the holodeck
/datum/martial_art/wrestling/holodeck
name = "Holodeck Wrestling"
/obj/item/storage/belt/champion/wrestling/holodeck
name = "Holodeck Wrestling Belt"
style = new /datum/martial_art/wrestling/holodeck
//Make sure that moves can only be used on people wearing the holodeck belt
/datum/martial_art/wrestling/holodeck/can_use(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(!(istype(D.mind?.martial_art, /datum/martial_art/wrestling/holodeck)))
return 0
else
return ..()
-1
View File
@@ -470,7 +470,6 @@
/datum/objective/steal,
/datum/objective/download,
/datum/objective/nuclear,
/datum/objective/capture,
/datum/objective/absorb,
/datum/objective/custom
)
+9
View File
@@ -31,6 +31,7 @@
//MUT_EXTRA - A mutation that is in the mutations tab, and can be given and taken away through though the DNA console. Has a 0 before it's name in the mutation section of the dna console
//MUT_OTHER Cannot be interacted with by players through normal means. I.E. wizards mutate
var/list/conflicts //any mutations that might conflict. put mutation typepath defines in here. make sure to enter it both ways (so that A conflicts with B, and B with A)
var/can_chromosome = CHROMOSOME_NONE //can we take chromosomes? 0: CHROMOSOME_NEVER never, 1:CHROMOSOME_NONE yeah, 2: CHROMOSOME_USED no, already have one
var/chromosome_name //purely cosmetic
var/modified = FALSE //ugly but we really don't want chromosomes and on_acquiring to overlap and apply double the powers
@@ -60,6 +61,14 @@
return TRUE
if(limb_req && !H.get_bodypart(limb_req))
return TRUE
for(var/M in H.dna.mutations)//check for conflicting powers
var/datum/mutation/human/mewtayshun = M
if(LAZYLEN(mewtayshun.conflicts))
for(var/cons in mewtayshun.conflicts)
var/datum/mutation/human/conflicter = cons
if(conflicter == type)
to_chat(H, "<span class='warning'>You feel your genes resisting something.</span>")
return TRUE
owner = H
dna = H.dna
dna.mutations += src
+7 -10
View File
@@ -41,7 +41,7 @@
desc = "You can breathe fire at a target."
school = "evocation"
charge_max = 600
clothes_req = FALSE
clothes_req = NONE
range = 20
base_icon_state = "fireball"
action_icon_state = "fireball0"
@@ -121,7 +121,7 @@
name = "Convoke Void" //magic the gathering joke here
desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly."
school = "evocation"
clothes_req = FALSE
clothes_req = NONE
charge_max = 600
invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!"
invocation_type = "shout"
@@ -155,7 +155,7 @@
dropmessage = "You let the electricity from your hand dissipate."
hand_path = /obj/item/melee/touch_attack/shock
charge_max = 400
clothes_req = FALSE
clothes_req = NONE
action_icon_state = "zap"
/obj/item/melee/touch_attack/shock
@@ -211,7 +211,7 @@
name = "Remember the Scent"
desc = "Get a scent off of the item you're currently holding to track it. With an empty hand, you'll track the scent you've remembered."
charge_max = 100
clothes_req = FALSE
clothes_req = NONE
range = -1
include_user = TRUE
action_icon_state = "nose"
@@ -289,8 +289,7 @@
/obj/effect/proc_holder/spell/self/self_amputation
name = "Drop a limb"
desc = "Concentrate to make a random limb pop right off your body."
clothes_req = FALSE
human_req = FALSE
clothes_req = NONE
charge_max = 100
action_icon_state = "autotomy"
@@ -327,8 +326,7 @@
/obj/effect/proc_holder/spell/self/lay_genetic_web
name = "Lay Web"
desc = "Drops a web. Only you will be able to traverse your web easily, making it pretty good for keeping you safe."
clothes_req = FALSE
human_req = FALSE
clothes_req = NONE
charge_max = 4 SECONDS //the same time to lay a web
action_icon = 'icons/mob/actions/actions_genetic.dmi'
action_icon_state = "lay_web"
@@ -369,8 +367,7 @@
/obj/effect/proc_holder/spell/self/tongue_spike
name = "Launch spike"
desc = "Shoot your tongue out in the direction you're facing, embedding it and dealing damage until they remove it."
clothes_req = FALSE
human_req = TRUE
clothes_req = NONE
charge_max = 100
action_icon = 'icons/mob/actions/actions_genetic.dmi'
action_icon_state = "spike"
+4 -2
View File
@@ -75,20 +75,21 @@
quality = POSITIVE
difficulty = 16
instability = 5
conflicts = list(GIGANTISM)
locked = TRUE // Default intert species for now, so locked from regular pool.
/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.transform = owner.transform.Scale(1, 0.8)
owner.pass_flags |= PASSTABLE
passtable_on(owner, GENETIC_MUTATION)
owner.visible_message("<span class='danger'>[owner] suddenly shrinks!</span>", "<span class='notice'>Everything around you seems to grow..</span>")
/datum/mutation/human/dwarfism/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.transform = owner.transform.Scale(1, 1.25)
owner.pass_flags &= ~PASSTABLE
passtable_off(owner, GENETIC_MUTATION)
owner.visible_message("<span class='danger'>[owner] suddenly grows!</span>", "<span class='notice'>Everything around you seems to shrink..</span>")
@@ -333,6 +334,7 @@
desc = "The cells within the subject spread out to cover more area, making the subject appear larger."
quality = MINOR_NEGATIVE
difficulty = 12
conflicts = list(DWARFISM)
/datum/mutation/human/gigantism/on_acquiring(mob/living/carbon/human/owner)
if(..())
+5 -3
View File
@@ -18,7 +18,6 @@
name = "Asteroid 1"
description = "I-spy with my little eye, something beginning with R."
/datum/map_template/ruin/space/asteroid2
id = "asteroid2"
suffix = "asteroid2.dmm"
@@ -187,6 +186,7 @@
name = "Abandoned Teleporter"
description = "In space construction the teleporter is often the first system brought online. \
This lonely half built teleporter is a sign of a proposed structure that for one reason or another just never got built."
always_place = TRUE
/datum/map_template/ruin/space/crashedclownship
id = "crashedclownship"
@@ -268,6 +268,7 @@
suffix = "whiteshipdock.dmm"
name = "Whiteship Dock"
description = "An abandoned but functional vessel parked in deep space, ripe for the taking."
always_place = TRUE
/datum/map_template/ruin/space/cat_experiments
id = "meow"
@@ -287,6 +288,7 @@
suffix = "hilbertshoteltestingsite.dmm"
name = "Hilbert Research Facility"
description = "A research facility of great bluespace discoveries. Long since abandoned, willingly or not..."
/datum/map_template/ruin/space/augmentation
id = "augmentationfacility"
suffix = "augmentationfacility.dmm"
@@ -376,13 +378,13 @@
id = "roid8"
suffix = "roid8.dmm"
name = "Dead wizard Roid"
description = "Mineral asteroid. Ft. Dead wizard and toilet paradox bag."
description = "Mineral asteroid. Ft. Dead wizard and toilet wand."
/datum/map_template/ruin/spacenearstation/roid9
id = "roid9"
suffix = "roid9.dmm"
name = "Monitoring Roid"
description = "Mineral asteroid. Ft. Station monitoring, syndie toolbox and erp."
description = "Mineral asteroid. Ft. Station monitoring, toolbox and erp."
/datum/map_template/ruin/spacenearstation/roid10
id = "roid10"
+1
View File
@@ -90,6 +90,7 @@
/datum/status_effect/staggered
id = "staggered"
blocks_sprint = TRUE
alert_type = null
/datum/status_effect/staggered/on_creation(mob/living/new_owner, set_duration)
if(isnum(set_duration))
-8
View File
@@ -88,14 +88,6 @@
if(quirk_holder)
quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
/datum/quirk/libido
name = "Nymphomania"
desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
value = 0
mob_trait = TRAIT_PERMABONER
gain_text = "<span class='notice'>You are feeling extra wild.</span>"
lose_text = "<span class='notice'>You don't feel that burning sensation anymore.</span>"
/datum/quirk/maso
name = "Masochism"
desc = "You are aroused by pain."
+201 -1
View File
@@ -324,6 +324,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Service Hallway"
icon_state = "hall_service"
/area/hallway/secondary/civilian
name = "Civilian Wing"
icon_state = "hallFS"
//Command
/area/bridge
@@ -1046,7 +1051,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Monastery Garden"
icon_state = "hydro"
//Science
/area/science
@@ -1393,3 +1397,199 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/fitness/pool
name = "Pool Area"
icon_state = "pool"
/area/crew_quarters/dorms/blue
name = "Blue Dorms"
icon_state = "Sleep"
nightshift_public_area = NIGHTSHIFT_AREA_NONE
/area/crew_quarters/dorms/purple
name = "Purple Dorms"
icon_state = "Sleep"
nightshift_public_area = NIGHTSHIFT_AREA_NONE
/area/crew_quarters/lounge/jazz
name = "Jazz Lounge"
icon_state = "yellow"
ambientsounds = list('sound/ambience/ambidet1.ogg','sound/ambience/ambidet2.ogg')
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
/area/crew_quarters/fitness/recreation
name = "Recreation Area"
icon_state = "fitness"
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
/area/crew_quarters/fitness/cogpool
name = "Pool"
icon_state = "fitness"
clockwork_warp_fail = "Pool's closed."
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
/area/crew_quarters/barbershop
name = "Barbershop"
icon_state = "blue"
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
/area/crew_quarters/observatory
name = "Observatory"
icon_state = "Sleep"
//Engineering
/area/engine/teg_hot
name = "Hot Loop"
icon_state = "red"
/area/engine/teg_cold
name = "Cold Loop"
icon_state = "blue"
/area/engine/workshop
name = "Engineering Workshop"
icon_state = "engine"
/area/security/courtroom/jury
name = "Jury Room"
icon_state = "courtroom"
/area/quartermaster/miningdock/airless
name = "Mining Dock"
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
valid_territory = FALSE
outdoors = TRUE
ambientsounds = SPACE
blob_allowed = FALSE //While part of the station, what good will it do you?
/area/quartermaster/miningdock/airless/no_grav
name = "Mining Dock"
icon_state = "mining"
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
valid_territory = FALSE
outdoors = TRUE
ambientsounds = SPACE
blob_allowed = FALSE //While part of the station, what good will it do you?
/area/janitor/aux
name = "Auxiliary Custodial Closet"
icon_state = "janitor"
flags_1 = NONE
/area/hydroponics/lobby
name = "Hydroponics Lobby"
icon_state = "hydro"
//Storage
/area/storage/emergency/generic
name = "Emergency Storage"
icon_state = "emergencystorage"
//Construction
/area/construction
name = "Construction Area"
icon_state = "yellow"
ambientsounds = ENGINEERING
/area/construction/secondary
name = "Secondary Construction Area"
icon_state = "yellow"
/area/construction/minisat_exterior
name = "Minisat Exterior"
icon_state = "yellow"
/area/construction/mining/aux_base
name = "Auxiliary Base Construction"
icon_state = "yellow"
/area/construction/mining/aux_base/closet
name = "Auxiliary Closet Construction"
icon_state = "yellow"
/area/construction/supplyshuttle
name = "Supply Shuttle"
icon_state = "yellow"
/area/construction/quarters
name = "Engineers' Quarters"
icon_state = "yellow"
/area/construction/qmaint
name = "Maintenance"
icon_state = "yellow"
/area/construction/hallway
name = "Hallway"
icon_state = "yellow"
/area/construction/solars
name = "Solar Panels"
icon_state = "yellow"
/area/construction/solarscontrol
name = "Solar Panel Control"
icon_state = "yellow"
/area/construction/storage
name = "Construction Site Storage"
icon_state = "yellow"
/area/construction/storage/wing
name = "Storage Wing"
icon_state = "storage_wing"
//Routers
/area/router
name = "Router"
icon_state = "yellow"
ambientsounds = ENGINEERING
/area/router/service
name = "Service Router"
icon_state = "green"
/area/router/public
name = "Public Router"
icon_state = "yellow"
/area/router/sec
name = "Security Router"
icon_state = "blue"
/area/router/medsci
name = "MedSci Router"
icon_state = "yellow"
/area/router/eva
name = "EVA Router"
icon_state = "yellow"
/area/router/air
name = "Airbridge Router"
icon_state = "red"
/area/router/eng
name = "Engineering Router"
icon_state = "yellow"
/area/router/aux
name = "Routing System"
icon_state = "yellow"
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
always_unpowered = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
valid_territory = FALSE
outdoors = TRUE
ambientsounds = SPACE
blob_allowed = FALSE //While part of the station, what good will it do you?
+1
View File
@@ -63,6 +63,7 @@
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
/// Color on minimaps, if it's null (which is default) it makes one at random.
var/minimap_color
+3
View File
@@ -99,6 +99,9 @@
/area/holodeck/rec_center/winterwonderland
name = "Holodeck - Winter Wonderland"
/area/holodeck/rec_center/wrestlingarena
name = "Holodeck - Wrestling Arena"
// Bad programs
/area/holodeck/rec_center/burn
+61 -8
View File
@@ -694,14 +694,64 @@
/atom/vv_get_dropdown()
. = ..()
. += "---"
var/turf/curturf = get_turf(src)
if (curturf)
.["Jump to"] = "?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]"
.["Modify Transform"] = "?_src_=vars;[HrefToken()];modtransform=[REF(src)]"
.["Add reagent"] = "?_src_=vars;[HrefToken()];addreagent=[REF(src)]"
.["Trigger EM pulse"] = "?_src_=vars;[HrefToken()];emp=[REF(src)]"
.["Trigger explosion"] = "?_src_=vars;[HrefToken()];explode=[REF(src)]"
VV_DROPDOWN_OPTION("", "---------")
if(!ismovableatom(src))
var/turf/curturf = get_turf(src)
if(curturf)
. += "<option value='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]'>Jump To</option>"
VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRANSFORM, "Modify Transform")
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
/atom/vv_do_topic(list/href_list)
. = ..()
if(href_list[VV_HK_ADD_REAGENT] && check_rights(R_VAREDIT))
if(!reagents)
var/amount = input(usr, "Specify the reagent size of [src]", "Set Reagent Size", 50) as num
if(amount)
create_reagents(amount)
if(reagents)
var/chosen_id = choose_reagent_id(usr)
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", reagents.maximum_volume) as num
if(amount)
reagents.add_reagent(chosen_id, amount)
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")
message_admins("<span class='notice'>[key_name(usr)] has added [amount] units of [chosen_id] to [src]</span>")
if(href_list[VV_HK_TRIGGER_EXPLOSION] && check_rights(R_FUN))
usr.client.cmd_admin_explosion(src)
if(href_list[VV_HK_TRIGGER_EMP] && check_rights(R_FUN))
usr.client.cmd_admin_emp(src)
if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT))
var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate")
var/matrix/M = transform
switch(result)
if("Scale")
var/x = input(usr, "Choose x mod","Transform Mod") as null|num
var/y = input(usr, "Choose y mod","Transform Mod") as null|num
if(!isnull(x) && !isnull(y))
transform = M.Scale(x,y)
if("Translate")
var/x = input(usr, "Choose x mod","Transform Mod") as null|num
var/y = input(usr, "Choose y mod","Transform Mod") as null|num
if(!isnull(x) && !isnull(y))
transform = M.Translate(x,y)
if("Rotate")
var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num
if(!isnull(angle))
transform = M.Turn(angle)
if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT))
var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text
if(newname)
vv_auto_rename(newname)
/atom/vv_get_header()
. = ..()
var/refid = REF(src)
. += "[VV_HREF_TARGETREF(refid, VV_HK_AUTO_RENAME, "<b id='name'>[src]</b>")]"
. += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir' id='dir'>[dir2text(dir) || dir]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
/atom/proc/drop_location()
var/atom/L = loc
@@ -709,6 +759,9 @@
return null
return L.AllowDrop() ? L : L.drop_location()
/atom/proc/vv_auto_rename(newname)
name = newname
/atom/Entered(atom/movable/AM, atom/oldLoc)
SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc)
+33 -3
View File
@@ -39,6 +39,37 @@
var/zfalling = FALSE
/// Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE]
var/blocks_emissive = FALSE
///Internal holder for emissive blocker object, do not use directly use blocks_emissive
var/atom/movable/emissive_blocker/em_block
/atom/movable/Initialize(mapload)
. = ..()
switch(blocks_emissive)
if(EMISSIVE_BLOCK_GENERIC)
update_emissive_block()
if(EMISSIVE_BLOCK_UNIQUE)
render_target = ref(src)
em_block = new(src, render_target)
vis_contents += em_block
/atom/movable/Destroy()
QDEL_NULL(em_block)
return ..()
/atom/movable/proc/update_emissive_block()
if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
return
if(length(managed_vis_overlays))
for(var/a in managed_vis_overlays)
var/obj/effect/overlay/vis/vs
if(vs.plane == EMISSIVE_BLOCKER_PLANE)
SSvis_overlays.remove_vis_overlay(src, list(vs))
break
SSvis_overlays.add_vis_overlay(src, icon, icon_state, EMISSIVE_BLOCKER_LAYER, EMISSIVE_BLOCKER_PLANE)
/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction)
if(!direction)
direction = DOWN
@@ -437,9 +468,8 @@
/atom/movable/vv_get_dropdown()
. = ..()
. -= "Jump to"
.["Follow"] = "?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(src)]"
.["Get"] = "?_src_=holder;[HrefToken()];admingetmovable=[REF(src)]"
. += "<option value='?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(src)]'>Follow</option>"
. += "<option value='?_src_=holder;[HrefToken()];admingetmovable=[REF(src)]'>Get</option>"
/atom/movable/proc/ex_check(ex_id)
if(!ex_id)
@@ -19,7 +19,7 @@
antag_flag = ROLE_BLOODSUCKER
false_report_weight = 1
restricted_jobs = list("AI","Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
protected_jobs = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 20
required_enemies = 2
recommended_enemies = 4
+2 -2
View File
@@ -88,13 +88,13 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
user.underwear = chosen_prof.underwear
user.undie_color = chosen_prof.undie_color
user.undershirt = chosen_prof.undershirt
user.shirt_color =chosen_prof.shirt_color
user.shirt_color = chosen_prof.shirt_color
user.socks = chosen_prof.socks
user.socks_color =chosen_prof.socks_color
chosen_dna.transfer_identity(user, 1)
user.updateappearance(mutcolor_update=1)
user.update_body()
user.update_body(TRUE)
user.domutcheck()
//vars hackery. not pretty, but better than the alternative.
+1 -1
View File
@@ -351,5 +351,5 @@ Credit where due:
/obj/item/paper/servant_primer/oui_getcontent(mob/target)
if(!is_servant_of_ratvar(target) && !isobserver(target))
return "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
return "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
return ..()
+44 -49
View File
@@ -54,16 +54,16 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
// Current storyteller
var/datum/dynamic_storyteller/storyteller = null
// Threat logging vars
/// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations
/// Target threat level right now. Events and antags will try to keep the round at this level.
var/threat_level = 0
/// Set at the beginning of the round. Spent by the mode to "purchase" rules.
var/threat = 0
/// The current antag threat. Recalculated every time a ruletype starts or ends.
var/threat = 0
/// Starting threat level, for things that increase it but can bring it back down.
var/initial_threat_level = 0
/// Things that cause a rolling threat adjustment to be displayed at roundend.
var/list/threat_tallies = list()
/// Running information about the threat. Can store text or datum entries.
var/list/threat_log = list()
var/list/threat_log = list()
/// As above, but with info such as refunds.
var/list/threat_log_verbose = list()
/// List of roundstart rules used for selecting the rules.
@@ -127,6 +127,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
var/only_ruleset_executed = FALSE
/// Antags rolled by rules so far, to keep track of and discourage scaling past a certain ratio of crew/antags especially on lowpop.
var/antags_rolled = 0
// Arbitrary threat addition, for fudging purposes.
var/added_threat = 50
/datum/game_mode/dynamic/New() // i have NO IDEA if this is the proper way to do this.
..()
@@ -150,11 +152,11 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
GLOB.dynamic_first_midround_delay_max = CONFIG_GET(number/dynamic_first_midround_delay_max)*600
/datum/game_mode/dynamic/admin_panel()
var/list/dat = list("<html><head><title>Game Mode Panel</title></head><body><h1><B>Game Mode Panel</B></h1>")
var/list/dat = list("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>Game Mode Panel</title></head><body><h1><B>Game Mode Panel</B></h1>")
dat += "Dynamic Mode <a href='?_src_=vars;[HrefToken()];Vars=[REF(src)]'>\[VV\]</A><a href='?src=\ref[src];[HrefToken()]'>\[Refresh\]</A><BR>"
dat += "Threat Level: <b>[threat_level]</b><br/>"
dat += "Target threat: <b>[threat_level]</b><br/>"
dat += "Threat to Spend: <b>[threat]</b> <a href='?src=\ref[src];[HrefToken()];adjustthreat=1'>\[Adjust\]</A> <a href='?src=\ref[src];[HrefToken()];threatlog=1'>\[View Log\]</a><br/>"
dat += "Current threat: <b>[threat]</b> <a href='?src=\ref[src];[HrefToken()];adjustthreat=1'>\[Adjust\]</A> <a href='?src=\ref[src];[HrefToken()];threatlog=1'>\[View Log\]</a><br/>"
dat += "<br/>"
dat += "Storyteller: <b>[storyteller.name]</b><br/>"
dat += "Parameters: centre = [GLOB.dynamic_curve_centre] ; width = [GLOB.dynamic_curve_width].<br/>"
@@ -172,9 +174,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
else
dat += "none.<br>"
dat += "<br>Injection Timers: (<b>[storyteller.get_injection_chance(TRUE)]%</b> chance)<BR>"
dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectlate=1'>\[Now!\]</a><BR>"
dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectmid=1'>\[Now!\]</a><BR>"
dat += "Event: [(event_injection_cooldown-world.time)>60*10 ? "[round((event_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(event_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];forceevent=1'>\[Now!\]</a><BR>"
dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];injectlate=1'>\[Now!\]</a><BR>"
dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];injectmid=1'>\[Now!\]</a><BR>"
dat += "Event: [(event_injection_cooldown-world.time)>60*10 ? "[round((event_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(event_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];forceevent=1'>\[Now!\]</a><BR>"
usr << browse(dat.Join(), "window=gamemode_panel;size=500x500")
/datum/game_mode/dynamic/Topic(href, href_list)
@@ -261,11 +263,11 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
. += "<b>Uncharted Space</b></center><BR>"
. += "Congratulations and thank you for participating in the NT 'Frontier' space program! Your station is actively orbiting a high value system far from the nearest support stations. Little is known about your region of space, and the opportunity to encounter the unknown invites greater glory. You are encouraged to elevate security as necessary to protect Nanotrasen assets."
set_security_level(SEC_LEVEL_BLUE)
if(80 to 99)
if(80 to 95)
. += "<b>Black Orbit</b></center><BR>"
. += "As part of a mandatory security protocol, we are required to inform you that as a result of your orbital pattern directly behind an astrological body (oriented from our nearest observatory), your station will be under decreased monitoring and support. It is anticipated that your extreme location and decreased surveillance could pose security risks. Avoid unnecessary risks and attempt to keep your station in one piece."
set_security_level(SEC_LEVEL_AMBER)
if(100)
if(96 to 100)
. += "<b>Impending Doom</b></center><BR>"
. += "Your station is somehow in the middle of hostile territory, in clear view of any enemy of the corporation. Your likelihood to survive is low, and station destruction is expected and almost inevitable. Secure any sensitive material and neutralize any enemy you will come across. It is important that you at least try to maintain the station.<BR>"
. += "Good luck."
@@ -330,7 +332,6 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
peaceful_percentage = round(LORENTZ_CUMULATIVE_DISTRIBUTION(relative_threat, GLOB.dynamic_curve_centre, GLOB.dynamic_curve_width), 0.01)*100
threat = threat_level
SSblackbox.record_feedback("tally","dynamic_threat",threat_level,"Initial threat level")
SSblackbox.record_feedback("tally","dynamic_threat",GLOB.dynamic_curve_centre,"Curve centre")
SSblackbox.record_feedback("tally","dynamic_threat",GLOB.dynamic_curve_width,"Curve width")
@@ -340,9 +341,10 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
storyteller = new GLOB.dynamic_storyteller_type // this is where all the initialization happens
storyteller.on_start()
SSblackbox.record_feedback("text","dynamic_storyteller",1,storyteller.name)
message_admins("Dynamic mode parameters for the round:")
message_admins("Centre is [GLOB.dynamic_curve_centre], Width is [GLOB.dynamic_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].")
message_admins("Stacking limit is [GLOB.dynamic_stacking_limit], Classic secret is [GLOB.dynamic_classic_secret ? "Enabled" : "Disabled"], High population limit is [GLOB.dynamic_high_pop_limit].")
message_admins("Dynamic mode parameters for the round:\n\
Storyteller is [storyteller.name].\n\
Centre is [GLOB.dynamic_curve_centre], Width is [GLOB.dynamic_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].\n\
Stacking limit is [GLOB.dynamic_stacking_limit], Classic secret is [GLOB.dynamic_classic_secret ? "Enabled" : "Disabled"], High population limit is [GLOB.dynamic_high_pop_limit].")
log_game("DYNAMIC: Dynamic mode parameters for the round:")
log_game("DYNAMIC: Centre is [GLOB.dynamic_curve_centre], Width is [GLOB.dynamic_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].")
log_game("DYNAMIC: Stacking limit is [GLOB.dynamic_stacking_limit], Classic secret is [GLOB.dynamic_classic_secret ? "Enabled" : "Disabled"], High population limit is [GLOB.dynamic_high_pop_limit].")
@@ -404,7 +406,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
/datum/game_mode/dynamic/post_setup(report)
update_playercounts()
for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
..()
@@ -463,7 +465,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
log_game("DYNAMIC: Additional ruleset picked successfully, now [executed_rules.len] picked. [extra_rulesets_amount] remaining.")
else
if(threat >= 50)
if(threat_level >= 50)
message_admins("DYNAMIC: Picking first roundstart ruleset failed. You should report this.")
log_game("DYNAMIC: Picking first roundstart ruleset failed. drafted_rules.len = [drafted_rules.len] and threat = [threat]/[threat_level]")
return FALSE
@@ -509,10 +511,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
drafted_rules -= starting_rule
starting_rule.trim_candidates()
var/added_threat = starting_rule.scale_up(extra_rulesets_amount, threat)
starting_rule.scale_up(extra_rulesets_amount, threat_level)
if (starting_rule.pre_execute())
spend_threat(starting_rule.cost + added_threat)
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE)
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> [starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE)
if(starting_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(starting_rule.flags & ONLY_RULESET)
@@ -534,8 +535,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
/datum/game_mode/dynamic/proc/execute_roundstart_rule(sent_rule)
var/datum/dynamic_ruleset/rule = sent_rule
if(rule.execute())
if(rule.persistent)
current_rules += rule
current_rules += rule
SSblackbox.record_feedback("associative","dynamic_rulesets",1,rule.get_blackbox_info())
return TRUE
rule.clean_up() // Refund threat, delete teams and so on.
@@ -607,8 +607,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
if ((forced || (new_rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && new_rule.cost <= threat)))
new_rule.trim_candidates()
if (new_rule.ready(forced))
spend_threat(new_rule.cost)
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> -[new_rule.cost] threat", verbose = TRUE)
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> [new_rule.cost] threat", verbose = TRUE)
if (new_rule.execute()) // This should never fail since ready() returned 1
if(new_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
@@ -617,8 +616,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
log_game("DYNAMIC: Making a call to a specific ruleset...[new_rule.name]!")
SSblackbox.record_feedback("associative","dynamic_rulesets",1,new_rule.get_blackbox_info())
executed_rules += new_rule
if (new_rule.persistent)
current_rules += new_rule
current_rules += new_rule
return TRUE
else if (forced)
log_game("DYNAMIC: The ruleset [new_rule.name] couldn't be executed due to lack of eligible players.")
@@ -629,8 +627,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
var/datum/dynamic_ruleset/rule = sent_rule
if (rule.execute())
log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
spend_threat(rule.cost)
log_threat("[rule.ruletype] [rule.name] spent [rule.cost]", verbose = TRUE)
log_threat("[rule.ruletype] [rule.name] added [rule.cost]", verbose = TRUE)
if(rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(rule.flags & ONLY_RULESET)
@@ -649,7 +646,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
return FALSE
/datum/game_mode/dynamic/process()
if (pop_last_updated < world.time - (60 SECONDS))
if (pop_last_updated < world.time - (120 SECONDS))
pop_last_updated = world.time
update_playercounts()
@@ -658,9 +655,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
current_rules -= rule
SSblackbox.record_feedback("tally","dynamic",1,"Rulesets finished")
SSblackbox.record_feedback("associative","dynamic_rulesets_finished",1,rule.get_blackbox_info())
storyteller.do_process()
if (midround_injection_cooldown < world.time)
if (GLOB.dynamic_forced_extended)
return
@@ -717,7 +714,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
current_players[CURRENT_OBSERVERS].Add(M)
continue
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
threat = storyteller.calculate_threat() + added_threat
/// Removes type from the list
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
for(var/I in type_list)
@@ -767,25 +764,23 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
SSblackbox.record_feedback("tally","dynamic",1,"Successful latejoin injections")
latejoin_injection_cooldown = storyteller.get_latejoin_cooldown() + world.time
/// Refund threat, but no more than threat_level.
/datum/game_mode/dynamic/proc/refund_threat(regain)
threat = min(threat_level,threat+regain)
SSblackbox.record_feedback("tally","dynamic_threat",regain,"Refunded threat")
log_threat("[regain] refunded. Threat is now [threat].", verbose = TRUE)
/// Generate threat and increase the threat_level if it goes beyond, capped at 100
/// Increase the threat level.
/datum/game_mode/dynamic/proc/create_threat(gain)
threat = min(100, threat+gain)
if(threat > threat_level)
threat_level = threat
SSblackbox.record_feedback("tally","dynamic_threat",gain,"Created threat")
log_threat("[gain] created. Threat is now [threat] and threat level is now [threat_level].", verbose = TRUE)
threat_level += gain
SSblackbox.record_feedback("tally","dynamic_threat",gain,"Created threat level")
log_threat("[gain] created. Threat level is now [threat_level].", verbose = TRUE)
/// Expend threat, can't fall under 0.
/// Decrease the threat level.
/datum/game_mode/dynamic/proc/remove_threat(loss)
threat_level -= loss
SSblackbox.record_feedback("tally","dynamic_threat",loss,"Removed threat level")
log_threat("[loss] removed. Threat level is now [threat_level].", verbose = TRUE)
/// Fill up more of the threat level.
/datum/game_mode/dynamic/proc/spend_threat(cost)
threat = max(threat-cost,0)
SSblackbox.record_feedback("tally","dynamic_threat",cost,"Threat spent")
log_threat("[cost] spent. Threat is now [threat].", verbose = TRUE)
added_threat += cost
SSblackbox.record_feedback("tally","dynamic_threat",cost,"Threat added")
log_threat("[cost] added. Threat is now [threat].", verbose = TRUE)
/// Turns the value generated by lorentz distribution to threat value between 0 and 100.
/datum/game_mode/dynamic/proc/lorentz_to_threat(x)
@@ -174,8 +174,8 @@
/// This is called if persistent variable is true everytime SSTicker ticks.
/datum/dynamic_ruleset/proc/rule_process()
return
return TRUE
/// Called on game mode pre_setup for roundstart rulesets.
/// Do everything you need to do before job is assigned here.
/// IMPORTANT: ASSIGN special_role HERE
@@ -201,8 +201,7 @@
/// Runs from gamemode process() if ruleset fails to start, like delayed rulesets not getting valid candidates.
/// This one only handles refunding the threat, override in ruleset to clean up the rest.
/datum/dynamic_ruleset/proc/clean_up()
mode.refund_threat(cost + (scaled_times * scaling_cost))
mode.log_threat("[ruletype] [name] refunded [cost + (scaled_times * scaling_cost)]",verbose=TRUE)
return
/// Gets weight of the ruleset
/// Note that this decreases weight if repeatable is TRUE and repeatable_weight_decrease is higher than 0
@@ -241,5 +241,5 @@
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
flags = TRAITOR_RULESET
flags = TRAITOR_RULESET | MINOR_RULESET
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 2)
@@ -106,7 +106,7 @@
if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles) && (!(M in candidates) || (M.mind.assigned_role in restricted_roles)))
job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it
var/threat = round(mode.threat_level/10)
var/threat = CLAMP(round(mode.threat_level/10),1,10)
if (job_check < required_enemies[threat])
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough enemy roles")
return FALSE
@@ -216,7 +216,7 @@
var/player_count = mode.current_players[CURRENT_LIVING_PLAYERS].len
var/antag_count = mode.current_players[CURRENT_LIVING_ANTAGS].len
var/max_traitors = round(player_count / 10) + 1
if ((antag_count < max_traitors) && prob(mode.threat_level))//adding traitors if the antag population is getting low
if ((antag_count < max_traitors) && prob(min(100,mode.threat_level)))//adding traitors if the antag population is getting low
return ..()
else
return FALSE
@@ -315,7 +315,6 @@
/datum/dynamic_ruleset/midround/from_ghosts/wizard
name = "Wizard"
config_tag = "midround_wizard"
persistent = TRUE
antag_datum = /datum/antagonist/wizard
antag_flag = ROLE_WIZARD
enemy_roles = list("Security Officer","Detective","Head of Security", "Captain")
@@ -344,7 +343,6 @@
/datum/dynamic_ruleset/midround/from_ghosts/wizard/rule_process() // i can literally copy this from are_special_antags_dead it's great
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
return FALSE
for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead()
if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard))
return FALSE
@@ -417,7 +415,7 @@
required_candidates = 1
blocking_rules = list(/datum/dynamic_ruleset/roundstart/clockcult)
weight = 4
cost = 10
cost = 20
requirements = list(101,101,101,80,60,50,50,50,50,50)
high_population_requirement = 50
repeatable = TRUE
@@ -666,9 +664,6 @@
Mind.transfer_to(Ninja)
var/datum/antagonist/ninja/ninjadatum = new
ninjadatum.helping_station = pick(TRUE,FALSE)
if(ninjadatum.helping_station)
mode.refund_threat(cost+5)
mode.log_threat("Ninja was helping station; [cost+5] cost refunded.")
Mind.add_antag_datum(ninjadatum)
if(Ninja.mind != Mind) //something has gone wrong!
@@ -802,11 +802,10 @@
/datum/dynamic_ruleset/roundstart/bloodsucker
name = "Bloodsuckers"
config_tag = "bloodsucker"
persistent = TRUE
antag_flag = ROLE_BLOODSUCKER
antag_datum = ANTAG_DATUM_BLOODSUCKER
minimum_required_age = 0
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
protected_roles = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
restricted_roles = list("Cyborg", "AI")
required_candidates = 1
weight = 2
@@ -5,17 +5,19 @@
var/list/property_weights = list() // See below.
var/curve_centre = 0 // As GLOB.dynamic_curve_centre.
var/curve_width = 1.8 // As GLOB.dynamic_curve_width.
var/forced_threat_level = -1
var/forced_threat_level = -1 // As GLOB.dynamic_forced_threat_level
/*
NO_ASSASSIN: Will not have permanent assassination targets.
WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level.
USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre.
FORCE_IF_WON: If this mode won the vote, forces it
*/
var/flags = 0
var/dead_player_weight = 1 // How much dead players matter for threat calculation
var/weight = 3 // Weights for randomly picking storyteller. Multiplied by score after voting.
var/event_frequency_lower = 6 MINUTES // How rare events will be, at least.
var/event_frequency_upper = 20 MINUTES // How rare events will be, at most.
var/pop_antag_ratio = 5 // How many non-antags there should be vs antags.
var/min_players = -1 // How many players are required for this one to start.
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
/**
@@ -39,6 +41,31 @@ Property weights are:
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
mode.event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
/datum/dynamic_storyteller/proc/calculate_threat()
var/threat = 0
for(var/datum/antagonist/A in GLOB.antagonists)
if(A?.owner?.current && A.owner.current.stat != DEAD)
threat += A.threat()
for(var/r in SSevents.running)
var/datum/round_event/R = r
threat += R.threat()
for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list)
var/turf/T = get_turf(H)
if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction))
threat += H.threat()
for(var/obj/item/phylactery/P in GLOB.poi_list)
threat += 25 // can't be giving them too much of a break
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
if (M?.mind?.assigned_role && M.stat != DEAD)
var/datum/job/J = SSjob.GetJob(M.mind.assigned_role)
if(J)
if(length(M.mind.antag_datums))
threat += J.GetThreat()
else
threat -= J.GetThreat()
threat += (mode.current_players[CURRENT_DEAD_PLAYERS].len)*dead_player_weight
return round(threat,0.1)
/datum/dynamic_storyteller/proc/do_process()
return
@@ -83,30 +110,14 @@ Property weights are:
if(mode.forced_injection)
mode.forced_injection = !dry_run
return 100
var/chance = 0
// If the high pop override is in effect, we reduce the impact of population on the antag injection chance
var/high_pop_factor = (mode.current_players[CURRENT_LIVING_PLAYERS].len >= GLOB.dynamic_high_pop_limit)
var/max_pop_per_antag = max(pop_antag_ratio,15 - round(mode.threat_level/10) - round(mode.current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
if (!mode.current_players[CURRENT_LIVING_ANTAGS].len)
chance += 80 // No antags at all? let's boost those odds!
else
var/current_pop_per_antag = mode.current_players[CURRENT_LIVING_PLAYERS].len / mode.current_players[CURRENT_LIVING_ANTAGS].len
if (current_pop_per_antag > max_pop_per_antag)
chance += min(50, 25+10*(current_pop_per_antag-max_pop_per_antag))
else
chance += 25-10*(max_pop_per_antag-current_pop_per_antag)
if (mode.current_players[CURRENT_DEAD_PLAYERS].len > mode.current_players[CURRENT_LIVING_PLAYERS].len)
chance -= 30 // More than half the crew died? ew, let's calm down on antags
if (mode.threat > 70)
chance += 15
if (mode.threat < 30)
chance -= 15
return round(max(0,chance))
var/threat_perc = mode.threat/mode.threat_level
return round(max(0,100*(1-(threat_perc*threat_perc*threat_perc))))
/datum/dynamic_storyteller/proc/roundstart_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level) && mode.threat >= rule.cost) // If we got the population and threat required
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level)) // If we got the population and threat required
rule.candidates = mode.candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
@@ -114,32 +125,43 @@ Property weights are:
for(var/property in property_weights)
if(property in rule.property_weights) // just treat it as 0 if it's not in there
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult
return drafted_rules
/datum/dynamic_storyteller/proc/midround_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules)
// if there are antags OR the rule is an antag rule, antag_acceptable will be true.
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
rule.trim_candidates()
var/threat_weight = 1
if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
pick this particular ruleset.
Let's use a toy example: there's 60 threat level and 10 threat spent.
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
is 2.26 times as likely to be picked, all other things considered.
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
*/
threat_weight = 1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
else if(mode.threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
return drafted_rules
/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer)
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level - mode.threat))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
@@ -150,56 +172,56 @@ Property weights are:
rule.candidates = list(newPlayer)
rule.trim_candidates()
var/threat_weight = 1
if(!(rule.flags & MINOR_RULESET))
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
else if(mode.threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
return drafted_rules
/datum/dynamic_storyteller/proc/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost)
if(rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
else if(mode.threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
return drafted_rules
/datum/dynamic_storyteller/cowabunga
/datum/dynamic_storyteller/chaotic
name = "Chaotic"
config_tag = "chaotic"
curve_centre = 10
desc = "High chaos modes. Revs, wizard, clock cult. Multiple antags at once. Chaos is kept up all round."
property_weights = list("extended" = -1, "chaos" = 10)
property_weights = list("extended" = -1, "chaos" = 1)
weight = 1
event_frequency_lower = 2 MINUTES
event_frequency_upper = 10 MINUTES
flags = WAROPS_ALWAYS_ALLOWED
pop_antag_ratio = 4
min_players = 40
var/refund_cooldown = 0
/datum/dynamic_storyteller/cowabunga/get_midround_cooldown()
/datum/dynamic_storyteller/chaotic/do_process()
if(refund_cooldown < world.time)
mode.create_threat(20)
mode.log_threat("Chaotic storyteller ramped up the chaos. Threat level is now [mode.threat_level].")
refund_cooldown = world.time + 20 MINUTES
/datum/dynamic_storyteller/chaotic/get_midround_cooldown()
return ..() / 4
/datum/dynamic_storyteller/cowabunga/get_latejoin_cooldown()
/datum/dynamic_storyteller/chaotic/get_latejoin_cooldown()
return ..() / 4
/datum/dynamic_storyteller/cowabunga/do_process()
if(refund_cooldown < world.time)
mode.refund_threat(40)
mode.log_threat("Chaotic storyteller refunded 40 threat. Threat is now [mode.threat].")
refund_cooldown = world.time + 1200 SECONDS
/datum/dynamic_storyteller/team
name = "Teamwork"
config_tag = "teamwork"
@@ -207,6 +229,7 @@ Property weights are:
curve_centre = 2
curve_width = 1.5
weight = 2
min_players = 30
flags = WAROPS_ALWAYS_ALLOWED
property_weights = list("valid" = 3, "trust" = 5)
@@ -223,23 +246,97 @@ Property weights are:
flags = WAROPS_ALWAYS_ALLOWED
property_weights = list("valid" = 1, "conversion" = 20)
/datum/dynamic_storyteller/classic
/datum/dynamic_storyteller/random
name = "Random"
config_tag = "random"
desc = "No special weights attached. Anything goes."
weight = 4
curve_width = 4
pop_antag_ratio = 7
flags = USE_PREF_WEIGHTS
weight = 1
desc = "No weighting at all; every ruleset has the same chance of happening. Cooldowns vary wildly. As random as it gets."
/datum/dynamic_storyteller/random/on_start()
..()
GLOB.dynamic_forced_threat_level = rand(0,100)
/datum/dynamic_storyteller/random/get_midround_cooldown()
return rand(GLOB.dynamic_midround_delay_min/2, GLOB.dynamic_midround_delay_max*2)
/datum/dynamic_storyteller/random/get_event_cooldown()
return rand(GLOB.dynamic_event_delay_min/2, GLOB.dynamic_event_delay_max*2)
/datum/dynamic_storyteller/random/get_latejoin_cooldown()
return rand(GLOB.dynamic_latejoin_delay_min/2, GLOB.dynamic_latejoin_delay_max*2)
/datum/dynamic_storyteller/random/get_injection_chance()
return 50 // i would do rand(0,100) but it's actually the same thing when you do the math
/datum/dynamic_storyteller/random/calculate_threat()
return 0 // what IS threat
/datum/dynamic_storyteller/random/roundstart_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level)) // If we got the population and threat required
rule.candidates = mode.candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/random/midround_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
rule.trim_candidates()
if (rule.ready())
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/random/latejoin_draft(mob/living/carbon/human/newPlayer)
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
// No stacking : only one round-ender, unless threat level > stacking_limit.
if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(rule.flags & HIGHLANDER_RULESET && mode.highlander_executed)
continue
rule.candidates = list(newPlayer)
rule.trim_candidates()
if (rule.ready())
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/random/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
if(rule.ready())
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/story
name = "Story"
config_tag = "story"
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies."
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies. Has a buildup-climax-falling action threat curve."
weight = 2
curve_width = 2
pop_antag_ratio = 7
property_weights = list("story_potential" = 10)
property_weights = list("story_potential" = 2)
/datum/dynamic_storyteller/story/calculate_threat()
var/current_time = (world.time / SSautotransfer.targettime)*180
mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1)
..()
/datum/dynamic_storyteller/classic
name = "Classic"
config_tag = "classic"
desc = "No special antagonist weights. Good variety, but not like random. Uses your chaos preference to weight."
flags = USE_PREF_WEIGHTS
/datum/dynamic_storyteller/suspicion
name = "Intrigue"
@@ -247,8 +344,8 @@ Property weights are:
desc = "Antags that instill distrust in the crew. Traitors, bloodsuckers."
weight = 2
curve_width = 2
pop_antag_ratio = 7
property_weights = list("trust" = -5)
dead_player_weight = 2
property_weights = list("trust" = -3)
/datum/dynamic_storyteller/liteextended
name = "Calm"
@@ -256,10 +353,10 @@ Property weights are:
desc = "Low-chaos round. Few antags. No conversion."
curve_centre = -3
curve_width = 0.5
flags = NO_ASSASSIN
flags = NO_ASSASSIN | FORCE_IF_WON
weight = 1
pop_antag_ratio = 10
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
dead_player_weight = 5
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
/datum/dynamic_storyteller/no_antag
name = "Extended"
@@ -267,7 +364,7 @@ Property weights are:
desc = "No standard antags. Threatening events may still spawn."
curve_centre = -5
curve_width = 0.5
flags = NO_ASSASSIN
flags = NO_ASSASSIN | FORCE_IF_WON
weight = 1
property_weights = list("extended" = 2)
+3 -3
View File
@@ -323,7 +323,7 @@
var/free_tickets = CONFIG_GET(number/default_antag_tickets)
//Max extra tickets you can use
var/additional_tickets = CONFIG_GET(number/max_tickets_per_roll)
var/list/ckey_to_mind = list() //this is admittedly shitcode but I'm webediting
var/list/prev_tickets = SSpersistence.antag_rep //cache for hyper-speed in theory. how many tickets someone has stored
var/list/curr_tickets = list() //how many tickets someone has for *this* antag roll, so with the free tickets
@@ -337,7 +337,7 @@
continue
curr_tickets[mind_ckey] = amount
ckey_to_mind[mind_ckey] = M //make sure we can look them up after picking
if(!return_list) //return a single guy
var/ckey
if(length(curr_tickets))
@@ -584,7 +584,7 @@
//By default nuke just ends the round
/datum/game_mode/proc/OnNukeExplosion(off_station)
nuke_off_station = off_station
if(off_station < 2)
if(!off_station)
station_was_nuked = TRUE //Will end the round on next check.
//Additional report section in roundend report
+3 -1
View File
@@ -4,6 +4,7 @@
can_coexist_with_others = FALSE
job_rank = ROLE_GANG
antagpanel_category = "Gang"
threat = 2
var/hud_type = "gangster"
var/message_name = "Gangster"
var/datum/team/gang/gang
@@ -167,6 +168,7 @@
name = "Gang boss"
hud_type = "gang_boss"
message_name = "Leader"
threat = 10
/datum/antagonist/gang/boss/on_gain()
..()
@@ -474,4 +476,4 @@
#undef MAXIMUM_RECALLS
#undef INFLUENCE_INTERVAL
#undef INFLUENCE_INTERVAL
+2 -2
View File
@@ -663,7 +663,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
if(count)
target_amount = count
update_explanation_text()
/*
/datum/objective/capture
name = "capture"
var/captured_amount = 0
@@ -709,7 +709,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
if(count)
target_amount = count
update_explanation_text()
*/
//Changeling Objectives
/datum/objective/absorb
+5 -2
View File
@@ -77,14 +77,14 @@
/datum/sabotage_objective/processing/supermatter/can_run()
return (locate(/obj/machinery/power/supermatter_crystal) in GLOB.machines)
/*
/datum/sabotage_objective/station_integrity
name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal."
sabotage_type = "integrity"
/datum/sabotage_objective/station_integrity/check_conditions()
return 5-(max(SSticker.station_integrity*4,320)/80)
*/
/datum/sabotage_objective/cloner
name = "Destroy all Nanotrasen cloning machines."
sabotage_type = "cloner"
@@ -98,6 +98,9 @@
special_equipment = list(/obj/item/aiModule/syndicate)
excludefromjob = list("Chief Engineer","Research Director","Head of Personnel","Captain","Chief Medical Officer","Head Of Security")
/datum/sabotage_objective/ai_law/can_run()
return length(active_ais())
/datum/sabotage_objective/ai_law/check_conditions()
for (var/i in GLOB.ai_list)
var/mob/living/silicon/ai/aiPlayer = i
+33 -23
View File
@@ -207,11 +207,14 @@
/obj/machinery/sleeper/ui_data()
var/list/data = list()
var/chemical_list = list()
var/blood_percent = 0
data["occupied"] = occupant ? 1 : 0
data["open"] = state_open
data["efficiency"] = efficiency
data["current_vol"] = reagents.total_volume
data["tot_capacity"] = reagents.maximum_volume
data["blood_levels"] = blood_percent
data["blood_status"] = "Patient either has no blood, or does not require it to function."
data["chemical_list"] = chemical_list
data["chems"] = list()
for(var/chem in available_chems)
@@ -247,10 +250,13 @@
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
data["occupant"]["reagents"] = list()
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
if(mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
chemical_list += list(list("name" = R.name, "volume" = R.volume))
else
chemical_list = "Patient has no reagents."
data["occupant"]["failing_organs"] = list()
var/mob/living/carbon/C = mob_occupant
if(C)
@@ -259,21 +265,25 @@
continue
data["occupant"]["failing_organs"] += list(list("name" = Or.name))
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
var/blood_id = C.get_blood_id()
if(blood_id)
data["occupant"]["blood"] = list() // We can start populating this list.
var/blood_type = C.dna.blood_type
if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(R)
blood_type = R.name
else
blood_type = blood_id
data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio)
data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume
data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE
data["occupant"]["blood"]["bloodType"] = blood_type
if(istype(C)) //Non-carbons shouldn't be able to enter sleepers, but this is to prevent runtimes if something ever breaks
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
var/blood_id = C.get_blood_id()
var/blood_warning = ""
if(blood_percent < 80)
blood_warning = "Patient has low blood levels."
if(blood_percent < 60)
blood_warning = "Patient has DANGEROUSLY low blood levels."
if(blood_id)
var/blood_type = C.dna.blood_type
if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(R)
blood_type = R.name
else
blood_type = blood_id
data["blood_status"] = "Patient has [blood_type] type blood. [blood_warning]"
data["blood_levels"] = blood_percent
return data
/obj/machinery/sleeper/ui_act(action, params)
@@ -309,14 +319,14 @@
if(allowed(usr))
if(!is_operational())
return
reagents.remove_reagent(chem, 10)
reagents.remove_reagent(chem, 1000)
return
if(chem in available_chems)
if(!is_operational())
return
/*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in
if(R.purity < 0.8)*/
reagents.remove_reagent(chem, 10)
reagents.remove_reagent(chem, 1000)
else
visible_message("<span class='warning'>Access Denied.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+2 -2
View File
@@ -240,10 +240,10 @@
to_chat(AI, "<b>[U]</b> holds <a href='?_src_=usr;show_paper=1;'>\a [itemname]</a> up to one of your cameras ...")
else
to_chat(AI, "<b><a href='?src=[REF(AI)];track=[html_encode(U.name)]'>[U]</a></b> holds <a href='?_src_=usr;show_paper=1;'>\a [itemname]</a> up to one of your cameras ...")
AI.last_paper_seen = "<HTML><HEAD><TITLE>[itemname]</TITLE></HEAD><BODY><TT>[info]</TT></BODY></HTML>"
AI.last_paper_seen = "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[itemname]</TITLE></HEAD><BODY><TT>[info]</TT></BODY></HTML>"
else if (O.client && O.client.eye == src)
to_chat(O, "[U] holds \a [itemname] up to one of the cameras ...")
O << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", itemname, info), text("window=[]", itemname))
O << browse(text("<HTML><HEAD<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", itemname, info), text("window=[]", itemname))
return
else if(istype(I, /obj/item/camera_bug))
+2
View File
@@ -180,6 +180,7 @@
//Get the clone body ready
maim_clone(H)
ADD_TRAIT(H, TRAIT_MUTATION_STASIS, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
@@ -369,6 +370,7 @@
return
REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_MUTATION_STASIS, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, CLONING_POD_TRAIT)
+1 -1
View File
@@ -62,7 +62,7 @@
if(stat & BROKEN)
overlay_state = "[icon_state]_broken"
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha=128)
/obj/machinery/computer/power_change()
..()
@@ -159,6 +159,8 @@
if(CHECK_BITFIELD(obj_flags, EMAGGED) && !exploding_hell)
exploding_hell = TRUE
explode_EVERYTHING()
if(QDELETED(src))
return
if(mine_sound)
switch(rand(1,3)) //Play every time a mine is hit
if(1)
@@ -367,10 +369,10 @@
var/row_limit = rows-1
var/column_limit = columns-1
var/mine_limit_v2 = mine_limit
if(rows > 11)
row_limit = 10
if(columns > 11)
column_limit = 10
if(rows > 21)
row_limit = 20
if(columns > 21)
column_limit = 20
if(mine_limit > (rows*columns) * 0.25)
mine_limit_v2 = 24
message_admins("[key_name_admin(user)] failed an emagged Minesweeper arcade and has unleashed an explosion armageddon of size [row_limit],[column_limit] around [ADMIN_LOOKUPFLW(user.loc)]!")
@@ -378,15 +380,38 @@
explosion(loc, 2, 5, 10, 15) //Thought you could survive by putting as few mines as possible, huh??
else
explosion(loc, 1, 3, rand(1,5), rand(1,10))
for(var/y69=y-row_limit;y69<y+row_limit;y69++) //Create a shitton of explosions in irl turfs if we lose, it will probably kill us
for(var/x69=x-column_limit;x69<x+column_limit;x69++)
if(prob(mine_limit_v2)) //Probability of explosion happening, according to how many mines were on the board... up to a limit
var/explosionloc
explosionloc = locate(y69,x69,z)
explosion(explosionloc, 0, rand(1,2),rand(1,5),rand(3,10), adminlog = FALSE)
var/list/targets = list()
var/cur_y = y - round(row_limit * 0.5, 1)
var/starting_row = 1
if(cur_y < 1)
starting_row -= cur_y - 1
cur_y = 1
var/start_x = x - round(column_limit * 0.5, 1)
var/starting_column = 1
if(start_x < 1)
starting_column -= start_x - 1
start_x = 1
for(var/row in starting_row to length(table)) //translate the mines locations into actual turf coordinates.
if(!locate(cur_y, start_x, z))
break
var/cur_x = start_x
for(var/column in starting_column to length(table[row]))
var/coord_value = table[row][column]
if(coord_value == 10 || coord_value == 0) //there is a mine in here.
var/turf/T = locate(cur_y, cur_x, z)
if(!T)
break
targets += T
cur_x++
cur_y++
var/num_explosions = 0
for(var/T in shuffle(targets)) //Create a shitton of explosions in irl turfs if we lose, it will probably kill us
addtimer(CALLBACK(GLOBAL_PROC, /proc/explosion, T, 0, rand(1,2),rand(1,5),rand(3,10), FALSE), 15 * ++num_explosions)
if(num_explosions == mine_limit_v2)
return
#undef MINESWEEPERIMG
#undef MINESWEEPER_GAME_MAIN_MENU
#undef MINESWEEPER_GAME_PLAYING
#undef MINESWEEPER_GAME_LOST
#undef MINESWEEPER_GAME_WON
#undef MINESWEEPER_GAME_WON
+1 -1
View File
@@ -94,4 +94,4 @@
overlay_state = "alert:0"
. |= overlay_state
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha=128)
+8 -5
View File
@@ -11,16 +11,19 @@
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R)
if(!istype(R))
return 0
return FALSE
if(isAI(user))
if (R.connected_ai != user)
return 0
return FALSE
if(iscyborg(user))
if (R != user)
return 0
return FALSE
if(R.scrambledcodes)
return 0
return 1
return FALSE
if (hasSiliconAccessInArea(user) && !issilicon(user))
if (!Adjacent(user))
return FALSE
return TRUE
/obj/machinery/computer/robotics/ui_interact(mob/user)
. = ..()
@@ -94,4 +94,4 @@
overlay_state = "alert:0"
. |= overlay_state
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha=128)
+56 -1
View File
@@ -1,13 +1,68 @@
/obj/machinery/door/poddoor/shutters
gender = PLURAL
name = "shutters"
desc = "Heavy duty metal shutters that open mechanically."
desc = "Mechanical metal shutters operated by a button with a magnetic seal, keeping them airtight."
icon = 'icons/obj/doors/shutters.dmi'
layer = SHUTTER_LAYER
closingLayer = SHUTTER_LAYER
armor = list("melee" = 20, "bullet" = 20, "laser" = 20, "energy" = 75, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70)
damage_deflection = 20
max_integrity = 100
/obj/machinery/door/poddoor/shutters/preopen
icon_state = "open"
density = FALSE
opacity = 0
// The below shutters are the original ones from the TG codebase. They are remaining as "secure" shutters. If anyone wants to improve their animation, feel free.
// The original shutters are now shutters_old.dmi; copy the naming format of the files into new a new .dmi to add new shutters that work with the poddoor code for animating the doors.
// Originally, the shutters were reskins of blast doors. Eighty hits with the Cap's sabre to destroy one shutter is far too powerful considering shutters cannot be deconstructed (yet).
// If you're a mapper and want super strong shutter, use the 'old' ones.
/obj/machinery/door/poddoor/shutters/old
name = "strong shutters"
desc = "These shutters have an armoured frame; it looks like plasteel. These shutters look robust enough to survive explosions."
icon = 'icons/obj/doors/shutters_old.dmi'
icon_state = "closed"
armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 75, "bomb" = 30, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70)
max_integrity = 300
/obj/machinery/door/poddoor/shutters/old/preopen
icon_state = "open"
density = FALSE
opacity = 0
// End of old shutter stuff. Credit for the old shutter sprites to TG.
/obj/machinery/door/poddoor/shutters/radiation
name = "radiation shutters"
desc = "Lead-lined shutters painted yellow with a radioactive hazard symbol on it. Blocks out most radiation"
icon = 'icons/obj/doors/shutters_radiation.dmi'
icon_state = "closed"
rad_insulation = 0.2
/obj/machinery/door/poddoor/shutters/radiation/preopen
icon_state = "open"
density = FALSE
opacity = 0
rad_insulation = 1
/obj/machinery/door/poddoor/shutters/radiation/do_animate(animation)
..()
switch(animation)
if("opening")
rad_insulation = 1
if("closing")
rad_insulation = 0.2
/obj/machinery/door/poddoor/shutters/window
name = "windowed shutters"
desc = "Mechanical shutters that have some form of plastic window in them, allowing you to see through the shutters at all times."
icon = 'icons/obj/doors/shutters_window.dmi'
icon_state = "closed"
opacity = 0
glass = 1
/obj/machinery/door/poddoor/shutters/window/preopen
icon_state = "open"
density = FALSE
+5 -5
View File
@@ -77,23 +77,23 @@
if(is_station_level(z))
. += "fire_[GLOB.security_level]"
SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", EMISSIVE_LAYER, EMISSIVE_PLANE, dir)
else
. += "fire_[SEC_LEVEL_GREEN]"
SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", EMISSIVE_LAYER, EMISSIVE_PLANE, dir)
var/area/A = src.loc
A = A.loc
if(!detecting || !A.fire)
. += "fire_off"
SSvis_overlays.add_vis_overlay(src, icon, "fire_off", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
SSvis_overlays.add_vis_overlay(src, icon, "fire_off", EMISSIVE_LAYER, EMISSIVE_PLANE, dir)
else if(obj_flags & EMAGGED)
. += "fire_emagged"
SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", EMISSIVE_LAYER, EMISSIVE_PLANE, dir)
else
. += "fire_on"
SSvis_overlays.add_vis_overlay(src, icon, "fire_on", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
SSvis_overlays.add_vis_overlay(src, icon, "fire_on", EMISSIVE_LAYER, EMISSIVE_PLANE, dir)
/obj/machinery/firealarm/emp_act(severity)
. = ..()
@@ -141,7 +141,7 @@
if(href_list["photo"])
var/mob/M = usr
M << browse_rsc(picture.picture_image, "pda_photo.png")
M << browse("<html><head><title>PDA Photo</title></head>" \
M << browse("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>PDA Photo</title></head>" \
+ "<body style='overflow:hidden;margin:0;text-align:center'>" \
+ "<img src='pda_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />" \
+ "</body></html>", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y];can-close=true")
+3 -1
View File
@@ -42,7 +42,9 @@
/obj/mecha/combat/honker/get_stats_html()
var/output = {"<html>
<head><title>[src.name] data</title>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>[src.name] data</title>
<style>
body {color: #00ff00; background: #32CD32; font-family:"Courier",monospace; font-size: 12px;}
hr {border: 1px solid #0f0; color: #fff; background-color: #000;}
@@ -125,6 +125,7 @@
return
return {"<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>[patient] statistics</title>
<script language='javascript' type='text/javascript'>
[js_byjax]
@@ -259,7 +260,8 @@
. = ..()
create_reagents(max_volume, NO_REACT)
syringes = new
known_reagents = list(/datum/reagent/medicine/epinephrine = "Epinephrine", /datum/reagent/medicine/charcoal = "Charcoal")
known_reagents = list(/datum/reagent/medicine/epinephrine = "Epinephrine", /datum/reagent/medicine/charcoal = "Charcoal", /datum/reagent/medicine/prussian_blue = "Prussian Blue", \
/datum/reagent/medicine/dexalin = "Dexalin", /datum/reagent/medicine/insulin = "Insulin", /datum/reagent/medicine/kelotane = "Kelotane", /datum/reagent/medicine/bicaridine = "Bicaridine")
processed_reagents = new
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/detach()
@@ -390,6 +392,7 @@
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_reagents_page()
var/output = {"<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>Reagent Synthesizer</title>
<script language='javascript' type='text/javascript'>
[js_byjax]
+2 -1
View File
@@ -297,7 +297,8 @@
left_part += "<hr><a href='?src=[REF(src)];screen=main'>Return</a>"
dat = {"<html>
<head>
<title>[name]</title>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>[name] data</title>
<style>
.res_name {font-weight: bold; text-transform: capitalize;}
.red {color: #f00;}
+1 -1
View File
@@ -11,7 +11,7 @@
/obj/machinery/computer/mecha/ui_interact(mob/user)
. = ..()
var/dat = "<html><head><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
var/dat = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
if(screen == 0)
dat += "<h3>Tracking beacons data</h3>"
var/list/trackerlist = list()
+8 -3
View File
@@ -5,7 +5,9 @@
/obj/mecha/proc/get_stats_html()
. = {"<html>
<head><title>[src.name] data</title>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>[name] data</title>
<style>
body {color: #00ff00; background: #000000; font-family:"Lucida Console",monospace; font-size: 12px;}
hr {border: 1px solid #0f0; color: #0f0; background-color: #0f0;}
@@ -149,7 +151,7 @@
/obj/mecha/proc/get_log_html()
. = "<html><head><title>[src.name] Log</title></head><body style='font: 13px 'Courier', monospace;'>"
. = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[src.name] Log</title></head><body style='font: 13px 'Courier', monospace;'>"
for(var/list/entry in log)
. += {"<div style='font-weight: bold;'>[entry["time"]] [time2text(entry["date"],"MMM DD")] [entry["year"]]</div>
<div style='margin-left:15px; margin-bottom:10px;'>[entry["message"]]</div>
@@ -162,7 +164,9 @@
if(!id_card || !user)
return
. = {"<html>
<head><style>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style>
h1 {font-size:15px;margin-bottom:4px;}
body {color: #00ff00; background: #000000; font-family:"Courier New", Courier, monospace; font-size: 12px;}
a {color:#0f0;}
@@ -192,6 +196,7 @@
return
. = {"<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style>
body {color: #00ff00; background: #000000; font-family:"Courier New", Courier, monospace; font-size: 12px;}
a {padding:2px 5px; background:#32CD32;color:#000;display:block;margin:2px;text-align:center;text-decoration:none;}

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