Merge branch 'master' into shield_bashing

This commit is contained in:
kevinz000
2020-04-15 19:34:08 -07:00
committed by GitHub
420 changed files with 3772 additions and 2976 deletions
+4 -1
View File
@@ -179,7 +179,7 @@
// #define SPEECH_FORCED 7
#define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum)
#define COMSIG_MOB_SPELL_CAST_CHECK "mob_spell_cast_check" //called from base of /obj/effect/proc_holder/spell/cast_check(): (spell)
#define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //called from base of /obj/effect/proc_holder/spell/can_cast(): (spell)
// /mob/living signals
#define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs)
@@ -190,6 +190,7 @@
#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
#define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive)
#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" //sent when a mob/login() finishes: (client)
#define COMSIG_MOB_CLIENT_LOGOUT "comsig_mob_client_logout" //sent when a mob/logout() starts: (client)
#define COMSIG_MOB_CLIENT_MOVE "comsig_mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc)
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
// This returns flags as defined for block in __DEFINES/combat.dm!
@@ -242,12 +243,14 @@
#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args)
#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable)
#define COMSIG_ITEM_WORN_OVERLAYS "item_worn_overlays" //from base of obj/item/worn_overlays(): (isinhands, icon_file, used_state, style_flags, list/overlays)
// THE FOLLOWING TWO BLOCKS SHOULD RETURN BLOCK FLAGS AS DEFINED IN __DEFINES/combat.dm!
#define COMSIG_ITEM_CHECK_BLOCK "check_block" //from base of obj/item/check_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
#define COMSIG_ITEM_RUN_BLOCK "run_block" //from base of obj/item/run_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
// /obj/item/clothing signals
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
#define COMSIG_SUIT_MADE_HELMET "suit_made_helmet" //from base of obj/item/clothing/suit/MakeHelmet(): (helmet)
// /obj/item/implant signals
#define COMSIG_IMPLANT_ACTIVATED "implant_activated" //from base of /obj/item/implant/proc/activate(): ()
+28
View File
@@ -0,0 +1,28 @@
#define DYE_REGISTRY_UNDER "under"
#define DYE_REGISTRY_JUMPSKIRT "jumpskirt"
#define DYE_REGISTRY_GLOVES "gloves"
#define DYE_REGISTRY_SNEAKERS "sneakers"
#define DYE_REGISTRY_FANNYPACK "fannypack"
#define DYE_REGISTRY_BEDSHEET "bedsheet"
#define DYE_RED "red"
#define DYE_ORANGE "orange"
#define DYE_YELLOW "yellow"
#define DYE_GREEN "green"
#define DYE_BLUE "blue"
#define DYE_PURPLE "purple"
#define DYE_BLACK "black"
#define DYE_WHITE "white"
#define DYE_RAINBOW "rainbow"
#define DYE_MIME "mime"
#define DYE_COSMIC "cosmic"
#define DYE_QM "qm"
#define DYE_LAW "law"
#define DYE_CAPTAIN "captain"
#define DYE_HOP "hop"
#define DYE_HOS "hos"
#define DYE_CE "ce"
#define DYE_RD "rd"
#define DYE_CMO "cmo"
#define DYE_REDCOAT "redcoat"
#define DYE_CLOWN "clown"
+1 -9
View File
@@ -1,13 +1,5 @@
/*ALL DEFINES RELATED TO INVENTORY OBJECTS, MANAGEMENT, ETC, GO HERE*/
//ITEM INVENTORY WEIGHT, FOR w_class
#define WEIGHT_CLASS_TINY 1 //Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money
#define WEIGHT_CLASS_SMALL 2 //Pockets can hold small and tiny items, ex: Flashlight, Multitool, Grenades, GPS Device
#define WEIGHT_CLASS_NORMAL 3 //Standard backpacks can carry tiny, small & normal items, ex: Fire extinguisher, Stunbaton, Gas Mask, Metal Sheets
#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in a normal bag, ex: Defibrillator, Backpack, Space Suits
#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons - Can not fit in Boh
#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh
//Inventory depth: limits how many nested storage items you can access directly.
//1: stuff in mob, 2: stuff in backpack, 3: stuff in box in backpack, etc
#define INVENTORY_DEPTH 3
@@ -155,7 +147,7 @@
//flags for covering body parts
#define GLASSESCOVERSEYES (1<<0)
#define MASKCOVERSEYES (1<<1) // get rid of some of the other retardation in these flags
#define MASKCOVERSEYES (1<<1) // get rid of some of the other stupidity in these flags
#define HEADCOVERSEYES (1<<2) // feel free to realloc these numbers for other purposes
#define MASKCOVERSMOUTH (1<<3) // on other items, these are just for mask/head
#define HEADCOVERSMOUTH (1<<4)
+2 -1
View File
@@ -67,6 +67,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
#define isvampire(A) (is_species(A,/datum/species/vampire))
// Citadel specific species
#define isipcperson(A) (is_species(A, /datum/species/ipc))
@@ -263,4 +264,4 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
#define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob))
#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs))
#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs))
@@ -129,11 +129,20 @@
#define HUD_PLANE 21
#define HUD_LAYER 21
#define HUD_RENDER_TARGET "HUD_PLANE"
#define ABOVE_HUD_PLANE 22
#define ABOVE_HUD_LAYER 22
#define VOLUMETRIC_STORAGE_BOX_PLANE 23
#define VOLUMETRIC_STORAGE_BOX_LAYER 23
#define VOLUMETRIC_STORAGE_BOX_RENDER_TARGET "VOLUME_STORAGE_BOX_PLANE"
#define VOLUMETRIC_STORAGE_ITEM_PLANE 24
#define VOLUMETRIC_STORAGE_ITEM_LAYER 24
#define VOLUMETRIC_STORAGE_ITEM_RENDER_TARGET "VOLUME_STORAGE_ITEM_PLANE"
#define ABOVE_HUD_PLANE 25
#define ABOVE_HUD_LAYER 25
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
#define SPLASHSCREEN_LAYER 23
#define SPLASHSCREEN_PLANE 23
#define SPLASHSCREEN_LAYER 30
#define SPLASHSCREEN_PLANE 30
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
+4 -1
View File
@@ -59,6 +59,7 @@
#define MOVESPEED_ID_SPECIES "SPECIES_SPEED_MOD"
#define MOVESPEED_ID_SMALL_STRIDE "SMALL_STRIDE"
#define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG"
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
#define MOVESPEED_ID_SHRINK_RAY "SHRUNKEN_SPEED_MODIFIER"
@@ -78,4 +79,6 @@
#define MOVESPEED_ID_COLD "COLD"
#define MOVESPEED_ID_HUNGRY "HUNGRY"
#define MOVESPEED_ID_DAMAGE_SLOWDOWN "DAMAGE"
#define MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING "FLYING"
#define MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING "FLYING"
#define MOVESPEED_ID_CIRRHOSIS "CIRRHOSIS"
+3 -3
View File
@@ -45,9 +45,9 @@ Ask ninjanomnom if they're around
// WARNING: The deines below could have disastrous consequences if tweaked incorrectly. See: The great SM purge of Oct.6.2017
// contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1/(steps*RAD_DISTANCE_COEFFICIENT), 1))
// contamination_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT
#define RAD_MINIMUM_CONTAMINATION 350 // How strong does a radiation wave have to be to contaminate objects
#define RAD_MINIMUM_CONTAMINATION 300 // How strong does a radiation wave have to be to contaminate objects
#define RAD_CONTAMINATION_CHANCE_COEFFICIENT 0.005 // Higher means higher strength scaling contamination chance
#define RAD_CONTAMINATION_STR_COEFFICIENT 0.3 // Higher means higher strength scaling contamination strength
#define RAD_CONTAMINATION_STR_COEFFICIENT 0.99 // Higher means higher strength scaling contamination strength
#define RAD_DISTANCE_COEFFICIENT 1 // Lower means further rad spread
#define RAD_HALF_LIFE 90 // The half-life of contaminated objects
#define RAD_HALF_LIFE 90 // The half-life of contaminated objects
+47
View File
@@ -0,0 +1,47 @@
// storage_flags variable on /datum/component/storage
// Storage limits. These can be combined (and usually are combined).
/// Check max_items and contents.len when trying to insert
#define STORAGE_LIMIT_MAX_ITEMS (1<<0)
/// Check max_combined_w_class.
#define STORAGE_LIMIT_COMBINED_W_CLASS (1<<1)
/// Use the new volume system. Will automatically force rendering to use the new volume/baystation scaling UI so this is kind of incompatible with stuff like stack storage etc etc.
#define STORAGE_LIMIT_VOLUME (1<<2)
/// Use max_w_class
#define STORAGE_LIMIT_MAX_W_CLASS (1<<3)
#define STORAGE_FLAGS_LEGACY_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_COMBINED_W_CLASS | STORAGE_LIMIT_MAX_W_CLASS)
#define STORAGE_FLAGS_VOLUME_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_VOLUME | STORAGE_LIMIT_MAX_W_CLASS)
//ITEM INVENTORY WEIGHT, FOR w_class
/// Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money
#define WEIGHT_CLASS_TINY 1
/// Pockets can hold small and tiny items, ex: Flashlight, Multitool, Grenades, GPS Device
#define WEIGHT_CLASS_SMALL 2
/// Standard backpacks can carry tiny, small & normal items, ex: Fire extinguisher, Stunbaton, Gas Mask, Metal Sheets
#define WEIGHT_CLASS_NORMAL 3
/// Items that can be weilded or equipped but not stored in a normal bag, ex: Defibrillator, Backpack, Space Suits
#define WEIGHT_CLASS_BULKY 4
/// Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons - Can not fit in Boh
#define WEIGHT_CLASS_HUGE 5
/// Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh
#define WEIGHT_CLASS_GIGANTIC 6
/// Macro for automatically getting the volume of an item from its w_class.
#define AUTO_SCALE_VOLUME(w_class) (2 ** w_class)
/// Macro for automatically getting the volume of a storage item from its max_w_class and max_combined_w_class.
#define AUTO_SCALE_STORAGE_VOLUME(w_class, max_combined_w_class) (AUTO_SCALE_VOLUME(w_class) * (max_combined_w_class / w_class))
// UI defines
/// Size of volumetric box icon
#define VOLUMETRIC_STORAGE_BOX_ICON_SIZE 32
/// Size of EACH left/right border icon for volumetric boxes
#define VOLUMETRIC_STORAGE_BOX_BORDER_SIZE 1
/// Minimum pixels an item must have in volumetric scaled storage UI
#define MINIMUM_PIXELS_PER_ITEM 6
/// Maximum number of objects that will be allowed to be displayed using the volumetric display system. Arbitrary number to prevent server lockups.
#define MAXIMUM_VOLUMETRIC_ITEMS 256
/// How much padding to give between items
#define VOLUMETRIC_STORAGE_ITEM_PADDING 1
/// How much padding to give to edges
#define VOLUMETRIC_STORAGE_EDGE_PADDING 1
+21
View File
@@ -550,6 +550,27 @@
for(var/thing in flat_list)
.[thing] = TRUE
/proc/deep_list2params(list/deep_list)
var/list/L = list()
for(var/i in deep_list)
var/key = i
if(isnum(key))
L += "[key]"
continue
if(islist(key))
key = deep_list2params(key)
else if(!istext(key))
key = "[REF(key)]"
L += "[key]"
var/value = deep_list[key]
if(!isnull(value))
if(islist(value))
value = deep_list2params(value)
else if(!(istext(key) || isnum(key)))
value = "[REF(value)]"
L["[key]"] = "[value]"
return list2params(L)
//Picks from the list, with some safeties, and returns the "default" arg if it fails
#define DEFAULTPICK(L, default) ((islist(L) && length(L)) ? pick(L) : default)
+1 -1
View File
@@ -183,7 +183,7 @@
return
// Better recursive loop, technically sort of not actually recursive cause that shit is retarded, enjoy.
// Better recursive loop, technically sort of not actually recursive cause that shit is stupid, enjoy.
//No need for a recursive limit either
/proc/recursive_mob_check(atom/O,client_check=1,sight_check=1,include_radio=1)
+8
View File
@@ -89,6 +89,14 @@
INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL()
for(var/path in subtypesof(/area/holodeck))
var/area/holodeck/A = path
var/list/compatibles = initial(A.compatible_holodeck_comps)
if(!compatibles || initial(A.abstract_type) == path)
continue
for(var/comp in compatibles)
LAZYADD(GLOB.holodeck_areas_prototypes[comp], A)
//creates every subtype of prototype (excluding prototype) and adds it to list L.
//if no list/L is provided, one is created.
/proc/init_subtypes(prototype, list/L)
+2 -1
View File
@@ -209,7 +209,8 @@
"ipc_antenna" = "None",
"flavor_text" = "",
"meat_type" = "Mammalian",
"body_model" = MALE
"body_model" = MALE,
"body_size" = RESIZE_DEFAULT_SIZE
))
/proc/random_hair_style(gender)
+13 -9
View File
@@ -27,12 +27,20 @@
return
var/area/A = get_area(source)
var/atom/nested_loc = source.loc
var/spawn_waves = TRUE
while(nested_loc != A)
if(nested_loc.rad_flags & RAD_PROTECT_CONTENTS)
return
spawn_waves = FALSE
break
nested_loc = nested_loc.loc
for(var/dir in GLOB.cardinals)
new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate)
if(spawn_waves)
for(var/dir in GLOB.cardinals)
new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate)
var/static/last_huge_pulse = 0
if(intensity > 3000 && world.time > last_huge_pulse + 200)
last_huge_pulse = world.time
log = TRUE
var/list/things = get_rad_contents(source) //copypasta because I don't want to put special code in waves to handle their origin
for(var/k in 1 to things.len)
@@ -41,11 +49,7 @@
continue
thing.rad_act(intensity)
var/static/last_huge_pulse = 0
if(intensity > 3000 && world.time > last_huge_pulse + 200)
last_huge_pulse = world.time
log = TRUE
if(log)
var/turf/_source_T = isturf(source) ? source : get_turf(source)
log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(_source_T)] ")
var/turf/_source_T = get_turf(source)
log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(_source_T)][spawn_waves ? "" : " (contained by [nested_loc.name])"]")
return TRUE
+1 -1
View File
@@ -513,7 +513,7 @@
if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED)
SSticker.show_roundend_report(owner.client, FALSE)
/datum/action/report/IsAvailable()
/datum/action/report/IsAvailable(silent = FALSE)
return 1
/datum/action/report/Topic(href,href_list)
+13 -2
View File
@@ -8,10 +8,8 @@
/proc/invertHTML(HTMLstring)
if(!istext(HTMLstring))
CRASH("Given non-text argument!")
return
else if(length(HTMLstring) != 7)
CRASH("Given non-HTML argument!")
return
else if(length_char(HTMLstring) != 7)
CRASH("Given non-hex symbols in argument!")
var/textr = copytext(HTMLstring, 2, 4)
@@ -1565,3 +1563,16 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
if(channels_to_use.len)
world.TgsChatBroadcast()
//Checks to see if either the victim has a garlic necklace or garlic in their blood
/proc/blood_sucking_checks(var/mob/living/carbon/target, check_neck, check_blood)
//Bypass this if the target isnt carbon.
if(!iscarbon(target))
return TRUE
if(check_neck)
if(istype(target.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace))
return FALSE
if(check_blood)
if(target.reagents.has_reagent(/datum/reagent/consumable/garlic))
return FALSE
return TRUE
+14 -8
View File
@@ -251,13 +251,19 @@ GLOBAL_LIST_INIT(bitfields, list(
"COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST
),
"shield_flags" = list(
"SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
"SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
"SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
"SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
"SHIELD_BASH_WALL_DISARM" = SHIELD_BASH_WALL_DISARM,
"SHIELD_BASH_ALWAYS_DISARM" = SHIELD_BASH_ALWAYS_DISARM,
"SHIELD_BASH_GROUND_SLAM" = SHIELD_BASH_GROUND_SLAM,
"SHIELD_BASH_GROUND_SLAM_DISARM" = SHIELD_BASH_GROUND_SLAM_DISARM
"SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
"SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
"SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
"SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
"SHIELD_BASH_WALL_DISARM" = SHIELD_BASH_WALL_DISARM,
"SHIELD_BASH_ALWAYS_DISARM" = SHIELD_BASH_ALWAYS_DISARM,
"SHIELD_BASH_GROUND_SLAM" = SHIELD_BASH_GROUND_SLAM,
"SHIELD_BASH_GROUND_SLAM_DISARM" = SHIELD_BASH_GROUND_SLAM_DISARM
),
"storage_flags" = list(
"STORAGE_LIMIT_MAX_ITEMS" = STORAGE_LIMIT_MAX_ITEMS,
"STORAGE_LIMIT_MAX_W_CLASS" = STORAGE_LIMIT_MAX_W_CLASS,
"STORAGE_LIMIT_COMBINED_W_CLASS" = STORAGE_LIMIT_COMBINED_W_CLASS,
"STORAGE_LIMIT_VOLUME" = STORAGE_LIMIT_VOLUME
)
))
+2
View File
@@ -50,3 +50,5 @@ 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
GLOBAL_LIST_EMPTY(holodeck_areas_prototypes) //List of holodeck area prototypes per holodeck computer type
+1 -1
View File
@@ -334,7 +334,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
return
var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!antag)
if(!antag?.cult_team)
return
var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives
+1 -1
View File
@@ -367,7 +367,7 @@
blood_display.hud = src
infodisplay += blood_display
vamprank_display = new /obj/screen/bloodsucker/rank_counter // Vampire Rank
vamprank_display = new /obj/screen/bloodsucker/rank_counter // Bloodsucker Rank
vamprank_display.hud = src
infodisplay += vamprank_display
-38
View File
@@ -210,20 +210,6 @@
user.swap_hand(held_index)
return TRUE
/obj/screen/close
name = "close"
layer = ABOVE_HUD_LAYER
plane = ABOVE_HUD_PLANE
icon_state = "backpack_close"
/obj/screen/close/Initialize(mapload, new_master)
. = ..()
master = new_master
/obj/screen/close/Click()
var/datum/component/storage/S = master
S.hide_from(usr)
return TRUE
/obj/screen/drop
name = "drop"
@@ -406,30 +392,6 @@
else
icon_state = "act_rest0"
/obj/screen/storage
name = "storage"
icon_state = "block"
screen_loc = "7,7 to 10,8"
layer = HUD_LAYER
plane = HUD_PLANE
/obj/screen/storage/Initialize(mapload, new_master)
. = ..()
master = new_master
/obj/screen/storage/Click(location, control, params)
if(world.time <= usr.next_move)
return TRUE
if(usr.incapacitated())
return TRUE
if (ismecha(usr.loc)) // stops inventory actions in a mech
return TRUE
if(master)
var/obj/item/I = usr.get_active_held_item()
if(I)
master.attackby(null, I, usr, params)
return TRUE
/obj/screen/throw_catch
name = "throw/catch"
icon = 'icons/mob/screen_midnight.dmi'
+110
View File
@@ -0,0 +1,110 @@
/obj/screen/storage
name = "storage"
var/insertion_click = FALSE
/obj/screen/storage/Initialize(mapload, new_master)
. = ..()
master = new_master
/obj/screen/storage/Click(location, control, params)
if(!insertion_click)
return ..()
if(world.time <= usr.next_move)
return TRUE
if(usr.incapacitated())
return TRUE
if (ismecha(usr.loc)) // stops inventory actions in a mech
return TRUE
if(master)
var/obj/item/I = usr.get_active_held_item()
if(I)
master.attackby(null, I, usr, params)
return TRUE
/obj/screen/storage/boxes
name = "storage"
icon_state = "block"
screen_loc = "7,7 to 10,8"
layer = HUD_LAYER
plane = HUD_PLANE
insertion_click = TRUE
/obj/screen/storage/close
name = "close"
layer = ABOVE_HUD_LAYER
plane = ABOVE_HUD_PLANE
icon_state = "backpack_close"
/obj/screen/storage/close/Click()
var/datum/component/storage/S = master
S.close(usr)
return TRUE
/obj/screen/storage/left
icon_state = "storage_start"
insertion_click = TRUE
/obj/screen/storage/right
icon_state = "storage_end"
insertion_click = TRUE
/obj/screen/storage/continuous
icon_state = "storage_continue"
insertion_click = TRUE
/obj/screen/storage/volumetric_box
icon_state = "stored_continue"
var/obj/item/our_item
/obj/screen/storage/volumetric_box/Initialize(mapload, new_master, our_item)
src.our_item = our_item
return ..()
/obj/screen/storage/volumetric_box/Destroy()
our_item = null
return ..()
/obj/screen/storage/volumetric_box/Click(location, control, params)
return our_item.Click(location, control, params)
/obj/screen/storage/volumetric_box/center
icon_state = "stored_continue"
var/obj/screen/storage/stored_left/left
var/obj/screen/storage/stored_right/right
var/pixel_size
/obj/screen/storage/volumetric_box/center/Initialize(mapload, new_master, our_item)
left = new(null, src, our_item)
right = new(null, src, our_item)
return ..()
/obj/screen/storage/volumetric_box/center/Destroy()
QDEL_NULL(left)
QDEL_NULL(right)
return ..()
/obj/screen/storage/volumetric_box/center/proc/on_screen_objects()
return list(src, left, right)
/**
* Sets the size of this box screen object and regenerates its left/right borders. This includes the actual border's size!
*/
/obj/screen/storage/volumetric_box/center/proc/set_pixel_size(pixels)
if(pixel_size == pixels)
return
pixel_size = pixels
cut_overlays()
//our icon size is 32 pixels.
transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0)
left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
add_overlay(left)
add_overlay(right)
/obj/screen/storage/stored_left
icon_state = "stored_start"
appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM // Yes I know RESET_TRANSFORM is in APPEARANCE_UI but we're hard-asserting this incase someone changes it.
/obj/screen/storage/stored_right
icon_state = "stored_end"
appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM
+1 -1
View File
@@ -131,7 +131,7 @@
I.do_stagger_action(src, user)
if(I.force)
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
if(I.damtype == BRUTE)
if(prob(33))
I.add_mob_blood(src)
var/turf/location = get_turf(src)
@@ -449,3 +449,27 @@
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_FLAG
config_entry_value = list(GEN_VISIBLE_NO_CLOTHES, GEN_VISIBLE_NO_UNDIES, GEN_VISIBLE_NEVER) //refer to cit_helpers for all toggles.
//Body size configs, the feature will be disabled if both min and max have the same value.
/datum/config_entry/number/body_size_min
config_entry_value = RESIZE_DEFAULT_SIZE
min_val = 0.1 //to avoid issues with zeros and negative values.
max_val = RESIZE_DEFAULT_SIZE
/datum/config_entry/number/body_size_max
config_entry_value = RESIZE_DEFAULT_SIZE
min_val = RESIZE_DEFAULT_SIZE
//Pun-Pun movement slowdown given to characters with a body size smaller than this value,
//to compensate for their smaller hitbox.
//To disable, just make sure the value is lower than 'body_size_min'
/datum/config_entry/number/threshold_body_size_slowdown
config_entry_value = RESIZE_DEFAULT_SIZE * 0.85
min_val = 0
max_val = RESIZE_DEFAULT_SIZE
//multiplicative slowdown multiplier. See 'dna.update_body_size' for the operation.
//doesn't apply to floating or crawling mobs
/datum/config_entry/number/body_size_slowdown_multiplier
config_entry_value = 0.25
min_val = 0.1 //To encourage folks to disable the slowdown through the above config instead.
-2
View File
@@ -27,13 +27,11 @@
var/hook_path = text2path("/hook/[hook]")
if(!hook_path)
CRASH("Invalid hook '/hook/[hook]' called.")
return 0
var/caller = new hook_path
var/status = 1
for(var/P in typesof("[hook_path]/proc"))
if(!call(caller, P)(arglist(args)))
CRASH("Hook '[P]' failed or runtimed.")
status = 0
return status
+8 -2
View File
@@ -38,11 +38,17 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
if(istext(key))
value = arguments[key]
if(!(istext(key) || isnum(key)))
key = REF(key)
if(islist(key)) // CITADEL EDIT
key = deep_list2params(key)
else
key = REF(key)
key = "[key]" // Key is stringified so numbers dont break things
if(!isnull(value))
if(!(istext(value) || isnum(value)))
value = REF(value)
if(islist(value)) // CITADEL EDIT
value = deep_list2params(value)
else
value = REF(value)
named_arguments["[key]"] = value
else
fullid += "[key]"
+8 -5
View File
@@ -21,9 +21,6 @@ SUBSYSTEM_DEF(fail2topic)
DropFirewallRule() // Clear the old bans if any still remain
if (world.system_type == UNIX && enabled)
enabled = FALSE
subsystem_log("DISABLED - UNIX systems are not supported.")
if(!enabled)
flags |= SS_NO_FIRE
can_fire = FALSE
@@ -90,7 +87,10 @@ SUBSYSTEM_DEF(fail2topic)
fail_counts -= ip
rate_limiting -= ip
. = shell("netsh advfirewall firewall add rule name=\"[rule_name]\" dir=in interface=any action=block remoteip=[ip]")
if (world.system_type == UNIX)
. = shell("iptables -A [rule_name] -s [ip] -j DROP")
else
. = shell("netsh advfirewall firewall add rule name=\"[rule_name]\" dir=in interface=any action=block remoteip=[ip]")
if (.)
subsystem_log("Failed to ban [ip]. Exit code: [.].")
@@ -105,7 +105,10 @@ SUBSYSTEM_DEF(fail2topic)
active_bans = list()
. = shell("netsh advfirewall firewall delete rule name=\"[rule_name]\"")
if (world.system_type == UNIX)
. = shell("iptables -F [rule_name]") //Let's just assume that folks running linux are smart enough to have a dedicated chain configured for this.
else
. = shell("netsh advfirewall firewall delete rule name=\"[rule_name]\"")
if (.)
subsystem_log("Failed to drop firewall rule. Exit code: [.].")
+2 -1
View File
@@ -192,7 +192,8 @@ SUBSYSTEM_DEF(persistence)
if(!json)
return
saved_storytellers = json["data"]
average_dynamic_threat = saved_storytellers[4]
if(saved_storytellers.len > 3)
average_dynamic_threat = saved_storytellers[4]
saved_storytellers.len = 3
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
@@ -86,7 +86,6 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
circuit_fabricator_recipe_list["Tools"] = list(
/obj/item/integrated_electronics/wirer,
/obj/item/integrated_electronics/debugger,
/obj/item/integrated_electronics/analyzer,
/obj/item/integrated_electronics/detailer,
/obj/item/card/data,
/obj/item/card/data/full_color,
@@ -47,7 +47,6 @@ PROCESSING_SUBSYSTEM_DEF(weather)
break
if (!ispath(weather_datum_type, /datum/weather))
CRASH("run_weather called with invalid weather_datum_type: [weather_datum_type || "null"]")
return
if (isnull(z_levels))
z_levels = SSmapping.levels_by_trait(initial(weather_datum_type.target_trait))
@@ -55,7 +54,6 @@ PROCESSING_SUBSYSTEM_DEF(weather)
z_levels = list(z_levels)
else if (!islist(z_levels))
CRASH("run_weather called with invalid z_levels: [z_levels || "null"]")
return
var/datum/weather/W = new weather_datum_type(z_levels)
W.telegraph()
+1 -1
View File
@@ -763,7 +763,7 @@ SUBSYSTEM_DEF(vote)
remove_from_client()
Remove(owner)
/datum/action/vote/IsAvailable()
/datum/action/vote/IsAvailable(silent = FALSE)
return 1
/datum/action/vote/proc/remove_from_client()
+51 -52
View File
@@ -6,13 +6,15 @@
/datum/action
var/name = "Generic Action"
var/desc = null
var/obj/target = null
var/atom/target = null
var/check_flags = 0
var/required_mobility_flags = MOBILITY_USE
var/processing = FALSE
var/obj/screen/movable/action_button/button = null
var/buttontooltipstyle = ""
var/transparent_when_unavailable = TRUE
var/use_target_appearance = FALSE
var/list/target_appearance_matrix //if set, will be used to transform the target button appearance as an arglist.
var/button_icon = 'icons/mob/actions/backgrounds.dmi' //This is the file for the BACKGROUND icon
var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND //And this is the state for the background icon
@@ -88,14 +90,14 @@
/datum/action/proc/Trigger()
if(!IsAvailable())
return FALSE
if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER)
if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, target) & COMPONENT_ACTION_BLOCK_TRIGGER)
return FALSE
return TRUE
/datum/action/proc/Process()
return
/datum/action/proc/IsAvailable()
/datum/action/proc/IsAvailable(silent = FALSE)
if(!owner)
return FALSE
var/mob/living/L = owner
@@ -116,29 +118,42 @@
return TRUE
/datum/action/proc/UpdateButtonIcon(status_only = FALSE, force = FALSE)
if(button)
if(!status_only)
button.name = name
button.desc = desc
if(owner && owner.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND)
var/list/settings = owner.hud_used.get_action_buttons_icons()
if(button.icon != settings["bg_icon"])
button.icon = settings["bg_icon"]
if(button.icon_state != settings["bg_state"])
button.icon_state = settings["bg_state"]
else
if(button.icon != button_icon)
button.icon = button_icon
if(button.icon_state != background_icon_state)
button.icon_state = background_icon_state
if(!button)
return
if(!status_only)
button.name = name
button.desc = desc
if(owner && owner.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND)
var/list/settings = owner.hud_used.get_action_buttons_icons()
if(button.icon != settings["bg_icon"])
button.icon = settings["bg_icon"]
if(button.icon_state != settings["bg_state"])
button.icon_state = settings["bg_state"]
else
if(button.icon != button_icon)
button.icon = button_icon
if(button.icon_state != background_icon_state)
button.icon_state = background_icon_state
if(!use_target_appearance)
ApplyIcon(button, force)
if(!IsAvailable())
button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0)
else
button.color = rgb(255,255,255,255)
return 1
else if(target && button.appearance_cache != target.appearance) //replace with /ref comparison if this is not valid.
var/mutable_appearance/M = new(target)
M.layer = FLOAT_LAYER
M.plane = FLOAT_PLANE
if(target_appearance_matrix)
var/list/L = target_appearance_matrix
M.transform = matrix(L[1], L[2], L[3], L[4], L[5], L[6])
button.cut_overlays()
button.add_overlay(M)
button.appearance_cache = target.appearance
if(!IsAvailable(TRUE))
button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0)
else
button.color = rgb(255,255,255,255)
return 1
/datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button, force = FALSE)
if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force))
@@ -165,6 +180,7 @@
/datum/action/item_action
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
button_icon_state = null
use_target_appearance = TRUE
// If you want to override the normal icon being the item
// then change this to an icon state
@@ -188,23 +204,6 @@
I.ui_action_click(owner, src)
return 1
/datum/action/item_action/ApplyIcon(obj/screen/movable/action_button/current_button, force)
if(button_icon && button_icon_state)
// If set, use the custom icon that we set instead
// of the item appearence
..()
else if(target && current_button.appearance_cache != target.appearance) //replace with /ref comparison if this is not valid.
var/obj/item/I = target
var/old_layer = I.layer
var/old_plane = I.plane
I.layer = FLOAT_LAYER //AAAH
I.plane = FLOAT_PLANE //^ what that guy said
current_button.cut_overlays()
current_button.add_overlay(I)
I.layer = old_layer
I.plane = old_plane
current_button.appearance_cache = I.appearance
/datum/action/item_action/toggle_light
name = "Toggle Light"
@@ -308,7 +307,7 @@
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "vortex_recall"
/datum/action/item_action/vortex_recall/IsAvailable()
/datum/action/item_action/vortex_recall/IsAvailable(silent = FALSE)
if(istype(target, /obj/item/hierophant_club))
var/obj/item/hierophant_club/H = target
if(H.teleporting)
@@ -320,7 +319,7 @@
background_icon_state = "bg_clock"
buttontooltipstyle = "clockcult"
/datum/action/item_action/clock/IsAvailable()
/datum/action/item_action/clock/IsAvailable(silent = FALSE)
if(!is_servant_of_ratvar(owner))
return 0
return ..()
@@ -329,7 +328,7 @@
name = "Create Judicial Marker"
desc = "Allows you to create a stunning Judicial Marker at any location in view. Click again to disable."
/datum/action/item_action/clock/toggle_visor/IsAvailable()
/datum/action/item_action/clock/toggle_visor/IsAvailable(silent = FALSE)
if(!is_servant_of_ratvar(owner))
return 0
if(istype(target, /obj/item/clothing/glasses/judicial_visor))
@@ -408,7 +407,7 @@
/datum/action/item_action/jetpack_stabilization
name = "Toggle Jetpack Stabilization"
/datum/action/item_action/jetpack_stabilization/IsAvailable()
/datum/action/item_action/jetpack_stabilization/IsAvailable(silent = FALSE)
var/obj/item/tank/jetpack/J = target
if(!istype(J) || !J.on)
return 0
@@ -465,7 +464,7 @@
/datum/action/item_action/organ_action
check_flags = AB_CHECK_CONSCIOUS
/datum/action/item_action/organ_action/IsAvailable()
/datum/action/item_action/organ_action/IsAvailable(silent = FALSE)
var/obj/item/organ/I = target
if(!I.owner)
return 0
@@ -634,32 +633,32 @@
return FALSE
if(target)
var/obj/effect/proc_holder/S = target
S.Click()
S.Trigger(usr)
return TRUE
/datum/action/spell_action/IsAvailable()
/datum/action/spell_action/IsAvailable(silent = FALSE)
if(!target)
return FALSE
return TRUE
/datum/action/spell_action/spell
/datum/action/spell_action/spell/IsAvailable()
/datum/action/spell_action/spell/IsAvailable(silent = FALSE)
if(!target)
return FALSE
var/obj/effect/proc_holder/spell/S = target
if(owner)
return S.can_cast(owner, FALSE, TRUE)
return S.can_cast(owner, FALSE, silent)
return FALSE
/datum/action/spell_action/alien
/datum/action/spell_action/alien/IsAvailable()
/datum/action/spell_action/alien/IsAvailable(silent = FALSE)
if(!target)
return FALSE
var/obj/effect/proc_holder/alien/ab = target
if(owner)
return ab.cost_check(ab.check_turf,owner,1)
return ab.cost_check(ab.check_turf,owner,silent)
return FALSE
@@ -701,7 +700,7 @@
button.maptext_width = 24
button.maptext_height = 12
/datum/action/cooldown/IsAvailable()
/datum/action/cooldown/IsAvailable(silent = FALSE)
return next_use_time <= world.time
/datum/action/cooldown/proc/StartCooldown()
@@ -294,3 +294,12 @@
/obj/item/bedsheet/cosmos = 1)
time = 60
category = CAT_CLOTHING
/datum/crafting_recipe/garlic_necklace
name = "Garlic Necklace"
result = /obj/item/clothing/neck/garlic_necklace
reqs = list(/obj/item/reagent_containers/food/snacks/grown/garlic = 15,
/obj/item/stack/cable_coil = 10)
time = 100 //Takes awhile to put all the garlics on the coil and knot it.
category = CAT_CLOTHING
+4 -4
View File
@@ -1,8 +1,8 @@
//This component applies a customizable drop_shadow filter to its wearer when they toggle combat mode on or off. This can stack.
/datum/component/wearertargeting/phantomthief
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
signals = list(COMSIG_LIVING_COMBAT_ENABLED)
dupe_mode = COMPONENT_DUPE_ALLOWED
signals = list(COMSIG_LIVING_COMBAT_ENABLED, COMSIG_LIVING_COMBAT_DISABLED)
proctype = .proc/handlefilterstuff
var/filter_x
var/filter_y
@@ -19,8 +19,8 @@
filter_color = _color
valid_slots = _valid_slots
/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate)
if(!combatmodestate)
/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(mob/living/user, was_forced = FALSE)
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
user.remove_filter("phantomthief")
else
user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color))
+1 -2
View File
@@ -25,7 +25,6 @@
RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, .proc/rad_attack)
else
CRASH("Something that wasn't an atom was given /datum/component/radioactive")
return
if(strength > RAD_MINIMUM_CONTAMINATION)
SSradiation.warn(src)
@@ -84,4 +83,4 @@
#undef RAD_AMOUNT_LOW
#undef RAD_AMOUNT_MEDIUM
#undef RAD_AMOUNT_HIGH
#undef RAD_AMOUNT_EXTREME
#undef RAD_AMOUNT_EXTREME
@@ -60,7 +60,7 @@
_contents_limbo = null
if(_user_limbo)
for(var/i in _user_limbo)
show_to(i)
ui_show(i)
_user_limbo = null
/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE)
@@ -18,7 +18,7 @@
return
. = COMPONENT_NO_ATTACK_HAND
if(!check_locked(source, user, TRUE))
show_to(user)
ui_show(user)
A.do_jiggle()
if(rustle_sound)
playsound(A, "rustle", 50, 1, -5)
@@ -3,6 +3,7 @@
allow_quick_gather = TRUE
allow_quick_empty = TRUE
click_gather = TRUE
storage_flags = STORAGE_FLAGS_LEGACY_DEFAULT
max_w_class = WEIGHT_CLASS_NORMAL
max_combined_w_class = 100
max_items = 100
@@ -1,6 +1,7 @@
//Stack-only storage.
/datum/component/storage/concrete/stack
display_numerical_stacking = TRUE
storage_flags = STORAGE_FLAGS_LEGACY_DEFAULT
var/max_combined_stack_amount = 300
max_w_class = WEIGHT_CLASS_NORMAL
max_combined_w_class = WEIGHT_CLASS_NORMAL * 14
+74 -149
View File
@@ -21,9 +21,16 @@
var/locked = FALSE //when locked nothing can see inside or use it.
var/max_w_class = WEIGHT_CLASS_SMALL //max size of objects that will fit.
var/max_combined_w_class = 14 //max combined sizes of objects that will fit.
var/max_items = 7 //max number of objects that will fit.
/// Storage flags, including what kinds of limiters we use for how many items we can hold
var/storage_flags = STORAGE_FLAGS_LEGACY_DEFAULT
/// Max w_class we can hold. Applies to [STORAGE_LIMIT_COMBINED_W_CLASS] and [STORAGE_LIMIT_VOLUME]
var/max_w_class = WEIGHT_CLASS_SMALL
/// Max combined w_class. Applies to [STORAGE_LIMIT_COMBINED_W_CLASS]
var/max_combined_w_class = WEIGHT_CLASS_SMALL * 7
/// Max items we can hold. Applies to [STORAGE_LIMIT_MAX_ITEMS]
var/max_items = 7
/// Max volume we can hold. Applies to [STORAGE_LIMIT_VOLUME]. Auto scaled on New() if unset.
var/max_volume
var/emp_shielded = FALSE
@@ -39,8 +46,17 @@
var/display_numerical_stacking = FALSE //stack things of the same type and show as a single object with a number.
var/obj/screen/storage/boxes //storage display object
var/obj/screen/close/closer //close button object
/// "legacy"/default view mode's storage "boxes"
var/obj/screen/storage/boxes/ui_boxes
/// New volumetric storage display mode's left side
var/obj/screen/storage/left/ui_left
/// New volumetric storage display mode's center 'blocks'
var/obj/screen/storage/continuous/ui_continuous
/// The close button, used in all modes. Frames right side in volumetric mode.
var/obj/screen/storage/close/ui_close
/// Associative list of list(item = screen object) for volumetric storage item screen blocks
var/list/ui_item_blocks
var/current_maxscreensize
var/allow_big_nesting = FALSE //allow storage objects of the same or greater size.
@@ -68,9 +84,6 @@
return COMPONENT_INCOMPATIBLE
if(master)
change_master(master)
boxes = new(null, src)
closer = new(null, src)
orient2hud()
RegisterSignal(parent, COMSIG_CONTAINS_STORAGE, .proc/on_check)
RegisterSignal(parent, COMSIG_IS_STORAGE_LOCKED, .proc/check_locked)
@@ -111,8 +124,15 @@
/datum/component/storage/Destroy()
close_all()
QDEL_NULL(boxes)
QDEL_NULL(closer)
QDEL_NULL(ui_boxes)
QDEL_NULL(ui_close)
QDEL_NULL(ui_continuous)
QDEL_NULL(ui_left)
// DO NOT USE QDEL_LIST_ASSOC.
if(ui_item_blocks)
for(var/i in ui_item_blocks)
qdel(ui_item_blocks[i]) //qdel the screen object not the item
ui_item_blocks.Cut()
LAZYCLEARLIST(is_using)
return ..()
@@ -286,7 +306,7 @@
if(!_target)
_target = get_turf(parent)
if(usr)
hide_from(usr)
ui_hide(usr)
var/list/contents = contents()
var/atom/real_location = real_location()
for(var/obj/item/I in contents)
@@ -300,106 +320,8 @@
if(check_locked())
close_all()
/datum/component/storage/proc/_process_numerical_display()
. = list()
for(var/obj/item/I in accessible_items())
if(QDELETED(I))
continue
if(!.[I.type])
.[I.type] = new /datum/numbered_display(I, 1)
else
var/datum/numbered_display/ND = .[I.type]
ND.number++
. = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE)
//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing.
/datum/component/storage/proc/orient2hud(mob/user, maxcolumns)
var/list/accessible_contents = accessible_items()
var/adjusted_contents = length(accessible_contents)
//Numbered contents display
var/list/datum/numbered_display/numbered_contents
if(display_numerical_stacking)
numbered_contents = _process_numerical_display()
adjusted_contents = numbered_contents.len
var/columns = CLAMP(max_items, 1, maxcolumns ? maxcolumns : screen_max_columns)
var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows)
standard_orient_objs(rows, columns, numbered_contents)
//This proc draws out the inventory and places the items on it. It uses the standard position.
/datum/component/storage/proc/standard_orient_objs(rows, cols, list/obj/item/numerical_display_contents)
boxes.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+cols-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]"
var/cx = screen_start_x
var/cy = screen_start_y
if(islist(numerical_display_contents))
for(var/type in numerical_display_contents)
var/datum/numbered_display/ND = numerical_display_contents[type]
ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE
ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
ND.sample_object.maptext = "<font color='white'>[(ND.number > 1)? "[ND.number]" : ""]</font>"
ND.sample_object.layer = ABOVE_HUD_LAYER
ND.sample_object.plane = ABOVE_HUD_PLANE
cx++
if(cx - screen_start_x >= cols)
cx = screen_start_x
cy++
if(cy - screen_start_y >= rows)
break
else
for(var/obj/O in accessible_items())
if(QDELETED(O))
continue
O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
O.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
O.maptext = ""
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
cx++
if(cx - screen_start_x >= cols)
cx = screen_start_x
cy++
if(cy - screen_start_y >= rows)
break
closer.screen_loc = "[screen_start_x + cols]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y]"
/datum/component/storage/proc/show_to(mob/M, set_screen_size = TRUE)
if(!M.client)
return FALSE
var/list/cview = getviewsize(M.client.view)
var/maxallowedscreensize = cview[1]-8
if(set_screen_size)
current_maxscreensize = maxallowedscreensize
else if(current_maxscreensize)
maxallowedscreensize = current_maxscreensize
if(M.active_storage != src && (M.stat == CONSCIOUS))
for(var/obj/item/I in accessible_items())
if(I.on_found(M))
return FALSE
if(M.active_storage)
M.active_storage.hide_from(M)
orient2hud(M, (isliving(M) ? maxallowedscreensize : 7))
M.client.screen |= boxes
M.client.screen |= closer
M.client.screen |= accessible_items()
M.active_storage = src
LAZYOR(is_using, M)
return TRUE
/datum/component/storage/proc/hide_from(mob/M)
if(!M.client)
return TRUE
var/atom/real_location = real_location()
M.client.screen -= boxes
M.client.screen -= closer
M.client.screen -= real_location.contents
if(M.active_storage == src)
M.active_storage = null
LAZYREMOVE(is_using, M)
return TRUE
/datum/component/storage/proc/close(mob/M)
hide_from(M)
ui_hide(M)
/datum/component/storage/proc/close_all()
. = FALSE
@@ -418,25 +340,6 @@
var/datum/component/storage/concrete/master = master()
master.emp_act(source, severity)
//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right.
//The numbers are calculated from the bottom-left The bottom-left slot being 1,1.
/datum/component/storage/proc/orient_objs(tx, ty, mx, my)
var/atom/real_location = real_location()
var/cx = tx
var/cy = ty
boxes.screen_loc = "[tx]:,[ty] to [mx],[my]"
for(var/obj/O in real_location)
if(QDELETED(O))
continue
O.screen_loc = "[cx],[cy]"
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
cx++
if(cx > mx)
cx = tx
cy--
closer.screen_loc = "[mx+1],[my]"
//Resets something that is being removed from storage.
/datum/component/storage/proc/_removal_reset(atom/movable/thing)
if(!istype(thing))
@@ -448,6 +351,9 @@
/datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing)
_removal_reset(thing)
if(LAZYACCESS(ui_item_blocks, thing))
qdel(ui_item_blocks[thing])
ui_item_blocks -= thing
refresh_mob_views()
//Call this proc to handle the removal of an item from the storage item. The item will be moved to the new_location target, if that is null it's being deleted
@@ -462,7 +368,7 @@
/datum/component/storage/proc/refresh_mob_views()
var/list/seeing = can_see_contents()
for(var/i in seeing)
show_to(i)
ui_show(i)
return TRUE
/datum/component/storage/proc/can_see_contents()
@@ -559,7 +465,7 @@
A.add_fingerprint(M)
if(!force && (check_locked(null, M) || !M.CanReach(parent, view_only = TRUE)))
return FALSE
show_to(M, !ghost)
ui_show(M, !ghost)
/datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M)
if(isitem(O))
@@ -587,10 +493,6 @@
if(M && !stop_messages)
host.add_fingerprint(M)
return FALSE
if(real_location.contents.len >= max_items)
if(!stop_messages)
to_chat(M, "<span class='warning'>[host] is full, make some space!</span>")
return FALSE //Storage item is full
if(length(can_hold))
if(!is_type_in_typecache(I, can_hold))
if(!stop_messages)
@@ -600,17 +502,34 @@
if(!stop_messages)
to_chat(M, "<span class='warning'>[host] cannot hold [I]!</span>")
return FALSE
if(I.w_class > max_w_class)
if(!stop_messages)
to_chat(M, "<span class='warning'>[I] is too big for [host]!</span>")
return FALSE
var/sum_w_class = I.w_class
for(var/obj/item/_I in real_location)
sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it.
if(sum_w_class > max_combined_w_class)
if(!stop_messages)
to_chat(M, "<span class='warning'>[I] won't fit in [host], make some space!</span>")
return FALSE
// STORAGE LIMITS
if(storage_flags & STORAGE_LIMIT_MAX_ITEMS)
if(real_location.contents.len >= max_items)
if(!stop_messages)
to_chat(M, "<span class='warning'>[host] has too many things in it, make some space!</span>")
return FALSE //Storage item is full
if(storage_flags & STORAGE_LIMIT_MAX_W_CLASS)
if(I.w_class > max_w_class)
if(!stop_messages)
to_chat(M, "<span class='warning'>[I] is too long for [host]!</span>")
return FALSE
if(storage_flags & STORAGE_LIMIT_COMBINED_W_CLASS)
var/sum_w_class = I.w_class
for(var/obj/item/_I in real_location)
sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it.
if(sum_w_class > max_combined_w_class)
if(!stop_messages)
to_chat(M, "<span class='warning'>[I] won't fit in [host], make some space!</span>")
return FALSE
if(storage_flags & STORAGE_LIMIT_VOLUME)
var/sum_volume = I.get_w_volume()
for(var/obj/item/_I in real_location)
sum_volume += _I.get_w_volume()
if(sum_volume > get_max_volume())
if(!stop_messages)
to_chat(M, "<span class='warning'>[I] is too spacious to fit in [host], make some space!</span>")
return FALSE
/////////////////
if(isitem(host))
var/obj/item/IP = host
var/datum/component/storage/STR_I = I.GetComponent(/datum/component/storage)
@@ -742,7 +661,7 @@
if(A.loc == user)
. = COMPONENT_NO_ATTACK_HAND
if(!check_locked(source, user, TRUE))
show_to(user)
ui_show(user)
A.do_jiggle()
/datum/component/storage/proc/signal_on_pickup(datum/source, mob/user)
@@ -761,7 +680,7 @@
return do_quick_empty(loctarget)
/datum/component/storage/proc/signal_hide_attempt(datum/source, mob/target)
return hide_from(target)
return ui_hide(target)
/datum/component/storage/proc/on_alt_click(datum/source, mob/user)
if(!isliving(user) || !user.CanReach(parent))
@@ -790,7 +709,7 @@
user.visible_message("<span class='warning'>[user] draws [I] from [parent]!</span>", "<span class='notice'>You draw [I] from [parent].</span>")
return TRUE
/datum/component/storage/proc/action_trigger(datum/signal_source, datum/action/source)
/datum/component/storage/proc/action_trigger(datum/action/source, obj/target)
gather_mode_switch(source.owner)
return COMPONENT_ACTION_BLOCK_TRIGGER
@@ -803,3 +722,9 @@
to_chat(user, "[parent] now picks up all items in a tile at once.")
if(COLLECT_ONE)
to_chat(user, "[parent] now picks up one item at a time.")
/**
* Gets our max volume
*/
/datum/component/storage/proc/get_max_volume()
return max_volume || AUTO_SCALE_STORAGE_VOLUME(max_w_class, max_combined_w_class)
+293
View File
@@ -0,0 +1,293 @@
/**
* Generates a list of numbered_display datums for the numerical display system.
*/
/datum/component/storage/proc/_process_numerical_display()
. = list()
for(var/obj/item/I in accessible_items())
if(QDELETED(I))
continue
if(!.[I.type])
.[I.type] = new /datum/numbered_display(I, 1)
else
var/datum/numbered_display/ND = .[I.type]
ND.number++
. = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE)
/**
* Orients all objects in legacy mode, and returns the objects to show to the user.
*/
/datum/component/storage/proc/orient2hud_legacy(mob/user, maxcolumns)
. = list()
var/list/accessible_contents = accessible_items()
var/adjusted_contents = length(accessible_contents)
//Numbered contents display
var/list/datum/numbered_display/numbered_contents
if(display_numerical_stacking)
numbered_contents = _process_numerical_display()
adjusted_contents = numbered_contents.len
var/columns = CLAMP(max_items, 1, maxcolumns ? maxcolumns : screen_max_columns)
var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows)
// First, boxes.
ui_boxes = get_ui_boxes()
ui_boxes.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+columns-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]"
. += ui_boxes
// Then, closer.
ui_close = get_ui_close()
ui_close.screen_loc = "[screen_start_x + columns]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y]"
. += ui_close
// Then orient the actual items.
var/cx = screen_start_x
var/cy = screen_start_y
if(islist(numbered_contents))
for(var/type in numbered_contents)
var/datum/numbered_display/ND = numbered_contents[type]
ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE
ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
ND.sample_object.maptext = "<font color='white'>[(ND.number > 1)? "[ND.number]" : ""]</font>"
ND.sample_object.layer = ABOVE_HUD_LAYER
ND.sample_object.plane = ABOVE_HUD_PLANE
. += ND.sample_object
cx++
if(cx - screen_start_x >= columns)
cx = screen_start_x
cy++
if(cy - screen_start_y >= rows)
break
else
for(var/obj/O in accessible_items())
if(QDELETED(O))
continue
O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
O.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
O.maptext = ""
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
. += O
cx++
if(cx - screen_start_x >= columns)
cx = screen_start_x
cy++
if(cy - screen_start_y >= rows)
break
/**
* Orients all objects in .. volumetric mode. Does not support numerical display!
*/
/datum/component/storage/proc/orient2hud_volumetric(mob/user, maxcolumns)
. = list()
// Generate ui_item_blocks for missing ones and render+orient.
var/list/atom/contents = accessible_items()
// our volume
var/our_volume = get_max_volume()
var/horizontal_pixels = (maxcolumns * world.icon_size) - (VOLUMETRIC_STORAGE_EDGE_PADDING * 2)
var/max_horizontal_pixels = horizontal_pixels * screen_max_rows
// sigh loopmania time
var/used = 0
// define outside for performance
var/volume
var/list/volume_by_item = list()
var/list/percentage_by_item = list()
for(var/obj/item/I in contents)
volume = I.get_w_volume()
used += volume
volume_by_item[I] = volume
percentage_by_item[I] = volume / get_max_volume()
var/padding_pixels = ((length(percentage_by_item) - 1) * VOLUMETRIC_STORAGE_ITEM_PADDING) + VOLUMETRIC_STORAGE_EDGE_PADDING * 2
var/min_pixels = (MINIMUM_PIXELS_PER_ITEM * length(percentage_by_item)) + padding_pixels
// do the check for fallback for when someone has too much gamer gear
if((min_pixels) > (max_horizontal_pixels + 4)) // 4 pixel grace zone
to_chat(user, "<span class='warning'>[parent] was showed to you in legacy mode due to your items overrunning the three row limit! Consider not carrying too much or bugging a maintainer to raise this limit!</span>")
return orient2hud_legacy(user, maxcolumns)
// after this point we are sure we can somehow fit all items into our max number of rows.
// determine rows
var/rows = CLAMP(CEILING(min_pixels / horizontal_pixels, 1), 1, screen_max_rows)
var/overrun = FALSE
if(used > our_volume)
// congratulations we are now in overrun mode. everything will be crammed to minimum storage pixels.
to_chat(user, "<span class='warning'>[parent] rendered in overrun mode due to more items inside than the maximum volume supports.</span>")
overrun = TRUE
// how much we are using
var/using_horizontal_pixels = horizontal_pixels * rows
// item padding
using_horizontal_pixels -= padding_pixels
// define outside for marginal performance boost
var/obj/item/I
// start at this pixel from screen_start_x.
var/current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING
var/row = 1
LAZYINITLIST(ui_item_blocks)
for(var/i in percentage_by_item)
I = i
var/percent = percentage_by_item[I]
if(!ui_item_blocks[I])
ui_item_blocks[I] = new /obj/screen/storage/volumetric_box/center(null, src, I)
var/obj/screen/storage/volumetric_box/center/B = ui_item_blocks[I]
var/pixels_to_use = overrun? MINIMUM_PIXELS_PER_ITEM : max(using_horizontal_pixels * percent, MINIMUM_PIXELS_PER_ITEM)
var/addrow = FALSE
if(CEILING(pixels_to_use, 1) >= FLOOR(horizontal_pixels - current_pixel - VOLUMETRIC_STORAGE_EDGE_PADDING, 1))
pixels_to_use = horizontal_pixels - current_pixel - VOLUMETRIC_STORAGE_EDGE_PADDING
addrow = TRUE
// now that we have pixels_to_use, place our thing and add it to the returned list.
B.screen_loc = I.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + VOLUMETRIC_STORAGE_ITEM_PADDING, 1)],[screen_start_y+row-1]:[screen_pixel_y]"
// add the used pixels to pixel after we place the object
current_pixel += pixels_to_use + VOLUMETRIC_STORAGE_ITEM_PADDING
// set various things
B.set_pixel_size(pixels_to_use)
B.layer = VOLUMETRIC_STORAGE_BOX_LAYER
B.plane = VOLUMETRIC_STORAGE_BOX_PLANE
B.name = I.name
I.mouse_opacity = MOUSE_OPACITY_ICON
I.maptext = ""
I.layer = VOLUMETRIC_STORAGE_ITEM_LAYER
I.plane = VOLUMETRIC_STORAGE_ITEM_PLANE
// finally add our things.
. += B.on_screen_objects()
. += I
// go up a row if needed
if(addrow)
row++
current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING
// Then, continuous section.
ui_continuous = get_ui_continuous()
ui_continuous.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+maxcolumns-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]"
. += ui_continuous
// Then, left.
ui_left = get_ui_left()
ui_left.screen_loc = "[screen_start_x]:[screen_pixel_x - 2],[screen_start_y]:[screen_pixel_y] to [screen_start_x]:[screen_pixel_x - 2],[screen_start_y+rows-1]:[screen_pixel_y]"
. += ui_left
// Then, closer, which is also our right element.
ui_close = get_ui_close()
ui_close.screen_loc = "[screen_start_x + maxcolumns]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x + maxcolumns]:[screen_pixel_x],[screen_start_y + row - 1]:[screen_pixel_y]"
. += ui_close
/**
* Shows our UI to a mob.
*/
/datum/component/storage/proc/ui_show(mob/M, set_screen_size = TRUE)
if(!M.client)
return FALSE
var/list/cview = getviewsize(M.client.view)
// in tiles
var/maxallowedscreensize = cview[1]-8
if(set_screen_size)
current_maxscreensize = maxallowedscreensize
else if(current_maxscreensize)
maxallowedscreensize = current_maxscreensize
// we got screen size, register signal
RegisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_logout, override = TRUE)
if(M.active_storage != src)
if(M.active_storage)
M.active_storage.ui_hide(M)
M.active_storage = src
LAZYOR(is_using, M)
if(volumetric_ui())
//new volumetric ui bay-style
M.client.screen |= orient2hud_volumetric(M, maxallowedscreensize)
else
//old ui
M.client.screen |= orient2hud_legacy(M, maxallowedscreensize)
return TRUE
/**
* VV hooked to ensure no lingering screen objects.
*/
/datum/component/storage/vv_edit_var(var_name, var_value)
var/list/old
if(var_name == NAMEOF(src, storage_flags))
old = is_using.Copy()
for(var/i in is_using)
ui_hide(i)
. = ..()
if(old)
for(var/i in old)
ui_show(i)
/**
* Proc triggered by signal to ensure logging out clients don't linger.
*/
/datum/component/storage/proc/on_logout(datum/source, client/C)
ui_hide(source)
/**
* Hides our UI from a mob
*/
/datum/component/storage/proc/ui_hide(mob/M)
if(!M.client)
return TRUE
UnregisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT)
M.client.screen -= list(ui_boxes, ui_close, ui_left, ui_continuous) + get_ui_item_objects_hide()
if(M.active_storage == src)
M.active_storage = null
LAZYREMOVE(is_using, M)
return TRUE
/**
* Returns TRUE if we are using volumetric UI instead of box UI
*/
/datum/component/storage/proc/volumetric_ui()
var/atom/real_location = real_location()
return (storage_flags & STORAGE_LIMIT_VOLUME) && (length(real_location.contents) <= MAXIMUM_VOLUMETRIC_ITEMS) && !display_numerical_stacking
/**
* Gets the ui item objects to ui_hide.
*/
/datum/component/storage/proc/get_ui_item_objects_hide()
if(!volumetric_ui())
var/atom/real_location = real_location()
return real_location.contents
else
. = list()
for(var/i in ui_item_blocks)
// get both the box and the item
. += ui_item_blocks[i]
. += i
/**
* Gets our ui_boxes, making it if it doesn't exist.
*/
/datum/component/storage/proc/get_ui_boxes()
if(!ui_boxes)
ui_boxes = new(null, src)
return ui_boxes
/**
* Gets our ui_left, making it if it doesn't exist.
*/
/datum/component/storage/proc/get_ui_left()
if(!ui_left)
ui_left = new(null, src)
return ui_left
/**
* Gets our ui_close, making it if it doesn't exist.
*/
/datum/component/storage/proc/get_ui_close()
if(!ui_close)
ui_close = new(null, src)
return ui_close
/**
* Gets our ui_continuous, making it if it doesn't exist.
*/
/datum/component/storage/proc/get_ui_continuous()
if(!ui_continuous)
ui_continuous = new(null, src)
return ui_continuous
+1 -1
View File
@@ -176,7 +176,7 @@
/**
*The following procs simply acts as hooks for quit(), since components do not use callbacks anymore
*/
/datum/component/virtual_reality/proc/action_trigger(datum/signal_source, datum/action/source)
/datum/component/virtual_reality/proc/action_trigger(datum/action/source, obj/target)
quit()
return COMPONENT_ACTION_BLOCK_TRIGGER
-1
View File
@@ -19,7 +19,6 @@
var/datum/component/wet_floor/WF = newcomp //Lets make an assumption
if(WF.gc()) //See if it's even valid, still. Also does LAZYLEN and stuff for us.
CRASH("Wet floor component tried to inherit another, but the other was able to garbage collect while being inherited! What a waste of time!")
return
for(var/i in WF.time_left_list)
add_wet(text2num(i), WF.time_left_list[i])
+1 -1
View File
@@ -19,7 +19,7 @@
dashing_item = dasher
holder = user
/datum/action/innate/dash/IsAvailable()
/datum/action/innate/dash/IsAvailable(silent = FALSE)
if(current_charges > 0)
return TRUE
else
-2
View File
@@ -175,11 +175,9 @@
if(!islist(jsonlist))
if(!istext(jsonlist))
CRASH("Invalid JSON")
return
jsonlist = json_decode(jsonlist)
if(!islist(jsonlist))
CRASH("Invalid JSON")
return
if(!jsonlist["DATUM_TYPE"])
return
if(!ispath(jsonlist["DATUM_TYPE"]))
+1 -1
View File
@@ -9,7 +9,7 @@
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 0.75
desc = "Some speculate that this virus is the cause of the Space Wizard Federation's existence. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
desc = "Some speculate that this virus is the cause of the Space Wizard Federation's existence. Subjects affected show the signs of mental hysteria, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
severity = DISEASE_SEVERITY_HARMFUL
required_organs = list(/obj/item/bodypart/head)
+17
View File
@@ -41,6 +41,7 @@
/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0)
if(!istype(destination))
return
var/old_size = destination.dna.features["body_size"]
destination.dna.unique_enzymes = unique_enzymes
destination.dna.uni_identity = uni_identity
destination.dna.blood_type = blood_type
@@ -56,6 +57,8 @@
if(transfer_SE)
destination.dna.mutation_index = mutation_index
destination.dna.update_body_size(old_size)
SEND_SIGNAL(destination, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, src, transfer_SE)
/datum/dna/proc/copy_dna(datum/dna/new_dna)
@@ -368,7 +371,9 @@
/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures)
if(newfeatures)
var/old_size = dna.features["body_size"]
dna.features = newfeatures
dna.update_body_size(old_size)
if(mrace)
var/datum/species/newrace = new mrace.type
@@ -644,3 +649,15 @@
gib()
else
set_species(/datum/species/dullahan)
/datum/dna/proc/update_body_size(old_size)
if(!holder || features["body_size"] == old_size)
return
holder.resize = features["body_size"] / old_size
holder.update_transform()
var/danger = CONFIG_GET(number/threshold_body_size_slowdown)
if(features["body_size"] < danger)
var/slowdown = 1 + round(danger/features["body_size"], 0.1) * CONFIG_GET(number/body_size_slowdown_multiplier)
holder.add_movespeed_modifier(MOVESPEED_ID_SMALL_STRIDE, TRUE, 100, NONE, TRUE, slowdown, ALL, FLOATING|CRAWLING)
else if(old_size < danger)
holder.remove_movespeed_modifier(MOVESPEED_ID_SMALL_STRIDE)
+2 -2
View File
@@ -71,7 +71,7 @@
name = "bugged mob"
desc = "Yell at coderbrush."
icon = null
alternate_worn_icon = 'icons/mob/animals_held.dmi'
mob_overlay_icon = 'icons/mob/animals_held.dmi'
righthand_file = 'icons/mob/animals_held_rh.dmi'
lefthand_file = 'icons/mob/animals_held_lh.dmi'
icon_state = ""
@@ -86,7 +86,7 @@
assimilate(target)
if(alt_worn)
alternate_worn_icon = alt_worn
mob_overlay_icon = alt_worn
if(worn_state)
item_state = worn_state
icon_state = worn_state
+187
View File
@@ -0,0 +1,187 @@
#define POLYCHROMIC_ALTCLICK (1<<0)
#define POLYCHROMIC_ACTION (1<<1)
#define POLYCHROMIC_NO_HELD (1<<2)
#define POLYCHROMIC_NO_WORN (1<<3)
/datum/element/polychromic
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 3
var/overlays_states //A list or a number of states. In the latter case, the atom icon_state/item_state will be used followed by a number.
var/list/colors_by_atom = list() //list of color strings or mutable appearances, depending on the above variable.
var/icon_file
var/worn_file //used in place of items' held or mob overlay icons if present.
var/list/overlays_names //wrap numbers into text strings please.
var/list/actions_by_atom = list()
var/poly_flags
var/static/list/suits_with_helmet_typecache = typecacheof(list(/obj/item/clothing/suit/hooded, /obj/item/clothing/suit/space/hardsuit))
var/list/helmet_by_suit = list() //because poly winter coats exist.
var/list/suit_by_helmet = list() //Idem.
/datum/element/polychromic/Attach(datum/target, list/colors, states, _flags = POLYCHROMIC_ACTION|POLYCHROMIC_NO_HELD, _icon, _worn, list/names = list("Primary", "Secondary", "Tertiary", "Quaternary", "Quinary", "Senary"))
. = ..()
var/make_appearances = islist(states)
var/states_len = make_appearances ? length(states) : states
var/names_len = length(names)
if(!states_len || !names_len || colors_by_atom[target] || !isatom(target))
return ELEMENT_INCOMPATIBLE
var/atom/A = target
overlays_states = states
icon_file = _icon
worn_file = _worn
poly_flags = _flags
var/mut_icon = icon_file || A.icon
var/list/L = list()
for(var/I in 1 to states_len)
var/col = LAZYACCESS(colors, I) || "#FFFFFF"
L += make_appearances ? mutable_appearance(mut_icon, overlays_states[I], color = col) : col
colors_by_atom[A] = L
RegisterSignal(A, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlays)
if(_flags & POLYCHROMIC_ALTCLICK)
RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/on_examine)
RegisterSignal(A, COMSIG_CLICK_ALT, .proc/set_color)
if(!overlays_names && names) //generate
overlays_names = names
var/diff = states_len - names_len
if(diff > 0)
for(var/i in 1 to diff)
overlays_names += "[names_len + i]°"
else if(diff < 0)
overlays_names.len += diff
if(isitem(A))
if(_flags & POLYCHROMIC_ACTION)
RegisterSignal(A, COMSIG_ITEM_EQUIPPED, .proc/grant_user_action)
RegisterSignal(A, COMSIG_ITEM_DROPPED, .proc/remove_user_action)
if(!(_flags & POLYCHROMIC_NO_WORN) || !(_flags & POLYCHROMIC_NO_HELD))
A.AddElement(/datum/element/update_icon_updates_onmob)
RegisterSignal(A, COMSIG_ITEM_WORN_OVERLAYS, .proc/apply_worn_overlays)
if(suits_with_helmet_typecache[A.type])
RegisterSignal(A, COMSIG_SUIT_MADE_HELMET, .proc/register_helmet)
else if(_flags & POLYCHROMIC_ACTION && ismob(A)) //in the event mob update icon procs are ever standarized.
var/datum/action/polychromic/P = new(A)
RegisterSignal(P, COMSIG_ACTION_TRIGGER, .proc/activate_action)
actions_by_atom[A] = P
P.Grant(A)
A.update_icon() //apply the overlays.
/datum/element/polychromic/Detach(atom/A)
. = ..()
colors_by_atom -= A
var/datum/action/polychromic/P = actions_by_atom[A]
if(P)
actions_by_atom -= A
qdel(P)
UnregisterSignal(A, list(COMSIG_PARENT_EXAMINE, COMSIG_CLICK_ALT, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ITEM_WORN_OVERLAYS, COMSIG_SUIT_MADE_HELMET))
if(isitem(A))
var/obj/item/clothing/head/H = helmet_by_suit[A]
if(H)
UnregisterSignal(H, list(COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ITEM_WORN_OVERLAYS, COMSIG_PARENT_QDELETING))
helmet_by_suit -= A
suit_by_helmet -= H
colors_by_atom -= H
if(!QDELETED(H))
H.update_icon() //removing the overlays
if(!(poly_flags & POLYCHROMIC_NO_WORN) || !(poly_flags & POLYCHROMIC_NO_HELD))
A.RemoveElement(/datum/element/update_icon_updates_onmob)
if(!QDELETED(A) && ismob(A.loc))
var/mob/M = A.loc
if(!(poly_flags & POLYCHROMIC_NO_HELD) && M.is_holding(A))
M.update_inv_hands()
else if(!(poly_flags & POLYCHROMIC_NO_WORN))
M.regenerate_icons()
if(!QDELETED(A))
A.update_icon() //removing the overlays
/datum/element/polychromic/proc/apply_overlays(atom/source, list/overlays)
var/list/L = colors_by_atom[source]
var/f_icon = icon_file || source.icon
if(isnum(overlays_states))
for(var/i in 1 to overlays_states)
overlays += mutable_appearance(f_icon, "[source.icon_state]-[i]", color = L[i])
else
overlays += colors_by_atom[source]
/datum/element/polychromic/proc/apply_worn_overlays(obj/item/source, isinhands, icon, used_state, style_flags, list/overlays)
if(poly_flags & (isinhands ? POLYCHROMIC_NO_HELD : POLYCHROMIC_NO_WORN))
return
var/f_icon = worn_file || icon
var/list/L = colors_by_atom[source]
if(isnum(overlays_states))
for(var/i in 1 to overlays_states)
overlays += mutable_appearance(f_icon, "[used_state]-[i]", color = L[i])
else
for(var/i in 1 to length(overlays_states))
var/mutable_appearance/M = L[i]
overlays += mutable_appearance(f_icon, overlays_states[i], color = M.color)
/datum/element/polychromic/proc/set_color(atom/source, mob/user)
var/choice = input(user,"Polychromic options", "Recolor [source]") as null|anything in overlays_names
if(!choice || QDELETED(source) || !user.canUseTopic(source, BE_CLOSE, NO_DEXTERY))
return
var/index = overlays_names.Find(choice)
var/list/L = colors_by_atom[source]
if(!L) // Ummmmmh.
return
var/mutable_appearance/M = L[index]
var/old_color = istype(M) ? M.color : M
var/ncolor = input(user, "Polychromic options", "Choose [choice] Color", old_color) as color|null
if(!ncolor || QDELETED(source) || !colors_by_atom[source] || !user.canUseTopic(source, BE_CLOSE, NO_DEXTERY))
return
ncolor = sanitize_hexcolor(ncolor, 6, TRUE, old_color)
if(istype(M))
M.color = ncolor
else
L[index] = ncolor
source.update_icon()
return TRUE
/datum/element/polychromic/proc/grant_user_action(atom/source, mob/user, slot)
if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED || slot == SLOT_HANDCUFFED || slot == SLOT_GENERC_DEXTROUS_STORAGE)
return
var/datum/action/polychromic/P = actions_by_atom[source]
if(!P)
P = new (source)
P.name = "Modify [source]'\s Colors"
actions_by_atom[source] = P
P.check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
RegisterSignal(P, COMSIG_ACTION_TRIGGER, .proc/activate_action)
P.Grant(user)
/datum/element/polychromic/proc/remove_user_action(atom/source, mob/user)
var/datum/action/polychromic/P = actions_by_atom[source]
P?.Remove(user)
/datum/element/polychromic/proc/activate_action(datum/action/source, atom/target)
set_color(target, source.owner)
/datum/element/polychromic/proc/on_examine(atom/source, mob/user, list/examine_list)
examine_list += "<span class='notice'>Alt-click to recolor it.</span>"
/datum/element/polychromic/proc/register_helmet(atom/source, obj/item/clothing/head/H)
suit_by_helmet[H] = source
helmet_by_suit[source] = H
colors_by_atom[H] = colors_by_atom[source]
RegisterSignal(H, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlays)
RegisterSignal(H, COMSIG_ITEM_WORN_OVERLAYS, .proc/apply_worn_overlays)
RegisterSignal(H, COMSIG_PARENT_QDELETING, .proc/unregister_helmet)
/datum/element/polychromic/proc/unregister_helmet(atom/source)
var/obj/item/clothing/suit/S = suit_by_helmet[source]
suit_by_helmet -= source
helmet_by_suit -= S
colors_by_atom -= source
/datum/action/polychromic
name = "Modify Polychromic Colors"
background_icon_state = "bg_polychromic"
use_target_appearance = TRUE
button_icon_state = null
target_appearance_matrix = list(0.8,0,0,0,0.8,0)
+6 -6
View File
@@ -12,7 +12,7 @@
RegisterSignal(target, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(target, COMSIG_ITEM_DROPPED, .proc/on_drop)
else if(ismob(target))
RegisterSignal(target, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast)
RegisterSignal(target, COMSIG_MOB_SPELL_CAN_CAST, .proc/on_cast)
stacked_spellcasting_by_user[target]++
else
return ELEMENT_INCOMPATIBLE
@@ -21,24 +21,24 @@
/datum/element/spellcasting/Detach(datum/target)
. = ..()
UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_MOB_SPELL_CAST_CHECK))
UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_MOB_SPELL_CAN_CAST))
if(users_by_item[target])
var/mob/user = users_by_item[target]
stacked_spellcasting_by_user[user]--
if(!stacked_spellcasting_by_user[user])
stacked_spellcasting_by_user -= user
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
UnregisterSignal(user, COMSIG_MOB_SPELL_CAN_CAST)
else if(ismob(target))
stacked_spellcasting_by_user[target]--
if(!stacked_spellcasting_by_user[target])
stacked_spellcasting_by_user -= target
/datum/element/spellcasting/proc/on_equip(datum/source, mob/equipper, slot)
if(!(slot in cast_slots))
if(!(cast_slots & slotdefine2slotbit(slot)))
return
users_by_item[source] = equipper
if(!stacked_spellcasting_by_user[equipper])
RegisterSignal(equipper, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast)
RegisterSignal(equipper, COMSIG_MOB_SPELL_CAN_CAST, .proc/on_cast)
stacked_spellcasting_by_user[equipper]++
/datum/element/spellcasting/proc/on_drop(datum/source, mob/user)
@@ -48,7 +48,7 @@
stacked_spellcasting_by_user[user]--
if(!stacked_spellcasting_by_user[user])
stacked_spellcasting_by_user -= user
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
UnregisterSignal(user, COMSIG_MOB_SPELL_CAN_CAST)
/datum/element/spellcasting/proc/on_cast(mob/caster, obj/effect/proc_holder/spell)
return cast_flags
@@ -5,7 +5,7 @@
. = ..()
if(!istype(target, /obj/item))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/update_onmob)
RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/update_onmob, override = TRUE)
/datum/element/update_icon_updates_onmob/proc/update_onmob(obj/item/target)
if(ismob(target.loc))
+1 -1
View File
@@ -128,7 +128,7 @@
// Can most things breathe?
if(trace_gases)
continue
if(A_gases[/datum/gas/oxygen] >= 16)
if(A_gases[/datum/gas/oxygen] <= 16)
continue
if(A_gases[/datum/gas/plasma])
continue
+2 -2
View File
@@ -145,7 +145,7 @@
log_combat(A, D, "punched")
var/picked_hit_type = pick("punches", "kicks")
var/bonus_damage = damage_roll(A,D)
if(CHECK_MOBILITY(D, MOBILITY_STAND))
if(!CHECK_MOBILITY(D, MOBILITY_STAND))
bonus_damage += 10
picked_hit_type = "stomps on"
D.apply_damage(bonus_damage, BRUTE, affecting, armor_block)
@@ -165,7 +165,7 @@
return TRUE
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
var/armor_block = D.run_armor_check(affecting, "melee")
var/damage = damage_roll(A,D)
var/damage = (damage_roll(A,D)*2)
if(D.mobility_flags & MOBILITY_STAND)
D.visible_message("<span class='danger'>[A] reprimands [D]!</span>", \
"<span class='userdanger'>You're slapped by [A]!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
+1 -1
View File
@@ -185,7 +185,7 @@
. = ..()
if(A.incapacitated(FALSE, TRUE)) //NO STUN
return BULLET_ACT_HIT
if(CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DODGING ON THE FLOOR
if(!CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DODGING ON THE FLOOR
return BULLET_ACT_HIT
if(A.dna && A.dna.check_mutation(HULK)) //NO HULK
return BULLET_ACT_HIT
+1 -1
View File
@@ -114,7 +114,7 @@
. = ..()
if(A.incapacitated(FALSE, TRUE)) //NO STUN
return BULLET_ACT_HIT
if(CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DEFLECTION ON THE FLOOR
if(!CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DEFLECTION ON THE FLOOR
return BULLET_ACT_HIT
if(A.dna && A.dna.check_mutation(HULK)) //NO HULK
return BULLET_ACT_HIT
+1 -1
View File
@@ -19,7 +19,7 @@
integrity_modifier = 0.1
sheet_type = /obj/item/stack/sheet/glass
value_per_unit = 0.0025
armor_modifiers = list("melee" = 0.2, "bullet" = 0.2, "laser" = 0, "energy" = 1, "bomb" = 0, "bio" = 0.2, "rad" = 0.2, "fire" = 1, "acid" = 0.2) // yeah ok retard
armor_modifiers = list("melee" = 0.2, "bullet" = 0.2, "laser" = 0, "energy" = 1, "bomb" = 0, "bio" = 0.2, "rad" = 0.2, "fire" = 1, "acid" = 0.2) // yeah ok
/*
Color matrices are like regular colors but unlike with normal colors, you can go over 255 on a channel.
+4
View File
@@ -26,3 +26,7 @@
/datum/generecipe/tonguechem
required = "/datum/mutation/human/tongue_spike; /datum/mutation/human/stimmed"
result = TONGUESPIKECHEM
/datum/generecipe/hulk
required = "/datum/mutation/human/strong; /datum/mutation/human/radioactive"
result = HULK
+2 -2
View File
@@ -79,7 +79,7 @@
message = " [message] "
//Time for a friendly game of SS13
message = replacetext(message," stupid "," smart ")
message = replacetext(message," retard "," genius ")
message = replacetext(message," idiot "," genius ")
message = replacetext(message," unrobust "," robust ")
message = replacetext(message," dumb "," smart ")
message = replacetext(message," awful "," great ")
@@ -263,7 +263,7 @@
message = replacetext(message," thank you "," thank you, thank you very much ")
message = replacetext(message," what are you "," whatcha ")
message = replacetext(message," yes ",pick(" sure", "yea "))
message = replacetext(message," faggot "," square ")
message = replacetext(message," dumbass "," square ")
message = replacetext(message," muh valids "," getting my kicks ")
speech_args[SPEECH_MESSAGE] = trim(message)
+1 -1
View File
@@ -117,7 +117,7 @@
continue
contam_atoms += thing
var/did_contam = 0
if(length(can_contam))
if(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]
-1
View File
@@ -38,7 +38,6 @@
..()
if(!istype(holder, holder_type))
CRASH("Wire holder is not of the expected type!")
return
src.holder = holder
if(randomize)
+4
View File
@@ -6,6 +6,8 @@
hidden = TRUE
var/obj/machinery/computer/holodeck/linked
var/list/compatible_holodeck_comps
var/abstract_type = /area/holodeck
var/restricted = 0 // if true, program goes on emag list
/*
@@ -53,6 +55,8 @@
*/
/area/holodeck/rec_center
name = "\improper Recreational Holodeck"
compatible_holodeck_comps = list(/obj/machinery/computer/holodeck)
abstract_type = /area/holodeck/rec_center
/area/holodeck/rec_center/offline
name = "Holodeck - Offline"
+1 -4
View File
@@ -584,11 +584,8 @@
stoplag(1)
qdel(progress)
to_chat(user, "<span class='notice'>You dump as much of [src_object.parent]'s contents into [STR.insert_preposition]to [src] as you can.</span>")
STR.orient2hud(user)
src_object.orient2hud(user)
if(user.active_storage) //refresh the HUD to show the transfered contents
user.active_storage.close(user)
user.active_storage.show_to(user)
user.active_storage.ui_show(user)
return TRUE
/atom/proc/get_dumping_location(obj/item/storage/source,mob/user)
-2
View File
@@ -147,7 +147,6 @@
return "health-85"
else
return "health-100"
return "0"
//HOOKS
@@ -323,7 +322,6 @@
return "crit"
else
return "dead"
return "dead"
//Sillycone hooks
/mob/living/silicon/proc/diag_hud_set_health()
+34 -55
View File
@@ -9,8 +9,14 @@
var/list/vassal_allowed_antags = list(/datum/antagonist/brother, /datum/antagonist/traitor, /datum/antagonist/traitor/internal_affairs, /datum/antagonist/survivalist, \
/datum/antagonist/rev, /datum/antagonist/nukeop, /datum/antagonist/pirate, /datum/antagonist/cult, /datum/antagonist/abductee, /datum/antagonist/valentine, /datum/antagonist/heartbreaker,)
// The antags you're allowed to be if turning Vassal.
/proc/isvamp(mob/living/M)
return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/bloodsucker)
/proc/AmBloodsucker(mob/living/M, falseIfInDisguise = FALSE)
if(!M.mind)
return FALSE
// No Datum
if(!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
return FALSE
return TRUE
/datum/game_mode/bloodsucker
name = "bloodsucker"
@@ -70,49 +76,27 @@
// Gamemode is all done being set up. We have all our Vamps. We now pick objectives and let them know what's happening.
/datum/game_mode/bloodsucker/post_setup()
// Sunlight (Creating Bloodsuckers manually will check to create this, too)
check_start_sunlight()
// Vamps
for(var/datum/mind/bloodsucker in bloodsuckers)
// spawn() --> Run block of code but game continues on past it.
// sleep() --> Run block of code and freeze code there (including whoever called us) until it's resolved.
//Clean Bloodsucker Species (racist?)
//clean_invalid_species(bloodsucker)
// TO-DO !!!
// Add Bloodsucker Antag Datum (or remove from list on Fail)
if (!make_bloodsucker(bloodsucker))
if(!make_bloodsucker(bloodsucker))
bloodsuckers -= bloodsucker
// NOTE: Hunters are done in ..() parent proc
return ..()
// Checking for ACTUALLY Dead Vamps
/datum/game_mode/bloodsucker/are_special_antags_dead()
// Bloodsucker not Final Dead
for(var/datum/mind/bloodsucker in bloodsuckers)
if(!bloodsucker.AmFinalDeath())
return FALSE
return TRUE
// Init Sunlight (called from datum_bloodsucker.on_gain(), in case game mode isn't even Bloodsucker
/datum/game_mode/proc/check_start_sunlight()
// Already Sunlight (and not about to cancel)
if (istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me)
if(istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me)
return
bloodsucker_sunlight = new ()
// End Sun (last bloodsucker removed)
/datum/game_mode/proc/check_cancel_sunlight()
// No Sunlight
if (!istype(bloodsucker_sunlight))
if(!istype(bloodsucker_sunlight))
return
if (bloodsuckers.len <= 0)
if(bloodsuckers.len <= 0)
bloodsucker_sunlight.cancel_me = TRUE
qdel(bloodsucker_sunlight)
bloodsucker_sunlight = null
@@ -151,43 +135,37 @@
// Not High Enough
if(creator)
var/datum/antagonist/bloodsucker/creator_bloodsucker = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if(!istype(creator_bloodsucker) || creator_bloodsucker.vamplevel < BLOODSUCKER_LEVEL_TO_EMBRACE)
if(!istype(creator_bloodsucker) || creator_bloodsucker.bloodsucker_level < BLOODSUCKER_LEVEL_TO_EMBRACE)
to_chat(creator, "<span class='danger'>Your blood is too thin to turn this corpse!</span>")
return FALSE
return TRUE
/datum/game_mode/proc/make_bloodsucker(datum/mind/bloodsucker, datum/mind/creator = null) // NOTE: This is a game_mode/proc, NOT a game_mode/bloodsucker/proc! We need to access this function despite the game mode.
if (!can_make_bloodsucker(bloodsucker))
if(!can_make_bloodsucker(bloodsucker))
return FALSE
// Create Datum: Fledgling
var/datum/antagonist/bloodsucker/A
// [FLEDGLING]
if (creator)
if(creator)
A = new (bloodsucker)
A.creator = creator
bloodsucker.add_antag_datum(A)
// Log
message_admins("[bloodsucker] has become a Bloodsucker, and was created by [creator].")
log_admin("[bloodsucker] has become a Bloodsucker, and was created by [creator].")
// [MASTER]
else
A = bloodsucker.add_antag_datum(ANTAG_DATUM_BLOODSUCKER)
return TRUE
/datum/game_mode/proc/remove_bloodsucker(datum/mind/bloodsucker)
bloodsucker.remove_antag_datum(ANTAG_DATUM_BLOODSUCKER)
/datum/game_mode/proc/clean_invalid_species(datum/mind/bloodsucker)
// Only checking for Humans here
if (!ishuman(bloodsucker.current) || !bloodsucker.current.client)
if(!ishuman(bloodsucker.current) || !bloodsucker.current.client)
return
var/am_valid = TRUE
var/mob/living/carbon/human/H = bloodsucker.current
@@ -202,7 +180,7 @@
// everyone will wonder why you're a human with Plasma clothes (jk they'll know you're antag)
// Convert to HUMAN (along with ID and PDA)
if (!am_valid)
if(!am_valid)
H.set_species(/datum/species/human)
H.real_name = H.client.prefs.custom_names["human"]
var/obj/item/card/id/ID = H.wear_id?.GetID()
@@ -211,12 +189,13 @@
ID.update_label()
/datum/game_mode/proc/can_make_vassal(mob/living/target, datum/mind/creator, display_warning=TRUE)//, check_antag_or_loyal=FALSE)
/datum/game_mode/proc/can_make_vassal(mob/living/target, datum/mind/creator, display_warning = TRUE)//, check_antag_or_loyal=FALSE)
// Not Correct Type: Abort
if (!iscarbon(target) || !creator)
if(!iscarbon(target) || !creator)
return FALSE
if (target.stat > UNCONSCIOUS)
if(target.stat > UNCONSCIOUS)
return FALSE
// Check Overdose: Am I even addicted to blood? Do I even have any in me?
//if (!target.reagents.addiction_list || !target.reagents.reagent_list)
//message_admins("DEBUG2: can_make_vassal() Abort: No reagents")
@@ -233,23 +212,23 @@
//message_admins("DEBUG4: can_make_vassal() Abort: No Blood")
// return 0
// No Mind!
if (!target.mind || !target.mind.key)
if (display_warning)
if(!target.mind || !target.mind.key)
if(display_warning)
to_chat(creator, "<span class='danger'>[target] isn't self-aware enough to be made into a Vassal.</span>")
return FALSE
// Already MY Vassal
var/datum/antagonist/vassal/V = target.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
if (istype(V) && V.master)
if (V.master.owner == creator)
if (display_warning)
if(istype(V) && V.master)
if(V.master.owner == creator)
if(display_warning)
to_chat(creator, "<span class='danger'>[target] is already your loyal Vassal!</span>")
else
if (display_warning)
if(display_warning)
to_chat(creator, "<span class='danger'>[target] is the loyal Vassal of another Bloodsucker!</span>")
return FALSE
// Already Antag or Loyal (Vamp Hunters count as antags)
if (target.mind.enslaved_to || AmInvalidAntag(target.mind)) //!VassalCheckAntagValid(target.mind, check_antag_or_loyal)) // HAS_TRAIT(target, TRAIT_MINDSHIELD, "implant") ||
if (display_warning)
if(target.mind.enslaved_to || AmInvalidAntag(target.mind)) //!VassalCheckAntagValid(target.mind, check_antag_or_loyal)) // HAS_TRAIT(target, TRAIT_MINDSHIELD, "implant") ||
if(display_warning)
to_chat(creator, "<span class='danger'>[target] resists the power of your blood to dominate their mind!</span>")
return FALSE
return TRUE
@@ -268,24 +247,24 @@
return FALSE
// Does even ONE antag appear in this mind that isn't in the list? Then FAIL!
for(var/datum/antagonist/antag_datum in M.antag_datums)
if (!(antag_datum.type in vassal_allowed_antags)) // vassal_allowed_antags is a list stored in the game mode, above.
if(!(antag_datum.type in vassal_allowed_antags)) // vassal_allowed_antags is a list stored in the game mode, above.
//message_admins("DEBUG VASSAL: Found Invalid: [antag_datum] // [antag_datum.type]")
return TRUE
//message_admins("DEBUG VASSAL: Valid Antags! (total of [M.antag_datums.len])")
// WHEN YOU DELETE THE ABOVE: Remove the 3 second timer on converting the vassal too.
return FALSE
/datum/game_mode/proc/make_vassal(mob/living/target, datum/mind/creator)
if (!can_make_vassal(target,creator))
/datum/game_mode/proc/make_vassal(var/mob/living/target, var/datum/mind/creator)
if(!can_make_vassal(target, creator))
return FALSE
// Make Vassal
var/datum/antagonist/vassal/V = new (target.mind)
var/datum/antagonist/vassal/V = new(target.mind)
var/datum/antagonist/bloodsucker/B = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
V.master = B
target.mind.add_antag_datum(V, V.master.get_team())
// Update Bloodsucker Title (we're a daddy now)
B.SelectTitle(am_fledgling = FALSE) // Only works if you have no title yet.
// Log
// Log it
message_admins("[target] has become a Vassal, and is enslaved to [creator].")
log_admin("[target] has become a Vassal, and is enslaved to [creator].")
return TRUE
@@ -119,7 +119,6 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
C.appearance = chosen_prof.appearance_list[slot]
C.name = chosen_prof.name_list[slot]
C.flags_cover = chosen_prof.flags_cover_list[slot]
C.item_color = chosen_prof.item_color_list[slot]
C.item_state = chosen_prof.item_state_list[slot]
if(equip)
user.equip_to_slot_or_del(C, GLOB.slot2slot[slot])
+8 -6
View File
@@ -45,8 +45,11 @@ Credit where due:
// PROCS //
///////////
/proc/is_servant_of_ratvar(mob/M)
return istype(M) && !isobserver(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/clockcult)
/proc/is_servant_of_ratvar(mob/M, require_full_power = FALSE, holy_water_check = FALSE)
if(!istype(M) || isobserver(M))
return FALSE
var/datum/antagonist/clockcult/D = M?.mind?.has_antag_datum(/datum/antagonist/clockcult)
return D && (!require_full_power || !D.neutered) && (!holy_water_check || !D.ignore_holy_water)
/proc/is_eligible_servant(mob/M)
if(!istype(M))
@@ -70,12 +73,14 @@ Credit where due:
return TRUE
return FALSE
/proc/add_servant_of_ratvar(mob/L, silent = FALSE, create_team = TRUE)
/proc/add_servant_of_ratvar(mob/L, silent = FALSE, create_team = TRUE, override_type)
if(!L || !L.mind)
return
var/update_type = /datum/antagonist/clockcult
if(silent)
update_type = /datum/antagonist/clockcult/silent
if(override_type) //prioritizes
update_type = override_type
var/datum/antagonist/clockcult/C = new update_type(L.mind)
C.make_team = create_team
C.show_in_roundend = create_team //tutorial scarabs begone
@@ -105,9 +110,6 @@ Credit where due:
L.playsound_local(get_turf(L), 'sound/ambience/antag/clockcultalr.ogg', 40, TRUE, frequency = 100000, pressure_affected = FALSE)
flash_color(L, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 5)
/proc/remove_servant_of_ratvar(mob/L, silent = FALSE)
if(!L || !L.mind)
return
@@ -63,7 +63,7 @@
attack_verb_on = list("slipped")
clumsy_check = FALSE
sharpness = IS_BLUNT
item_color = "yellow"
sword_color = "yellow"
heat = 0
light_color = "#ffff00"
var/next_trombone_allowed = 0
+6 -3
View File
@@ -3,8 +3,11 @@
/datum/game_mode
var/list/datum/mind/cult = list()
/proc/iscultist(mob/living/M)
return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/cult)
/proc/iscultist(mob/living/M, require_full_power = FALSE, holy_water_check = FALSE)
if(!istype(M))
return FALSE
var/datum/antagonist/cult/D = M?.mind?.has_antag_datum(/datum/antagonist/cult)
return D && (!require_full_power || !D.neutered) && (!holy_water_check || !D.ignore_holy_water)
/datum/team/cult/proc/is_sacrifice_target(datum/mind/mind)
for(var/datum/objective/sacrifice/sac_objective in objectives)
@@ -93,7 +96,7 @@
add_cultist(cult_mind, 0, equip=TRUE)
if(!main_cult)
var/datum/antagonist/cult/C = cult_mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(C && C.cult_team)
if(C?.cult_team)
main_cult = C.cult_team
..()
+5 -3
View File
@@ -205,7 +205,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
if(threatadd > 0)
create_threat(threatadd)
else
spend_threat(-threatadd)
remove_threat(threatadd)
else if (href_list["injectlate"])
latejoin_injection_cooldown = 0
forced_injection = TRUE
@@ -247,6 +247,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
. += "<b>Peaceful Waypoint</b></center><BR>"
. += "Your station orbits deep within controlled, core-sector systems and serves as a waypoint for routine traffic through Nanotrasen's trade empire. Due to the combination of high security, interstellar traffic, and low strategic value, it makes any direct threat of violence unlikely. Your primary enemies will be incompetence and bored crewmen: try to organize team-building events to keep staffers interested and productive. However, even deep in our territory there may be subversive elements, especially for such a high-value target as your station. Keep an eye out, but don't expect much trouble."
set_security_level(SEC_LEVEL_GREEN)
station_goals.len = 0
for(var/T in subtypesof(/datum/station_goal))
var/datum/station_goal/G = new T
if(!(G in station_goals))
@@ -257,6 +258,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
. += "<b>Core Territory</b></center><BR>"
. += "Your station orbits within reliably mundane, secure space. Although Nanotrasen has a firm grip on security in your region, the valuable resources and strategic position aboard your station make it a potential target for infiltrations. Monitor crew for non-loyal behavior, but expect a relatively tame shift free of large-scale destruction. We expect great things from your station."
set_security_level(SEC_LEVEL_GREEN)
station_goals.len = 0
for(var/T in subtypesof(/datum/station_goal))
var/datum/station_goal/G = new T
if(!(G in station_goals))
@@ -496,7 +498,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
starting_rule = pickweight(drafted_rules)
// Check if the ruleset is highlander and if a highlander ruleset has been executed
else if(starting_rule.flags & HIGHLANDER_RULESET) // Should already be filtered out, but making sure. Check filtering at end of proc if reported.
if(threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(threat_level <= GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(highlander_executed)
drafted_rules -= starting_rule
if(drafted_rules.len <= 0)
@@ -723,7 +725,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
threat = storyteller.calculate_threat() + added_threat
if(threat_average_weight)
var/cur_sample_weight = world.time - last_threat_sample_time
threat_average = ((threat_average * threat_average_weight) + threat) / (threat_average_weight + cur_sample_weight)
threat_average = ((threat_average * threat_average_weight) + (threat * cur_sample_weight)) / (threat_average_weight + cur_sample_weight)
threat_average_weight += cur_sample_weight
last_threat_sample_time = world.time
else
@@ -222,6 +222,26 @@
message_admins("[M.name] was made into a bloodsucker by dynamic.")
return TRUE
//////////////////////////////////////////////
// //
// CHANGELINGS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/latejoin/changeling
name = "Changeling Infiltrator"
config_tag = "latejoin_changeling"
antag_flag = ROLE_CHANGELING
antag_datum = /datum/antagonist/changeling
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 = 15
requirements = list(101,101,101,101,101,101,101,101,101,101)
property_weights = list("trust" = -2, "valid" = 2)
high_population_requirement = 101
//////////////////////////////////////////////
// //
// COLLECTOR //
-2
View File
@@ -381,14 +381,12 @@
for(var/obj/machinery/camera/C in oview(4, M))
if(C.can_use()) // check if camera disabled
return C
break
return null
/proc/near_range_camera(var/mob/M)
for(var/obj/machinery/camera/C in range(4, M))
if(C.can_use()) // check if camera disabled
return C
break
return null
+2 -2
View File
@@ -144,6 +144,8 @@
return FALSE
if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
return FALSE
if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker
return FALSE
if(clonemind.active) //somebody is using that mind
if( ckey(clonemind.key)!=ckey )
return FALSE
@@ -159,8 +161,6 @@
mess = TRUE
update_icon()
return FALSE
if(isvamp(clonemind)) //If the mind is a bloodsucker
return FALSE
attempting = TRUE //One at a time!!
countdown.start()
+2 -2
View File
@@ -45,11 +45,11 @@
if (ismob(user) && !isliving(user)) // ghosts don't need cameras
return
if (!network)
CRASH("No camera network")
stack_trace("No camera network")
user.unset_machine()
return FALSE
if (!(islist(network)))
CRASH("Camera network is not a list")
stack_trace("Camera network is not a list")
user.unset_machine()
return FALSE
@@ -292,6 +292,10 @@
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
CentCom_announce(input, usr)
to_chat(usr, "<span class='notice'>Message transmitted to Central Command.</span>")
for(var/client/X in GLOB.admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
SEND_SOUND(X, sound('sound/effects/printer.ogg'))
window_flash(X, ignorepref = FALSE)
usr.log_talk(input, LOG_SAY, tag="CentCom announcement")
deadchat_broadcast("<span class='deadsay'><span class='name'>[usr.real_name]</span> has messaged CentCom, \"[input]\" at <span class='name'>[get_area_name(usr, TRUE)]</span>.</span>", usr)
CM.lastTimeUsed = world.time
@@ -309,6 +313,10 @@
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
Syndicate_announce(input, usr)
to_chat(usr, "<span class='danger'>SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.</span>")
for(var/client/X in GLOB.admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
SEND_SOUND(X, sound('sound/effects/printer.ogg'))
window_flash(X, ignorepref = FALSE)
usr.log_talk(input, LOG_SAY, tag="Syndicate announcement")
deadchat_broadcast("<span class='deadsay'><span class='name'>[usr.real_name]</span> has messaged the Syndicate, \"[input]\" at <span class='name'>[get_area_name(usr, TRUE)]</span>.</span>", usr)
CM.lastTimeUsed = world.time
@@ -12,5 +12,5 @@
for(var/obj/machinery/door/D in locate(src.x,src.y,src.z))
if(!istype(D, /obj/machinery/door/window) && D.density)
return 0
//There are no false wall checks because that would be fucking retarded
//There are no false wall checks because that would be fucking
return 1
+2 -2
View File
@@ -57,7 +57,7 @@
var/turf/target = locate(target_x, target_y, z)
ghost.forceMove(target)
/obj/machinery/launchpad/proc/isAvailable()
/obj/machinery/launchpad/proc/isAvailable(silent = FALSE)
if(stat & NOPOWER)
return FALSE
if(panel_open)
@@ -198,7 +198,7 @@
QDEL_NULL(briefcase)
return ..()
/obj/machinery/launchpad/briefcase/isAvailable()
/obj/machinery/launchpad/briefcase/isAvailable(silent = FALSE)
if(closed)
return FALSE
return ..()
-1
View File
@@ -469,7 +469,6 @@ GLOBAL_LIST_EMPTY(allConsoles)
if(newmessagepriority < EXTREME_MESSAGE_PRIORITY)
newmessagepriority = EXTREME_MESSAGE_PRIORITY
update_icon()
if(1)
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
say(title)
messages += "<span class='bad'>!!!Extreme Priority!!!</span><BR><b>From:</b> [linkedsender]<BR>[message]"
+148 -101
View File
@@ -1,3 +1,111 @@
//dye registry, add dye colors and their resulting output here if you want the sprite to change instead of just the color.
GLOBAL_LIST_INIT(dye_registry, list(
DYE_REGISTRY_UNDER = list(
DYE_RED = /obj/item/clothing/under/color/red,
DYE_ORANGE = /obj/item/clothing/under/color/orange,
DYE_YELLOW = /obj/item/clothing/under/color/yellow,
DYE_GREEN = /obj/item/clothing/under/color/green,
DYE_BLUE = /obj/item/clothing/under/color/blue,
DYE_PURPLE = /obj/item/clothing/under/color/lightpurple,
DYE_BLACK = /obj/item/clothing/under/color/black,
DYE_WHITE = /obj/item/clothing/under/color/white,
DYE_RAINBOW = /obj/item/clothing/under/color/rainbow,
DYE_MIME = /obj/item/clothing/under/rank/civilian/mime,
DYE_CLOWN = /obj/item/clothing/under/rank/civilian/clown,
DYE_QM = /obj/item/clothing/under/rank/cargo/qm,
DYE_LAW = /obj/item/clothing/under/suit/black,
DYE_CAPTAIN = /obj/item/clothing/under/rank/captain,
DYE_HOP = /obj/item/clothing/under/rank/civilian/head_of_personnel,
DYE_HOS = /obj/item/clothing/under/rank/security/head_of_security,
DYE_CE = /obj/item/clothing/under/rank/engineering/chief_engineer,
DYE_RD = /obj/item/clothing/under/rank/rnd/research_director,
DYE_CMO = /obj/item/clothing/under/rank/medical/chief_medical_officer,
DYE_REDCOAT = /obj/item/clothing/under/costume/redcoat
),
DYE_REGISTRY_JUMPSKIRT = list(
DYE_RED = /obj/item/clothing/under/color/jumpskirt/red,
DYE_ORANGE = /obj/item/clothing/under/color/jumpskirt/orange,
DYE_YELLOW = /obj/item/clothing/under/color/jumpskirt/yellow,
DYE_GREEN = /obj/item/clothing/under/color/jumpskirt/green,
DYE_BLUE = /obj/item/clothing/under/color/jumpskirt/blue,
DYE_PURPLE = /obj/item/clothing/under/color/jumpskirt/lightpurple,
DYE_BLACK = /obj/item/clothing/under/color/jumpskirt/black,
DYE_WHITE = /obj/item/clothing/under/color/jumpskirt/white,
DYE_RAINBOW = /obj/item/clothing/under/color/jumpskirt/rainbow
),
DYE_REGISTRY_GLOVES = list(
DYE_RED = /obj/item/clothing/gloves/color/red,
DYE_ORANGE = /obj/item/clothing/gloves/color/orange,
DYE_YELLOW = /obj/item/clothing/gloves/color/yellow,
DYE_GREEN = /obj/item/clothing/gloves/color/green,
DYE_BLUE = /obj/item/clothing/gloves/color/blue,
DYE_PURPLE = /obj/item/clothing/gloves/color/purple,
DYE_BLACK = /obj/item/clothing/gloves/color/black,
DYE_WHITE = /obj/item/clothing/gloves/color/white,
DYE_RAINBOW = /obj/item/clothing/gloves/color/rainbow,
DYE_MIME = /obj/item/clothing/gloves/color/white,
DYE_CLOWN = /obj/item/clothing/gloves/color/rainbow,
DYE_QM = /obj/item/clothing/gloves/color/brown,
DYE_CAPTAIN = /obj/item/clothing/gloves/color/captain,
DYE_HOP = /obj/item/clothing/gloves/color/grey,
DYE_HOS = /obj/item/clothing/gloves/color/black,
DYE_CE = /obj/item/clothing/gloves/color/black,
DYE_RD = /obj/item/clothing/gloves/color/grey,
DYE_CMO = /obj/item/clothing/gloves/color/latex/nitrile,
DYE_REDCOAT = /obj/item/clothing/gloves/color/white
),
DYE_REGISTRY_SNEAKERS = list(
DYE_RED = /obj/item/clothing/shoes/sneakers/red,
DYE_ORANGE = /obj/item/clothing/shoes/sneakers/orange,
DYE_YELLOW = /obj/item/clothing/shoes/sneakers/yellow,
DYE_GREEN = /obj/item/clothing/shoes/sneakers/green,
DYE_BLUE = /obj/item/clothing/shoes/sneakers/blue,
DYE_PURPLE = /obj/item/clothing/shoes/sneakers/purple,
DYE_BLACK = /obj/item/clothing/shoes/sneakers/black,
DYE_WHITE = /obj/item/clothing/shoes/sneakers/white,
DYE_RAINBOW = /obj/item/clothing/shoes/sneakers/rainbow,
DYE_MIME = /obj/item/clothing/shoes/sneakers/black,
DYE_QM = /obj/item/clothing/shoes/sneakers/brown,
DYE_CAPTAIN = /obj/item/clothing/shoes/sneakers/brown,
DYE_HOP = /obj/item/clothing/shoes/sneakers/brown,
DYE_CE = /obj/item/clothing/shoes/sneakers/brown,
DYE_RD = /obj/item/clothing/shoes/sneakers/brown,
DYE_CMO = /obj/item/clothing/shoes/sneakers/brown
),
DYE_REGISTRY_FANNYPACK = list(
DYE_RED = /obj/item/storage/belt/fannypack/red,
DYE_ORANGE = /obj/item/storage/belt/fannypack/orange,
DYE_YELLOW = /obj/item/storage/belt/fannypack/yellow,
DYE_GREEN = /obj/item/storage/belt/fannypack/green,
DYE_BLUE = /obj/item/storage/belt/fannypack/blue,
DYE_PURPLE = /obj/item/storage/belt/fannypack/purple,
DYE_BLACK = /obj/item/storage/belt/fannypack/black,
DYE_WHITE = /obj/item/storage/belt/fannypack/white
),
DYE_REGISTRY_BEDSHEET = list(
DYE_RED = /obj/item/bedsheet/red,
DYE_ORANGE = /obj/item/bedsheet/orange,
DYE_YELLOW = /obj/item/bedsheet/yellow,
DYE_GREEN = /obj/item/bedsheet/green,
DYE_BLUE = /obj/item/bedsheet/blue,
DYE_PURPLE = /obj/item/bedsheet/purple,
DYE_BLACK = /obj/item/bedsheet/black,
DYE_WHITE = /obj/item/bedsheet,
DYE_RAINBOW = /obj/item/bedsheet/rainbow,
DYE_MIME = /obj/item/bedsheet/mime,
DYE_CLOWN = /obj/item/bedsheet/clown,
DYE_QM = /obj/item/bedsheet/qm,
DYE_LAW = /obj/item/bedsheet/black,
DYE_CAPTAIN = /obj/item/bedsheet/captain,
DYE_HOP = /obj/item/bedsheet/hop,
DYE_HOS = /obj/item/bedsheet/hos,
DYE_CE = /obj/item/bedsheet/ce,
DYE_RD = /obj/item/bedsheet/rd,
DYE_CMO = /obj/item/bedsheet/cmo,
DYE_COSMIC = /obj/item/bedsheet/cosmos
)
))
/obj/machinery/washing_machine
name = "washing machine"
desc = "Gets rid of those pesky bloodstains, or your money back!"
@@ -13,27 +121,22 @@
/obj/machinery/washing_machine/examine(mob/user)
. = ..()
. += "<span class='notice'>Alt-click it to start a wash cycle.</span>"
if(!busy)
. += "<span class='notice'><b>Alt-click</b> it to start a wash cycle.</span>"
/obj/machinery/washing_machine/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src))
return
if(busy)
return
if(state_open)
to_chat(user, "<span class='notice'>Close the door first</span>")
return TRUE
if(bloody_mess)
to_chat(user, "<span class='warning'>[src] must be cleaned up first.</span>")
return TRUE
if(has_corgi)
bloody_mess = 1
busy = TRUE
update_icon()
addtimer(CALLBACK(src, .proc/wash_cycle), 200)
@@ -76,6 +179,28 @@
color_source = null
update_icon()
/obj/item/proc/dye_item(dye_color)
if(undyeable)
return FALSE
if(dying_key)
if(!GLOB.dye_registry[dying_key])
log_runtime("Item just tried to be dyed with an invalid registry key: [dying_key]")
return FALSE
var/obj/item/target_type = GLOB.dye_registry[dying_key][dye_color]
if(target_type)
icon = initial(target_type.icon)
icon_state = initial(target_type.icon_state)
lefthand_file = initial(target_type.lefthand_file)
righthand_file = initial(target_type.righthand_file)
item_state = initial(target_type.item_state)
mob_overlay_icon = initial(target_type.mob_overlay_icon)
inhand_x_dimension = initial(target_type.inhand_x_dimension)
inhand_y_dimension = initial(target_type.inhand_y_dimension)
name = initial(target_type.name)
desc = "[initial(target_type.desc)] The colors look a little dodgy."
return target_type //successfully "appearance copy" dyed something; returns the target type as a hacky way of extending
add_atom_colour(dye_color, FIXED_COLOUR_PRIORITY)
return FALSE
//what happens to this object when washed inside a washing machine
/atom/movable/proc/machine_wash(obj/machinery/washing_machine/WM)
@@ -89,105 +214,27 @@
new /obj/item/reagent_containers/food/snacks/meat/slab/corgi(loc)
qdel(src)
/obj/item/paper/machine_wash(obj/machinery/washing_machine/WM)
if(WM.color_source)
if(istype(WM.color_source, /obj/item/toy/crayon))
var/obj/item/toy/crayon/CR = WM.color_source
add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY)
/obj/item/reagents_containers/rag/towel/machine_wash(obj/machinery/washing_machine/WM)
if(WM.color_source)
if(istype(WM.color_source, /obj/item/toy/crayon))
var/obj/item/toy/crayon/CR = WM.color_source
add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY)
/mob/living/simple_animal/pet/dog/corgi/machine_wash(obj/machinery/washing_machine/WM)
gib()
/obj/item/clothing/under/color/machine_wash(obj/machinery/washing_machine/WM)
jumpsuit_wash(WM)
/obj/item/clothing/under/rank/machine_wash(obj/machinery/washing_machine/WM)
jumpsuit_wash(WM)
/obj/item/clothing/under/proc/jumpsuit_wash(obj/machinery/washing_machine/WM)
/obj/item/machine_wash(obj/machinery/washing_machine/WM)
if(WM.color_source)
var/wash_color = WM.color_source.item_color
var/obj/item/clothing/under/U
for(var/T in typesof(/obj/item/clothing/under/color))
var/obj/item/clothing/under/color/J = T
if(wash_color == initial(J.item_color))
U = J
break
if(!U)
for(var/T in typesof(/obj/item/clothing/under/rank))
var/obj/item/clothing/under/rank/R = T
if(wash_color == initial(R.item_color))
U = R
break
if(U)
item_state = initial(U.item_state)
icon_state = initial(U.icon_state)
item_color = wash_color
name = initial(U.name)
desc = "The colors are a bit dodgy."
can_adjust = initial(U.can_adjust)
if(!can_adjust && adjusted) //we deadjust the uniform if it's now unadjustable
toggle_jumpsuit_adjust()
dye_item(WM.color_source.dye_color)
/obj/item/clothing/gloves/color/machine_wash(obj/machinery/washing_machine/WM)
if(WM.color_source)
var/wash_color = WM.color_source.item_color
for(var/T in typesof(/obj/item/clothing/gloves/color))
var/obj/item/clothing/gloves/color/G = T
if(wash_color == initial(G.item_color))
item_state = initial(G.item_state)
icon_state = initial(G.icon_state)
item_color = wash_color
name = initial(G.name)
desc = "The colors are a bit dodgy."
break
/obj/item/clothing/under/dye_item(dye_color, dye_key)
. = ..()
if(.)
var/obj/item/clothing/under/U = .
can_adjust = initial(U.can_adjust)
if(!can_adjust && adjusted) //we deadjust the uniform if it's now unadjustable
toggle_jumpsuit_adjust()
/obj/item/clothing/shoes/sneakers/machine_wash(obj/machinery/washing_machine/WM)
if(chained)
chained = 0
slowdown = SHOES_SLOWDOWN
new /obj/item/restraints/handcuffs(loc)
if(WM.color_source)
var/wash_color = WM.color_source.item_color
for(var/T in typesof(/obj/item/clothing/shoes/sneakers))
var/obj/item/clothing/shoes/sneakers/S = T
if(wash_color == initial(S.item_color))
icon_state = initial(S.icon_state)
item_color = wash_color
name = initial(S.name)
desc = "The colors are a bit dodgy."
break
/obj/item/bedsheet/machine_wash(obj/machinery/washing_machine/WM)
if(WM.color_source)
var/wash_color = WM.color_source.item_color
for(var/T in typesof(/obj/item/bedsheet))
var/obj/item/bedsheet/B = T
if(wash_color == initial(B.item_color))
icon_state = initial(B.icon_state)
item_color = wash_color
name = initial(B.name)
desc = "The colors are a bit dodgy."
break
/obj/item/clothing/head/soft/machine_wash(obj/machinery/washing_machine/WM)
if(WM.color_source)
var/wash_color = WM.color_source.item_color
for(var/T in typesof(/obj/item/clothing/head/soft))
var/obj/item/clothing/head/soft/H = T
if(wash_color == initial(H.item_color))
icon_state = initial(H.icon_state)
item_color = wash_color
name = initial(H.name)
desc = "The colors are a bit dodgy."
break
..()
/obj/machinery/washing_machine/relaymove(mob/user)
container_resist(user)
@@ -223,27 +270,27 @@
if(istype(W, /obj/item/clothing/head/mob_holder))
to_chat(user, "<span class='warning'>It's too unwieldly to put in this way.</span>")
return 1
return TRUE
else if(user.a_intent != INTENT_HARM)
if (!state_open)
to_chat(user, "<span class='warning'>Open the door first!</span>")
return 1
return TRUE
if(bloody_mess)
to_chat(user, "<span class='warning'>[src] must be cleaned up first.</span>")
return 1
return TRUE
if(contents.len >= max_wash_capacity)
to_chat(user, "<span class='warning'>The washing machine is full!</span>")
return 1
return TRUE
if(!user.transferItemToLoc(W, src))
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you cannot put it in the washing machine!</span>")
return 1
return TRUE
if(istype(W, /obj/item/toy/crayon) || istype(W, /obj/item/stamp))
if(W.dye_color)
color_source = W
update_icon()
+43 -18
View File
@@ -2,6 +2,7 @@
icon = 'icons/effects/landmarks_static.dmi'
icon_state = "random_loot"
layer = OBJ_LAYER
var/spawn_on_turf = TRUE
var/lootcount = 1 //how many items will be spawned
var/lootdoubles = TRUE //if the same item can be spawned twice
var/list/loot //a list of possible items to spawn e.g. list(/obj/item, /obj/structure, /obj/effect)
@@ -10,7 +11,7 @@
/obj/effect/spawner/lootdrop/Initialize(mapload)
..()
if(loot && loot.len)
var/turf/T = get_turf(src)
var/atom/A = spawn_on_turf ? get_turf(src) : loc
var/loot_spawned = 0
while((lootcount-loot_spawned) && loot.len)
var/lootspawn = pickweight(loot)
@@ -18,7 +19,7 @@
loot.Remove(lootspawn)
if(lootspawn)
var/atom/movable/spawned_loot = new lootspawn(T)
var/atom/movable/spawned_loot = new lootspawn(A)
if (!fan_out_items)
if (pixel_x != 0)
spawned_loot.pixel_x = pixel_x
@@ -449,6 +450,7 @@
/obj/effect/spawner/lootdrop/low_loot_toilet
name = "random low toilet spawner"
lootcount = 1
spawn_on_turf = FALSE
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
//This is ment for "low" loot that anyone could fine in a toilet, for better gear use high loot toilet
loot = list("" = 30,
@@ -458,41 +460,42 @@
/obj/item/clothing/glasses/sunglasses/blindfold = 4,
/obj/item/clothing/glasses/sunglasses = 1,
/obj/item/toy/plush/random = 5,
/obj/effect/spawner/lootdrop/gloves = 5,
/obj/effect/spawner/lootdrop/glowstick = 5,
/obj/effect/spawner/lootdrop/coin = 3,
/obj/effect/spawner/lootdrop/cig_packs = 10,
/obj/effect/spawner/lootdrop/cigars_cases = 2,
/obj/effect/spawner/lootdrop/space_cash = 5,
/obj/effect/spawner/lootdrop/gloves/no_turf = 5,
/obj/effect/spawner/lootdrop/glowstick/no_turf = 5,
/obj/effect/spawner/lootdrop/coin/no_turf = 3,
/obj/effect/spawner/lootdrop/cig_packs/no_turf = 10,
/obj/effect/spawner/lootdrop/cigars_cases/no_turf = 2,
/obj/effect/spawner/lootdrop/space_cash/no_turf = 5,
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
/obj/item/storage/pill_bottle/dice = 5,
/obj/item/toy/cards/deck = 5,
/obj/effect/spawner/lootdrop/druggie_pill = 5
/obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5
)
/obj/effect/spawner/lootdrop/prison_loot_toilet
name = "random prison toilet spawner"
lootcount = 1
spawn_on_turf = FALSE
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
//This is ment for "prison" loot that is rather rare and ment for "prisoners if they get a crowbar to fine, or sec.
loot = list("" = 10,
/obj/item/lighter = 5,
/obj/item/poster/random_contraband = 5,
/obj/item/clothing/glasses/sunglasses = 5,
/obj/effect/spawner/lootdrop/coin = 5,
/obj/effect/spawner/lootdrop/cig_packs = 10,
/obj/effect/spawner/lootdrop/cigars_cases = 5,
/obj/effect/spawner/lootdrop/coin/no_turf = 5,
/obj/effect/spawner/lootdrop/cig_packs/no_turf = 10,
/obj/effect/spawner/lootdrop/cigars_cases/no_turf = 5,
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
/obj/item/storage/pill_bottle/dice = 5,
/obj/item/toy/cards/deck = 5,
/obj/effect/spawner/lootdrop/druggie_pill = 5,
/obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5,
/obj/item/kitchen/knife = 5,
/obj/item/screwdriver = 5,
/obj/item/crowbar/red = 0.5, //Dont you need a crowbar to open this?
/obj/item/crowbar/red = 1, //Dont you need a crowbar to open this?
/obj/item/stack/medical/bruise_pack = 3,
/obj/item/reagent_containers/food/drinks/bottle/vodka = 2,
/obj/item/radio = 5,
/obj/item/flashlight = 4.5,
/obj/item/flashlight = 4,
/obj/item/clothing/mask/breath = 2,
/obj/item/tank/internals/emergency_oxygen = 3,
/obj/item/storage/box/mre/menu4/safe = 3,
@@ -502,13 +505,14 @@
/obj/effect/spawner/lootdrop/high_loot_toilet
name = "random high toilet spawner"
lootcount = 1
spawn_on_turf = FALSE
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
//The items inside are always going to be something usefull, illegal and likely traitorous.
loot = list(
/obj/item/clothing/glasses/sunglasses = 5,
/obj/effect/spawner/lootdrop/coin = 5,
/obj/effect/spawner/lootdrop/space_cash = 5,
/obj/effect/spawner/lootdrop/druggie_pill = 5,
/obj/effect/spawner/lootdrop/coin/no_turf = 5,
/obj/effect/spawner/lootdrop/space_cash/no_turf = 5,
/obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5,
/obj/item/storage/fancy/cigarettes/cigpack_syndicate = 5,
/obj/item/suppressor = 5,
/obj/item/toy/cards/deck/syndicate = 5,
@@ -521,3 +525,24 @@
/obj/item/clothing/gloves/combat = 10,
/obj/item/clothing/shoes/sneakers/noslip = 10
)
/obj/effect/spawner/lootdrop/coin/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/space_cash/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/druggie_pill/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/gloves/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/cig_packs/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/cigars_cases/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/glowstick/no_turf
spawn_on_turf = FALSE
+34 -6
View File
@@ -8,9 +8,20 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
name = "item"
icon = 'icons/obj/items_and_weapons.dmi'
blocks_emissive = EMISSIVE_BLOCK_GENERIC
///icon state name for inhand overlays
var/item_state = null
///Icon file for left hand inhand overlays
var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
///Icon file for right inhand overlays
var/righthand_file = 'icons/mob/inhands/items_righthand.dmi'
///Icon file for mob worn overlays.
///no var for state because it should *always* be the same as icon_state
var/icon/mob_overlay_icon
//Forced mob worn layer instead of the standard preferred ssize.
var/alternate_worn_layer
var/list/alternate_screams = list() //REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
//Dimensions of the icon file used when this item is worn, eg: hats.dmi
@@ -22,10 +33,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/inhand_x_dimension = 32
var/inhand_y_dimension = 32
//Not on /clothing because for some reason any /obj/item can technically be "worn" with enough fuckery.
var/icon/alternate_worn_icon = null//If this is set, update_icons() will find on mob (WORN, NOT INHANDS) states in this file instead, primary use: badminnery/events
var/alternate_worn_layer = null//If this is set, update_icons() will force the on mob state (WORN, NOT INHANDS) onto this layer, instead of it's default
max_integrity = 200
obj_flags = NONE
@@ -34,7 +41,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/hitsound = null
var/usesound = null
var/throwhitsound = null
/// Weight class for how much storage capacity it uses and how big it physically is meaning storages can't hold it if their maximum weight class isn't as high as it.
var/w_class = WEIGHT_CLASS_NORMAL
/// Volume override for the item, otherwise automatically calculated from w_class.
var/w_volume
/// The amount of stamina it takes to swing an item in a normal melee attack do not lie to me and say it's for realism because it ain't. If null it will autocalculate from w_class.
var/total_mass //Total mass in arbitrary pound-like values. If there's no balance reasons for an item to have otherwise, this var should be the item's weight in pounds.
@@ -61,8 +72,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
//Citadel Edit for digitigrade stuff
var/mutantrace_variation = NONE //Are there special sprites for specific situations? Don't use this unless you need to.
var/item_color = null //this needs deprecating, soonish
var/body_parts_covered = 0 //see setup.dm for appropriate bit flags
var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets)
var/permeability_coefficient = 1 // for chemicals/diseases
@@ -109,6 +118,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/trigger_guard = TRIGGER_GUARD_NONE
///Used as the dye color source in the washing machine only (at the moment). Can be a hex color or a key corresponding to a registry entry, see washing_machine.dm
var/dye_color
///Whether the item is unaffected by standard dying.
var/undyeable = FALSE
///What dye registry should be looked at when dying this item; see washing_machine.dm
var/dying_key
//Grinder vars
var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only
var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder!
@@ -422,6 +438,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
item_flags |= IN_INVENTORY
user.update_equipment_speed_mods()
//Overlays for the worn overlay so you can overlay while you overlay
//eg: ammo counters, primed grenade flashing, etc.
//"icon_file" is used automatically for inhands etc. to make sure it gets the right inhand file
/obj/item/proc/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = list()
SEND_SIGNAL(src, COMSIG_ITEM_WORN_OVERLAYS, isinhands, icon_file, used_state, style_flags, .)
//sometimes we only want to grant the item's action if it's equipped in a specific slot.
/obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED) //these aren't true slots, so avoid granting actions there
@@ -845,6 +868,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
return
return ..()
/// Get an item's volume that it uses when being stored.
/obj/item/proc/get_w_volume()
// if w_volume is 0 you fucked up anyways lol
return w_volume || AUTO_SCALE_VOLUME(w_class)
/obj/item/proc/embedded(mob/living/carbon/human/embedded_mob)
return
+4 -5
View File
@@ -113,7 +113,7 @@
cable_overlay.color = GLOB.cable_colors[colors[current_color_index]]
. += cable_overlay
/obj/item/twohanded/rcl/worn_overlays(isinhands, icon_file, style_flags = NONE)
/obj/item/twohanded/rcl/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands || !(loaded?.amount))
return
@@ -201,7 +201,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
return //If we've run out, display message and exit
else
last = null
loaded.item_color = colors[current_color_index]
loaded.color = colors[current_color_index]
last = loaded.place_turf(get_turf(src), user, turn(user.dir, 180))
is_empty(user) //If we've run out, display message
update_icon()
@@ -223,7 +223,6 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
continue
if(C.d1 == 0)
return C
break
return
@@ -277,7 +276,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
if(T.intact || !T.can_have_cabling())
return
loaded.item_color = colors[current_color_index]
loaded.color = colors[current_color_index]
var/obj/structure/cable/linkingCable = findLinkingCable(user)
if(linkingCable)
@@ -299,7 +298,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
var/cwname = colors[current_color_index]
to_chat(user, "Color changed to [cwname]!")
if(loaded)
loaded.item_color= colors[current_color_index]
loaded.color = colors[current_color_index]
update_icon()
if(wiring_gui_menu)
wiringGuiUpdate(user)
+1 -1
View File
@@ -15,7 +15,7 @@
lefthand_file = 'modular_citadel/icons/mob/inhands/balls_left.dmi'
righthand_file = 'modular_citadel/icons/mob/inhands/balls_right.dmi'
item_state = "tennis_classic"
alternate_worn_icon = 'modular_citadel/icons/mob/mouthball.dmi'
mob_overlay_icon = 'modular_citadel/icons/mob/mouthball.dmi'
slot_flags = ITEM_SLOT_HEAD | ITEM_SLOT_NECK | ITEM_SLOT_EARS //Fluff item, put it wherever you want!
throw_range = 14
w_class = WEIGHT_CLASS_SMALL
+10 -1
View File
@@ -38,7 +38,6 @@
/obj/item/bodybag/bluespace
name = "bluespace body bag"
desc = "A folded bluespace body bag designed for the storage and transportation of cadavers."
icon = 'icons/obj/bodybag.dmi'
icon_state = "bluebodybag_folded"
unfoldedbag_path = /obj/structure/closet/body_bag/bluespace
w_class = WEIGHT_CLASS_SMALL
@@ -81,3 +80,13 @@
return
loc.visible_message("<span class='warning'>[user] suddenly appears in front of [loc]!</span>", "<span class='userdanger'>[user] breaks free of [src]!</span>")
qdel(src)
// Containment bodybag
/obj/item/bodybag/containment
name = "radiation containment body bag"
desc = "A folded heavy body bag designed for the storage and transportation of heavily irradiated cadavers."
icon_state = "radbodybag_folded"
unfoldedbag_path = /obj/structure/closet/body_bag/containment
w_class = WEIGHT_CLASS_NORMAL
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
+26 -14
View File
@@ -26,7 +26,7 @@
var/icon_uncapped
var/use_overlays = FALSE
item_color = "red"
var/crayon_color = "red"
w_class = WEIGHT_CLASS_TINY
attack_verb = list("attacked", "coloured")
grind_results = list()
@@ -83,7 +83,9 @@
. = ..()
// Makes crayons identifiable in things like grinders
if(name == "crayon")
name = "[item_color] crayon"
name = "[crayon_color] crayon"
dye_color = crayon_color
drawtype = pick(all_drawables)
@@ -484,65 +486,75 @@
/obj/item/toy/crayon/red
icon_state = "crayonred"
paint_color = "#DA0000"
item_color = "red"
crayon_color = "red"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/red = 1)
dye_color = DYE_RED
/obj/item/toy/crayon/orange
icon_state = "crayonorange"
paint_color = "#FF9300"
item_color = "orange"
crayon_color = "orange"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/orange = 1)
dye_color = DYE_ORANGE
/obj/item/toy/crayon/yellow
icon_state = "crayonyellow"
paint_color = "#FFF200"
item_color = "yellow"
crayon_color = "yellow"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/yellow = 1)
dye_color = DYE_YELLOW
/obj/item/toy/crayon/green
icon_state = "crayongreen"
paint_color = "#A8E61D"
item_color = "green"
crayon_color = "green"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/green = 1)
dye_color = DYE_GREEN
/obj/item/toy/crayon/blue
icon_state = "crayonblue"
paint_color = "#00B7EF"
item_color = "blue"
crayon_color = "blue"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/blue = 1)
dye_color = DYE_BLUE
/obj/item/toy/crayon/purple
icon_state = "crayonpurple"
paint_color = "#DA00FF"
item_color = "purple"
crayon_color = "purple"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/purple = 1)
dye_color = DYE_PURPLE
/obj/item/toy/crayon/black
icon_state = "crayonblack"
paint_color = "#1C1C1C" //Not completely black because total black looks bad. So Mostly Black.
item_color = "black"
crayon_color = "black"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/black = 1)
dye_color = DYE_BLACK
/obj/item/toy/crayon/white
icon_state = "crayonwhite"
paint_color = "#FFFFFF"
item_color = "white"
crayon_color = "white"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/white = 1)
dye_color = DYE_WHITE
/obj/item/toy/crayon/mime
icon_state = "crayonmime"
desc = "A very sad-looking crayon."
paint_color = "#FFFFFF"
item_color = "mime"
crayon_color = "mime"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/invisible = 1)
charges = -1
dye_color = DYE_MIME
/obj/item/toy/crayon/rainbow
icon_state = "crayonrainbow"
paint_color = "#FFF000"
item_color = "rainbow"
crayon_color = "rainbow"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent = 1)
drawtype = RANDOM_ANY // just the default starter.
dye_color = DYE_RAINBOW
charges = -1
@@ -580,12 +592,12 @@
/obj/item/storage/crayons/update_overlays()
. = ..()
for(var/obj/item/toy/crayon/crayon in contents)
add_overlay(mutable_appearance('icons/obj/crayons.dmi', crayon.item_color))
add_overlay(mutable_appearance('icons/obj/crayons.dmi', crayon.crayon_color))
/obj/item/storage/crayons/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = W
switch(C.item_color)
switch(C.crayon_color)
if("mime")
to_chat(usr, "This crayon is too sad to be contained in this box.")
return
+2 -2
View File
@@ -807,9 +807,9 @@ GLOBAL_LIST_EMPTY(PDAs)
// If it didn't reach, note that fact
if (!signal.data["done"])
to_chat(user, "<span class='notice'>ERROR: Server isn't responding.</span>")
return
if (!silent)
playsound(src, 'sound/machines/terminal_error.ogg', 15, 1)
return
var/target_text = signal.format_target()
if(allow_emojis)
@@ -998,9 +998,9 @@ GLOBAL_LIST_EMPTY(PDAs)
var/obj/item/card/id/idcard = C
if(!idcard.registered_name)
to_chat(user, "<span class='warning'>\The [src] rejects the ID!</span>")
return
if (!silent)
playsound(src, 'sound/machines/terminal_error.ogg', 15, 1)
return
if(!owner)
owner = idcard.registered_name
+2 -2
View File
@@ -692,14 +692,14 @@ Code:
return
GLOB.news_network.SubmitArticle(message,host_pda.owner,current_channel)
host_pda.Topic(null,list("choice"=num2text(host_pda.mode)))
return
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
return
if("Newscaster Switch Channel")
current_channel = host_pda.msg_input()
host_pda.Topic(null,list("choice"=num2text(host_pda.mode)))
return
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
return
//emoji previews
if(href_list["emoji"])
@@ -149,7 +149,7 @@ Code:
name = "shock collar"
desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.."
icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi'
alternate_worn_icon = 'modular_citadel/icons/mob/citadel/neck.dmi'
mob_overlay_icon = 'modular_citadel/icons/mob/citadel/neck.dmi'
icon_state = "shockcollar"
item_state = "shockcollar"
body_parts_covered = NECK
+1 -3
View File
@@ -275,10 +275,8 @@ SLIME SCANNER
//LIVER
else if(istype(O, /obj/item/organ/liver))
var/obj/item/organ/liver/L = O
if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated
if(L.organ_flags & ORGAN_FAILING && H.stat != DEAD) //might be depreciated
temp_message += "<span class='danger'>Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!</span>"
if(L.swelling > 20)
temp_message += " <span class='danger'>Subject is suffering from an enlarged liver.</span>" //i.e. shrink their liver or give them a transplant.
//HEART
else if(ishuman(M) && (istype(O, /obj/item/organ/heart)))
+5 -5
View File
@@ -51,8 +51,8 @@
to_chat(user, "<span class='warning'>You have already forged a seal on [src]!</span>")
else
var/obj/item/toy/crayon/C = O
name = "[C.item_color] secret documents"
icon_state = "docs_[C.item_color]"
forgedseal = C.item_color
to_chat(user, "<span class='notice'>You forge the official seal with a [C.item_color] crayon. No one will notice... right?</span>")
update_icon()
name = "[C.crayon_color] secret documents"
icon_state = "docs_[C.crayon_color]"
forgedseal = C.crayon_color
to_chat(user, "<span class='notice'>You forge the official seal with a [C.crayon_color] crayon. No one will notice... right?</span>")
update_icon()
+3 -10
View File
@@ -113,7 +113,7 @@
desc = "Looks like some cables tied together. Could be used to tie something up."
icon_state = "cuff"
item_state = "coil"
color = "red"
color = "#ff0000"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
custom_materials = list(/datum/material/iron=150, /datum/material/glass=75)
@@ -132,35 +132,28 @@
to_chat(user, "<span class='notice'>You unwind the cable restraints back into coil</span>")
/obj/item/restraints/handcuffs/cable/red
item_color = "red"
color = "#ff0000"
/obj/item/restraints/handcuffs/cable/yellow
item_color = "yellow"
color = "#ffff00"
/obj/item/restraints/handcuffs/cable/blue
item_color = "blue"
color = "#1919c8"
/obj/item/restraints/handcuffs/cable/green
item_color = "green"
color = "#00aa00"
/obj/item/restraints/handcuffs/cable/pink
item_color = "pink"
color = "#ff3ccd"
/obj/item/restraints/handcuffs/cable/orange
item_color = "orange"
color = "#ff8000"
/obj/item/restraints/handcuffs/cable/cyan
item_color = "cyan"
color = "#00ffff"
/obj/item/restraints/handcuffs/cable/white
item_color = "white"
color = null
/obj/item/restraints/handcuffs/cable/random
@@ -209,7 +202,7 @@
custom_materials = null
breakouttime = 450 //Deciseconds = 45s
trashtype = /obj/item/restraints/handcuffs/cable/zipties/used
item_color = "white"
color = null
/obj/item/restraints/handcuffs/cable/zipties/used
desc = "A pair of broken zipties."
+3 -3
View File
@@ -122,7 +122,7 @@
/obj/item/clothing/head/helmet/chaplain/cage
name = "cage"
desc = "A cage that restrains the will of the self, allowing one to see the profane world for what it is."
alternate_worn_icon = 'icons/mob/large-worn-icons/64x64/head.dmi'
mob_overlay_icon = 'icons/mob/large-worn-icons/64x64/head.dmi'
icon_state = "cage"
item_state = "cage"
worn_x_dimension = 64
@@ -303,8 +303,8 @@
block_chance = 50
var/shield_icon = "shield-red"
/obj/item/nullrod/staff/worn_overlays(isinhands, icon_file, style_flags = NONE)
. = list()
/obj/item/nullrod/staff/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(isinhands)
. += mutable_appearance('icons/effects/effects.dmi', shield_icon, MOB_LAYER + 0.01)
+1 -1
View File
@@ -5,7 +5,7 @@
actions_types = list(/datum/action/item_action/hands_free/activate)
var/activated = TRUE //1 for implant types that can be activated, 0 for ones that are "always on" like mindshield implants
var/mob/living/imp_in = null
item_color = "b"
var/implant_color = "b"
var/allow_multiple = FALSE
var/uses = -1
item_flags = DROPDEL
@@ -2,7 +2,7 @@
name = "freedom implant"
desc = "Use this to escape from those evil Red Shirts."
icon_state = "freedom"
item_color = "r"
implant_color = "r"
uses = 4
@@ -2,7 +2,7 @@
name = "storage implant"
desc = "Stores up to two big items in a bluespace pocket."
icon_state = "storage"
item_color = "r"
implant_color = "r"
var/max_slot_stacking = 4
var/obj/item/storage/bluespace_pocket/pocket
@@ -15,7 +15,7 @@
/obj/item/implantcase/update_icon_state()
if(imp)
icon_state = "implantcase-[imp.item_color]"
icon_state = "implantcase-[imp.implant_color]"
else
icon_state = "implantcase-0"
+1 -1
View File
@@ -172,7 +172,7 @@
It can cook multiple items at once.
<h2>Processor:</h2>
Use it to process certain ingredients (meat into faggot, doughslice into spaghetti, potato into fries,etc...)
Use it to process certain ingredients (meat into meatball, doughslice into spaghetti, potato into fries,etc...)
<h2>Gibber:</h2>
Stuff an animal in it to grind it into meat.
+27 -40
View File
@@ -5,12 +5,15 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
var/brightness_on = 3
var/sword_color
total_mass = 0.4 //Survival flashlights typically weigh around 5 ounces.
/obj/item/melee/transforming/energy/Initialize()
. = ..()
total_mass_on = (total_mass_on ? total_mass_on : (w_class_on * 0.75))
if(active)
if(sword_color)
icon_state = "sword[sword_color]"
set_light(brightness_on)
START_PROCESSING(SSobj, src)
@@ -37,8 +40,8 @@
. = ..()
if(.)
if(active)
if(item_color)
icon_state = "sword[item_color]"
if(sword_color)
icon_state = "sword[sword_color]"
START_PROCESSING(SSobj, src)
set_light(brightness_on)
else
@@ -103,12 +106,19 @@
embedding = list("embed_chance" = 75, "embedded_impact_pain_multiplier" = 10)
armour_penetration = 35
block_chance = 50
var/list/possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
/obj/item/melee/transforming/energy/sword/Initialize(mapload)
. = ..()
set_sword_color()
/obj/item/melee/transforming/energy/sword/proc/set_sword_color()
if(LAZYLEN(possible_colors))
light_color = possible_colors[pick(possible_colors)]
/obj/item/melee/transforming/energy/sword/transform_weapon(mob/living/user, supress_message_text)
. = ..()
if(active)
if(. && item_color)
icon_state = "sword[item_color]"
AddElement(/datum/element/sword_point)
else
RemoveElement(/datum/element/sword_point)
@@ -119,7 +129,9 @@
return ..()
/obj/item/melee/transforming/energy/sword/cyborg
item_color = "red"
sword_color = "red"
light_color = "#ff0000"
possible_colors = null
var/hitcost = 50
/obj/item/melee/transforming/energy/sword/cyborg/attack(mob/M, var/mob/living/silicon/robot/R)
@@ -140,7 +152,7 @@
icon = 'icons/obj/surgery.dmi'
icon_state = "esaw_0"
icon_state_on = "esaw_1"
item_color = null //stops icon from breaking when turned on.
sword_color = null //stops icon from breaking when turned on.
hitcost = 75 //Costs more than a standard cyborg esword
w_class = WEIGHT_CLASS_NORMAL
sharpness = IS_SHARP
@@ -152,15 +164,13 @@
return NONE
/obj/item/melee/transforming/energy/sword/saber
var/list/possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
var/hacked = FALSE
/obj/item/melee/transforming/energy/sword/saber/Initialize(mapload)
. = ..()
/obj/item/melee/transforming/energy/sword/saber/set_sword_color()
if(LAZYLEN(possible_colors))
var/set_color = pick(possible_colors)
item_color = set_color
light_color = possible_colors[set_color]
sword_color = pick(possible_colors)
light_color = possible_colors[sword_color]
/obj/item/melee/transforming/energy/sword/saber/process()
. = ..()
@@ -185,7 +195,7 @@
if(istype(W, /obj/item/multitool))
if(!hacked)
hacked = TRUE
item_color = "rainbow"
sword_color = "rainbow"
to_chat(user, "<span class='warning'>RNBW_ENGAGE</span>")
if(active)
@@ -204,6 +214,7 @@
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
icon_state_on = "cutlass1"
light_color = "#ff0000"
possible_colors = null
/obj/item/melee/transforming/energy/blade
name = "energy blade"
@@ -271,32 +282,8 @@
return TRUE
/obj/item/melee/transforming/energy/sword/cx/transform_weapon(mob/living/user, supress_message_text)
active = !active //I'd use a ..() here but it'd inherit from the regular esword's proc instead, so SPAGHETTI CODE
if(active) //also I'd need to rip out the iconstate changing bits
force = force_on
throwforce = throwforce_on
hitsound = hitsound_on
throw_speed = 4
if(attack_verb_on.len)
attack_verb = attack_verb_on
w_class = w_class_on
START_PROCESSING(SSobj, src)
set_light(brightness_on)
update_icon()
else
force = initial(force)
throwforce = initial(throwforce)
hitsound = initial(hitsound)
throw_speed = initial(throw_speed)
if(attack_verb_off.len)
attack_verb = attack_verb_off
w_class = initial(w_class)
STOP_PROCESSING(SSobj, src)
set_light(0)
update_icon()
transform_messages(user, supress_message_text)
add_fingerprint(user)
return TRUE
. = ..()
update_icon()
/obj/item/melee/transforming/energy/sword/cx/transform_messages(mob/living/user, supress_message_text)
playsound(user, active ? 'sound/weapons/nebon.ogg' : 'sound/weapons/neboff.ogg', 65, 1)
@@ -337,7 +324,7 @@
. = ..()
. += "<span class='notice'>Alt-click to recolor it.</span>"
/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file, style_flags = NONE)
/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(active)
if(isinhands)
+22 -22
View File
@@ -7,7 +7,7 @@
desc = "Used to recolor floors and walls. Can be removed by the janitor."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "paint_neutral"
item_color = "FFFFFF"
var/paint_color = "FFFFFF"
item_state = "paintcan"
w_class = WEIGHT_CLASS_NORMAL
resistance_flags = FLAMMABLE
@@ -16,37 +16,37 @@
/obj/item/paint/red
name = "red paint"
item_color = "C73232" //"FF0000"
paint_color = "C73232" //"FF0000"
icon_state = "paint_red"
/obj/item/paint/green
name = "green paint"
item_color = "2A9C3B" //"00FF00"
paint_color = "2A9C3B" //"00FF00"
icon_state = "paint_green"
/obj/item/paint/blue
name = "blue paint"
item_color = "5998FF" //"0000FF"
paint_color = "5998FF" //"0000FF"
icon_state = "paint_blue"
/obj/item/paint/yellow
name = "yellow paint"
item_color = "CFB52B" //"FFFF00"
paint_color = "CFB52B" //"FFFF00"
icon_state = "paint_yellow"
/obj/item/paint/violet
name = "violet paint"
item_color = "AE4CCD" //"FF00FF"
paint_color = "AE4CCD" //"FF00FF"
icon_state = "paint_violet"
/obj/item/paint/black
name = "black paint"
item_color = "333333"
paint_color = "333333"
icon_state = "paint_black"
/obj/item/paint/white
name = "white paint"
item_color = "FFFFFF"
paint_color = "FFFFFF"
icon_state = "paint_white"
@@ -61,31 +61,31 @@
return
switch(t1)
if("red")
item_color = "C73232"
paint_color = "C73232"
if("pink")
item_color = "FFC0CD"
paint_color = "FFC0CD"
if("blue")
item_color = "5998FF"
paint_color = "5998FF"
if("cyan")
item_color = "00FFFF"
paint_color = "00FFFF"
if("green")
item_color = "2A9C3B"
paint_color = "2A9C3B"
if("lime")
item_color = "00FF00"
paint_color = "00FF00"
if("yellow")
item_color = "CFB52B"
paint_color = "CFB52B"
if("orange")
item_color = "fFA700"
paint_color = "fFA700"
if("violet")
item_color = "AE4CCD"
paint_color = "AE4CCD"
if("purple")
item_color = "800080"
paint_color = "800080"
if("white")
item_color = "FFFFFF"
paint_color = "FFFFFF"
if("gray")
item_color = "808080"
paint_color = "808080"
if("black")
item_color = "333333"
paint_color = "333333"
icon_state = "paint_[t1]"
add_fingerprint(user)
@@ -99,7 +99,7 @@
return
if(!isturf(target) || isspaceturf(target))
return
var/newcolor = "#" + item_color
var/newcolor = "#" + paint_color
target.add_atom_colour(newcolor, WASHABLE_COLOUR_PRIORITY)
/obj/item/paint/paint_remover
+1 -1
View File
@@ -214,7 +214,7 @@
/obj/item/clothing/head/helmet/plate/crusader/prophet
name = "Prophet's Hat"
desc = "A religious-looking hat."
alternate_worn_icon = 'icons/mob/large-worn-icons/64x64/head.dmi'
mob_overlay_icon = 'icons/mob/large-worn-icons/64x64/head.dmi'
flags_1 = 0
armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 50, "bomb" = 70, "bio" = 50, "rad" = 50, "fire" = 60, "acid" = 60) //religion protects you from disease and radiation, honk.
worn_x_dimension = 64
@@ -663,21 +663,19 @@
var/maxReduction = 1
/obj/effect/proc_holder/silicon/cyborg/vtecControl/Click(mob/living/silicon/robot/user)
var/mob/living/silicon/robot/self = usr
/obj/effect/proc_holder/silicon/cyborg/vtecControl/Trigger(mob/living/silicon/robot/user)
currentState = (currentState + 1) % 3
if(istype(self))
if(istype(user))
switch(currentState)
if (0)
self.speed = initial(self.speed)
user.speed = initial(user.speed)
if (1)
self.speed = initial(self.speed) - maxReduction * 0.5
user.speed = initial(user.speed) - maxReduction * 0.5
if (2)
self.speed = initial(self.speed) - maxReduction * 1
user.speed = initial(user.speed) - maxReduction * 1
action.button_icon_state = "Chevron_State_[currentState]"
action.UpdateButtonIcon()
return
return TRUE
@@ -5,6 +5,7 @@
icon = 'icons/obj/telescience.dmi'
icon_state = "bluespace_crystal"
singular_name = "bluespace crystal"
dye_color = DYE_COSMIC
w_class = WEIGHT_CLASS_TINY
custom_materials = list(/datum/material/bluespace=MINERAL_MATERIAL_AMOUNT)
points = 50

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