This commit is contained in:
Ghommie
2020-01-04 13:35:05 +01:00
489 changed files with 24949 additions and 14497 deletions
+8 -9
View File
@@ -9,13 +9,12 @@
#define META_GAS_FUSION_POWER 7
//ATMOS
//stuff you should probably leave well alone!
#define R_IDEAL_GAS_EQUATION 8.31446261815324 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa
#define TCMB 2.7 // -270.3degC
#define TCRYO 225 // -48.15degC
#define T0C 273.15 // 0degC
#define T20C 293.15 // 20degC
#define STEFANBOLTZMANN (5.670373*10e-8) // W/(m^2*K^4)
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa
#define TCMB 2.7 // -270.3degC
#define TCRYO 225 // -48.15degC
#define T0C 273.15 // 0degC
#define T20C 293.15 // 20degC
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity
@@ -150,9 +149,9 @@
//OPEN TURF ATMOS
#define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15" //the default air mix that open turfs spawn
#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms
#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms
#define AIRLESS_ATMOS "TEMP=2.7" //space
#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs
#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs
#define BURNMIX_ATMOS "o2=2500;plasma=5000;TEMP=370" //used in the holodeck burn test program
//ATMOSPHERICS DEPARTMENT GAS TANK TURFS
+9 -1
View File
@@ -109,8 +109,16 @@
#define MEDIHOUND_SLEEPER (1<<0)
#define EATING_NOISES (1<<1)
#define DIGESTION_NOISES (1<<2)
#define BREAST_ENLARGEMENT (1<<3)
#define PENIS_ENLARGEMENT (1<<4)
#define FORCED_FEM (1<<5)
#define FORCED_MASC (1<<6)
#define HYPNO (1<<7)
#define NEVER_HYPNO (1<<8)
#define NO_APHRO (1<<9)
#define NO_ASS_SLAP (1<<10)
#define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES)
#define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES|BREAST_ENLARGEMENT|PENIS_ENLARGEMENT)
//component stuff
#define COMSIG_COMBAT_TOGGLED "combatmode_toggled" //called by combat mode toggle on all equipped items. args: (mob/user, combatmode)
+4
View File
@@ -54,6 +54,10 @@
#define EXAMINE_POSITION_BEFORE 2
//End positions
#define COMPONENT_EXNAME_CHANGED 1
#define COMSIG_ATOM_UPDATE_ICON "atom_update_icon" //from base of atom/update_icon(): ()
#define COMSIG_ATOM_NO_UPDATE_ICON_STATE 1
#define COMSIG_ATOM_NO_UPDATE_OVERLAYS 2
#define COMSIG_ATOM_UPDATE_OVERLAYS "atom_update_overlays" //from base of atom/update_overlays(): (list/new_overlays)
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom)
#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
#define COMPONENT_ATOM_BLOCK_EXIT 1
+14
View File
@@ -0,0 +1,14 @@
#define CURRENT_LIVING_PLAYERS 1
#define CURRENT_LIVING_ANTAGS 2
#define CURRENT_DEAD_PLAYERS 3
#define CURRENT_OBSERVERS 4
#define NO_ASSASSIN (1<<0)
#define WAROPS_ALWAYS_ALLOWED (1<<1)
#define ONLY_RULESET (1<<0)
#define HIGHLANDER_RULESET (1<<1)
#define TRAITOR_RULESET (1<<2)
#define MINOR_RULESET (1<<3)
#define RULESET_STOP_PROCESSING 1
+2
View File
@@ -224,6 +224,8 @@ GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list(
#define isorgan(A) (istype(A, /obj/item/organ))
#define isclothing(A) (istype(A, /obj/item/clothing))
GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
/obj/item/pen,
/obj/item/screwdriver,
+8 -3
View File
@@ -38,8 +38,6 @@ require only minor tweaks.
#define ZTRAIT_SPACE_RUINS "Space Ruins"
#define ZTRAIT_LAVA_RUINS "Lava Ruins"
#define ZTRAIT_ISOLATED_RUINS "Isolated Ruins" //Placing ruins on z levels with this trait will use turf reservation instead of usual placement.
// prevents certain turfs from being stripped by a singularity
#define ZTRAIT_PLANET "Planet"
// number - bombcap is multiplied by this before being applied to bombs
#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier"
@@ -60,11 +58,18 @@ require only minor tweaks.
// CROSSLINKED - mixed in with the cross-linked space pool
#define CROSSLINKED "Cross"
// string - type path of the z-level's baseturf (defaults to space)
#define ZTRAIT_BASETURF "Baseturf"
// default trait definitions, used by SSmapping
#define ZTRAITS_CENTCOM list(ZTRAIT_CENTCOM = TRUE)
#define ZTRAITS_STATION list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_STATION = TRUE)
#define ZTRAITS_SPACE list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_SPACE_RUINS = TRUE)
#define ZTRAITS_LAVALAND list(ZTRAIT_MINING = TRUE, ZTRAIT_LAVA_RUINS = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 5)
#define ZTRAITS_LAVALAND list(\
ZTRAIT_MINING = TRUE, \
ZTRAIT_LAVA_RUINS = TRUE, \
ZTRAIT_BOMBCAP_MULTIPLIER = 5, \
ZTRAIT_BASETURF = /turf/open/lava/smooth/lava_land_surface)
#define ZTRAITS_REEBE list(ZTRAIT_REEBE = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 0.5)
#define DL_NAME "name"
+2 -1
View File
@@ -7,4 +7,5 @@
#define MARTIALART_MUSHPUNCH "mushroom punch"
#define MARTIALART_KRAVMAGA "krav maga"
#define MARTIALART_CQC "CQC"
#define MARTIALART_PLASMAFIST "plasma fist"
#define MARTIALART_PLASMAFIST "plasma fist"
#define MARTIALART_RISINGBASS "rising bass"
+2
View File
@@ -504,3 +504,5 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define FOURSPACES "&nbsp;&nbsp;&nbsp;&nbsp;"
#define CRYOMOBS 'icons/obj/cryo_mobs.dmi'
#define CANT_REENTER_ROUND -1
+1
View File
@@ -41,6 +41,7 @@
#define VOICEBOX_TOGGLABLE (1<<6) //The voicebox in this clothing can be toggled.
#define VOICEBOX_DISABLED (1<<7) //The voicebox is currently turned off.
#define IGNORE_HAT_TOSS (1<<8) //Hats with negative effects when worn (i.e the tinfoil hat).
#define SCAN_REAGENTS (1<<9) // Allows helmets and glasses to scan reagents.
// Flags for the organ_flags var on /obj/item/organ
+6 -3
View File
@@ -134,6 +134,7 @@
#define TRAIT_NORUNNING "norunning" // You walk!
#define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites.
#define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat.
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
//non-mob traits
@@ -160,17 +161,16 @@
#define TRAIT_TAGGER "tagger"
#define TRAIT_PHOTOGRAPHER "photographer"
#define TRAIT_MUSICIAN "musician"
#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
#define TRAIT_NYMPHO "nymphomania"
#define TRAIT_MASO "masochism"
#define TRAIT_EXHIBITIONIST "exhibitionist"
#define TRAIT_HIGH_BLOOD "high_blood"
#define TRAIT_PHARMA "hepatic_pharmacokinesis"
#define TRAIT_PARA "paraplegic"
#define TRAIT_EMPATH "empath"
#define TRAIT_FRIENDLY "friendly"
#define TRAIT_ASSBLASTUSA "assblastusa"
#define TRAIT_CULT_EYES "cult_eyes"
#define TRAIT_AUTO_CATCH_ITEM "auto_catch_item"
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
#define TRAIT_FREESPRINT "free_sprinting"
@@ -193,6 +193,7 @@
#define ABSTRACT_ITEM_TRAIT "abstract-item"
#define STATUS_EFFECT_TRAIT "status-effect"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
#define GHOSTROLE_TRAIT "ghostrole"
// unique trait sources, still defines
#define STATUE_MUTE "statue"
@@ -226,7 +227,9 @@
#define NINJA_SUIT_TRAIT "ninja-suit"
#define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant"
#define SLEEPING_CARP_TRAIT "sleeping_carp"
#define RISING_BASS_TRAIT "rising_bass"
#define ABDUCTOR_ANTAGONIST "abductor-antagonist"
#define NUKEOP_ANTAGONIST "nukeop-antagonist"
#define MADE_UNCLONEABLE "made-uncloneable"
#define NUKEOP_TRAIT "nuke-op"
#define DEATHSQUAD_TRAIT "deathsquad"
+6
View File
@@ -0,0 +1,6 @@
#define PLURALITY_VOTING 0
#define APPROVAL_VOTING 1
#define RANKED_CHOICE_VOTING 2
#define SCORE_VOTING 3
GLOBAL_LIST_INIT(vote_score_options,list("Bad","Poor","Acceptable","Good","Great"))
+2
View File
@@ -157,6 +157,8 @@
WRITE_LOG(GLOB.config_error_log, text)
SEND_TEXT(world.log, text)
/proc/log_mapping(text)
WRITE_LOG(GLOB.world_map_error_log, text)
/* For logging round startup. */
/proc/start_log(log)
+1 -1
View File
@@ -447,7 +447,7 @@
var/list/candidates = list()
for(var/mob/dead/observer/G in GLOB.player_list)
if(G.reenter_round_timeout < world.realtime)
if(G.can_reenter_round(TRUE))
candidates += G
return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates)
-3
View File
@@ -12,6 +12,3 @@
#define is_reserved_level(z) SSmapping.level_trait(z, ZTRAIT_RESERVED)
#define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY)
// If true, the singularity cannot strip away asteroid turf on this Z
#define is_planet_level(z) SSmapping.level_trait(z, ZTRAIT_PLANET)
+3 -2
View File
@@ -20,8 +20,6 @@
else
return "000"
#define UNDIE_COLORABLE(U) (U?.has_color)
/proc/random_underwear(gender)
if(!GLOB.underwear_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/bottom, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
@@ -76,6 +74,8 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/insect_wings, GLOB.insect_wings_list)
if(!GLOB.insect_fluffs_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/insect_fluff, GLOB.insect_fluffs_list)
if(!GLOB.insect_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/insect_markings, GLOB.insect_markings_list)
//CIT CHANGES - genitals and such
if(!GLOB.cock_shapes_list.len)
@@ -151,6 +151,7 @@
"caps" = pick(GLOB.caps_list),
"insect_wings" = pick(GLOB.insect_wings_list),
"insect_fluff" = "None",
"insect_markings" = pick(GLOB.insect_markings_list),
"taur" = "None",
"mam_body_markings" = pick(snowflake_markings_list),
"mam_ears" = pick(snowflake_ears_list),
+3
View File
@@ -19,6 +19,9 @@
var/list/mob_data = list()
if(isnewplayer(m))
continue
if (m.client && m.client.prefs && m.client.prefs.auto_ooc)
if (!(m.client.prefs.chat_toggles & CHAT_OOC))
m.client.prefs.chat_toggles ^= CHAT_OOC
if(m.mind)
if(m.stat != DEAD && !isbrain(m) && !iscameramob(m))
num_survivors++
-10
View File
@@ -758,16 +758,6 @@ GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
/obj/item/stack/rods,
/obj/item/pipe)))
/proc/can_embed(obj/item/W)
if(W.get_sharpness())
return 1
if(is_pointed(W))
return 1
if(is_type_in_typecache(W, GLOB.can_embed_types))
return 1
/*
Checks if that loc and dir has an item on the wall
*/
+1
View File
@@ -143,6 +143,7 @@ GLOBAL_LIST_INIT(bitfields, list(
"VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE,
"VOICEBOX_DISABLED" = VOICEBOX_DISABLED,
"IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS,
"SCAN_REAGENTS" = SCAN_REAGENTS
),
"tesla_flags" = list(
"TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE,
+1
View File
@@ -37,6 +37,7 @@ GLOBAL_LIST_EMPTY(deco_wings_list)
GLOBAL_LIST_EMPTY(r_wings_list)
GLOBAL_LIST_EMPTY(insect_wings_list)
GLOBAL_LIST_EMPTY(insect_fluffs_list)
GLOBAL_LIST_EMPTY(insect_markings_list)
GLOBAL_LIST_EMPTY(caps_list)
GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites
@@ -115,5 +115,6 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/clothing/shoes/kindleKicks = 1,
/obj/item/autosurgeon/penis = 1,
/obj/item/autosurgeon/testicles = 1,
/obj/item/storage/box/marshmallow = 2,
"" = 3
))
+2
View File
@@ -48,3 +48,5 @@ GLOBAL_LIST_EMPTY(sortedAreas)
GLOBAL_LIST_EMPTY_TYPED(areas_by_type, /area)
GLOBAL_LIST_EMPTY(all_abstract_markers)
GLOBAL_LIST_EMPTY(stationroom_landmarks) //List of all spawns for stationrooms
+2
View File
@@ -28,6 +28,8 @@ GLOBAL_VAR(world_job_debug_log)
GLOBAL_PROTECT(world_job_debug_log)
GLOBAL_VAR(world_virus_log)
GLOBAL_PROTECT(world_virus_log)
GLOBAL_VAR(world_map_error_log)
GLOBAL_PROTECT(world_map_error_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
+18
View File
@@ -195,89 +195,107 @@
// Language menu
using = new /obj/screen/language_menu
using.screen_loc = ui_borg_language_menu
using.hud = src
static_inventory += using
//AI core
using = new /obj/screen/ai/aicore()
using.screen_loc = ui_ai_core
using.hud = src
static_inventory += using
//Camera list
using = new /obj/screen/ai/camera_list()
using.screen_loc = ui_ai_camera_list
using.hud = src
static_inventory += using
//Track
using = new /obj/screen/ai/camera_track()
using.screen_loc = ui_ai_track_with_camera
using.hud = src
static_inventory += using
//Camera light
using = new /obj/screen/ai/camera_light()
using.screen_loc = ui_ai_camera_light
using.hud = src
static_inventory += using
//Crew Monitoring
using = new /obj/screen/ai/crew_monitor()
using.screen_loc = ui_ai_crew_monitor
using.hud = src
static_inventory += using
//Crew Manifest
using = new /obj/screen/ai/crew_manifest()
using.screen_loc = ui_ai_crew_manifest
using.hud = src
static_inventory += using
//Alerts
using = new /obj/screen/ai/alerts()
using.screen_loc = ui_ai_alerts
using.hud = src
static_inventory += using
//Announcement
using = new /obj/screen/ai/announcement()
using.screen_loc = ui_ai_announcement
using.hud = src
static_inventory += using
//Shuttle
using = new /obj/screen/ai/call_shuttle()
using.screen_loc = ui_ai_shuttle
using.hud = src
static_inventory += using
//Laws
using = new /obj/screen/ai/state_laws()
using.screen_loc = ui_ai_state_laws
using.hud = src
static_inventory += using
//PDA message
using = new /obj/screen/ai/pda_msg_send()
using.screen_loc = ui_ai_pda_send
using.hud = src
static_inventory += using
//PDA log
using = new /obj/screen/ai/pda_msg_show()
using.screen_loc = ui_ai_pda_log
using.hud = src
static_inventory += using
//Take image
using = new /obj/screen/ai/image_take()
using.screen_loc = ui_ai_take_picture
using.hud = src
static_inventory += using
//View images
using = new /obj/screen/ai/image_view()
using.screen_loc = ui_ai_view_images
using.hud = src
static_inventory += using
//Medical/Security sensors
using = new /obj/screen/ai/sensors()
using.screen_loc = ui_ai_sensor
using.hud = src
static_inventory += using
//Multicamera mode
using = new /obj/screen/ai/multicam()
using.screen_loc = ui_ai_multicam
using.hud = src
static_inventory += using
//Add multicamera camera
using = new /obj/screen/ai/add_multicam()
using.screen_loc = ui_ai_add_multicam
using.hud = src
static_inventory += using
+17 -6
View File
@@ -43,18 +43,20 @@
using.icon = ui_style
using.icon_state = "swap_1"
using.screen_loc = ui_swaphand_position(owner,1)
using.hud = src
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand_position(owner,2)
using.hud = src
static_inventory += using
using = new /obj/screen/act_intent/alien()
using.icon_state = mymob.a_intent
static_inventory += using
action_intent = using
action_intent = new /obj/screen/act_intent/alien()
action_intent.icon_state = mymob.a_intent
action_intent.hud = src
static_inventory += action_intent
if(isalienhunter(mymob))
var/mob/living/carbon/alien/humanoid/hunter/H = mymob
@@ -64,43 +66,52 @@
using = new/obj/screen/language_menu
using.screen_loc = ui_alien_language_menu
using.hud = src
static_inventory += using
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
using.hud = src
static_inventory += using
using = new /obj/screen/resist()
using.icon = ui_style
using.screen_loc = ui_pull_resist
using.hud = src
hotkeybuttons += using
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = ui_style
throw_icon.screen_loc = ui_drop_throw
throw_icon.hud = src
hotkeybuttons += throw_icon
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_pull_resist
static_inventory += pull_icon
//begin indicators
healths = new /obj/screen/healths/alien()
healths.hud = src
infodisplay += healths
alien_plasma_display = new /obj/screen/alien/plasma_display()
alien_plasma_display.hud = src
infodisplay += alien_plasma_display
if(!isalienqueen(mymob))
alien_queen_finder = new /obj/screen/alien/alien_queen_finder
alien_queen_finder.hud = src
infodisplay += alien_queen_finder
zone_select = new /obj/screen/zone_sel/alien()
zone_select.update_icon(mymob)
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+12 -6
View File
@@ -5,26 +5,32 @@
..()
var/obj/screen/using
using = new /obj/screen/act_intent/alien()
using.icon_state = mymob.a_intent
static_inventory += using
action_intent = using
action_intent = new /obj/screen/act_intent/alien()
action_intent.icon_state = mymob.a_intent
action_intent.hud = src
static_inventory += action_intent
healths = new /obj/screen/healths/alien()
healths.hud = src
infodisplay += healths
alien_queen_finder = new /obj/screen/alien/alien_queen_finder()
alien_queen_finder.hud = src
infodisplay += alien_queen_finder
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_alien.dmi'
pull_icon.update_icon(mymob)
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_pull_resist
hotkeybuttons += pull_icon
using = new/obj/screen/language_menu
using.screen_loc = ui_alien_language_menu
using.hud = src
static_inventory += using
zone_select = new /obj/screen/zone_sel/alien()
zone_select.update_icon(mymob)
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
+9
View File
@@ -133,17 +133,21 @@
blobpwrdisplay.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
blobpwrdisplay.layer = ABOVE_HUD_LAYER
blobpwrdisplay.plane = ABOVE_HUD_PLANE
blobpwrdisplay.hud = src
infodisplay += blobpwrdisplay
healths = new /obj/screen/healths/blob()
healths.hud = src
infodisplay += healths
using = new /obj/screen/blob/BlobHelp()
using.screen_loc = "WEST:6,NORTH:-3"
using.hud = src
static_inventory += using
using = new /obj/screen/blob/JumpToNode()
using.screen_loc = ui_inventory
using.hud = src
static_inventory += using
using = new /obj/screen/blob/JumpToCore()
@@ -153,18 +157,22 @@
using = new /obj/screen/blob/Blobbernaut()
using.screen_loc = ui_belt
using.hud = src
static_inventory += using
using = new /obj/screen/blob/ResourceBlob()
using.screen_loc = ui_back
using.hud = src
static_inventory += using
using = new /obj/screen/blob/NodeBlob()
using.screen_loc = ui_hand_position(2)
using.hud = src
static_inventory += using
using = new /obj/screen/blob/FactoryBlob()
using.screen_loc = ui_hand_position(1)
using.hud = src
static_inventory += using
using = new /obj/screen/blob/ReadaptChemical()
@@ -174,4 +182,5 @@
using = new /obj/screen/blob/RelocateCore()
using.screen_loc = ui_storage2
using.hud = src
static_inventory += using
+2
View File
@@ -3,7 +3,9 @@
..()
blobpwrdisplay = new /obj/screen/healths/blob/naut/core()
blobpwrdisplay.hud = src
infodisplay += blobpwrdisplay
healths = new /obj/screen/healths/blob/naut()
healths.hud = src
infodisplay += healths
+3 -1
View File
@@ -5,9 +5,11 @@
..()
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_construct_pull
static_inventory += pull_icon
healths = new /obj/screen/healths/construct()
healths.hud = src
infodisplay += healths
+10 -2
View File
@@ -9,11 +9,13 @@
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drone_drop
using.hud = src
static_inventory += using
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_drone_pull
static_inventory += pull_icon
@@ -26,6 +28,7 @@
using.screen_loc = ui_swaphand_position(owner,1)
using.layer = HUD_LAYER
using.plane = HUD_PLANE
using.hud = src
static_inventory += using
using = new /obj/screen/inventory()
@@ -35,14 +38,19 @@
using.screen_loc = ui_swaphand_position(owner,2)
using.layer = HUD_LAYER
using.plane = HUD_PLANE
using.hud = src
static_inventory += using
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
zone_select.hud = src
zone_select.update_icon()
lingchemdisplay = new /obj/screen/ling/chems()
lingchemdisplay.hud = src
devilsouldisplay = new /obj/screen/devil/soul_counter
devilsouldisplay.hud = src
infodisplay += devilsouldisplay
+10 -2
View File
@@ -6,11 +6,13 @@
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drone_drop
using.hud = src
static_inventory += using
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_drone_pull
static_inventory += pull_icon
@@ -20,12 +22,14 @@
using.icon = ui_style
using.icon_state = "swap_1_m"
using.screen_loc = ui_swaphand_position(owner,1)
using.hud = src
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand_position(owner,2)
using.hud = src
static_inventory += using
if(mymob.possible_a_intents)
@@ -36,20 +40,24 @@
action_intent = new /obj/screen/act_intent
action_intent.icon = ui_style
action_intent.icon_state = mymob.a_intent
action_intent.hud = src
static_inventory += action_intent
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
using = new /obj/screen/craft
using.icon = ui_style
using.hud = src
static_inventory += using
using = new /obj/screen/area_creator
using.icon = ui_style
using.hud = src
static_inventory += using
mymob.client.screen = list()
+6
View File
@@ -50,26 +50,32 @@
using = new /obj/screen/ghost/jumptomob()
using.screen_loc = ui_ghost_jumptomob
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/orbit()
using.screen_loc = ui_ghost_orbit
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/reenter_corpse()
using.screen_loc = ui_ghost_reenter_corpse
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/teleport()
using.screen_loc = ui_ghost_teleport
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/pai()
using.screen_loc = ui_ghost_pai
using.hud = src
static_inventory += using
using = new /obj/screen/language_menu
using.icon = ui_style
using.hud = src
static_inventory += using
/datum/hud/ghost/show_hud(version = 0, mob/viewmob)
+6
View File
@@ -4,26 +4,32 @@
var/obj/screen/using
healths = new /obj/screen/healths/guardian()
healths.hud = src
infodisplay += healths
using = new /obj/screen/guardian/Manifest()
using.screen_loc = ui_hand_position(2)
using.hud = src
static_inventory += using
using = new /obj/screen/guardian/Recall()
using.screen_loc = ui_hand_position(1)
using.hud = src
static_inventory += using
using = new owner.toggle_button_type()
using.screen_loc = ui_storage1
using.hud = src
static_inventory += using
using = new /obj/screen/guardian/ToggleLight()
using.screen_loc = ui_inventory
using.hud = src
static_inventory += using
using = new /obj/screen/guardian/Communicate()
using.screen_loc = ui_back
using.hud = src
static_inventory += using
/datum/hud/dextrous/guardian/New(mob/living/simple_animal/hostile/guardian/owner) //for a dextrous guardian
+3
View File
@@ -61,6 +61,9 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
// subtypes can override this to force a specific UI style
var/ui_style
//Citadel stuff
var/obj/screen/arousal
/datum/hud/New(mob/owner)
mymob = owner
-2
View File
@@ -1,2 +0,0 @@
/datum/hud
var/obj/screen/arousal
+38 -6
View File
@@ -95,18 +95,21 @@
using.icon = ui_style
if(!widescreenlayout) // CIT CHANGE
using.screen_loc = ui_boxcraft // CIT CHANGE
using.hud = src
static_inventory += using
using = new/obj/screen/language_menu
using.icon = ui_style
if(!widescreenlayout) // CIT CHANGE
using.screen_loc = ui_boxlang // CIT CHANGE
using.hud = src
static_inventory += using
using = new /obj/screen/area_creator
using.icon = ui_style
if(!widescreenlayout) // CIT CHANGE
using.screen_loc = ui_boxarea // CIT CHANGE
using.hud = src
static_inventory += using
using = new /obj/screen/voretoggle() //We fancy Vore now
@@ -114,16 +117,19 @@
using.screen_loc = ui_voremode
if(!widescreenlayout)
using.screen_loc = ui_boxvore
using.hud = src
static_inventory += using
action_intent = new /obj/screen/act_intent/segmented
action_intent.icon_state = mymob.a_intent
action_intent.hud = src
static_inventory += action_intent
using = new /obj/screen/mov_intent
using.icon = tg_ui_icon_to_cit_ui(ui_style) // CIT CHANGE - overrides mov intent icon
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//CITADEL CHANGES - sprint button
@@ -131,19 +137,21 @@
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.icon_state = (owner.sprinting ? "act_sprint_on" : "act_sprint")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//END OF CITADEL CHANGES
//same as above but buffer.
using = new /obj/screen/sprint_buffer
using.screen_loc = ui_sprintbufferloc
sprint_buffer = using
static_inventory += using
sprint_buffer = new /obj/screen/sprint_buffer
sprint_buffer.screen_loc = ui_sprintbufferloc
sprint_buffer.hud = src
static_inventory += sprint_buffer
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
using.hud = src
static_inventory += using
inv_box = new /obj/screen/inventory()
@@ -168,12 +176,14 @@
using.icon = ui_style
using.icon_state = "swap_1"
using.screen_loc = ui_swaphand_position(owner,1)
using.hud = src
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand_position(owner,2)
using.hud = src
static_inventory += using
inv_box = new /obj/screen/inventory()
@@ -235,28 +245,33 @@
using = new /obj/screen/resist()
using.icon = ui_style
using.screen_loc = ui_overridden_resist // CIT CHANGE - changes this to overridden resist
using.hud = src
hotkeybuttons += using
//CIT CHANGES - rest and combat mode buttons
using = new /obj/screen/restbutton()
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.screen_loc = ui_pull_resist
using.hud = src
static_inventory += using
using = new /obj/screen/combattoggle()
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.screen_loc = ui_combat_toggle
using.hud = src
static_inventory += using
//END OF CIT CHANGES
using = new /obj/screen/human/toggle()
using.icon = ui_style
using.screen_loc = ui_inventory
using.hud = src
static_inventory += using
using = new /obj/screen/human/equip()
using.icon = ui_style
using.screen_loc = ui_equip_position(mymob)
using.hud = src
static_inventory += using
inv_box = new /obj/screen/inventory()
@@ -311,54 +326,71 @@
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = ui_style
throw_icon.screen_loc = ui_drop_throw
throw_icon.hud = src
hotkeybuttons += throw_icon
internals = new /obj/screen/internals()
internals.hud = src
infodisplay += internals
healths = new /obj/screen/healths()
healths.hud = src
infodisplay += healths
//CIT CHANGE - adds arousal and stamina to hud
arousal = new /obj/screen/arousal()
arousal.icon_state = (owner.canbearoused == 1 ? "arousal0" : "")
arousal.hud = src
infodisplay += arousal
staminas = new /obj/screen/staminas()
staminas.hud = src
infodisplay += staminas
if(!CONFIG_GET(flag/disable_stambuffer))
staminabuffer = new /obj/screen/staminabuffer()
staminabuffer.hud = src
infodisplay += staminabuffer
//END OF CIT CHANGES
healthdoll = new /obj/screen/healthdoll()
healthdoll.hud = src
infodisplay += healthdoll
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_pull_resist
static_inventory += pull_icon
lingchemdisplay = new /obj/screen/ling/chems()
lingchemdisplay.hud = src
infodisplay += lingchemdisplay
lingstingdisplay = new /obj/screen/ling/sting()
lingstingdisplay.hud = src
infodisplay += lingstingdisplay
devilsouldisplay = new /obj/screen/devil/soul_counter
devilsouldisplay.hud = src
infodisplay += devilsouldisplay
blood_display = new /obj/screen/bloodsucker/blood_counter // Blood Volume
blood_display.hud = src
infodisplay += blood_display
vamprank_display = new /obj/screen/bloodsucker/rank_counter // Vampire Rank
vamprank_display.hud = src
infodisplay += vamprank_display
sunlight_display = new /obj/screen/bloodsucker/sunlight_counter // Sunlight
sunlight_display.hud = src
infodisplay += sunlight_display
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+1 -1
View File
@@ -6,9 +6,9 @@
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_living_pull
pull_icon.hud = src
static_inventory += pull_icon
healths = new /obj/screen/healths/lavaland_elite()
+16 -2
View File
@@ -7,21 +7,25 @@
action_intent.icon = ui_style
action_intent.icon_state = mymob.a_intent
action_intent.screen_loc = ui_acti
action_intent.hud = src
static_inventory += action_intent
using = new /obj/screen/mov_intent()
using.icon = ui_style
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
using = new/obj/screen/language_menu
using.icon = ui_style
using.hud = src
static_inventory += using
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
using.hud = src
static_inventory += using
build_hand_slots()
@@ -30,12 +34,14 @@
using.icon = ui_style
using.icon_state = "swap_1_m" //extra wide!
using.screen_loc = ui_swaphand_position(owner,1)
using.hud = src
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand_position(owner,2)
using.hud = src
static_inventory += using
inv_box = new /obj/screen/inventory()
@@ -76,30 +82,37 @@
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = ui_style
throw_icon.screen_loc = ui_drop_throw
throw_icon.hud = src
hotkeybuttons += throw_icon
internals = new /obj/screen/internals()
internals.hud = src
infodisplay += internals
healths = new /obj/screen/healths()
healths.hud = src
infodisplay += healths
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_pull_resist
pull_icon.hud = src
pull_icon.update_icon()
static_inventory += pull_icon
lingchemdisplay = new /obj/screen/ling/chems()
lingchemdisplay.hud = src
infodisplay += lingchemdisplay
lingstingdisplay = new /obj/screen/ling/sting()
lingstingdisplay.hud = src
infodisplay += lingstingdisplay
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
mymob.client.screen = list()
@@ -107,6 +120,7 @@
using = new /obj/screen/resist()
using.icon = ui_style
using.screen_loc = ui_pull_resist
using.hud = src
hotkeybuttons += using
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+1
View File
@@ -3,4 +3,5 @@
..()
healths = new /obj/screen/healths/revenant()
healths.hud = src
infodisplay += healths
+17 -2
View File
@@ -118,26 +118,31 @@
using = new/obj/screen/robot/language_menu
using.screen_loc = ui_borg_language_menu
using.hud = src
static_inventory += using
//Radio
using = new /obj/screen/robot/radio()
using.screen_loc = ui_borg_radio
using.hud = src
static_inventory += using
//Module select
using = new /obj/screen/robot/module1()
using.screen_loc = ui_inv1
using.hud = src
static_inventory += using
mymobR.inv1 = using
using = new /obj/screen/robot/module2()
using.screen_loc = ui_inv2
using.hud = src
static_inventory += using
mymobR.inv2 = using
using = new /obj/screen/robot/module3()
using.screen_loc = ui_inv3
using.hud = src
static_inventory += using
mymobR.inv3 = using
@@ -146,36 +151,43 @@
//Photography stuff
using = new /obj/screen/ai/image_take()
using.screen_loc = ui_borg_camera
using.hud = src
static_inventory += using
using = new /obj/screen/ai/image_view()
using.screen_loc = ui_borg_album
using.hud = src
static_inventory += using
//Sec/Med HUDs
using = new /obj/screen/robot/sensors()
using.screen_loc = ui_borg_sensor
using.hud = src
static_inventory += using
//Headlamp control
using = new /obj/screen/robot/lamp()
using.screen_loc = ui_borg_lamp
using.hud = src
static_inventory += using
mymobR.lamp_button = using
//Thrusters
using = new /obj/screen/robot/thrusters()
using.screen_loc = ui_borg_thrusters
using.hud = src
static_inventory += using
mymobR.thruster_button = using
//Intent
action_intent = new /obj/screen/act_intent/robot()
action_intent.icon_state = mymob.a_intent
action_intent.hud = src
static_inventory += action_intent
//Health
healths = new /obj/screen/healths/robot()
healths.hud = src
infodisplay += healths
//Installed Module
@@ -185,17 +197,20 @@
//Store
module_store_icon = new /obj/screen/robot/store()
module_store_icon.hud = src
module_store_icon.screen_loc = ui_borg_store
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
pull_icon.update_icon(mymob)
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_borg_pull
hotkeybuttons += pull_icon
zone_select = new /obj/screen/zone_sel/robot()
zone_select.update_icon(mymob)
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
+70 -71
View File
@@ -110,21 +110,21 @@
// At this point in client Click() code we have passed the 1/10 sec check and little else
// We don't even know if it's a middle click
if(world.time <= usr.next_move)
return 1
return TRUE
if(usr.incapacitated())
return 1
return TRUE
if(ismecha(usr.loc)) // stops inventory actions in a mech
return 1
return TRUE
if(hud && hud.mymob && slot_id)
if(hud?.mymob && slot_id)
var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id)
if(inv_item)
return inv_item.Click(location, control, params)
if(usr.attack_ui(slot_id))
usr.update_inv_hands()
return 1
return TRUE
/obj/screen/inventory/MouseEntered()
..()
@@ -135,35 +135,37 @@
cut_overlay(object_overlays)
object_overlays.Cut()
/obj/screen/inventory/update_icon()
/obj/screen/inventory/update_icon_state()
if(!icon_empty)
icon_empty = icon_state
if(hud && hud.mymob && slot_id && icon_full)
if(hud?.mymob && slot_id && icon_full)
if(hud.mymob.get_item_by_slot(slot_id))
icon_state = icon_full
else
icon_state = icon_empty
/obj/screen/inventory/proc/add_overlays()
var/mob/user = hud.mymob
var/mob/user = hud?.mymob
if(hud && user && slot_id)
var/obj/item/holding = user.get_active_held_item()
if(!user || !slot_id)
return
if(!holding || user.get_item_by_slot(slot_id))
return
var/obj/item/holding = user.get_active_held_item()
var/image/item_overlay = image(holding)
item_overlay.alpha = 92
if(!holding || user.get_item_by_slot(slot_id))
return
if(!user.can_equip(holding, slot_id, TRUE))
item_overlay.color = "#FF0000"
else
item_overlay.color = "#00ff00"
var/image/item_overlay = image(holding)
item_overlay.alpha = 92
object_overlays += item_overlay
add_overlay(object_overlays)
if(!user.can_equip(holding, slot_id, TRUE))
item_overlay.color = "#FF0000"
else
item_overlay.color = "#00ff00"
object_overlays += item_overlay
add_overlay(object_overlays)
/obj/screen/inventory/hand
var/mutable_appearance/handcuff_overlay
@@ -171,45 +173,50 @@
var/held_index = 0
/obj/screen/inventory/hand/update_icon()
..()
. = ..()
if(!handcuff_overlay)
var/state = (!(held_index % 2)) ? "markus" : "gabrielle"
handcuff_overlay = mutable_appearance('icons/mob/screen_gen.dmi', state)
cut_overlays()
cut_overlay(list(handcuff_overlay, blocked_overlay, "hand_active"))
if(hud && hud.mymob)
if(iscarbon(hud.mymob))
var/mob/living/carbon/C = hud.mymob
if(C.handcuffed)
add_overlay(handcuff_overlay)
if(!hud?.mymob)
return
if(held_index)
if(!C.has_hand_for_held_index(held_index))
add_overlay(blocked_overlay)
if(iscarbon(hud.mymob))
var/mob/living/carbon/C = hud.mymob
if(C.handcuffed)
add_overlay(handcuff_overlay)
if(held_index == hud.mymob.active_hand_index)
add_overlay("hand_active")
if(held_index)
if(!C.has_hand_for_held_index(held_index))
add_overlay(blocked_overlay)
if(held_index == hud.mymob.active_hand_index)
add_overlay("hand_active")
/obj/screen/inventory/hand/Click(location, control, params)
// At this point in client Click() code we have passed the 1/10 sec check and little else
// We don't even know if it's a middle click
if(world.time <= usr.next_move)
return 1
if(usr.incapacitated() || isobserver(usr))
return 1
if (ismecha(usr.loc)) // stops inventory actions in a mech
return 1
var/mob/user = hud?.mymob
if(usr != user)
return TRUE
if(world.time <= user.next_move)
return TRUE
if(user.incapacitated())
return TRUE
if (ismecha(user.loc)) // stops inventory actions in a mech
return TRUE
if(hud.mymob.active_hand_index == held_index)
var/obj/item/I = hud.mymob.get_active_held_item()
if(user.active_hand_index == held_index)
var/obj/item/I = user.get_active_held_item()
if(I)
I.Click(location, control, params)
else
hud.mymob.swap_hand(held_index)
return 1
user.swap_hand(held_index)
return TRUE
/obj/screen/close
name = "close"
@@ -343,12 +350,8 @@
/obj/screen/mov_intent/Click()
toggle(usr)
/obj/screen/mov_intent/update_icon(mob/user)
if(!user && hud)
user = hud.mymob
if(!user)
return
switch(user.m_intent)
/obj/screen/mov_intent/update_icon_state()
switch(hud?.mymob?.m_intent)
if(MOVE_INTENT_WALK)
icon_state = "walking"
if(MOVE_INTENT_RUN)
@@ -369,10 +372,8 @@
return
usr.stop_pulling()
/obj/screen/pull/update_icon(mob/mymob)
if(!mymob)
return
if(mymob.pulling)
/obj/screen/pull/update_icon_state()
if(hud?.mymob?.pulling)
icon_state = "pull"
else
icon_state = "pull0"
@@ -401,11 +402,11 @@
var/mob/living/L = usr
L.lay_down()
/obj/screen/rest/update_icon(mob/mymob)
if(!isliving(mymob))
/obj/screen/rest/update_icon_state()
var/mob/living/user = hud?.mymob
if(!istype(user))
return
var/mob/living/L = mymob
if(!L.resting)
if(!user.resting)
icon_state = "act_rest"
else
icon_state = "act_rest0"
@@ -448,7 +449,7 @@
name = "damage zone"
icon_state = "zone_sel"
screen_loc = ui_zonesel
var/selecting = BODY_ZONE_CHEST
var/overlay_icon = 'icons/mob/screen_gen.dmi'
var/static/list/hover_overlays_cache = list()
var/hovering
@@ -541,26 +542,24 @@
return BODY_ZONE_HEAD
/obj/screen/zone_sel/proc/set_selected_zone(choice, mob/user)
if(isobserver(user))
if(user != hud?.mymob)
return
if(choice != selecting)
selecting = choice
update_icon(usr)
return 1
if(choice != hud.mymob.zone_selected)
hud.mymob.zone_selected = choice
update_icon()
/obj/screen/zone_sel/update_icon(mob/user)
cut_overlays()
add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[selecting]"))
user.zone_selected = selecting
return TRUE
/obj/screen/zone_sel/update_overlays()
. = ..()
if(!hud?.mymob)
return
. += mutable_appearance(overlay_icon, "[hud.mymob.zone_selected]")
/obj/screen/zone_sel/alien
icon = 'icons/mob/screen_alien.dmi'
/obj/screen/zone_sel/alien/update_icon(mob/user)
cut_overlays()
add_overlay(mutable_appearance('icons/mob/screen_alien.dmi', "[selecting]"))
user.zone_selected = selecting
overlay_icon = 'icons/mob/screen_alien.dmi'
/obj/screen/zone_sel/robot
icon = 'icons/mob/screen_cyborg.dmi'
+6
View File
@@ -69,24 +69,30 @@
using = new /obj/screen/swarmer/FabricateTrap()
using.screen_loc = ui_hand_position(2)
using.hud = src
static_inventory += using
using = new /obj/screen/swarmer/Barricade()
using.screen_loc = ui_hand_position(1)
using.hud = src
static_inventory += using
using = new /obj/screen/swarmer/Replicate()
using.screen_loc = ui_zonesel
using.hud = src
static_inventory += using
using = new /obj/screen/swarmer/RepairSelf()
using.screen_loc = ui_storage1
using.hud = src
static_inventory += using
using = new /obj/screen/swarmer/ToggleLight()
using.screen_loc = ui_back
using.hud = src
static_inventory += using
using = new /obj/screen/swarmer/ContactSwarmers()
using.screen_loc = ui_inventory
using.hud = src
static_inventory += using
+11 -9
View File
@@ -98,17 +98,19 @@
take_damage(I.force, I.damtype, "melee", 1)
/mob/living/attacked_by(obj/item/I, mob/living/user)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(iscarbon(user))
var/mob/living/carbon/tempcarb = user
if(!tempcarb.combatmode)
totitemdamage *= 0.5
if(user.resting)
totitemdamage *= 0.5
//CIT CHANGES END HERE
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
return FALSE
send_item_attack_message(I, user)
if(I.force)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(iscarbon(user))
var/mob/living/carbon/tempcarb = user
if(!tempcarb.combatmode)
totitemdamage *= 0.5
if(user.resting)
totitemdamage *= 0.5
//CIT CHANGES END HERE
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
if(prob(33))
+2
View File
@@ -91,6 +91,8 @@
var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves
return
if (istype(glasses) && glasses.ranged_attack(src,A,mouseparams))
return
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_ranged_attack(src, A, mouseparams)
@@ -151,6 +151,7 @@
var/key_mode
var/value_mode
var/splitter = " "
var/lowercase = TRUE
/datum/config_entry/keyed_list/New()
. = ..()
@@ -167,7 +168,9 @@
var/key_value = null
if(key_pos || value_mode == VALUE_MODE_FLAG)
key_name = lowertext(copytext(str_val, 1, key_pos))
key_name = copytext(str_val, 1, key_pos)
if(lowercase)
key_name = lowertext(key_name)
key_value = copytext(str_val, key_pos + 1)
var/new_key
var/new_value
@@ -14,6 +14,7 @@
var/list/modes // allowed modes
var/list/gamemode_cache
var/list/votable_modes // votable modes
var/list/storyteller_cache
var/list/mode_names
var/list/mode_reports
var/list/mode_false_report_weight
@@ -37,6 +38,7 @@
CRASH("/datum/controller/configuration/Load() called more than once!")
InitEntries()
LoadModes()
storyteller_cache = typecacheof(/datum/dynamic_storyteller, TRUE)
if(fexists("[directory]/config.txt") && LoadEntries("config.txt") <= 1)
var/list/legacy_configs = list("game_options.txt", "dbconfig.txt", "comms.txt")
for(var/I in legacy_configs)
@@ -227,6 +229,7 @@
for(var/T in gamemode_cache)
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
// for future reference: just use initial() lol
var/datum/game_mode/M = new T()
if(M.config_tag)
@@ -317,6 +320,14 @@
return new T
return new /datum/game_mode/extended()
/datum/controller/configuration/proc/pick_storyteller(storyteller_name)
for(var/T in storyteller_cache)
var/datum/dynamic_storyteller/S = T
var/name = initial(S.name)
if(name && name == storyteller_name)
return T
return /datum/dynamic_storyteller/classic
/datum/controller/configuration/proc/get_runnable_modes()
var/list/datum/game_mode/runnable_modes = new
var/list/probabilities = Get(/datum/config_entry/keyed_list/probability)
@@ -376,6 +376,12 @@
/datum/config_entry/flag/disable_stambuffer
/datum/config_entry/keyed_list/box_random_engine
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_FLAG
lowercase = FALSE
splitter = "-"
/datum/config_entry/number/auto_transfer_delay
config_entry_value = 72000
min_val = 0
+4 -1
View File
@@ -315,7 +315,7 @@ SUBSYSTEM_DEF(air)
var/starting_ats = active_turfs.len
sleep(world.tick_lag)
var/timer = world.timeofday
warning("There are [starting_ats] active turfs at roundstart, this is a mapping error caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required)")
log_mapping("There are [starting_ats] active turfs at roundstart caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required).")
for(var/turf/T in active_turfs)
GLOB.active_turfs_startlist += T
@@ -382,6 +382,9 @@ SUBSYSTEM_DEF(air)
CHECK_TICK
/datum/controller/subsystem/air/proc/setup_template_machinery(list/atmos_machines)
if(!initialized)
return
for(var/A in atmos_machines)
var/obj/machinery/atmospherics/AM = A
AM.atmosinit()
+15 -1
View File
@@ -91,6 +91,7 @@ SUBSYSTEM_DEF(mapping)
var/list/space_ruins = levels_by_trait(ZTRAIT_SPACE_RUINS)
if (space_ruins.len)
seedRuins(space_ruins, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates)
SSmapping.seedStation()
loading_ruins = FALSE
#endif
repopulate_sorted_areas()
@@ -363,6 +364,8 @@ GLOBAL_LIST_EMPTY(the_station_areas)
lava_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/station))
station_room_templates[R.name] = R
/datum/controller/subsystem/mapping/proc/preloadShuttleTemplates()
var/list/unbuyable = generateMapList("[global.config.directory]/unbuyableshuttles.txt")
@@ -524,4 +527,15 @@ GLOBAL_LIST_EMPTY(the_station_areas)
if(!isolated_ruins_z)
isolated_ruins_z = add_new_zlevel("Isolated Ruins/Reserved", list(ZTRAIT_RESERVED = TRUE, ZTRAIT_ISOLATED_RUINS = TRUE))
initialize_reserved_level(isolated_ruins_z.z_value)
return isolated_ruins_z.z_value
return isolated_ruins_z.z_value
// Station Ruins
/datum/controller/subsystem/mapping
var/list/station_room_templates = list()
/datum/controller/subsystem/mapping/proc/seedStation()
for(var/V in GLOB.stationroom_landmarks)
var/obj/effect/landmark/stationroom/LM = V
LM.load()
if(GLOB.stationroom_landmarks.len)
seedStation() //I'm sure we can trust everyone not to insert a 1x1 rooms which loads a landmark which loads a landmark which loads a la...
+48 -14
View File
@@ -13,13 +13,14 @@ SUBSYSTEM_DEF(persistence)
var/list/saved_messages = list()
var/list/saved_modes = list(1,2,3)
var/list/saved_dynamic_rules = list(list(),list(),list())
var/list/saved_threat_levels = list(1,1,1)
var/list/saved_storytellers = list("foo","bar","baz","foo again","bar again")
var/list/saved_maps
var/list/saved_trophies = list()
var/list/spawned_objects = list()
var/list/antag_rep = list()
var/list/antag_rep_change = list()
var/list/picture_logging_information = list()
var/list/saved_votes = list()
var/list/obj/structure/sign/picture_frame/photo_frames
var/list/obj/item/storage/photo_album/photo_albums
@@ -29,9 +30,12 @@ SUBSYSTEM_DEF(persistence)
LoadChiselMessages()
LoadTrophies()
LoadRecentModes()
LoadRecentThreats()
LoadRecentStorytellers()
LoadRecentRulesets()
LoadRecentMaps()
LoadPhotoPersistence()
for(var/client/C in GLOB.clients)
LoadSavedVote(C.ckey)
if(CONFIG_GET(flag/use_antag_rep))
LoadAntagReputation()
LoadRandomizedRecipes()
@@ -169,14 +173,23 @@ SUBSYSTEM_DEF(persistence)
return
saved_modes = json["data"]
/datum/controller/subsystem/persistence/proc/LoadRecentThreats()
var/json_file = file("data/RecentThreatLevels.json")
/datum/controller/subsystem/persistence/proc/LoadRecentRulesets()
var/json_file = file("data/RecentRulesets.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_threat_levels = json["data"]
saved_dynamic_rules = json["data"]
/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers()
var/json_file = file("data/RecentStorytellers.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_storytellers = json["data"]
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
var/json_file = file("data/RecentMaps.json")
@@ -197,6 +210,15 @@ SUBSYSTEM_DEF(persistence)
return
antag_rep = json_decode(json)
/datum/controller/subsystem/persistence/proc/LoadSavedVote(var/ckey)
var/json_file = file("data/player_saves/[copytext(ckey,1,2)]/[ckey]/SavedVotes.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_votes[ckey] = json["data"]
/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
for(var/A in GLOB.trophy_cases)
var/obj/structure/displaycase/trophy/T = A
@@ -230,7 +252,7 @@ SUBSYSTEM_DEF(persistence)
CollectRoundtype()
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
CollectThreatLevel(mode)
CollectStoryteller(mode)
CollectRulesets(mode)
RecordMaps()
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
@@ -388,13 +410,16 @@ SUBSYSTEM_DEF(persistence)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectThreatLevel(var/datum/game_mode/dynamic/mode)
saved_threat_levels[3] = saved_threat_levels[2]
saved_threat_levels[2] = saved_threat_levels [1]
saved_threat_levels[1] = mode.threat_level
var/json_file = file("data/RecentThreatLevels.json")
/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode)
saved_storytellers.len = 5
saved_storytellers[5] = saved_storytellers[4]
saved_storytellers[4] = saved_storytellers[3]
saved_storytellers[3] = saved_storytellers[2]
saved_storytellers[2] = saved_storytellers[1]
saved_storytellers[1] = mode.storyteller.name
var/json_file = file("data/RecentStorytellers.json")
var/list/file_data = list()
file_data["data"] = saved_threat_levels
file_data["data"] = saved_storytellers
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
@@ -402,8 +427,9 @@ SUBSYSTEM_DEF(persistence)
saved_dynamic_rules[3] = saved_dynamic_rules[2]
saved_dynamic_rules[2] = saved_dynamic_rules[1]
saved_dynamic_rules[1] = list()
for(var/datum/dynamic_ruleset/ruleset in mode.executed_rules)
saved_dynamic_rules[1] += ruleset.config_tag
for(var/r in mode.executed_rules)
var/datum/dynamic_ruleset/rule = r
saved_dynamic_rules[1] += rule.config_tag
var/json_file = file("data/RecentRulesets.json")
var/list/file_data = list()
file_data["data"] = saved_dynamic_rules
@@ -473,3 +499,11 @@ SUBSYSTEM_DEF(persistence)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/SaveSavedVotes()
for(var/ckey in saved_votes)
var/json_file = file("data/player_saves/[copytext(ckey,1,2)]/[ckey]/SavedVotes.json")
var/list/file_data = list()
file_data["data"] = saved_votes[ckey]
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
@@ -6,6 +6,7 @@ PROCESSING_SUBSYSTEM_DEF(nanites)
var/list/datum/nanite_cloud_backup/cloud_backups = list()
var/list/mob/living/nanite_monitored_mobs = list()
var/list/datum/nanite_program/relay/nanite_relays = list()
var/neural_network_count = 0
/datum/controller/subsystem/processing/nanites/proc/check_hardware(datum/nanite_cloud_backup/backup)
if(QDELETED(backup.storage) || (backup.storage.stat & (NOPOWER|BROKEN)))
+7 -1
View File
@@ -401,6 +401,9 @@ SUBSYSTEM_DEF(ticker)
qdel(player)
living.notransform = TRUE
if(living.client)
if (living.client.prefs && living.client.prefs.auto_ooc)
if (living.client.prefs.chat_toggles & CHAT_OOC)
living.client.prefs.chat_toggles ^= CHAT_OOC
var/obj/screen/splash/S = new(living.client, TRUE)
S.Fade(TRUE)
livings += living
@@ -480,7 +483,10 @@ SUBSYSTEM_DEF(ticker)
SSticker.timeLeft = 900
SSticker.modevoted = TRUE
var/dynamic = CONFIG_GET(flag/dynamic_voting)
SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE)
if(dynamic)
SSvote.initiate_vote("dynamic","server",hideresults=TRUE,votesystem=SCORE_VOTING,forced=TRUE,vote_time = 2 MINUTES)
else
SSvote.initiate_vote("roundtype","server",hideresults=TRUE,votesystem=PLURALITY_VOTING,forced=TRUE, vote_time = 2 MINUTES)
/datum/controller/subsystem/ticker/Recover()
current_state = SSticker.current_state
+292 -76
View File
@@ -1,3 +1,5 @@
#define VOTE_COOLDOWN 10
SUBSYSTEM_DEF(vote)
name = "Vote"
wait = 10
@@ -8,13 +10,17 @@ SUBSYSTEM_DEF(vote)
var/initiator = null
var/started_time = null
var/time_remaining = 0
var/end_time = 0
var/mode = null
var/vote_system = PLURALITY_VOTING
var/question = null
var/list/choices = list()
var/list/choice_descs = list() // optional descriptions
var/list/voted = list()
var/list/voting = list()
var/list/saved = list()
var/list/generated_actions = list()
var/next_pop = 0
var/obfuscated = FALSE//CIT CHANGE - adds obfuscated/admin-only votes
@@ -22,28 +28,30 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/fire() //called by master_controller
if(mode)
time_remaining = round((started_time + CONFIG_GET(number/vote_period) - world.time)/10)
if(time_remaining < 0)
if(end_time < world.time)
result()
SSpersistence.SaveSavedVotes()
for(var/client/C in voting)
C << browse(null, "window=vote;can_close=0")
reset()
else
else if(next_pop < world.time)
var/datum/browser/client_popup
for(var/client/C in voting)
client_popup = new(C, "vote", "Voting Panel")
client_popup = new(C, "vote", "Voting Panel", nwidth=600,nheight=700)
client_popup.set_window_options("can_close=0")
client_popup.set_content(interface(C))
client_popup.open(0)
next_pop = world.time+VOTE_COOLDOWN
/datum/controller/subsystem/vote/proc/reset()
initiator = null
time_remaining = 0
end_time = 0
mode = null
question = null
choices.Cut()
choice_descs.Cut()
voted.Cut()
voting.Cut()
obfuscated = FALSE //CIT CHANGE - obfuscated votes
@@ -84,17 +92,114 @@ SUBSYSTEM_DEF(vote)
. += option
return .
/datum/controller/subsystem/vote/proc/calculate_condorcet_votes(var/blackbox_text)
// https://en.wikipedia.org/wiki/Schulze_method#Implementation
var/list/d[][] = new/list(choices.len,choices.len) // the basic vote matrix, how many times a beats b
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
for(var/a in 1 to choices.len)
for(var/b in a+1 to choices.len)
var/a_rank = this_vote.Find(a)
var/b_rank = this_vote.Find(b)
a_rank = a_rank ? a_rank : choices.len+1
b_rank = b_rank ? b_rank : choices.len+1
if(a_rank<b_rank)
d[a][b]++
else if(b_rank<a_rank)
d[b][a]++
//if equal, do nothing
var/list/p[][] = new/list(choices.len,choices.len) //matrix of shortest path from a to b
for(var/i in 1 to choices.len)
for(var/j in 1 to choices.len)
if(i != j)
var/pref_number = d[i][j]
var/opposite_pref = d[j][i]
if(pref_number>opposite_pref)
p[i][j] = d[i][j]
p[j][i] = 0
else
p[i][j] = 0
p[j][i] = d[i][j]
for(var/i in 1 to choices.len)
for(var/j in 1 to choices.len)
if(i != j)
for(var/k in 1 to choices.len) // YEAH O(n^3) !!
if(i != k && j != k)
p[j][k] = max(p[j][k],min(p[j][i], p[i][k]))
//one last pass, now that we've done the math
for(var/i in 1 to choices.len)
for(var/j in 1 to choices.len)
if(i != j)
SSblackbox.record_feedback("nested tally","voting",p[i][j],list(blackbox_text,"Shortest Paths",choices[i],choices[j]))
if(p[i][j] >= p[j][i])
choices[choices[i]]++ // higher shortest path = better candidate, so we add to choices here
// choices[choices[i]] is the schulze ranking, here, rather than raw vote numbers
/datum/controller/subsystem/vote/proc/calculate_majority_judgement_vote(var/blackbox_text)
// https://en.wikipedia.org/wiki/Majority_judgment
var/list/scores_by_choice = list()
for(var/choice in choices)
scores_by_choice[choice] = list()
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
var/list/pretty_vote = list()
for(var/choice in this_vote)
sorted_insert(scores_by_choice[choice],this_vote[choice],/proc/cmp_numeric_asc)
// START BALLOT GATHERING
pretty_vote += choice
pretty_vote[choice] = GLOB.vote_score_options[this_vote[choice]]
SSblackbox.record_feedback("associative","voting_ballots",1,pretty_vote)
// END BALLOT GATHERING
for(var/score_name in scores_by_choice)
var/list/score = scores_by_choice[score_name]
for(var/indiv_score in score)
SSblackbox.record_feedback("nested tally","voting",1,list(blackbox_text,"Scores",score_name,GLOB.vote_score_options[indiv_score]))
if(score.len == 0)
scores_by_choice -= score_name
while(scores_by_choice.len > 1)
var/highest_median = 0
for(var/score_name in scores_by_choice) // first get highest median
var/list/score = scores_by_choice[score_name]
if(!score.len)
scores_by_choice -= score_name
continue
var/median = score[max(1,round(score.len/2))]
if(median >= highest_median)
highest_median = median
for(var/score_name in scores_by_choice) // then, remove
var/list/score = scores_by_choice[score_name]
var/median = score[max(1,round(score.len/2))]
if(median < highest_median)
scores_by_choice -= score_name
for(var/score_name in scores_by_choice) // after removals
var/list/score = scores_by_choice[score_name]
if(score.len == 0)
choices[score_name] += 100 // we're in a tie situation--just go with the first one
return
var/median_pos = max(1,round(score.len/2))
score.Cut(median_pos,median_pos+1)
choices[score_name]++
/datum/controller/subsystem/vote/proc/announce_result()
var/list/winners = get_result()
var/vote_title_text
var/text
if(question)
text += "<b>[question]</b>"
vote_title_text = "[question]"
else
text += "<b>[capitalize(mode)] Vote</b>"
vote_title_text = "[capitalize(mode)] Vote"
if(vote_system == RANKED_CHOICE_VOTING)
calculate_condorcet_votes(vote_title_text)
if(vote_system == SCORE_VOTING)
calculate_majority_judgement_vote(vote_title_text)
var/list/winners = get_result()
var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic"
if(winners.len > 0)
if(question)
text += "<b>[question]</b>"
else
text += "<b>[capitalize(mode)] Vote</b>"
if(was_roundtype_vote)
stored_gamemode_votes = list()
if(!obfuscated && vote_system == RANKED_CHOICE_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!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
if(!votes)
@@ -116,17 +221,25 @@ SUBSYSTEM_DEF(vote)
log_vote(text)
remove_action_buttons()
to_chat(world, "\n<font color='purple'>[text]</font>")
switch(vote_system)
if(APPROVAL_VOTING,PLURALITY_VOTING)
for(var/i=1,i<=choices.len,i++)
SSblackbox.record_feedback("nested tally","voting",choices[choices[i]],list(vote_title_text,choices[i]))
if(RANKED_CHOICE_VOTING)
for(var/i=1,i<=voted.len,i++)
var/list/myvote = voted[voted[i]]
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
var/admintext = "Obfuscated results"
if(vote_system == RANKED_CHOICE_VOTING)
admintext += "\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!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
admintext += "\n<b>[choices[i]]:</b> [votes]"
message_admins(admintext)
return .
#define PEACE "calm"
#define CHAOS "chaotic"
/datum/controller/subsystem/vote/proc/result()
. = announce_result()
var/restart = 0
@@ -152,33 +265,15 @@ SUBSYSTEM_DEF(vote)
if("dynamic")
if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started.
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
GLOB.master_mode = "dynamic"
if("extended" in choices)
if(. == "extended")
GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff
choices[PEACE] += choices["extended"]
var/mean = 0
var/voters = 0
for(var/client/c in GLOB.clients)
var/vote = c.prefs.preferred_chaos
if(vote)
voters += 1
switch(vote)
if(CHAOS_NONE)
mean -= 0.1
if(CHAOS_LOW)
mean -= 0.05
if(CHAOS_HIGH)
mean += 0.05
if(CHAOS_MAX)
mean += 0.1
mean/=voters
if(voted.len != 0)
mean += (choices[PEACE]*-1+choices[CHAOS])/voted.len
GLOB.dynamic_curve_centre = mean*20
GLOB.dynamic_curve_width = CLAMP(2-abs(mean*5),0.5,4)
to_chat(world,"<span class='boldannounce'>Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width].</span>")
log_admin("Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width]")
if(. == "Secret")
GLOB.master_mode = "secret"
SSticker.save_mode(.)
message_admins("The gamemode has been voted for, and has been changed to: [GLOB.master_mode]")
log_admin("Gamemode has been voted for and switched to: [GLOB.master_mode].")
else
GLOB.master_mode = "dynamic"
var/datum/dynamic_storyteller/S = config.pick_storyteller(.)
GLOB.dynamic_storyteller_type = S
if("map")
var/datum/map_config/VM = config.maplist[.]
message_admins("The map has been voted for and will change to: [VM.map_name]")
@@ -196,27 +291,58 @@ SUBSYSTEM_DEF(vote)
else
to_chat(world, "<span style='boldannounce'>Notice:Restart vote will not restart the server automatically because there are active admins on.</span>")
message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")
return .
/datum/controller/subsystem/vote/proc/submit_vote(vote)
/datum/controller/subsystem/vote/proc/submit_vote(vote, score = 0)
if(mode)
if(CONFIG_GET(flag/no_dead_vote) && usr.stat == DEAD && !usr.client.holder)
return 0
if(!(usr.ckey in voted))
if(vote && 1<=vote && vote<=choices.len)
voted += usr.ckey
voted[usr.ckey] = vote
choices[choices[vote]]++ //check this
return vote
else if(vote && 1<=vote && vote<=choices.len)
choices[choices[voted[usr.ckey]]]--
voted[usr.ckey] = vote
choices[choices[vote]]++
return vote
if(vote && ISINRANGE(vote, 1, choices.len))
switch(vote_system)
if(PLURALITY_VOTING)
if(usr.ckey in voted)
choices[choices[voted[usr.ckey]]]--
voted[usr.ckey] = vote
choices[choices[vote]]++
return vote
else
voted += usr.ckey
voted[usr.ckey] = vote
choices[choices[vote]]++ //check this
return vote
if(APPROVAL_VOTING)
if(usr.ckey in voted)
if(vote in voted[usr.ckey])
voted[usr.ckey] -= vote
choices[choices[vote]]--
else
voted[usr.ckey] += vote
choices[choices[vote]]++
else
voted += usr.ckey
voted[usr.ckey] = list(vote)
choices[choices[vote]]++
return vote
if(RANKED_CHOICE_VOTING)
if(usr.ckey in voted)
if(vote in voted[usr.ckey])
voted[usr.ckey] -= vote
else
voted += usr.ckey
voted[usr.ckey] = list()
voted[usr.ckey] += vote
saved -= usr.ckey
if(SCORE_VOTING)
if(!(usr.ckey in voted))
voted += usr.ckey
voted[usr.ckey] = list()
voted[usr.ckey][choices[vote]] = score
saved -= usr.ckey
return 0
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes
/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
vote_system = votesystem
if(!mode)
if(started_time)
var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay))
@@ -257,11 +383,17 @@ SUBSYSTEM_DEF(vote)
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
choices.Add("secret", "extended")
if("dynamic")
var/saved_threats = SSpersistence.saved_threat_levels
if((saved_threats[1]+saved_threats[2]+saved_threats[3])>150)
choices.Add("extended",PEACE,CHAOS)
else
choices.Add(PEACE,CHAOS)
for(var/T in config.storyteller_cache)
var/datum/dynamic_storyteller/S = T
var/recent_rounds = 0
for(var/i in 1 to SSpersistence.saved_storytellers.len)
if(SSpersistence.saved_storytellers[i] == initial(S.name))
recent_rounds++
if(recent_rounds < initial(S.weight))
choices.Add(initial(S.name))
choice_descs.Add(initial(S.desc))
choices.Add("Secret")
choice_descs.Add("Standard secret. Switches mode if it wins.")
if("custom")
question = stripped_input(usr,"What is the vote for?")
if(!question)
@@ -280,9 +412,11 @@ SUBSYSTEM_DEF(vote)
if(mode == "custom")
text += "\n[question]"
log_vote(text)
var/vp = CONFIG_GET(number/vote_period)
var/vp = vote_time
if(vp == -1)
vp = CONFIG_GET(number/vote_period)
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=[REF(src)]'>here</a> to place your votes.\nYou have [DisplayTimeText(vp)] to vote.</font>")
time_remaining = round(vp/10)
end_time = started_time+vp
for(var/c in GLOB.clients)
SEND_SOUND(c, sound('sound/misc/server-ready.ogg'))
var/client/C = c
@@ -292,6 +426,11 @@ SUBSYSTEM_DEF(vote)
C.player_details.player_actions += V
V.Grant(C.mob)
generated_actions += V
if(forced)
var/datum/browser/popup = new(C, "vote", "Voting Panel",nwidth=600,nheight=700)
popup.set_window_options("can_close=0")
popup.set_content(SSvote.interface(C))
popup.open(0)
return 1
return 0
@@ -311,14 +450,71 @@ SUBSYSTEM_DEF(vote)
. += "<h2>Vote: '[question]'</h2>"
else
. += "<h2>Vote: [capitalize(mode)]</h2>"
. += "Time Left: [time_remaining] s<hr><ul>"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
var/ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i) ? TRUE : FALSE)
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
. += "</ul><hr>"
switch(vote_system)
if(PLURALITY_VOTING)
. += "<h3>Vote one.</h3>"
if(APPROVAL_VOTING)
. += "<h3>Vote any number of choices.</h3>"
if(RANKED_CHOICE_VOTING)
. += "<h3>Vote by order of preference. Revoting will demote to the bottom. 1 is your favorite, and higher numbers are worse.</h3>"
if(SCORE_VOTING)
. += "<h3>Grade the candidates by how much you like them.</h3>"
. += "<h3>No-votes have no power--your opinion is only heard if you vote!</h3>"
. += "Time Left: [DisplayTimeText(end_time-world.time)]<hr><ul>"
switch(vote_system)
if(PLURALITY_VOTING, APPROVAL_VOTING)
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
var/ivotedforthis = FALSE
switch(vote_system)
if(PLURALITY_VOTING)
ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i))
if(APPROVAL_VOTING)
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
if(choice_descs.len >= i)
. += "<li>[choice_descs[i]]</li>"
. += "</ul><hr>"
if(RANKED_CHOICE_VOTING)
var/list/myvote = voted[C.ckey]
for(var/i=1,i<=choices.len,i++)
var/vote = (myvote ? (myvote.Find(i)) : 0)
if(vote)
. += "<li><b><a href='?src=[REF(src)];vote=[i]'>[choices[i]]</a> ([vote])</b></li>"
else
. += "<li><a href='?src=[REF(src)];vote=[i]'>[choices[i]]</a></li>"
if(choice_descs.len >= i)
. += "<li>[choice_descs[i]]</li>"
. += "</ul><hr>"
if(!(C.ckey in saved))
. += "(<a href='?src=[REF(src)];vote=save'>Save vote</a>)"
else
. += "(Saved!)"
. += "(<a href='?src=[REF(src)];vote=load'>Load vote from save</a>)"
. += "(<a href='?src=[REF(src)];vote=reset'>Reset votes</a>)"
if(SCORE_VOTING)
var/list/myvote = voted[C.ckey]
for(var/i=1,i<=choices.len,i++)
. += "<li><b>[choices[i]]</b>"
for(var/r in 1 to GLOB.vote_score_options.len)
. += " <a href='?src=[REF(src)];vote=[i];score=[r]'>"
if((choices[i] in myvote) && myvote[choices[i]] == r)
. +="<b>([GLOB.vote_score_options[r]])</b>"
else
. +="[GLOB.vote_score_options[r]]"
. += "</a>"
. += "</li>"
if(choice_descs.len >= i)
. += "<li>[choice_descs[i]]</li>"
. += "</ul><hr>"
if(!(C.ckey in saved))
. += "(<a href='?src=[REF(src)];vote=save'>Save vote</a>)"
else
. += "(Saved!)"
. += "(<a href='?src=[REF(src)];vote=load'>Load vote from save</a>)"
. += "(<a href='?src=[REF(src)];vote=reset'>Reset votes</a>)"
if(admin)
. += "(<a href='?src=[REF(src)];vote=cancel'>Cancel Vote</a>) "
else
@@ -376,8 +572,31 @@ SUBSYSTEM_DEF(vote)
if("custom")
if(usr.client.holder)
initiate_vote("custom",usr.key)
if("reset")
if(usr.ckey in voted)
voted -= usr.ckey
if("save")
if(usr.ckey in voted)
if(!(usr.ckey in SSpersistence.saved_votes))
SSpersistence.saved_votes[usr.ckey] = list()
SSpersistence.saved_votes[usr.ckey][mode] = voted[usr.ckey]
saved += usr.ckey
if("load")
if(!(usr.ckey in SSpersistence.saved_votes))
SSpersistence.LoadSavedVote(usr.ckey)
if(!(usr.ckey in SSpersistence.saved_votes))
SSpersistence.saved_votes[usr.ckey] = list()
if(usr.ckey in voted)
SSpersistence.saved_votes[usr.ckey][mode] = voted[usr.ckey]
else
SSpersistence.saved_votes[usr.ckey][mode] = list()
voted[usr.ckey] = SSpersistence.saved_votes[usr.ckey][mode]
saved += usr.ckey
else
submit_vote(round(text2num(href_list["vote"])))
if(vote_system == SCORE_VOTING)
submit_vote(round(text2num(href_list["vote"])),round(text2num(href_list["score"])))
else
submit_vote(round(text2num(href_list["vote"])))
usr.vote()
/datum/controller/subsystem/vote/proc/remove_action_buttons()
@@ -392,7 +611,7 @@ SUBSYSTEM_DEF(vote)
set category = "OOC"
set name = "Vote"
var/datum/browser/popup = new(src, "vote", "Voting Panel")
var/datum/browser/popup = new(src, "vote", "Voting Panel",nwidth=600,nheight=700)
popup.set_window_options("can_close=0")
popup.set_content(SSvote.interface(client))
popup.open(0)
@@ -419,6 +638,3 @@ SUBSYSTEM_DEF(vote)
var/datum/player_details/P = GLOB.player_details[owner.ckey]
if(P)
P.player_actions -= src
#undef PEACE
#undef CHAOS
+2 -2
View File
@@ -32,7 +32,7 @@
if(ishuman(M) && source.force && source.get_sharpness())
var/mob/living/carbon/human/H = M
if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping()) && user.zone_selected == BODY_ZONE_HEAD) // Only sleeping, neck grabbed, or crit, can be sliced.
if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping()) && user.zone_selected == BODY_ZONE_PRECISE_MOUTH) // Only sleeping, neck grabbed, or crit, can be sliced.
if(H.has_status_effect(/datum/status_effect/neck_slice))
user.show_message("<span class='warning'>[H]'s neck has already been already cut, you can't make the bleeding any worse!</span>", 1, \
"<span class='warning'>Their neck has already been already cut, you can't make the bleeding any worse!</span>")
@@ -120,4 +120,4 @@
if(eater.safety_mode || (eater.stat & (BROKEN|NOPOWER))) //I'm so sorry.
return
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
Butcher(parent, L)
Butcher(parent, L)
+5 -4
View File
@@ -11,8 +11,9 @@
var/list/datum/nanite_program/programs = list()
var/max_programs = NANITE_PROGRAM_LIMIT
var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans, and does not display the program list on nanite scans
var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans
var/diagnostics = TRUE //if TRUE, displays program list when scanned by nanite scanners
/datum/component/nanites/Initialize(amount = 100, cloud = 0)
if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup))
return COMPONENT_INCOMPATIBLE
@@ -252,8 +253,8 @@
to_chat(user, "<span class='info'>Cloud ID: [cloud_id ? cloud_id : "Disabled"]</span>")
to_chat(user, "<span class='info'>================</span>")
to_chat(user, "<span class='info'>Program List:</span>")
if(stealth)
to_chat(user, "<span class='alert'>%#$ENCRYPTED&^@</span>")
if(!diagnostics)
to_chat(user, "<span class='alert'>Diagnostics Disabled</span>")
else
for(var/X in programs)
var/datum/nanite_program/NP = X
+2
View File
@@ -8,6 +8,8 @@
var/deflection_chance = 0 //Chance to deflect projectiles
var/reroute_deflection = FALSE //Delete the bullet, or actually deflect it in some direction?
var/block_chance = 0 //Chance to block melee attacks using items while on throw mode.
var/dodge_chance = 0
var/restraining = 0 //used in cqc's disarm_act to check if the disarmed is being restrained and so whether they should be put in a chokehold or not
var/help_verb
var/pacifism_check = TRUE //are the martial arts combos/attacks unable to be used by pacifist.
var/allow_temp_override = TRUE //if this martial art can be overridden by temporary martial arts
-1
View File
@@ -10,7 +10,6 @@
help_verb = /mob/living/carbon/human/proc/CQC_help
block_chance = 75
var/old_grab_state = null
var/restraining = FALSE
/datum/martial_art/cqc/reset_streak(mob/living/carbon/human/new_target)
. = ..()
+158
View File
@@ -0,0 +1,158 @@
#define SIDE_KICK_COMBO "DH"
#define SHOULDER_FLIP_COMBO "GHDGHH"
#define REPULSE_PUNCH_COMBO "GHGH"
#define FOOT_SMASH_COMBO "HH"
#define DEFT_SWITCH_COMBO "GDD"
/datum/martial_art/the_rising_bass
name = "The Rising Bass"
id = MARTIALART_RISINGBASS
dodge_chance = 100
allow_temp_override = FALSE
help_verb = /mob/living/carbon/human/proc/rising_bass_help
/datum/martial_art/the_rising_bass/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,SIDE_KICK_COMBO))
streak = ""
sideKick(A,D)
return 1
if(findtext(streak,SHOULDER_FLIP_COMBO))
streak = ""
shoulderFlip(A,D)
return 1
if(findtext(streak,REPULSE_PUNCH_COMBO))
streak = ""
repulsePunch(A,D)
return 1
if(findtext(streak,FOOT_SMASH_COMBO))
streak = ""
footSmash(A,D)
return 1
if(findtext(streak,DEFT_SWITCH_COMBO))
streak = ""
deftSwitch(A,D)
return 1
return 0
/datum/martial_art/the_rising_bass/proc/sideKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.IsKnockdown() || D.lying == 0)
var/turf/H = get_step(D, A.dir & (NORTH | SOUTH) ? pick(EAST, WEST) : pick(NORTH, SOUTH))
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
D.visible_message("<span class='warning'>[A] kicks [D] in the side, sliding them over!</span>", \
"<span class='userdanger'>[A] kicks you in the side, forcing you to step away!</span>")
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
D.apply_damage(5, BRUTE, BODY_ZONE_CHEST)
D.Knockdown(60)
var/L = H
for(var/obj/i in H.contents)
if(!istype(i,/mob) && i.density == 1)
L = D.loc
D.forceMove(L)
log_combat(A, D, "side kicked (Rising Bass)")
return 1
return basic_hit(A,D)
/datum/martial_art/the_rising_bass/proc/shoulderFlip(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.IsKnockdown() || !D.lying)
var/turf/H = get_step(A, get_dir(D,A))
var/L = H
for(var/obj/i in H.contents)
if(!istype(i,/mob) && i.density == 1)//(i.anchored == 1 && i.density == 1) || istype(i,/obj/structure) || istype(i,/turf/closed)
L = A.loc
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] flips [D] over their shoulder, slamming them into the ground!</span>", \
"<span class='userdanger'>[A] flips you over their shoulder, slamming you into the ground!</span>")
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
D.emote("scream")
D.apply_damage(10, BRUTE, BODY_ZONE_CHEST)
D.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
D.Sleeping(60)
D.Knockdown(300)
D.forceMove(L)
log_combat(A, D, "shoulder flipped (Rising Bass)")
return 1
return basic_hit(A,D)
/datum/martial_art/the_rising_bass/proc/repulsePunch(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.IsKnockdown() || !D.lying)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
D.visible_message("<span class='warning'>[A] smashes [D] in the chest, throwing them away!</span>", \
"<span class='userdanger'>[A] smashes you in the chest, repelling you away!</span>")
playsound(get_turf(A), 'sound/weapons/punch1.ogg', 50, 1, -1)
var/atom/F = get_edge_target_turf(D, get_dir(A, get_step_away(D, A)))
D.throw_at(F, 10, 1)
D.apply_damage(10, BRUTE, BODY_ZONE_CHEST)
D.Knockdown(90)
log_combat(A, D, "repulse punched (Rising Bass)")
return 1
return basic_hit(A,D)
/datum/martial_art/the_rising_bass/proc/footSmash(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.IsKnockdown() || !D.lying)
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
D.visible_message("<span class='warning'>[A] smashes their foot down on [D]'s foot!</span>", \
"<span class='userdanger'>[A] smashes your foot!</span>")
playsound(get_turf(A), 'sound/weapons/punch1.ogg', 50, 1, -1)
D.apply_damage(5, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
D.dropItemToGround(D.get_active_held_item())
log_combat(A, D, "foot smashed (Rising Bass)")
return 1
return basic_hit(A,D)
/datum/martial_art/the_rising_bass/proc/deftSwitch(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.IsKnockdown() || !D.lying)
if (D.get_active_held_item())
var/obj/item/G = D.get_active_held_item()
if (G && !(G.item_flags & (ABSTRACT|DROPDEL)) && D.temporarilyRemoveItemFromInventory(G))
A.put_in_hands(G)
D.visible_message("<span class='warning'>[A] slaps [D]'s hands, taking [G] from them!</span>", \
"<span class='userdanger'>[A] slaps you, taking [G] from you!</span>")
log_combat(A, D, "deft switched (Rising Bass)")
return 1
else
to_chat(A, "<i>[G] can't be taken out of [D]'s hands!</i>")
return 0
/datum/martial_art/the_rising_bass/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
if(check_streak(A,D))
return 1
return ..()
/datum/martial_art/the_rising_bass/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
return ..()
/datum/martial_art/the_rising_bass/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
return ..()
/mob/living/carbon/human/proc/rising_bass_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Rising Bass clan."
set category = "Rising Bass"
to_chat(usr, "<b><i>You retreat inward and recall the teachings of the Rising Bass...</i></b>")
to_chat(usr, "<span class='notice'>Side Kick</span>: Disarm Harm. Forces opponent to step to the side.")
to_chat(usr, "<span class='notice'>Shoulder Flip</span>: Grab Harm Disarm Grab Harm Harm. Flips opponent over your shoulder and stuns.")
to_chat(usr, "<span class='notice'>Repulse Punch</span>: Grab Harm Grab Harm. Slams the opponent far away from you.")
to_chat(usr, "<span class='notice'>Foot Smash</span>: Harm Harm. Stuns opponent, minor damage.")
to_chat(usr, "<span class='notice'>Deft Switch</span>: Grab Disarm Disarm. Switches the opponent's held item for your own. Most useful with nothing in your hand.")
/datum/martial_art/the_rising_bass/teach(mob/living/carbon/human/H, make_temporary = FALSE)
. = ..()
if(!.)
return
ADD_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT)
ADD_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT)
/datum/martial_art/the_rising_bass/on_remove(mob/living/carbon/human/H)
. = ..()
REMOVE_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT)
REMOVE_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT)
+1 -2
View File
@@ -185,9 +185,8 @@
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
block_chance = 50
/obj/item/twohanded/bostaff/update_icon()
/obj/item/twohanded/bostaff/update_icon_state()
icon_state = "bostaff[wielded]"
return
/obj/item/twohanded/bostaff/attack(mob/target, mob/living/user)
add_fingerprint(user)
+3
View File
@@ -135,6 +135,9 @@
if(L.client && L.client.prefs)
L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting...
L.update_arousal_hud() //Removes the old icon
if (L.client.prefs.auto_ooc)
if (L.client.prefs.chat_toggles & CHAT_OOC)
L.client.prefs.chat_toggles ^= CHAT_OOC
SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character)
+17 -7
View File
@@ -3,6 +3,7 @@
var/turf/master_turf //The center of the wave
var/steps=0 //How far we've moved
var/intensity //How strong it was originaly
var/remaining_contam //How much contaminated material it still has
var/range_modifier //Higher than 1 makes it drop off faster, 0.5 makes it drop off half etc
var/move_dir //The direction of movement
var/list/__dirs //The directions to the side of the wave, stored for easy looping
@@ -18,6 +19,7 @@
__dirs+=turn(dir, -90)
intensity = _intensity
remaining_contam = intensity
range_modifier = _range_modifier
can_contaminate = _can_contaminate
@@ -46,8 +48,9 @@
qdel(src)
return
radiate(atoms, FLOOR(strength, 1))
if(radiate(atoms, FLOOR(min(strength,remaining_contam), 1)))
//oof ow ouch
remaining_contam = max(0,remaining_contam-((min(strength,remaining_contam)-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT))
check_obstructions(atoms) // reduce our overall strength if there are radiation insulators
/datum/radiation_wave/proc/get_rad_atoms()
@@ -89,7 +92,8 @@
intensity *= (1-((1-thing.rad_insulation)/width))
/datum/radiation_wave/proc/radiate(list/atoms, strength)
var/contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1, 1/(steps*range_modifier))
var/can_contam = strength >= RAD_MINIMUM_CONTAMINATION
var/list/contam_atoms = list()
for(var/k in 1 to atoms.len)
var/atom/thing = atoms[k]
if(!thing)
@@ -109,8 +113,14 @@
))
if(!can_contaminate || blacklisted[thing.type])
continue
if(prob(contamination_chance)) // Only stronk rads get to have little baby rads
if(CHECK_BITFIELD(thing.rad_flags, RAD_NO_CONTAMINATE) || SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION)
continue
var/rad_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT
if(CHECK_BITFIELD(thing.rad_flags, RAD_NO_CONTAMINATE) || SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION)
continue
contam_atoms += thing
var/did_contam = 0
if(length(can_contam))
var/rad_strength = ((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT)/contam_atoms.len
for(var/k in 1 to contam_atoms.len)
var/atom/thing = contam_atoms[k]
thing.AddComponent(/datum/component/radioactive, rad_strength, source)
did_contam = 1
return did_contam
+21
View File
@@ -0,0 +1,21 @@
/datum/map_template/ruin/station
prefix = "_maps/RandomRuins/StationRuins/"
cost = 0
// Boxstation
// Engine
/datum/map_template/ruin/station/box/engine
id = "engine_sm"
suffix = "Box/Engine/engine_sm.dmm"
name = "Engine SM"
/datum/map_template/ruin/station/box/engine/singulo
id = "engine_singulo"
suffix = "Box/Engine/engine_singulo.dmm"
name = "Engine Singulo"
/datum/map_template/ruin/station/box/engine/tesla
id = "engine_tesla"
suffix = "Box/Engine/engine_tesla.dmm"
name = "Engine Tesla"
+2
View File
@@ -292,6 +292,7 @@
var/mob/living/carbon/C = owner
for(var/X in C.bodyparts)
var/obj/item/bodypart/BP = X
BP.max_damage *= 10
BP.brute_dam *= 10
BP.burn_dam *= 10
owner.toxloss *= 10
@@ -377,6 +378,7 @@
var/obj/item/bodypart/BP = X
BP.brute_dam *= 0.1
BP.burn_dam *= 0.1
BP.max_damage /= 10
owner.toxloss *= 0.1
owner.oxyloss *= 0.1
owner.cloneloss *= 0.1
-29
View File
@@ -88,15 +88,6 @@
if(quirk_holder)
quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
/datum/quirk/crocrin_immunity
name = "Crocin Immunity"
desc = "You're one of the few people in the galaxy who are genetically immune to Crocin and Hexacrocin products and their addictive properties! However, you can still get brain damage from Hexacrocin addiction."
mob_trait = TRAIT_CROCRIN_IMMUNE
value = 0
gain_text = "<span class='notice'>You feel more prudish.</span>"
lose_text = "<span class='notice'>You don't feel as prudish as before.</span>"
medical_record_text = "Patient exhibits a special gene that makes them immune to aphrodisiacs."
/datum/quirk/libido
name = "Nymphomania"
desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
@@ -130,23 +121,3 @@
mob_trait = TRAIT_EXHIBITIONIST
gain_text = "<span class='notice'>You feel like exposing yourself to the world.</span>"
lose_text = "<span class='notice'>Indecent exposure doesn't sound as charming to you anymore.</span>"
/datum/quirk/pharmacokinesis //Prevents unwanted organ additions.
name = "Acute hepatic pharmacokinesis"
desc = "You've a rare genetic disorder that causes Incubus draft and Sucubus milk to be absorbed by your liver instead."
value = 0
mob_trait = TRAIT_PHARMA
lose_text = "<span class='notice'>Your liver feels different.</span>"
medical_record_text = "Non-invasive tests report that the patient's metabolism is indeed incompatible with a certain \"stimulants\"."
var/active = FALSE
var/power = 0
var/cachedmoveCalc = 1
/datum/quirk/assblastusa
name = "Buns of Steel"
desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand."
mob_trait = TRAIT_ASSBLASTUSA
value = 0
medical_record_text = "Patient never skipped ass day."
gain_text = "<span class='notice'>Your ass rivals those of golems.</span>"
lose_text = "<span class='notice'>Your butt feels more squishy and slappable.</span>"
+11 -3
View File
@@ -326,8 +326,13 @@ GLOBAL_LIST_EMPTY(teleportlocs)
F.update_fire_light(fire)
for(var/obj/machinery/light/L in src)
L.update()
/area/proc/update_icon()
/**
* Update the icon state of the area
*
* Im not sure what the heck this does, somethign to do with weather being able to set icon
* states on areas?? where the heck would that even display?
*/
/area/update_icon_state()
var/weather_icon
for(var/V in SSweather.processing)
var/datum/weather/W = V
@@ -337,7 +342,10 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(!weather_icon)
icon_state = null
/area/space/update_icon()
/**
* Update the icon of the area (overridden to always be null for space
*/
/area/space/update_icon_state()
icon_state = null
/*
+30 -2
View File
@@ -24,6 +24,8 @@
var/list/add_overlays // a very temporary list of overlays to add
var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays
///overlays managed by update_overlays() to prevent removing overlays that weren't added by the same proc
var/list/managed_overlays
var/datum/proximity_monitor/proximity_monitor
var/buckle_message_cooldown = 0
@@ -45,7 +47,7 @@
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
GLOB._preloader.load(src)
world.preloader_load(src)
if(datum_flags & DF_USE_TAG)
GenerateTag()
@@ -164,7 +166,7 @@
return FALSE
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
if(does_attack_animation)
user.changeNext_move(CLICK_CD_MELEE)
@@ -310,6 +312,32 @@
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
/// Updates the icon of the atom
/atom/proc/update_icon()
// I expect we're going to need more return flags and options in this proc
var/signalOut = SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON)
if(!(signalOut & COMSIG_ATOM_NO_UPDATE_ICON_STATE))
update_icon_state()
if(!(signalOut & COMSIG_ATOM_NO_UPDATE_OVERLAYS))
var/list/new_overlays = update_overlays()
if(managed_overlays)
cut_overlay(managed_overlays)
managed_overlays = null
if(length(new_overlays))
managed_overlays = new_overlays
add_overlay(new_overlays)
/// Updates the icon state of the atom
/atom/proc/update_icon_state()
/// Updates the overlays of the atom
/atom/proc/update_overlays()
SHOULD_CALL_PARENT(1)
. = list()
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .)
/atom/proc/relaymove(mob/user)
if(buckle_message_cooldown <= world.time)
buckle_message_cooldown = world.time + 50
+3 -3
View File
@@ -519,12 +519,12 @@
step(src, AM.dir)
..()
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY)
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE)
if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY))
return
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force)
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, messy_throw)
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY) //If this returns FALSE then callback will not be called.
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE) //If this returns FALSE then callback will not be called.
. = FALSE
if (!target || speed <= 0)
return
@@ -57,7 +57,6 @@
..()
if(visualsOnly)
return
H.dna.add_mutation(CLOWNMUT)
H.dna.add_mutation(SMILE)
/datum/outfit/syndicate/clownop/leader
+30 -109
View File
@@ -1,14 +1,3 @@
#define CURRENT_LIVING_PLAYERS 1
#define CURRENT_LIVING_ANTAGS 2
#define CURRENT_DEAD_PLAYERS 3
#define CURRENT_OBSERVERS 4
#define ONLY_RULESET 1
#define HIGHLANDER_RULESET 2
#define TRAITOR_RULESET 4
#define MINOR_RULESET 8
#define RULESET_STOP_PROCESSING 1
// -- Injection delays
GLOBAL_VAR_INIT(dynamic_latejoin_delay_min, (10 MINUTES))
@@ -52,6 +41,8 @@ GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset)
// Forced threat level, setting this to zero or higher forces the roundstart threat to the value.
GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
GLOBAL_VAR_INIT(dynamic_storyteller_type, null)
/datum/game_mode/dynamic
name = "dynamic mode"
config_tag = "dynamic"
@@ -60,7 +51,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
announce_text = "Dynamic mode!" // This needs to be changed maybe
reroll_friendly = FALSE;
// 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
var/threat_level = 0
@@ -164,6 +156,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
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 += "<br/>"
dat += "Storyteller: <b>[storyteller.name]</b><br/>"
dat += "Parameters: centre = [GLOB.dynamic_curve_centre] ; width = [GLOB.dynamic_curve_width].<br/>"
dat += "<i>On average, <b>[peaceful_percentage]</b>% of the rounds are more peaceful.</i><br/>"
dat += "Forced extended: <a href='?src=\ref[src];[HrefToken()];forced_extended=1'><b>[GLOB.dynamic_forced_extended ? "On" : "Off"]</b></a><br/>"
@@ -178,7 +171,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
dat += "[DR.ruletype] - <b>[DR.name]</b><br>"
else
dat += "none.<br>"
dat += "<br>Injection Timers: (<b>[get_injection_chance(TRUE)]%</b> chance)<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>"
@@ -336,6 +329,9 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
SSblackbox.record_feedback("tally","dynamic_threat",peaceful_percentage,"Percent of same-vote rounds that are more peaceful")
/datum/game_mode/dynamic/can_start()
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].")
@@ -345,19 +341,12 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if(GLOB.dynamic_forced_threat_level >= 0)
threat_level = round(GLOB.dynamic_forced_threat_level, 0.1)
threat = threat_level
SSblackbox.record_feedback("tally","dynamic_threat",threat_level,"Threat level (forced by admins)")
SSblackbox.record_feedback("tally","dynamic_threat",threat_level,"Threat level (forced)")
else
generate_threat()
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_latejoin_delay_max + GLOB.dynamic_first_latejoin_delay_min)
latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_first_latejoin_delay_min, GLOB.dynamic_first_latejoin_delay_max)) + world.time
storyteller.start_injection_cooldowns()
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max)
midround_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!")
initial_threat_level = threat_level
return TRUE
@@ -391,7 +380,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
log_game("DYNAMIC: [roundstart_rules.len] rules.")
return TRUE
SSblackbox.record_feedback("tally","dynamic",roundstart_rules.len,"Roundstart rules considered")
SSblackbox.record_feedback("tally","dynamic",roundstart_rules.len,"Players readied up")
SSblackbox.record_feedback("tally","dynamic",roundstart_pop_ready,"Players readied up")
if(GLOB.dynamic_forced_roundstart_ruleset.len > 0)
rigged_roundstart()
else
@@ -429,13 +418,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (GLOB.dynamic_forced_extended)
log_game("DYNAMIC: Starting a round of forced extended.")
return TRUE
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules)
if (rule.acceptable(roundstart_pop_ready, threat_level) && threat >= rule.cost) // If we got the population and threat required
rule.candidates = candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
drafted_rules[rule] = rule.weight
var/list/drafted_rules = storyteller.roundstart_draft()
if(!drafted_rules.len)
message_admins("Not enough threat level for roundstart antags!")
log_game("DYNAMIC: Not enough threat level for roundstart antags!")
@@ -653,7 +636,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (rule.persistent)
current_rules += rule
return TRUE
rule.clean_up()
stack_trace("The [rule.ruletype] rule \"[rule.name]\" failed to execute.")
return FALSE
@@ -667,62 +649,41 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
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
// Somehow it managed to trigger midround multiple times so this was moved here.
// There is no way this should be able to trigger an injection twice now.
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
midround_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max)) + world.time)
midround_injection_cooldown = storyteller.get_midround_cooldown() + world.time
// Time to inject some threat into the round
if(EMERGENCY_ESCAPED_OR_ENDGAMED) // Unless the shuttle is gone
return
if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) // no rules after shuttle is auto-called
return
message_admins("DYNAMIC: Checking for midround injection.")
log_game("DYNAMIC: Checking for midround injection.")
update_playercounts()
if (get_injection_chance())
if (prob(storyteller.get_injection_chance()))
SSblackbox.record_feedback("tally","dynamic",1,"Attempted midround injections")
var/cur_threat_frac = threat/threat_level
var/list/drafted_rules = list()
var/antag_num = current_players[CURRENT_LIVING_ANTAGS].len
for (var/datum/dynamic_ruleset/midround/rule in midround_rules)
// if there are antags OR the rule is an antag rule, antag_acceptable will be true.
if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost)
// 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())
if(!antag_num)
drafted_rules[rule] = round(rule.get_weight() + (rule.cost * cur_threat_frac))
else
drafted_rules[rule] = rule.get_weight()
else if(threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
var/list/drafted_rules = storyteller.midround_draft()
if (drafted_rules.len > 0)
SSblackbox.record_feedback("tally","dynamic",1,"Successful midround injections")
picking_midround_latejoin_rule(drafted_rules)
else
midround_injection_cooldown = (midround_injection_cooldown + world.time)/2
// get_injection_chance can do things on fail
if(event_injection_cooldown < world.time)
SSblackbox.record_feedback("tally","dynamic",1,"Attempted event injections")
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
event_injection_cooldown = storyteller.get_event_cooldown() + world.time
message_admins("DYNAMIC: Doing event injection.")
log_game("DYNAMIC: Doing event injection.")
update_playercounts()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in events)
if(rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost)
if(rule.ready())
drafted_rules[rule] = rule.get_weight()
else if(threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
var/list/drafted_rules = storyteller.event_draft()
if(drafted_rules.len > 0)
SSblackbox.record_feedback("tally","dynamic",1,"Successful event injections")
picking_midround_latejoin_rule(drafted_rules)
@@ -741,38 +702,13 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (M.mind && (M.mind.special_role || M.mind.antag_datums?.len > 0))
current_players[CURRENT_LIVING_ANTAGS].Add(M)
else
if (istype(M,/mob/dead/observer))
if (isobserver(M))
var/mob/dead/observer/O = M
if (O.started_as_observer) // Observers
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)
/// Gets the chance for latejoin and midround injection, the dry_run argument is only used for forced injection.
/datum/game_mode/dynamic/proc/get_injection_chance(dry_run = FALSE)
if(forced_injection)
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 = (current_players[CURRENT_LIVING_PLAYERS].len >= GLOB.dynamic_high_pop_limit)
var/max_pop_per_antag = max(5,15 - round(threat_level/10) - round(current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
if (!current_players[CURRENT_LIVING_ANTAGS].len)
chance += 80 // No antags at all? let's boost those odds!
else
var/current_pop_per_antag = current_players[CURRENT_LIVING_PLAYERS].len / 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 (current_players[CURRENT_DEAD_PLAYERS].len > current_players[CURRENT_LIVING_PLAYERS].len)
chance -= 30 // More than half the crew died? ew, let's calm down on antags
if (threat > 70)
chance += 15
if (threat < 30)
chance -= 15
return round(max(0,chance))
/// Removes type from the list
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
for(var/I in type_list)
@@ -803,7 +739,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
return
if(EMERGENCY_ESCAPED_OR_ENDGAMED) // No more rules after the shuttle has left
return
if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) // no rules after shuttle is auto-called
return
update_playercounts()
if (forced_latejoin_rule)
@@ -814,28 +751,12 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
picking_midround_latejoin_rule(list(forced_latejoin_rule), forced = TRUE)
forced_latejoin_rule = null
else if (latejoin_injection_cooldown < world.time && prob(get_injection_chance()))
else if (latejoin_injection_cooldown < world.time && prob(storyteller.get_injection_chance()))
SSblackbox.record_feedback("tally","dynamic",1,"Attempted latejoin injections")
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/latejoin/rule in latejoin_rules)
if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost)
// 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 (threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(rule.flags & HIGHLANDER_RULESET && highlander_executed)
continue
rule.candidates = list(newPlayer)
rule.trim_candidates()
if (rule.ready())
drafted_rules[rule] = rule.get_weight()
var/list/drafted_rules = storyteller.latejoin_draft(newPlayer)
if (drafted_rules.len > 0 && picking_midround_latejoin_rule(drafted_rules))
SSblackbox.record_feedback("tally","dynamic",1,"Successful latejoin injections")
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min)
latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max)) + world.time
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)
@@ -80,9 +80,13 @@
/// Delay for when execute will get called from the time of post_setup (roundstart) or process (midround/latejoin).
/// Make sure your ruleset works with execute being called during the game when using this, and that the clean_up proc reverts it properly in case of faliure.
var/delay = 0
/// List of tags for use in storytellers.
var/list/property_weights = list()
/// Whether or not recent-round weight values are taken into account for this ruleset.
/// Weight reduction uses the same values as secret's recent-round mode weight reduction.
var/always_max_weight = FALSE
/// Weight reduction by recent-rounds. Saved on new.
var/weight_mult = 1
/datum/dynamic_ruleset/New()
..()
@@ -96,13 +100,11 @@
var/high_population_requirements = CONFIG_GET(keyed_list/dynamic_high_population_requirement)
var/list/repeated_mode_adjust = CONFIG_GET(number_list/repeated_mode_adjust)
if(config_tag in weights)
var/weight_mult = 1
if(!always_max_weight && SSpersistence.saved_dynamic_rules.len == 3 && repeated_mode_adjust.len == 3)
var/saved_dynamic_rules = SSpersistence.saved_dynamic_rules
for(var/i in 1 to 3)
if(config_tag in saved_dynamic_rules[i])
weight_mult -= (repeated_mode_adjust[i]/100)
weight = weights[config_tag] * weight_mult
if(config_tag in costs)
cost = costs[config_tag]
if(config_tag in requirementses)
@@ -58,6 +58,7 @@
cost = 10
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
requirements = list(70,60,50,50,40,40,40,30,20,15)
property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1)
high_population_requirement = 15
/datum/dynamic_ruleset/event/pirates/ready(forced = FALSE)
@@ -81,6 +82,7 @@
cost = 10
requirements = list(70,60,50,50,40,40,40,30,20,15)
high_population_requirement = 15
property_weights = list("chaos" = 1, "valid" = 1)
//////////////////////////////////////////////
// //
@@ -100,6 +102,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5) // yes, can happen on fake-extended
high_population_requirement = 5
repeatable = TRUE
property_weights = list("chaos" = 1, "extended" = 2)
/datum/dynamic_ruleset/event/ventclog/ready()
if(mode.threat_level > 30 && mode.threat >= 5 && prob(20))
@@ -133,10 +136,11 @@
required_enemies = list(1,1,0,0,0,0,0,0,0,0)
weight = 4
// no repeatable weight decrease. too variable to be unfun multiple times in one round
cost = 3
cost = 1
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("story_potential" = 1, "extended" = 1)
always_max_weight = TRUE
//////////////////////////////////////////////
@@ -156,6 +160,7 @@
repeatable_weight_decrease = 2
requirements = list(60,50,40,30,30,30,30,30,30,30)
high_population_requirement = 30
property_weights = list("extended" = -2)
/datum/dynamic_ruleset/event/meteor_wave/ready()
if(mode.threat_level > 40 && mode.threat >= 25 && prob(20))
@@ -190,6 +195,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/anomaly_flux
name = "Anomaly: Hyper-Energetic Flux"
@@ -203,6 +209,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 10
repeatable = TRUE
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/anomaly_gravitational
name = "Anomaly: Gravitational"
@@ -214,6 +221,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/anomaly_pyroclastic
name = "Anomaly: Pyroclastic"
@@ -227,6 +235,7 @@
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/anomaly_vortex
name = "Anomaly: Vortex"
@@ -240,6 +249,7 @@
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
property_weights = list("extended" = 1)
//////////////////////////////////////////////
// //
@@ -259,6 +269,7 @@
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
property_weights = list("extended" = -1, "chaos" = 1)
/datum/dynamic_ruleset/event/carp_migration
name = "Carp Migration"
@@ -270,6 +281,7 @@
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/communications_blackout
name = "Communications Blackout"
@@ -283,6 +295,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("extended" = 1, "chaos" = 1)
/datum/dynamic_ruleset/event/processor_overload
name = "Processor Overload"
@@ -296,6 +309,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("extended" = 1, "chaos" = 1)
always_max_weight = TRUE
/datum/dynamic_ruleset/event/space_dust
@@ -310,6 +324,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("extended" = 1)
always_max_weight = TRUE
/datum/dynamic_ruleset/event/major_dust
@@ -324,6 +339,7 @@
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/electrical_storm
name = "Electrical Storm"
@@ -337,6 +353,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/heart_attack
name = "Random Heart Attack"
@@ -350,6 +367,7 @@
requirements = list(101,101,101,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
property_weights = list("extended" = 1)
always_max_weight = TRUE
/datum/dynamic_ruleset/event/radiation_storm
@@ -362,3 +380,4 @@
required_enemies = list(1,1,1,1,1,1,1,1,1,1)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
property_weights = list("extended" = 1,"chaos" = 1)
@@ -69,8 +69,15 @@
high_population_requirement = 15
repeatable = TRUE
flags = TRAITOR_RULESET
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1)
always_max_weight = TRUE
/datum/dynamic_ruleset/latejoin/infiltrator/execute()
. = ..()
for(var/datum/mind/M in assigned)
log_admin("[M.name] was made into a traitor by dynamic.")
message_admins("[M.name] was made into a traitor by dynamic.")
//////////////////////////////////////////////
// //
// REVOLUTIONARY PROVOCATEUR //
@@ -94,6 +101,7 @@
requirements = list(101,101,70,40,40,40,40,40,40,40)
high_population_requirement = 40
flags = HIGHLANDER_RULESET
property_weights = list("trust" = -2, "chaos" = 2, "extended" = -2, "valid" = 2, "conversion" = 1)
var/required_heads_of_staff = 3
var/finished = FALSE
var/datum/team/revolution/revolution
@@ -123,6 +131,8 @@
revolution.update_objectives()
revolution.update_heads()
SSshuttle.registerHostileEnvironment(src)
log_admin("[M.name] was made into a revolutionary by dynamic.")
message_admins("[M.name] was made into a revolutionary by dynamic.")
return TRUE
else
log_game("DYNAMIC: [ruletype] [name] discarded [M.name] from head revolutionary due to ineligibility.")
@@ -187,30 +197,31 @@
//////////////////////////////////////////////
// //
// VAMPIRE //
// BLOODSUCKERS //
// //
//////////////////////////////////////////////
/*
/datum/dynamic_ruleset/latejoin/vampire
name = "vampire"
config_tag = "vampire_latejoin"
antag_flag = ROLE_VAMPIRE
antag_datum = ANTAG_DATUM_VAMPIRE
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain")
/datum/dynamic_ruleset/latejoin/bloodsucker
name = "Bloodsucker Infiltrator"
config_tag = "latejoin_bloodsucker"
antag_datum = ANTAG_DATUM_BLOODSUCKER
antag_flag = ROLE_TRAITOR
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 1
weight = 5
cost = 15
requirements = list(80,70,60,50,40,20,20,15,15,15)
weight = 3
cost = 10
property_weights = list("story_potential" = 2, "extended" = 2, "trust" = -2, "valid" = 1)
requirements = list(70,65,60,55,50,45,40,35,30,30)
high_population_requirement = 30
repeatable = TRUE
high_population_requirement = 15
/datum/dynamic_ruleset/latejoin/vampire/pre_execute()
/datum/dynamic_ruleset/latejoin/bloodsucker/execute()
var/mob/M = pick(candidates)
candidates -= M
assigned += M.mind
M.mind.restricted_roles = restricted_roles
M.mind.special_role = ROLE_VAMPIRE
M.mind.special_role = antag_flag
if(mode.make_bloodsucker(M.mind))
mode.bloodsuckers += M
log_admin("[M.name] was made into a bloodsucker by dynamic.")
message_admins("[M.name] was made into a bloodsucker by dynamic.")
return TRUE
*/
@@ -108,8 +108,12 @@
candidates = pollGhostCandidates("The mode is looking for volunteers to become a [name]", antag_flag, SSticker.mode, antag_flag, poll_time = 300)
if(!candidates || candidates.len <= required_candidates)
if(!candidates || candidates.len < required_candidates)
message_admins("The ruleset [name] did not receive enough applications.")
if(candidates)
message_admins("Only received [candidates.len], needed [required_candidates].")
else
message_admins("There were no candidates.")
log_game("DYNAMIC: The ruleset [name] did not receive enough applications.")
return FALSE
@@ -180,6 +184,7 @@
repeatable = TRUE
high_population_requirement = 15
flags = TRAITOR_RULESET
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1)
always_max_weight = TRUE
/datum/dynamic_ruleset/midround/autotraitor/acceptable(population = 0, threat = 0)
@@ -214,6 +219,8 @@
living_players -= M
var/datum/antagonist/traitor/newTraitor = new
M.mind.add_antag_datum(newTraitor)
log_admin("[M] was made into a traitor by dynamic.")
message_admins("[M] was made into a traitor by dynamic.")
return TRUE
@@ -237,6 +244,7 @@
requirements = list(101,101,70,50,50,50,40,30,30,30)
high_population_requirement = 30
required_type = /mob/living/silicon/ai
property_weights = list("story_potential" = 2, "trust" = 1, "chaos" = 2)
var/ion_announce = 33
var/removeDontImproveChance = 10
@@ -261,6 +269,8 @@
var/datum/antagonist/traitor/AI = new
M.mind.special_role = antag_flag
M.mind.add_antag_datum(AI)
log_admin("[M] was made into a malf AI by dynamic.")
message_admins("[M] was made into a malf AI by dynamic.")
if(prob(ion_announce))
priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", "ionstorm")
if(prob(removeDontImproveChance))
@@ -289,6 +299,7 @@
requirements = list(90,90,70,50,50,50,50,40,30,30)
high_population_requirement = 30
repeatable = TRUE
property_weights = list("story_potential" = 2, "trust" = 1, "chaos" = 2, "extended" = -2)
var/datum/mind/wizard
/datum/dynamic_ruleset/midround/from_ghosts/wizard/ready(forced = FALSE)
@@ -337,6 +348,7 @@
cost = 35
requirements = list(90,90,90,80,70,60,50,40,40,40)
high_population_requirement = 40
property_weights = list("story_potential" = 2, "trust" = 2, "chaos" = 2, "extended" = -2, "valid" = 2)
var/operative_cap = list(2,2,3,3,4,5,5,5,5,5)
var/datum/team/nuclear/nuke_team
flags = HIGHLANDER_RULESET
@@ -390,6 +402,7 @@
requirements = list(101,101,101,80,60,50,50,50,50,50)
high_population_requirement = 50
repeatable = TRUE
property_weights = list("story_potential" = -1, "trust" = 2, "chaos" = 2, "extended" = -2, "valid" = 2)
/datum/dynamic_ruleset/midround/from_ghosts/blob/ready(forced = FALSE)
if (required_candidates > (dead_players.len + list_observers.len))
@@ -421,6 +434,7 @@
high_population_requirement = 50
repeatable_weight_decrease = 2
repeatable = TRUE
property_weights = list("story_potential" = -1, "trust" = 1, "chaos" = 2, "extended" = -2, "valid" = 2)
var/list/vents = list()
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/ready(forced = FALSE)
@@ -476,6 +490,7 @@
high_population_requirement = 50
repeatable_weight_decrease = 2
repeatable = TRUE
property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 2)
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute()
@@ -521,6 +536,7 @@
weight = 4
cost = 5
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
high_population_requirement = 5
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/ready(forced = FALSE)
@@ -555,14 +571,18 @@
cost = 5
requirements = list(30,30,30,30,20,15,15,15,15,15)
high_population_requirement = 15
property_weights = list("story_potential" = -2, "extended" = -1)
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/ready(forced = FALSE)
/datum/dynamic_ruleset/midround/from_ghosts/revenant/acceptable(population = 0,threat = 0)
var/deadMobs = 0
for(var/mob/M in GLOB.dead_mob_list)
deadMobs++
if(deadMobs < REVENANT_SPAWN_THRESHOLD)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/ready(forced = FALSE)
if(required_candidates > (dead_players.len + list_observers.len))
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough ghosts")
return FALSE
@@ -607,6 +627,7 @@
weight = 4
cost = 15
requirements = list(101,101,101,90,80,70,60,50,40,30)
property_weights = list("story_potential" = -2, "extended" = -2, "integrity" = 2, "valid" = 2, "trust" = 2)
high_population_requirement = 30
var/list/spawn_locs = list()
@@ -659,6 +680,7 @@
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
high_population_requirement = 15
var/datum/team/abductor_team/team
property_weights = list("story_potential" = 1, "extended" = -2, "valid" = 1, "trust" = -1, "chaos" = 2)
repeatable_weight_decrease = 4
repeatable = TRUE
@@ -699,6 +721,7 @@
cost = 15
requirements = list(101,101,101,90,80,70,60,50,40,30)
high_population_requirement = 30
property_weights = list("story_potential" = 1, "extended" = -2, "valid" = 2)
var/list/spawn_locs = list()
var/spawn_loc
@@ -745,31 +768,3 @@
#undef ABDUCTOR_MAX_TEAMS
#undef REVENANT_SPAWN_THRESHOLD
//////////////////////////////////////////////
// //
// BLOODSUCKERS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/latejoin/bloodsucker
name = "Bloodsucker Infiltrator"
config_tag = "latejoin_bloodsucker"
antag_datum = ANTAG_DATUM_BLOODSUCKER
antag_flag = ROLE_TRAITOR
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 1
weight = 3
cost = 10
requirements = list(90,80,70,60,55,50,45,40,35,30)
high_population_requirement = 30
repeatable = TRUE
/datum/dynamic_ruleset/latejoin/bloodsucker/execute()
var/mob/M = pick(candidates)
assigned += M.mind
M.mind.special_role = antag_flag
if(mode.make_bloodsucker(M.mind))
mode.bloodsuckers += M
return TRUE
@@ -21,6 +21,7 @@
requirements = list(50,50,50,50,50,50,50,50,50,50)
high_population_requirement = 40
antag_cap = list(1,1,1,1,2,2,2,2,3,3)
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1, "valid" = 1)
always_max_weight = TRUE
var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec)
@@ -61,6 +62,7 @@
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
antag_cap = list(2,2,2,2,2,2,2,2,2,2) // Can pick 3 per team, but rare enough it doesn't matter.
property_weights = list("story_potential" = 1, "trust" = -1, "extended" = 1, "valid" = 1)
var/list/datum/team/brother_team/pre_brother_teams = list()
var/const/min_team_size = 2
@@ -108,6 +110,7 @@
cost = 15
scaling_cost = 15
requirements = list(101,101,101,101,101,101,101,101,101,101)
property_weights = list("trust" = -2, "valid" = 2)
high_population_requirement = 10
antag_cap = list(1,1,1,1,1,2,2,2,2,3)
var/team_mode_probability = 30
@@ -160,6 +163,7 @@
cost = 30
requirements = list(101,101,101,60,50,50,50,50,50,50)
high_population_requirement = 50
property_weights = list("story_potential" = 2, "trust" = 1, "chaos" = 2, "extended" = -2, "valid" = 2)
var/list/roundstart_wizards = list()
/datum/dynamic_ruleset/roundstart/wizard/acceptable(population=0, threat=0)
@@ -222,6 +226,7 @@
weight = 3
cost = 30
requirements = list(101,101,101,80,70,60,50,50,50,50)
property_weights = list("story_potential" = -1, "trust" = -1, "chaos" = 1, "conversion" = 1, "extended" = -2, "valid" = 2)
high_population_requirement = 50
flags = HIGHLANDER_RULESET
antag_cap = list(2,2,2,3,3,4,4,4,4,4)
@@ -283,6 +288,7 @@
high_population_requirement = 50
flags = HIGHLANDER_RULESET
antag_cap = list(1,1,2,3,4,5,5,5,5,5)
property_weights = list("story_potential" = 2, "trust" = 2, "chaos" = 2, "extended" = -2, "valid" = 2)
var/datum/team/nuclear/nuke_team
/datum/dynamic_ruleset/roundstart/nuclear/ready(forced = FALSE)
@@ -373,6 +379,7 @@
flags = HIGHLANDER_RULESET
// I give up, just there should be enough heads with 35 players...
minimum_players = 35
property_weights = list("trust" = -2, "chaos" = 2, "extended" = -2, "valid" = 2, "conversion" = 1)
var/datum/team/revolution/revolution
var/finished = FALSE
@@ -490,6 +497,7 @@
weight = 3
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
property_weights = list("extended" = 2)
high_population_requirement = 101
/datum/dynamic_ruleset/roundstart/extended/pre_execute()
@@ -517,6 +525,7 @@
high_population_requirement = 50
flags = HIGHLANDER_RULESET
antag_cap = list(2,3,3,4,4,4,4,4,4,4)
property_weights = list("trust" = 2, "chaos" = 2, "extended" = -2, "conversion" = 1, "valid" = 2)
var/ark_time
/datum/dynamic_ruleset/roundstart/clockcult/pre_execute()
@@ -616,6 +625,8 @@
antag_leader_datum = /datum/antagonist/nukeop/leader/clownop
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
property_weights = list("trust" = 2, "chaos" = 2, "extended" = -2, "story_potential" = 2, "valid" = 2)
/datum/dynamic_ruleset/roundstart/nuclear/clown_ops/pre_execute()
. = ..()
@@ -647,6 +658,7 @@
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
antag_cap = list(1,1,1,2,2,2,3,3,3,4)
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/roundstart/devil/pre_execute()
var/num_devils = antag_cap[indice_pop]
@@ -698,6 +710,7 @@
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
property_weights = list("extended" = -2, "chaos" = 2, "conversion" = 1, "valid" = 2)
var/players_per_carrier = 30
var/monkeys_to_win = 1
var/escaped_monkeys = 0
@@ -759,6 +772,7 @@
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
property_weights = list("extended" = -2, "chaos" = 2, "trust" = 2)
var/meteordelay = 2000
var/nometeors = 0
var/rampupdelta = 5
@@ -799,7 +813,8 @@
weight = 2
cost = 15
scaling_cost = 10
requirements = list(90,80,70,60,50,50,50,50,50,50)
property_weights = list("story_potential" = 1, "extended" = 1, "trust" = -2, "valid" = 1)
requirements = list(70,65,60,55,50,50,50,50,50,50)
high_population_requirement = 50
antag_cap = list(1,1,1,1,1,2,2,2,2,2)
@@ -0,0 +1,235 @@
/datum/dynamic_storyteller
var/name = "none"
var/desc = "A coder's idiocy."
var/list/property_weights = list()
var/curve_centre = 0
var/curve_width = 1.8
var/forced_threat_level = -1
var/flags = 0
var/weight = 3 // how many rounds need to have been recently played for this storyteller to be left out of the vote
var/datum/game_mode/dynamic/mode = null
/**
Property weights are:
"story_potential" -- essentially how many different ways the antag can be played.
"trust" -- How much it makes the crew trust each other. Negative values means they're suspicious. Team antags are like this.
"chaos" -- How chaotic it makes the round. Has some overlap with "valid" and somewhat contradicts "extended".
"valid" -- How likely the non-antag-enemy crew are to get involved, e.g. nukies encouraging the warden to
let everyone into the armory, wizard moving around and being a nuisance, nightmare busting lights.
"extended" -- How much the antag is conducive to a long round. Nukies and cults are bad for this; Wizard is less bad; and so on.
"conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason.
*/
/datum/dynamic_storyteller/New()
..()
if (istype(SSticker.mode, /datum/game_mode/dynamic))
mode = SSticker.mode
GLOB.dynamic_curve_centre = curve_centre
GLOB.dynamic_curve_width = curve_width
GLOB.dynamic_forced_threat_level = forced_threat_level
/datum/dynamic_storyteller/proc/start_injection_cooldowns()
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_latejoin_delay_max + GLOB.dynamic_first_latejoin_delay_min)
mode.latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_first_latejoin_delay_min, GLOB.dynamic_first_latejoin_delay_max)) + world.time
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max)
mode.midround_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time
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/do_process()
return
/datum/dynamic_storyteller/proc/on_start()
return
/datum/dynamic_storyteller/proc/get_midround_cooldown()
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
return round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max))
/datum/dynamic_storyteller/proc/get_event_cooldown()
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
return round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max))
/datum/dynamic_storyteller/proc/get_latejoin_cooldown()
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min)
return round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max))
/datum/dynamic_storyteller/proc/get_injection_chance(dry_run = FALSE)
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(5,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))
/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
rule.candidates = mode.candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
var/property_weight = 0
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
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)
// 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())
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/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)
// 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())
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/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.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
name = "Chaotic"
curve_centre = 10
desc = "Chaos: high. Variation: high. Likely antags: clock cult, revs, wizard."
property_weights = list("extended" = -1, "chaos" = 10)
weight = 2
flags = WAROPS_ALWAYS_ALLOWED
var/refund_cooldown
/datum/dynamic_storyteller/cowabunga/get_midround_cooldown()
return ..() / 4
/datum/dynamic_storyteller/cowabunga/get_latejoin_cooldown()
return ..() / 4
/datum/dynamic_storyteller/cowabunga/do_process()
if(refund_cooldown < world.time)
mode.refund_threat(10)
mode.log_threat("Cowabunga it is. Refunded 10 threat. Threat is now [mode.threat].")
refund_cooldown = world.time + 300 SECONDS
/datum/dynamic_storyteller/team
name = "Teamwork"
desc = "Chaos: high. Variation: low. Likely antags: nukies, clockwork cult, wizard, blob, xenomorph."
curve_centre = 2
curve_width = 1.5
weight = 2
flags = WAROPS_ALWAYS_ALLOWED
property_weights = list("valid" = 3, "trust" = 5)
/datum/dynamic_storyteller/team/get_injection_chance(dry_run = FALSE)
return (mode.current_players[CURRENT_LIVING_ANTAGS].len ? 0 : ..())
/datum/dynamic_storyteller/conversion
name = "Conversion"
desc = "Chaos: high. Variation: medium. Likely antags: cults, bloodsuckers, revs."
curve_centre = 3
curve_width = 1
weight = 2
flags = WAROPS_ALWAYS_ALLOWED
property_weights = list("valid" = 1, "conversion" = 20)
/datum/dynamic_storyteller/classic
name = "Random"
desc = "Chaos: varies. Variation: highest. No special weights attached."
weight = 6
curve_width = 4
/datum/dynamic_storyteller/memes
name = "Story"
desc = "Chaos: varies. Variation: high. Likely antags: abductors, nukies, wizard, traitor."
curve_width = 4
property_weights = list("story_potential" = 10)
/datum/dynamic_storyteller/suspicion
name = "Intrigue"
desc = "Chaos: low. Variation: high. Likely antags: traitor, bloodsucker. Rare: revs, blood cult."
curve_width = 4
property_weights = list("trust" = -5)
/datum/dynamic_storyteller/liteextended
name = "Calm"
desc = "Chaos: low. Variation: medium. Likely antags: bloodsuckers, traitors, sentient disease, revenant."
curve_centre = -5
curve_width = 0.5
flags = NO_ASSASSIN
weight = 2
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
/datum/dynamic_storyteller/liteextended/get_injection_chance(dry_run = FALSE)
return ..()/2
/datum/dynamic_storyteller/extended
name = "Extended"
desc = "Chaos: none. Variation: none. Likely antags: none."
curve_centre = -20
weight = 2
curve_width = 0.5
/datum/dynamic_storyteller/extended/on_start()
GLOB.dynamic_forced_extended = TRUE
+14 -13
View File
@@ -38,21 +38,22 @@
board.one_access = 1
board.accesses = req_one_access
/obj/machinery/button/update_icon()
cut_overlays()
/obj/machinery/button/update_icon_state()
if(panel_open)
icon_state = "button-open"
if(device)
add_overlay("button-device")
if(board)
add_overlay("button-board")
else if(stat & (NOPOWER|BROKEN))
icon_state = "[skin]-p"
else
if(stat & (NOPOWER|BROKEN))
icon_state = "[skin]-p"
else
icon_state = skin
icon_state = skin
/obj/machinery/button/update_overlays()
. = ..()
if(!panel_open)
return
if(device)
. += "button-device"
if(board)
. += "button-board"
/obj/machinery/button/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
@@ -168,7 +169,7 @@
if(device)
device.pulsed()
addtimer(CALLBACK(src, .proc/update_icon), 15)
addtimer(CALLBACK(src, /atom/.proc/update_icon), 15)
/obj/machinery/button/power_change()
..()
+1 -1
View File
@@ -292,7 +292,7 @@
new /obj/item/stack/cable_coil(loc, 2)
qdel(src)
/obj/machinery/camera/update_icon()
/obj/machinery/camera/update_icon_state()
if(!status)
icon_state = "[initial(icon_state)]1"
else if (stat & EMPED)
+3 -1
View File
@@ -67,7 +67,9 @@
/obj/item/clothing/shoes/kindleKicks = ARCADE_WEIGHT_RARE,
/obj/item/storage/belt/military/snack = ARCADE_WEIGHT_RARE,
/obj/item/clothing/mask/fakemoustache/italian = ARCADE_WEIGHT_RARE
/obj/item/clothing/mask/fakemoustache/italian = ARCADE_WEIGHT_RARE,
/obj/item/clothing/suit/hooded/wintercoat/ratvar/fake = ARCADE_WEIGHT_TRICK,
/obj/item/clothing/suit/hooded/wintercoat/narsie/fake = ARCADE_WEIGHT_TRICK
)
light_color = LIGHT_COLOR_GREEN
+15 -11
View File
@@ -38,17 +38,21 @@
defib.cell.give(180) //90% efficiency, slightly better than the cell charger's 87.5%
update_icon()
/obj/machinery/defibrillator_mount/update_icon()
cut_overlays()
if(defib)
add_overlay("defib")
if(defib.powered)
add_overlay(defib.safety ? "online" : "emagged")
var/ratio = defib.cell.charge / defib.cell.maxcharge
ratio = CEILING(ratio * 4, 1) * 25
add_overlay("charge[ratio]")
if(clamps_locked)
add_overlay("clamps")
/obj/machinery/defibrillator_mount/update_overlays()
. = ..()
if(!defib)
return
. += "defib"
if(defib.powered)
. += (defib.safety ? "online" : "emagged")
var/ratio = defib.cell.charge / defib.cell.maxcharge
ratio = CEILING(ratio * 4, 1) * 25
. += "charge[ratio]"
if(clamps_locked)
. += "clamps"
/obj/machinery/defibrillator_mount/get_cell()
if(defib)
+1 -1
View File
@@ -180,7 +180,7 @@
limit--
while(!FoundDoor && limit)
if (!FoundDoor)
log_world("### MAP WARNING, [src] at [AREACOORD(src)] failed to find a valid airlock to cyclelink with!")
log_mapping("[src] at [AREACOORD(src)] failed to find a valid airlock to cyclelink with!")
return
FoundDoor.cyclelinkedairlock = src
cyclelinkedairlock = FoundDoor
+17 -1
View File
@@ -222,5 +222,21 @@
. += "\t<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
/obj/machinery/iv_drip/telescopic
name = "telescopic IV drip"
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down."
icon_state = "iv_drip"
/obj/machinery/iv_drip/telescopic/update_icon()
..()
icon_state = icon_state + "_tele"
/obj/machinery/iv_drip/telescopic/AltClick(mob/user)
if (attached || beaker || !user.canUseTopic(src, BE_CLOSE))
return ..()
new /obj/item/tele_iv(get_turf(src))
qdel(src)
return TRUE
#undef IV_TAKING
#undef IV_INJECTING
#undef IV_INJECTING
@@ -262,14 +262,14 @@
occupant_message("Deconstructing [W]...")
if(do_after_cooldown(W))
chassis.spark_system.start()
W.ScrapeAway()
W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
playsound(W, 'sound/items/deconstruct.ogg', 50, 1)
else if(isfloorturf(target))
var/turf/open/floor/F = target
occupant_message("Deconstructing [F]...")
if(do_after_cooldown(target))
chassis.spark_system.start()
F.ScrapeAway()
F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
playsound(F, 'sound/items/deconstruct.ogg', 50, 1)
else if (istype(target, /obj/machinery/door/airlock))
occupant_message("Deconstructing [target]...")
@@ -282,7 +282,7 @@
var/turf/open/space/S = target
occupant_message("Building Floor...")
if(do_after_cooldown(S))
S.PlaceOnTop(/turf/open/floor/plating)
S.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
playsound(S, 'sound/items/deconstruct.ogg', 50, 1)
chassis.spark_system.start()
else if(isfloorturf(target))
@@ -123,7 +123,7 @@
if(metal)
var/turf/T = get_turf(src)
if(isspaceturf(T)) //Block up any exposed space
T.PlaceOnTop(/turf/open/floor/plating/foam)
T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR)
for(var/direction in GLOB.cardinals)
var/turf/cardinal_turf = get_step(T, direction)
if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf!
+49
View File
@@ -432,3 +432,52 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
GLOB.ruin_landmarks -= src
ruin_template = null
. = ..()
//------Station Rooms Landmarks------------//
/obj/effect/landmark/stationroom
var/list/template_names = list()
layer = BULLET_HOLE_LAYER
/obj/effect/landmark/stationroom/New()
..()
GLOB.stationroom_landmarks += src
/obj/effect/landmark/stationroom/Destroy()
if(src in GLOB.stationroom_landmarks)
GLOB.stationroom_landmarks -= src
return ..()
/obj/effect/landmark/stationroom/proc/load(template_name)
var/turf/T = get_turf(src)
if(!T)
return FALSE
if(!template_name)
for(var/t in template_names)
if(!SSmapping.station_room_templates[t])
log_world("Station room spawner placed at ([T.x], [T.y], [T.z]) has invalid ruin name of \"[t]\" in its list")
template_names -= t
template_name = safepick(template_names)
if(!template_name)
GLOB.stationroom_landmarks -= src
qdel(src)
return FALSE
var/datum/map_template/template = SSmapping.station_room_templates[template_name]
if(!template)
return FALSE
testing("Room \"[template_name]\" placed at ([T.x], [T.y], [T.z])")
template.load(T, centered = FALSE)
template.loaded++
GLOB.stationroom_landmarks -= src
qdel(src)
return TRUE
// The landmark for the Engine on Box
/obj/effect/landmark/stationroom/box/engine
template_names = list("Engine SM", "Engine Singulo", "Engine Tesla")
icon = 'icons/rooms/box/engine.dmi'
/obj/effect/landmark/stationroom/box/engine/New()
. = ..()
template_names = CONFIG_GET(keyed_list/box_random_engine)
+9 -8
View File
@@ -578,21 +578,22 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
itempush = 0 //too light to push anything
return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum)
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force)
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE)
thrownby = thrower
callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own
callback = CALLBACK(src, .proc/after_throw, callback, (spin && messy_throw)) //replace their callback with our own
. = ..(target, range, speed, thrower, spin, diagonals_first, callback, force)
/obj/item/proc/after_throw(datum/callback/callback)
/obj/item/proc/after_throw(datum/callback/callback, messy_throw)
if (callback) //call the original callback
. = callback.Invoke()
throw_speed = initial(throw_speed) //explosions change this.
item_flags &= ~IN_INVENTORY
var/matrix/M = matrix(transform)
M.Turn(rand(-170, 170))
transform = M
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
if(messy_throw)
var/matrix/M = matrix(transform)
M.Turn(rand(-170, 170))
transform = M
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
/obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/storage
if(!newLoc)
+202
View File
@@ -863,3 +863,205 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(reagents && reagents.total_volume)
hand_reagents()
///////////////
/////BONGS/////
///////////////
/obj/item/bong
name = "bong"
desc = "A water bong used for smoking dried plants."
icon = 'icons/obj/bongs.dmi'
icon_state = null
item_state = null
w_class = WEIGHT_CLASS_NORMAL
light_color = "#FFCC66"
var/icon_off = "bong"
var/icon_on = "bong_lit"
var/chem_volume = 100
var/last_used_time //for cooldown
var/firecharges = 0 //used for counting how many hits can be taken before the flame goes out
var/list/list_reagents = list() //For the base reagents bongs could get
/obj/item/bong/Initialize()
. = ..()
create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it
reagents.add_reagent_list(list_reagents)
icon_state = icon_off
/obj/item/bong/attackby(obj/item/O, mob/user, params)
. = ..()
//If we're using a dried plant..
if(istype(O,/obj/item/reagent_containers/food/snacks))
var/obj/item/reagent_containers/food/snacks/DP = O
if (DP.dry)
//Nothing if our bong is full
if (reagents.holder_full())
user.show_message("<span class='notice'>The bowl is full!</span>", MSG_VISUAL)
return
//Transfer reagents and remove the plant
user.show_message("<span class='notice'>You stuff the [DP] into the [src]'s bowl.</span>", MSG_VISUAL)
DP.reagents.trans_to(src, 100)
qdel(DP)
return
else
user.show_message("<span class='warning'>[DP] must be dried first!</span>", MSG_VISUAL)
return
if (O.get_temperature() <= 500)
return
if (reagents && reagents.total_volume) //if there's stuff in the bong
var/lighting_text = O.ignition_effect(src, user)
if(lighting_text)
//Logic regarding igniting it on
if (firecharges == 0)
user.show_message("<span class='notice'>You light the [src] with the [O]!</span>", MSG_VISUAL)
bongturnon()
else
user.show_message("<span class='notice'>You rekindle [src]'s flame with the [O]!</span>", MSG_VISUAL)
firecharges = 1
return
else
user.show_message("<span warning='notice'>There's nothing to light up in the bowl.</span>", MSG_VISUAL)
return
/obj/item/bong/CtrlShiftClick(mob/user) //empty reagents on alt click
..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if (reagents && reagents.total_volume)
user.show_message("<span class='notice'>You empty the [src].</span>", MSG_VISUAL)
reagents.clear_reagents()
if(firecharges)
firecharges = 0
bongturnoff()
else
user.show_message("<span class='notice'>The [src] is already empty.</span>", MSG_VISUAL)
/obj/item/bong/AltClick(mob/user)
..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(firecharges)
firecharges = 0
bongturnoff()
user.show_message("<span class='notice'>You quench the flame.</span>", MSG_VISUAL)
return TRUE
/obj/item/bong/examine(mob/user)
. = ..()
if(!reagents.total_volume)
. += "<span class='notice'>The bowl is empty.</span>"
else if (reagents.total_volume > 80)
. += "<span class='notice'>The bowl is filled to the brim.</span>"
else if (reagents.total_volume > 40)
. += "<span class='notice'>The bowl has plenty weed in it.</span>"
else
. += "<span class='notice'>The bowl has some weed in it.</span>"
. += "<span class='notice'>Ctrl+Shift-click to empty.</span>"
. += "<span class='notice'>Alt-click to extinguish.</span>"
/obj/item/bong/ignition_effect(atom/A, mob/user)
if(firecharges)
. = "<span class='notice'>[user] lights [A] off of the [src].</span>"
else
. = ""
/obj/item/bong/attack(mob/living/carbon/M, mob/living/carbon/user, obj/target)
//if it's lit up, some stuff in the bowl and the user is a target, and we're not on cooldown
if (M != user)
return ..()
if(user.is_mouth_covered(head_only = 1))
to_chat(user, "<span class='warning'>Remove your headgear first.</span>")
return ..()
if(user.is_mouth_covered(mask_only = 1))
to_chat(user, "<span class='warning'>Remove your mask first.</span>")
return ..()
if (!reagents.total_volume)
to_chat(user, "<span class='warning'>There's nothing in the bowl.</span>")
return ..()
if (!firecharges)
to_chat(user, "<span class='warning'>You have to light it up first.</span>")
return ..()
if (last_used_time + 30 >= world.time)
return ..()
var/hit_strength
var/noise
var/hittext = ""
//if the intent is help then you take a small hit, else a big one
if (user.a_intent == INTENT_HARM)
hit_strength = 2
noise = 100
hittext = "big hit"
else
hit_strength = 1
noise = 70
hittext = "hit"
//bubbling sound
playsound(user.loc,'sound/effects/bonghit.ogg', noise, 1)
last_used_time = world.time
//message
user.visible_message("<span class='notice'>[user] begins to take a [hittext] from the [src]!</span>", \
"<span class='notice'>You begin to take a [hittext] from [src].</span>")
//we take a hit here, after an uninterrupted delay
if(!do_after(user, 25, target = user))
return
if (!(reagents && reagents.total_volume))
return
var/fraction = 12 * hit_strength
var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
s.set_up(reagents, hit_strength, 18, user.loc)
s.start()
reagents.reaction(user, INGEST, fraction)
if(!reagents.trans_to(user, fraction))
reagents.remove_any(fraction)
if (hit_strength == 2 && prob(15))
user.emote("cough")
user.adjustOxyLoss(15)
user.visible_message("<span class='notice'>[user] takes a [hittext] from the [src]!</span>", \
"<span class='notice'>You take a [hittext] from [src].</span>")
firecharges = firecharges - 1
if (!firecharges)
bongturnoff()
if (!reagents.total_volume)
firecharges = 0
bongturnoff()
/obj/item/bong/proc/bongturnon()
icon_state = icon_on
set_light(3, 0.8)
/obj/item/bong/proc/bongturnoff()
icon_state = icon_off
set_light(0, 0.0)
/obj/item/bong/coconut
name = "coconut bong"
icon_off = "coconut_bong"
icon_on = "coconut_bong_lit"
desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo."
+9 -13
View File
@@ -47,8 +47,7 @@
/obj/item/defibrillator/update_icon()
update_power()
update_overlays()
update_charge()
return ..()
/obj/item/defibrillator/proc/update_power()
if(!QDELETED(cell))
@@ -59,23 +58,20 @@
else
powered = FALSE
/obj/item/defibrillator/proc/update_overlays()
cut_overlays()
/obj/item/defibrillator/update_overlays()
. = ..()
if(!on)
add_overlay("[initial(icon_state)]-paddles")
. += "[initial(icon_state)]-paddles"
if(powered)
add_overlay("[initial(icon_state)]-powered")
if(!cell)
add_overlay("[initial(icon_state)]-nocell")
if(!safety)
add_overlay("[initial(icon_state)]-emagged")
/obj/item/defibrillator/proc/update_charge()
if(powered) //so it doesn't show charge if it's unpowered
. += "[initial(icon_state)]-powered"
if(!QDELETED(cell))
var/ratio = cell.charge / cell.maxcharge
ratio = CEILING(ratio*4, 1) * 25
add_overlay("[initial(icon_state)]-charge[ratio]")
if(!cell)
. += "[initial(icon_state)]-nocell"
if(!safety)
. += "[initial(icon_state)]-emagged"
/obj/item/defibrillator/CheckParts(list/parts_list)
..()
@@ -2,7 +2,7 @@
name = "forcefield projector"
desc = "An experimental device that can create several forcefields at a distance."
icon = 'icons/obj/device.dmi'
icon_state = "signmaker_engi"
icon_state = "signmaker_forcefield"
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_flags = NOBLUDGEON
@@ -44,11 +44,6 @@
icon_state = "eng_cypherkey"
channels = list(RADIO_CHANNEL_ENGINEERING = 1)
/obj/item/encryptionkey/headset_rob
name = "robotics radio encryption key"
icon_state = "rob_cypherkey"
channels = list(RADIO_CHANNEL_SCIENCE = 1, RADIO_CHANNEL_ENGINEERING = 1)
/obj/item/encryptionkey/headset_med
name = "medical radio encryption key"
icon_state = "med_cypherkey"
@@ -123,12 +123,6 @@ GLOBAL_LIST_INIT(channel_tokens, list(
icon_state = "eng_headset"
keyslot = new /obj/item/encryptionkey/headset_eng
/obj/item/radio/headset/headset_rob
name = "robotics radio headset"
desc = "Made specifically for the roboticists, who cannot decide between departments."
icon_state = "rob_headset"
keyslot = new /obj/item/encryptionkey/headset_rob
/obj/item/radio/headset/headset_med
name = "medical radio headset"
desc = "A headset for the trained staff of the medbay."
@@ -230,6 +224,14 @@ GLOBAL_LIST_INIT(channel_tokens, list(
icon_state = "srv_headset"
keyslot = new /obj/item/encryptionkey/headset_service
/obj/item/radio/headset/headset_clown
name = "clown's headset"
desc = "A headset for the clown. Finally. A megaphone you can't take away."
icon_state = "srv_headset"
keyslot = new /obj/item/encryptionkey/headset_service
command = TRUE
commandspan = SPAN_CLOWN
/obj/item/radio/headset/headset_cent
name = "\improper CentCom headset"
desc = "A headset used by the upper echelons of Nanotrasen."
@@ -29,6 +29,7 @@
var/freqlock = FALSE // Frequency lock to stop the user from untuning specialist radios.
var/use_command = FALSE // If true, broadcasts will be large and BOLD.
var/command = FALSE // If true, use_command can be toggled at will.
var/commandspan = SPAN_COMMAND //allow us to set what the fuck we want for headsets
// Encryption key handling
var/obj/item/encryptionkey/keyslot
@@ -206,7 +207,7 @@
return
if(use_command)
spans |= SPAN_COMMAND
spans |= commandspan
/*
Roughly speaking, radios attempt to make a subspace transmission (which
@@ -224,7 +224,7 @@
merge_gases()
for(var/i in 1 to 6)
addtimer(CALLBACK(src, .proc/update_icon), 20 + (i - 1) * 10)
addtimer(CALLBACK(src, /atom/.proc/update_icon), 20 + (i - 1) * 10)
else if(valve_open && tank_one && tank_two)
split_gases()
+17
View File
@@ -414,6 +414,23 @@
name = "empty scroll"
icon_state = "blankscroll"
/obj/item/book/granter/martial/bass
martial = /datum/martial_art/the_rising_bass
name = "shifting scroll"
martialname = "rising bass"
desc = "A paper scroll that seems to move even as you read it, the letters never seem to stay still."
greet = "<span class='sciradio'>You have learned the ancient martial art of the Rising Bass. Your skill at running away has increased quite a bit. Use the combos to get away from opponents quickly. Along with this, you now dodge all projectiles and catch anything thrown at you.</span>"
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
remarks = list("The trick is to disarm them...","Running away helps in many situations...","Never stay still...","Fighting won't help unless you're forced to...", "Crush their limbs to incapacitate them...", "Stay as far away as possible...")
/obj/item/book/granter/martial/bass/onlearned(mob/living/carbon/user)
..()
if(oneuse == TRUE)
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"
/obj/item/book/granter/martial/plasma_fist
martial = /datum/martial_art/plasma_fist
name = "frayed scroll"
+1 -1
View File
@@ -79,7 +79,7 @@
/obj/item/holosign_creator/atmos
name = "ATMOS holofan projector"
desc = "A holographic projector that creates holographic barriers that prevent changes in atmosphere conditions."
icon_state = "signmaker_engi"
icon_state = "signmaker_atmos"
holosign_type = /obj/structure/holosign/barrier/atmos
creation_time = 0
max_signs = 3
+1 -1
View File
@@ -374,7 +374,7 @@
It appears to have a wooden grip and a shaved down guard."
icon_state = "cxsword_hilt_traitor"
force_on = 30
armour_penetration = 50
armour_penetration = 35
embedding = list("embedded_pain_multiplier" = 10, "embed_chance" = 75, "embedded_fall_chance" = 0, "embedded_impact_pain_multiplier" = 10)
block_chance = 50
hitsound_on = 'sound/weapons/blade1.ogg'
+3 -2
View File
@@ -216,10 +216,11 @@
return
else
if(last_hit < world.time)
if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return
if(ishuman(target))
var/mob/living/carbon/human/H = target
if (H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
return
if(check_martial_counter(H, user))
return
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
+3 -5
View File
@@ -11,11 +11,9 @@
var/charge_cost = 30
/obj/item/borg/stun/attack(mob/living/M, mob/living/user)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK))
playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(M.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK))
playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(iscyborg(user))
var/mob/living/silicon/robot/R = user
if(!R.cell.use(charge_cost))
+5 -7
View File
@@ -2,8 +2,8 @@
name = "medical pack"
singular_name = "medical pack"
icon = 'icons/obj/stack_objects.dmi'
amount = 6
max_amount = 6
amount = 12
max_amount = 12
w_class = WEIGHT_CLASS_TINY
full_w_class = WEIGHT_CLASS_TINY
throw_speed = 3
@@ -55,9 +55,8 @@
icon_state = "brutepack"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
var/heal_brute = 25
var/heal_brute = 20
self_delay = 20
max_amount = 12
grind_results = list("styptic_powder" = 10)
/obj/item/stack/medical/bruise_pack/heal(mob/living/M, mob/user)
@@ -92,7 +91,6 @@
var/stop_bleeding = 1800
var/heal_brute = 5
self_delay = 10
max_amount = 12
/obj/item/stack/medical/gauze/heal(mob/living/M, mob/user)
if(ishuman(M))
@@ -125,6 +123,7 @@
singular_name = "improvised gauze"
desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds."
stop_bleeding = 900
heal_brute = 0
/obj/item/stack/medical/gauze/cyborg
materials = list()
@@ -139,9 +138,8 @@
icon_state = "ointment"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
var/heal_burn = 25
var/heal_burn = 20
self_delay = 20
max_amount = 12
grind_results = list("silver_sulfadiazine" = 10)
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
@@ -673,7 +673,8 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
merge_type = /obj/item/stack/sheet/bone
GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \
new /datum/stack_recipe("see-through plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \
new /datum/stack_recipe("opaque plastic flaps", /obj/structure/plasticflaps/opaque, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
new /datum/stack_recipe("large trash cart", /obj/structure/closet/crate/bin,50),\
+7 -2
View File
@@ -192,9 +192,14 @@
var/obj/O
if(R.max_res_amount > 1) //Is it a stack?
O = new R.result_type(usr.drop_location(), R.res_amount * multiplier)
else
else if(ispath(R.result_type, /turf))
var/turf/T = usr.drop_location()
if(!isturf(T))
return
T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR)
O = new R.result_type(usr.drop_location())
O.setDir(usr.dir)
if(O)
O.setDir(usr.dir)
use(R.req_amount * multiplier)
//START: oh fuck i'm so sorry
+5 -4
View File
@@ -61,6 +61,7 @@
/obj/item/radio,
/obj/item/clothing/gloves,
/obj/item/holosign_creator,
/obj/item/forcefield_projector,
/obj/item/assembly/signaler
))
STR.can_hold = can_hold
@@ -458,8 +459,7 @@
/obj/item/extinguisher/mini,
/obj/item/radio,
/obj/item/clothing/gloves,
/obj/item/holosign_creator/atmos,
/obj/item/holosign_creator/engineering,
/obj/item/holosign_creator,
/obj/item/forcefield_projector,
/obj/item/assembly/signaler,
/obj/item/lightreplacer,
@@ -571,6 +571,7 @@
/obj/item/reagent_containers/spray,
/obj/item/soap,
/obj/item/holosign_creator,
/obj/item/forcefield_projector,
/obj/item/key/janitor,
/obj/item/clothing/gloves,
/obj/item/melee/flyswatter,
@@ -582,7 +583,7 @@
/obj/item/storage/belt/bandolier
name = "bandolier"
desc = "A bandolier for holding shotgun ammunition."
desc = "A bandolier for holding ammunition."
icon_state = "bandolier"
item_state = "bandolier"
@@ -592,7 +593,7 @@
STR.max_items = 18
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(
/obj/item/ammo_casing/shotgun
/obj/item/ammo_casing
))
/obj/item/storage/belt/bandolier/durathread

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