Merge branch 'master' into race_drinks

This commit is contained in:
TrilbySpaceClone
2020-04-14 19:21:47 -04:00
394 changed files with 3710 additions and 2909 deletions
+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"]))
+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
+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
+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)