mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 07:08:00 +01:00
Add new surgery tgui (#64579)
* Move element to component, start UI, move assets into their own directory * Complete UI * Stop when another surgery is started * Set your real zone since I forgot you actually need to start the surgery too * Bring this back since I was just removing it as part of a cleanup for asset cache, but I can't prove it's not used anymore * Remove unnecessary constructor I was using for something else * Fix signal override
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
/// From /datum/surgery/New(): (datum/surgery/surgery, surgery_location (body zone), obj/item/bodypart/targeted_limb)
|
||||
#define COMSIG_MOB_SURGERY_STARTED "mob_surgery_started"
|
||||
|
||||
/// From /datum/surgery_step/success(): (datum/surgery_step/step, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
|
||||
#define COMSIG_MOB_SURGERY_STEP_SUCCESS "mob_surgery_step_success"
|
||||
|
||||
@@ -132,5 +132,6 @@
|
||||
#define COMSIG_MOB_CTRL_CLICKED "mob_ctrl_clicked"
|
||||
///From base of mob/update_movespeed():area
|
||||
#define COMSIG_MOB_MOVESPEED_UPDATED "mob_update_movespeed"
|
||||
/// From /datum/surgery_step/success(): (datum/surgey_step/step, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
|
||||
#define COMSIG_MOB_SURGERY_STEP_SUCCESS "mob_surgery_step_success"
|
||||
/// From /atom/movable/screen/zone_sel/proc/set_selected_zone.
|
||||
/// Fires when the user has changed their selected body target.
|
||||
#define COMSIG_MOB_SELECTED_ZONE_SET "mob_set_selected_zone"
|
||||
|
||||
@@ -1035,3 +1035,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
. = "gigantic"
|
||||
else
|
||||
. = ""
|
||||
|
||||
/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
|
||||
/proc/sanitize_css_class_name(name)
|
||||
var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
|
||||
return replacetext(name, regex, "")
|
||||
|
||||
@@ -573,6 +573,7 @@
|
||||
if(choice != hud.mymob.zone_selected)
|
||||
hud.mymob.zone_selected = choice
|
||||
update_appearance()
|
||||
SEND_SIGNAL(user, COMSIG_MOB_SELECTED_ZONE_SET, choice)
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
/// Allows an item to be used to initiate surgeries.
|
||||
/datum/component/surgery_initiator
|
||||
/// The currently selected target that the user is proposing a surgery on
|
||||
var/datum/weakref/surgery_target_ref
|
||||
|
||||
/// The last user, as a weakref
|
||||
var/datum/weakref/last_user_ref
|
||||
|
||||
/datum/component/surgery_initiator/Initialize()
|
||||
. = ..()
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
/datum/component/surgery_initiator/Destroy(force, silent)
|
||||
last_user_ref = null
|
||||
surgery_target_ref = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/component/surgery_initiator/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/initiate_surgery_moment)
|
||||
|
||||
/datum/component/surgery_initiator/UnregisterFromParent()
|
||||
UnregisterSignal(parent, COMSIG_ITEM_ATTACK)
|
||||
unregister_signals()
|
||||
|
||||
/datum/component/surgery_initiator/proc/unregister_signals()
|
||||
var/mob/living/last_user = last_user_ref?.resolve()
|
||||
if (!isnull(last_user_ref))
|
||||
UnregisterSignal(last_user, COMSIG_MOB_SELECTED_ZONE_SET)
|
||||
|
||||
var/mob/living/surgery_target = surgery_target_ref?.resolve()
|
||||
if (!isnull(surgery_target_ref))
|
||||
UnregisterSignal(surgery_target, COMSIG_MOB_SURGERY_STARTED)
|
||||
|
||||
/// Does the surgery initiation.
|
||||
/datum/component/surgery_initiator/proc/initiate_surgery_moment(datum/source, atom/target, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
if(!isliving(target))
|
||||
return
|
||||
INVOKE_ASYNC(src, .proc/do_initiate_surgery_moment, target, user)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/datum/component/surgery_initiator/proc/do_initiate_surgery_moment(mob/living/target, mob/user)
|
||||
var/datum/surgery/current_surgery
|
||||
|
||||
for(var/i_one in target.surgeries)
|
||||
var/datum/surgery/surgeryloop = i_one
|
||||
if(surgeryloop.location == user.zone_selected)
|
||||
current_surgery = surgeryloop
|
||||
break
|
||||
|
||||
if (!isnull(current_surgery) && !current_surgery.step_in_progress)
|
||||
attempt_cancel_surgery(current_surgery, target, user)
|
||||
return
|
||||
|
||||
var/list/available_surgeries = get_available_surgeries(user, target)
|
||||
|
||||
if(!length(available_surgeries))
|
||||
if (target.body_position == LYING_DOWN)
|
||||
target.balloon_alert(user, "no surgeries available!")
|
||||
else
|
||||
target.balloon_alert(user, "make them lie down!")
|
||||
|
||||
return
|
||||
|
||||
unregister_signals()
|
||||
|
||||
last_user_ref = WEAKREF(user)
|
||||
surgery_target_ref = WEAKREF(target)
|
||||
|
||||
RegisterSignal(user, COMSIG_MOB_SELECTED_ZONE_SET, .proc/on_set_selected_zone)
|
||||
RegisterSignal(target, COMSIG_MOB_SURGERY_STARTED, .proc/on_mob_surgery_started)
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/datum/component/surgery_initiator/proc/get_available_surgeries(mob/user, mob/living/target)
|
||||
var/list/available_surgeries = list()
|
||||
|
||||
var/mob/living/carbon/carbon_target
|
||||
var/obj/item/bodypart/affecting
|
||||
if (iscarbon(target))
|
||||
carbon_target = target
|
||||
affecting = carbon_target.get_bodypart(check_zone(user.zone_selected))
|
||||
|
||||
for(var/datum/surgery/surgery as anything in GLOB.surgeries_list)
|
||||
if(!surgery.possible_locs.Find(user.zone_selected))
|
||||
continue
|
||||
if(affecting)
|
||||
if(!surgery.requires_bodypart)
|
||||
continue
|
||||
if(surgery.requires_bodypart_type && affecting.status != surgery.requires_bodypart_type)
|
||||
continue
|
||||
if(surgery.requires_real_bodypart && affecting.is_pseudopart)
|
||||
continue
|
||||
else if(carbon_target && surgery.requires_bodypart) //mob with no limb in surgery zone when we need a limb
|
||||
continue
|
||||
if(surgery.lying_required && target.body_position != LYING_DOWN)
|
||||
continue
|
||||
if(!surgery.can_start(user, target))
|
||||
continue
|
||||
for(var/path in surgery.target_mobtypes)
|
||||
if(istype(target, path))
|
||||
available_surgeries += surgery
|
||||
break
|
||||
|
||||
return available_surgeries
|
||||
|
||||
/// Does the surgery de-initiation.
|
||||
/datum/component/surgery_initiator/proc/attempt_cancel_surgery(datum/surgery/the_surgery, mob/living/patient, mob/user)
|
||||
var/selected_zone = user.zone_selected
|
||||
|
||||
if(the_surgery.status == 1)
|
||||
patient.surgeries -= the_surgery
|
||||
REMOVE_TRAIT(patient, TRAIT_ALLOWED_HONORBOUND_ATTACK, type)
|
||||
user.visible_message(
|
||||
span_notice("[user] removes [parent] from [patient]'s [parse_zone(selected_zone)]."),
|
||||
span_notice("You remove [parent] from [patient]'s [parse_zone(selected_zone)]."),
|
||||
)
|
||||
|
||||
patient.balloon_alert(user, "stopped work on [parse_zone(selected_zone)]")
|
||||
|
||||
qdel(the_surgery)
|
||||
return
|
||||
|
||||
if(!the_surgery.can_cancel)
|
||||
return
|
||||
|
||||
var/required_tool_type = TOOL_CAUTERY
|
||||
var/obj/item/close_tool = user.get_inactive_held_item()
|
||||
var/is_robotic = the_surgery.requires_bodypart_type == BODYPART_ROBOTIC
|
||||
|
||||
if(is_robotic)
|
||||
required_tool_type = TOOL_SCREWDRIVER
|
||||
|
||||
if(iscyborg(user))
|
||||
close_tool = locate(/obj/item/cautery) in user.held_items
|
||||
if(!close_tool)
|
||||
patient.balloon_alert(user, "need a cautery in an inactive slot to stop the surgery!")
|
||||
return
|
||||
else if(!close_tool || close_tool.tool_behaviour != required_tool_type)
|
||||
patient.balloon_alert(user, "need a [is_robotic ? "screwdriver": "cautery"] in your inactive hand to stop the surgery!")
|
||||
return
|
||||
|
||||
if(the_surgery.operated_bodypart)
|
||||
the_surgery.operated_bodypart.generic_bleedstacks -= 5
|
||||
|
||||
patient.surgeries -= the_surgery
|
||||
REMOVE_TRAIT(patient, TRAIT_ALLOWED_HONORBOUND_ATTACK, ELEMENT_TRAIT(type))
|
||||
|
||||
user.visible_message(
|
||||
span_notice("[user] closes [patient]'s [parse_zone(selected_zone)] with [close_tool] and removes [parent]."),
|
||||
span_notice("You close [patient]'s [parse_zone(selected_zone)] with [close_tool] and remove [parent]."),
|
||||
)
|
||||
|
||||
patient.balloon_alert(user, "closed up [parse_zone(selected_zone)]")
|
||||
|
||||
qdel(the_surgery)
|
||||
|
||||
/datum/component/surgery_initiator/proc/on_mob_surgery_started(mob/source, datum/surgery/surgery, surgery_location)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/living/last_user = last_user_ref.resolve()
|
||||
|
||||
if (surgery_location != last_user.zone_selected)
|
||||
return
|
||||
|
||||
if (!isnull(last_user))
|
||||
source.balloon_alert(last_user, "someone else started a surgery!")
|
||||
|
||||
ui_close()
|
||||
|
||||
/datum/component/surgery_initiator/proc/on_set_selected_zone(mob/source, new_zone)
|
||||
ui_interact(source)
|
||||
|
||||
/datum/component/surgery_initiator/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if (!ui)
|
||||
ui = new(user, src, "SurgeryInitiator")
|
||||
ui.open()
|
||||
|
||||
/datum/component/surgery_initiator/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if (.)
|
||||
return .
|
||||
|
||||
var/mob/user = usr
|
||||
var/mob/living/surgery_target = surgery_target_ref.resolve()
|
||||
|
||||
if (isnull(surgery_target))
|
||||
return TRUE
|
||||
|
||||
switch (action)
|
||||
if ("change_zone")
|
||||
var/zone = params["new_zone"]
|
||||
if (!(zone in list(
|
||||
BODY_ZONE_HEAD,
|
||||
BODY_ZONE_CHEST,
|
||||
BODY_ZONE_L_ARM,
|
||||
BODY_ZONE_R_ARM,
|
||||
BODY_ZONE_L_LEG,
|
||||
BODY_ZONE_R_LEG,
|
||||
BODY_ZONE_PRECISE_EYES,
|
||||
BODY_ZONE_PRECISE_MOUTH,
|
||||
BODY_ZONE_PRECISE_GROIN,
|
||||
)))
|
||||
return TRUE
|
||||
|
||||
var/atom/movable/screen/zone_sel/zone_selector = user.hud_used?.zone_select
|
||||
zone_selector?.set_selected_zone(zone, user)
|
||||
|
||||
return TRUE
|
||||
if ("start_surgery")
|
||||
for (var/datum/surgery/surgery as anything in get_available_surgeries(user, surgery_target))
|
||||
if (surgery.name == params["surgery_name"])
|
||||
try_choose_surgery(user, surgery_target, surgery)
|
||||
return TRUE
|
||||
|
||||
/datum/component/surgery_initiator/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/simple/body_zones),
|
||||
)
|
||||
|
||||
/datum/component/surgery_initiator/ui_data(mob/user)
|
||||
var/mob/living/surgery_target = surgery_target_ref.resolve()
|
||||
|
||||
var/list/surgeries = list()
|
||||
if (!isnull(surgery_target))
|
||||
for (var/datum/surgery/surgery as anything in get_available_surgeries(user, surgery_target))
|
||||
var/list/surgery_info = list(
|
||||
"name" = surgery.name,
|
||||
)
|
||||
|
||||
if (surgery_needs_exposure(surgery, surgery_target))
|
||||
surgery_info["blocked"] = TRUE
|
||||
|
||||
surgeries += list(surgery_info)
|
||||
|
||||
return list(
|
||||
"selected_zone" = user.zone_selected,
|
||||
"target_name" = surgery_target?.name,
|
||||
"surgeries" = surgeries,
|
||||
)
|
||||
|
||||
/datum/component/surgery_initiator/ui_close(mob/user)
|
||||
unregister_signals()
|
||||
surgery_target_ref = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/component/surgery_initiator/ui_status(mob/user, datum/ui_state/state)
|
||||
var/obj/item/item_parent = parent
|
||||
if (user != item_parent.loc)
|
||||
return UI_CLOSE
|
||||
|
||||
var/mob/living/surgery_target = surgery_target_ref?.resolve()
|
||||
if (isnull(surgery_target))
|
||||
return UI_CLOSE
|
||||
|
||||
if (!can_start_surgery(user, surgery_target))
|
||||
return UI_CLOSE
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/component/surgery_initiator/proc/can_start_surgery(mob/user, mob/living/target)
|
||||
if (!user.Adjacent(target))
|
||||
return FALSE
|
||||
|
||||
// The item was moved somewhere else
|
||||
if (!(parent in user))
|
||||
return FALSE
|
||||
|
||||
// While we were choosing, another surgery was started at the same location
|
||||
for (var/datum/surgery/surgery in target.surgeries)
|
||||
if (surgery.location == user.zone_selected)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/component/surgery_initiator/proc/try_choose_surgery(mob/user, mob/living/target, datum/surgery/surgery)
|
||||
if (!can_start_surgery(user, target))
|
||||
// This could have a more detailed message, but the UI closes when this is true anyway, so
|
||||
// if it ever comes up, it'll be because of lag.
|
||||
target.balloon_alert(user, "can't start the surgery!")
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/affecting_limb
|
||||
|
||||
var/selected_zone = user.zone_selected
|
||||
|
||||
if (iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
affecting_limb = carbon_target.get_bodypart(check_zone(selected_zone))
|
||||
|
||||
if (surgery.requires_bodypart == isnull(affecting_limb))
|
||||
if (surgery.requires_bodypart)
|
||||
target.balloon_alert(user, "patient has no [parse_zone(selected_zone)]!")
|
||||
else
|
||||
target.balloon_alert(user, "patient has \a [parse_zone(selected_zone)]!")
|
||||
|
||||
return
|
||||
|
||||
if (!isnull(affecting_limb) && surgery.requires_bodypart_type && affecting_limb.status != surgery.requires_bodypart_type)
|
||||
target.balloon_alert(user, "not the right type of limb!")
|
||||
return
|
||||
|
||||
if (surgery.lying_required && target.body_position != LYING_DOWN)
|
||||
target.balloon_alert(user, "patient is not lying down!")
|
||||
return
|
||||
|
||||
if (!surgery.can_start(user, target))
|
||||
target.balloon_alert(user, "can't start the surgery!")
|
||||
return
|
||||
|
||||
if (surgery_needs_exposure(surgery, target))
|
||||
target.balloon_alert(user, "expose [target.p_their()] [parse_zone(selected_zone)]!")
|
||||
return
|
||||
|
||||
ui_close()
|
||||
|
||||
var/datum/surgery/procedure = new surgery.type(target, selected_zone, affecting_limb)
|
||||
ADD_TRAIT(target, TRAIT_ALLOWED_HONORBOUND_ATTACK, type)
|
||||
|
||||
target.balloon_alert(user, "starting \"[lowertext(procedure.name)]\"")
|
||||
|
||||
user.visible_message(
|
||||
span_notice("[user] drapes [parent] over [target]'s [parse_zone(selected_zone)] to prepare for surgery."),
|
||||
span_notice("You drape [parent] over [target]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name]."),
|
||||
)
|
||||
|
||||
log_combat(user, target, "operated on", null, "(OPERATION TYPE: [procedure.name]) (TARGET AREA: [selected_zone])")
|
||||
|
||||
/datum/component/surgery_initiator/proc/surgery_needs_exposure(datum/surgery/surgery, mob/living/target)
|
||||
var/mob/living/user = last_user_ref?.resolve()
|
||||
if (isnull(user))
|
||||
return FALSE
|
||||
|
||||
return !surgery.ignore_clothes && !get_location_accessible(target, user.zone_selected)
|
||||
@@ -1,145 +0,0 @@
|
||||
/// Allows an item to be used to initiate surgeries.
|
||||
/datum/element/surgery_initiator
|
||||
element_flags = ELEMENT_DETACH
|
||||
|
||||
/datum/element/surgery_initiator/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!isitem(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/initiate_surgery_moment)
|
||||
|
||||
/datum/element/surgery_initiator/Detach(datum/source)
|
||||
UnregisterSignal(source, COMSIG_ITEM_ATTACK)
|
||||
return ..()
|
||||
|
||||
/// Does the surgery initiation.
|
||||
/datum/element/surgery_initiator/proc/initiate_surgery_moment(datum/source, atom/target, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
if(!isliving(target))
|
||||
return
|
||||
INVOKE_ASYNC(src, .proc/do_initiate_surgery_moment, source, target, user)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/datum/element/surgery_initiator/proc/do_initiate_surgery_moment(datum/source, atom/target, mob/user)
|
||||
var/mob/living/livingtarget = target
|
||||
var/mob/living/carbon/carbontarget
|
||||
var/obj/item/bodypart/affecting
|
||||
var/selected_zone = user.zone_selected
|
||||
if(iscarbon(livingtarget))
|
||||
carbontarget = livingtarget
|
||||
affecting = carbontarget.get_bodypart(check_zone(selected_zone))
|
||||
|
||||
var/datum/surgery/current_surgery
|
||||
|
||||
for(var/i_one in livingtarget.surgeries)
|
||||
var/datum/surgery/surgeryloop = i_one
|
||||
if(surgeryloop.location == selected_zone)
|
||||
current_surgery = surgeryloop
|
||||
|
||||
if(!current_surgery)
|
||||
var/list/all_surgeries = GLOB.surgeries_list.Copy()
|
||||
var/list/available_surgeries = list()
|
||||
|
||||
for(var/i_two in all_surgeries)
|
||||
var/datum/surgery/surgeryloop_two = i_two
|
||||
if(!surgeryloop_two.possible_locs.Find(selected_zone))
|
||||
continue
|
||||
if(affecting)
|
||||
if(!surgeryloop_two.requires_bodypart)
|
||||
continue
|
||||
if(surgeryloop_two.requires_bodypart_type && affecting.status != surgeryloop_two.requires_bodypart_type)
|
||||
continue
|
||||
if(surgeryloop_two.requires_real_bodypart && affecting.is_pseudopart)
|
||||
continue
|
||||
else if(carbontarget && surgeryloop_two.requires_bodypart) //mob with no limb in surgery zone when we need a limb
|
||||
continue
|
||||
if(surgeryloop_two.lying_required && livingtarget.body_position != LYING_DOWN)
|
||||
continue
|
||||
if(!surgeryloop_two.can_start(user, livingtarget))
|
||||
continue
|
||||
for(var/path in surgeryloop_two.target_mobtypes)
|
||||
if(istype(livingtarget, path))
|
||||
available_surgeries[surgeryloop_two.name] = surgeryloop_two
|
||||
break
|
||||
|
||||
if(!length(available_surgeries))
|
||||
return
|
||||
|
||||
var/pick_your_surgery = tgui_input_list(user, "Which procedure?", "Surgery", sort_list(available_surgeries))
|
||||
if(isnull(pick_your_surgery))
|
||||
return
|
||||
if(user?.Adjacent(livingtarget) && (source in user))
|
||||
var/datum/surgery/surgeryinstance_notonmob = available_surgeries[pick_your_surgery]
|
||||
|
||||
for(var/i_three in livingtarget.surgeries)
|
||||
var/datum/surgery/surgeryloop_three = i_three
|
||||
if(surgeryloop_three.location == selected_zone)
|
||||
return //during the input() another surgery was started at the same location.
|
||||
|
||||
//we check that the surgery is still doable after the input() wait.
|
||||
if(carbontarget)
|
||||
affecting = carbontarget.get_bodypart(check_zone(selected_zone))
|
||||
if(affecting)
|
||||
if(!surgeryinstance_notonmob.requires_bodypart)
|
||||
return
|
||||
if(surgeryinstance_notonmob.requires_bodypart_type && affecting.status != surgeryinstance_notonmob.requires_bodypart_type)
|
||||
return
|
||||
else if(carbontarget && surgeryinstance_notonmob.requires_bodypart)
|
||||
return
|
||||
if(surgeryinstance_notonmob.lying_required && livingtarget.body_position != LYING_DOWN)
|
||||
return
|
||||
if(!surgeryinstance_notonmob.can_start(user, livingtarget))
|
||||
return
|
||||
|
||||
if(surgeryinstance_notonmob.ignore_clothes || get_location_accessible(livingtarget, selected_zone))
|
||||
var/datum/surgery/procedure = new surgeryinstance_notonmob.type(livingtarget, selected_zone, affecting)
|
||||
ADD_TRAIT(livingtarget, TRAIT_ALLOWED_HONORBOUND_ATTACK, ELEMENT_TRAIT(type))
|
||||
user.visible_message(span_notice("[user] drapes [source] over [livingtarget]'s [parse_zone(selected_zone)] to prepare for surgery."), \
|
||||
span_notice("You drape [source] over [livingtarget]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name]."))
|
||||
|
||||
log_combat(user, livingtarget, "operated on", null, "(OPERATION TYPE: [procedure.name]) (TARGET AREA: [selected_zone])")
|
||||
else
|
||||
to_chat(user, span_warning("You need to expose [livingtarget]'s [parse_zone(selected_zone)] first!"))
|
||||
|
||||
else if(!current_surgery.step_in_progress)
|
||||
attempt_cancel_surgery(current_surgery, source, livingtarget, user)
|
||||
|
||||
/// Does the surgery de-initiation.
|
||||
/datum/element/surgery_initiator/proc/attempt_cancel_surgery(datum/surgery/the_surgery, obj/item/the_item, mob/living/the_patient, mob/user)
|
||||
var/selected_zone = user.zone_selected
|
||||
|
||||
if(the_surgery.status == 1)
|
||||
the_patient.surgeries -= the_surgery
|
||||
REMOVE_TRAIT(the_patient, TRAIT_ALLOWED_HONORBOUND_ATTACK, ELEMENT_TRAIT(type))
|
||||
user.visible_message(span_notice("[user] removes [the_item] from [the_patient]'s [parse_zone(selected_zone)]."), \
|
||||
span_notice("You remove [the_item] from [the_patient]'s [parse_zone(selected_zone)]."))
|
||||
qdel(the_surgery)
|
||||
return
|
||||
|
||||
if(!the_surgery.can_cancel)
|
||||
return
|
||||
|
||||
var/required_tool_type = TOOL_CAUTERY
|
||||
var/obj/item/close_tool = user.get_inactive_held_item()
|
||||
var/is_robotic = the_surgery.requires_bodypart_type == BODYPART_ROBOTIC
|
||||
|
||||
if(is_robotic)
|
||||
required_tool_type = TOOL_SCREWDRIVER
|
||||
|
||||
if(iscyborg(user))
|
||||
close_tool = locate(/obj/item/cautery) in user.held_items
|
||||
if(!close_tool)
|
||||
to_chat(user, span_warning("You need to equip a cautery in an inactive slot to stop [the_patient]'s surgery!"))
|
||||
return
|
||||
else if(!close_tool || close_tool.tool_behaviour != required_tool_type)
|
||||
to_chat(user, span_warning("You need to hold a [is_robotic ? "screwdriver" : "cautery"] in your inactive hand to stop [the_patient]'s surgery!"))
|
||||
return
|
||||
|
||||
if(the_surgery.operated_bodypart)
|
||||
the_surgery.operated_bodypart.generic_bleedstacks -= 5
|
||||
|
||||
the_patient.surgeries -= the_surgery
|
||||
REMOVE_TRAIT(the_patient, TRAIT_ALLOWED_HONORBOUND_ATTACK, ELEMENT_TRAIT(type))
|
||||
user.visible_message(span_notice("[user] closes [the_patient]'s [parse_zone(selected_zone)] with [close_tool] and removes [the_item]."), \
|
||||
span_notice("You close [the_patient]'s [parse_zone(selected_zone)] with [close_tool] and remove [the_item]."))
|
||||
qdel(the_surgery)
|
||||
@@ -33,7 +33,7 @@ LINEN BINS
|
||||
|
||||
/obj/item/bedsheet/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/surgery_initiator)
|
||||
AddComponent(/datum/component/surgery_initiator)
|
||||
AddElement(/datum/element/bed_tuckable, 0, 0, 0)
|
||||
if(bedsheet_type == BEDSHEET_DOUBLE)
|
||||
stack_amount *= 2
|
||||
|
||||
@@ -79,7 +79,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
for (var/asset_name in assets)
|
||||
.[asset_name] = SSassets.transport.get_asset_url(asset_name, assets[asset_name])
|
||||
|
||||
|
||||
// For registering or sending multiple others at once
|
||||
/datum/asset/group
|
||||
_abstract = /datum/asset/group
|
||||
|
||||
@@ -1,590 +0,0 @@
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
|
||||
/datum/asset/simple/tgui
|
||||
keep_local_name = TRUE
|
||||
assets = list(
|
||||
"tgui.bundle.js" = file("tgui/public/tgui.bundle.js"),
|
||||
"tgui.bundle.css" = file("tgui/public/tgui.bundle.css"),
|
||||
)
|
||||
|
||||
/datum/asset/simple/tgui_panel
|
||||
keep_local_name = TRUE
|
||||
assets = list(
|
||||
"tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"),
|
||||
"tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"),
|
||||
)
|
||||
|
||||
/datum/asset/simple/headers
|
||||
assets = list(
|
||||
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
|
||||
"alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
|
||||
"batt_5.gif" = 'icons/program_icons/batt_5.gif',
|
||||
"batt_20.gif" = 'icons/program_icons/batt_20.gif',
|
||||
"batt_40.gif" = 'icons/program_icons/batt_40.gif',
|
||||
"batt_60.gif" = 'icons/program_icons/batt_60.gif',
|
||||
"batt_80.gif" = 'icons/program_icons/batt_80.gif',
|
||||
"batt_100.gif" = 'icons/program_icons/batt_100.gif',
|
||||
"charging.gif" = 'icons/program_icons/charging.gif',
|
||||
"downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
|
||||
"downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
|
||||
"ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
|
||||
"ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
|
||||
"power_norm.gif" = 'icons/program_icons/power_norm.gif',
|
||||
"power_warn.gif" = 'icons/program_icons/power_warn.gif',
|
||||
"sig_high.gif" = 'icons/program_icons/sig_high.gif',
|
||||
"sig_low.gif" = 'icons/program_icons/sig_low.gif',
|
||||
"sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
|
||||
"sig_none.gif" = 'icons/program_icons/sig_none.gif',
|
||||
"smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
|
||||
"smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
|
||||
"smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
|
||||
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
|
||||
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
|
||||
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
|
||||
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif',
|
||||
"robotact.gif" = 'icons/program_icons/robotact.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/radar_assets
|
||||
assets = list(
|
||||
"ntosradarbackground.png" = 'icons/ui_icons/tgui/ntosradar_background.png',
|
||||
"ntosradarpointer.png" = 'icons/ui_icons/tgui/ntosradar_pointer.png',
|
||||
"ntosradarpointerS.png" = 'icons/ui_icons/tgui/ntosradar_pointer_S.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/circuit_assets
|
||||
assets = list(
|
||||
"grid_background.png" = 'icons/ui_icons/tgui/grid_background.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/pda
|
||||
name = "pda"
|
||||
assets = list(
|
||||
"atmos" = 'icons/pda_icons/pda_atmos.png',
|
||||
"back" = 'icons/pda_icons/pda_back.png',
|
||||
"bell" = 'icons/pda_icons/pda_bell.png',
|
||||
"blank" = 'icons/pda_icons/pda_blank.png',
|
||||
"boom" = 'icons/pda_icons/pda_boom.png',
|
||||
"bucket" = 'icons/pda_icons/pda_bucket.png',
|
||||
"medbot" = 'icons/pda_icons/pda_medbot.png',
|
||||
"floorbot" = 'icons/pda_icons/pda_floorbot.png',
|
||||
"cleanbot" = 'icons/pda_icons/pda_cleanbot.png',
|
||||
"crate" = 'icons/pda_icons/pda_crate.png',
|
||||
"cuffs" = 'icons/pda_icons/pda_cuffs.png',
|
||||
"eject" = 'icons/pda_icons/pda_eject.png',
|
||||
"flashlight" = 'icons/pda_icons/pda_flashlight.png',
|
||||
"honk" = 'icons/pda_icons/pda_honk.png',
|
||||
"mail" = 'icons/pda_icons/pda_mail.png',
|
||||
"medical" = 'icons/pda_icons/pda_medical.png',
|
||||
"menu" = 'icons/pda_icons/pda_menu.png',
|
||||
"mule" = 'icons/pda_icons/pda_mule.png',
|
||||
"notes" = 'icons/pda_icons/pda_notes.png',
|
||||
"power" = 'icons/pda_icons/pda_power.png',
|
||||
"rdoor" = 'icons/pda_icons/pda_rdoor.png',
|
||||
"reagent" = 'icons/pda_icons/pda_reagent.png',
|
||||
"refresh" = 'icons/pda_icons/pda_refresh.png',
|
||||
"scanner" = 'icons/pda_icons/pda_scanner.png',
|
||||
"signaler" = 'icons/pda_icons/pda_signaler.png',
|
||||
"skills" = 'icons/pda_icons/pda_skills.png',
|
||||
"status" = 'icons/pda_icons/pda_status.png',
|
||||
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
|
||||
"emoji" = 'icons/pda_icons/pda_emoji.png',
|
||||
"droneblacklist" = 'icons/pda_icons/pda_droneblacklist.png',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/paper
|
||||
name = "paper"
|
||||
assets = list(
|
||||
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
|
||||
"stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png',
|
||||
"stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png',
|
||||
"stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png',
|
||||
"stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png',
|
||||
"stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png',
|
||||
"stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png',
|
||||
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
|
||||
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
|
||||
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
|
||||
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png',
|
||||
"stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png',
|
||||
"stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
|
||||
"stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
|
||||
"stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/irv
|
||||
assets = list(
|
||||
"jquery-ui.custom-core-widgit-mouse-sortable.min.js" = 'html/jquery/jquery-ui.custom-core-widgit-mouse-sortable.min.js',
|
||||
)
|
||||
|
||||
/datum/asset/group/irv
|
||||
children = list(
|
||||
/datum/asset/simple/jquery,
|
||||
/datum/asset/simple/irv
|
||||
)
|
||||
|
||||
/datum/asset/simple/jquery
|
||||
legacy = TRUE
|
||||
assets = list(
|
||||
"jquery.min.js" = 'html/jquery/jquery.min.js',
|
||||
)
|
||||
|
||||
/datum/asset/simple/namespaced/fontawesome
|
||||
assets = list(
|
||||
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
|
||||
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
|
||||
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
|
||||
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css',
|
||||
)
|
||||
parents = list("font-awesome.css" = 'html/font-awesome/css/all.min.css')
|
||||
|
||||
/datum/asset/simple/namespaced/tgfont
|
||||
assets = list(
|
||||
"tgfont.eot" = file("tgui/packages/tgfont/static/tgfont.eot"),
|
||||
"tgfont.woff2" = file("tgui/packages/tgfont/static/tgfont.woff2"),
|
||||
)
|
||||
parents = list(
|
||||
"tgfont.css" = file("tgui/packages/tgfont/static/tgfont.css"),
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/chat
|
||||
name = "chat"
|
||||
|
||||
/datum/asset/spritesheet/chat/create_spritesheets()
|
||||
InsertAll("emoji", EMOJI_SET)
|
||||
// pre-loading all lanugage icons also helps to avoid meta
|
||||
InsertAll("language", 'icons/misc/language.dmi')
|
||||
// catch languages which are pulling icons from another file
|
||||
for(var/path in typesof(/datum/language))
|
||||
var/datum/language/L = path
|
||||
var/icon = initial(L.icon)
|
||||
if (icon != 'icons/misc/language.dmi')
|
||||
var/icon_state = initial(L.icon_state)
|
||||
Insert("language-[icon_state]", icon, icon_state=icon_state)
|
||||
|
||||
/datum/asset/simple/lobby
|
||||
assets = list(
|
||||
"playeroptions.css" = 'html/browser/playeroptions.css'
|
||||
)
|
||||
|
||||
/datum/asset/simple/namespaced/common
|
||||
assets = list("padlock.png" = 'icons/ui_icons/common/padlock.png')
|
||||
parents = list("common.css" = 'html/browser/common.css')
|
||||
|
||||
/datum/asset/simple/permissions
|
||||
assets = list(
|
||||
"search.js" = 'html/admin/search.js',
|
||||
"panels.css" = 'html/admin/panels.css'
|
||||
)
|
||||
|
||||
/datum/asset/group/permissions
|
||||
children = list(
|
||||
/datum/asset/simple/permissions,
|
||||
/datum/asset/simple/namespaced/common
|
||||
)
|
||||
|
||||
/datum/asset/simple/notes
|
||||
assets = list(
|
||||
"high_button.png" = 'icons/ui_icons/notes/high_button.png',
|
||||
"medium_button.png" = 'icons/ui_icons/notes/medium_button.png',
|
||||
"minor_button.png" = 'icons/ui_icons/notes/minor_button.png',
|
||||
"none_button.png" = 'icons/ui_icons/notes/none_button.png',
|
||||
)
|
||||
|
||||
/datum/asset/simple/arcade
|
||||
assets = list(
|
||||
"boss1.gif" = 'icons/ui_icons/arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/ui_icons/arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/ui_icons/arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/ui_icons/arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/ui_icons/arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/ui_icons/arcade/boss6.gif',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/achievements
|
||||
name ="achievements"
|
||||
|
||||
/datum/asset/spritesheet/simple/achievements/create_spritesheets()
|
||||
InsertAll("", ACHIEVEMENTS_SET)
|
||||
|
||||
/datum/asset/spritesheet/simple/pills
|
||||
name = "pills"
|
||||
assets = list(
|
||||
"pill1" = 'icons/ui_icons/pills/pill1.png',
|
||||
"pill2" = 'icons/ui_icons/pills/pill2.png',
|
||||
"pill3" = 'icons/ui_icons/pills/pill3.png',
|
||||
"pill4" = 'icons/ui_icons/pills/pill4.png',
|
||||
"pill5" = 'icons/ui_icons/pills/pill5.png',
|
||||
"pill6" = 'icons/ui_icons/pills/pill6.png',
|
||||
"pill7" = 'icons/ui_icons/pills/pill7.png',
|
||||
"pill8" = 'icons/ui_icons/pills/pill8.png',
|
||||
"pill9" = 'icons/ui_icons/pills/pill9.png',
|
||||
"pill10" = 'icons/ui_icons/pills/pill10.png',
|
||||
"pill11" = 'icons/ui_icons/pills/pill11.png',
|
||||
"pill12" = 'icons/ui_icons/pills/pill12.png',
|
||||
"pill13" = 'icons/ui_icons/pills/pill13.png',
|
||||
"pill14" = 'icons/ui_icons/pills/pill14.png',
|
||||
"pill15" = 'icons/ui_icons/pills/pill15.png',
|
||||
"pill16" = 'icons/ui_icons/pills/pill16.png',
|
||||
"pill17" = 'icons/ui_icons/pills/pill17.png',
|
||||
"pill18" = 'icons/ui_icons/pills/pill18.png',
|
||||
"pill19" = 'icons/ui_icons/pills/pill19.png',
|
||||
"pill20" = 'icons/ui_icons/pills/pill20.png',
|
||||
"pill21" = 'icons/ui_icons/pills/pill21.png',
|
||||
"pill22" = 'icons/ui_icons/pills/pill22.png',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/patches
|
||||
name = "patches"
|
||||
assets = list(
|
||||
"bandaid" = 'icons/ui_icons/patches/bandaid.png',
|
||||
"bandaid_brute" = 'icons/ui_icons/patches/bandaid_brute.png',
|
||||
"bandaid_burn" = 'icons/ui_icons/patches/bandaid_burn.png',
|
||||
"bandaid_both" = 'icons/ui_icons/patches/bandaid_both.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/condiments
|
||||
name = "condiments"
|
||||
assets = list(
|
||||
CONDIMASTER_STYLE_FALLBACK = 'icons/ui_icons/condiments/emptycondiment.png',
|
||||
"enzyme" = 'icons/ui_icons/condiments/enzyme.png',
|
||||
"flour" = 'icons/ui_icons/condiments/flour.png',
|
||||
"mayonnaise" = 'icons/ui_icons/condiments/mayonnaise.png',
|
||||
"milk" = 'icons/ui_icons/condiments/milk.png',
|
||||
"blackpepper" = 'icons/ui_icons/condiments/peppermillsmall.png',
|
||||
"rice" = 'icons/ui_icons/condiments/rice.png',
|
||||
"sodiumchloride" = 'icons/ui_icons/condiments/saltshakersmall.png',
|
||||
"soymilk" = 'icons/ui_icons/condiments/soymilk.png',
|
||||
"soysauce" = 'icons/ui_icons/condiments/soysauce.png',
|
||||
"sugar" = 'icons/ui_icons/condiments/sugar.png',
|
||||
"ketchup" = 'icons/ui_icons/condiments/ketchup.png',
|
||||
"capsaicin" = 'icons/ui_icons/condiments/hotsauce.png',
|
||||
"frostoil" = 'icons/ui_icons/condiments/coldsauce.png',
|
||||
"bbqsauce" = 'icons/ui_icons/condiments/bbqsauce.png',
|
||||
"cornoil" = 'icons/ui_icons/condiments/oliveoil.png',
|
||||
)
|
||||
|
||||
//this exists purely to avoid meta by pre-loading all language icons.
|
||||
/datum/asset/language/register()
|
||||
for(var/path in typesof(/datum/language))
|
||||
set waitfor = FALSE
|
||||
var/datum/language/L = new path ()
|
||||
L.get_icon()
|
||||
|
||||
/datum/asset/spritesheet/pipes
|
||||
name = "pipes"
|
||||
|
||||
/datum/asset/spritesheet/pipes/create_spritesheets()
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi'))
|
||||
InsertAll("", each, GLOB.alldirs)
|
||||
|
||||
/datum/asset/spritesheet/supplypods
|
||||
name = "supplypods"
|
||||
|
||||
/datum/asset/spritesheet/supplypods/create_spritesheets()
|
||||
for (var/style in 1 to length(GLOB.podstyles))
|
||||
if (style == STYLE_SEETHROUGH)
|
||||
Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi' , "seethrough-icon"))
|
||||
continue
|
||||
var/base = GLOB.podstyles[style][POD_BASE]
|
||||
if (!base)
|
||||
Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi', "invisible-icon"))
|
||||
continue
|
||||
var/icon/podIcon = icon('icons/obj/supplypods.dmi', base)
|
||||
var/door = GLOB.podstyles[style][POD_DOOR]
|
||||
if (door)
|
||||
door = "[base]_door"
|
||||
podIcon.Blend(icon('icons/obj/supplypods.dmi', door), ICON_OVERLAY)
|
||||
var/shape = GLOB.podstyles[style][POD_SHAPE]
|
||||
if (shape == POD_SHAPE_NORML)
|
||||
var/decal = GLOB.podstyles[style][POD_DECAL]
|
||||
if (decal)
|
||||
podIcon.Blend(icon('icons/obj/supplypods.dmi', decal), ICON_OVERLAY)
|
||||
var/glow = GLOB.podstyles[style][POD_GLOW]
|
||||
if (glow)
|
||||
glow = "pod_glow_[glow]"
|
||||
podIcon.Blend(icon('icons/obj/supplypods.dmi', glow), ICON_OVERLAY)
|
||||
Insert("pod_asset[style]", podIcon)
|
||||
|
||||
// Representative icons for each research design
|
||||
/datum/asset/spritesheet/research_designs
|
||||
name = "design"
|
||||
|
||||
/datum/asset/spritesheet/research_designs/create_spritesheets()
|
||||
for (var/path in subtypesof(/datum/design))
|
||||
var/datum/design/D = path
|
||||
|
||||
var/icon_file
|
||||
var/icon_state
|
||||
var/icon/I
|
||||
|
||||
if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest
|
||||
icon_file = initial(D.research_icon)
|
||||
icon_state = initial(D.research_icon_state)
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
else
|
||||
// construct the icon and slap it into the resource cache
|
||||
var/atom/item = initial(D.build_path)
|
||||
if (!ispath(item, /atom))
|
||||
// biogenerator outputs to beakers by default
|
||||
if (initial(D.build_type) & BIOGENERATOR)
|
||||
item = /obj/item/reagent_containers/glass/beaker/large
|
||||
else
|
||||
continue // shouldn't happen, but just in case
|
||||
|
||||
// circuit boards become their resulting machines or computers
|
||||
if (ispath(item, /obj/item/circuitboard))
|
||||
var/obj/item/circuitboard/C = item
|
||||
var/machine = initial(C.build_path)
|
||||
if (machine)
|
||||
item = machine
|
||||
|
||||
// Check for GAGS support where necessary
|
||||
var/greyscale_config = initial(item.greyscale_config)
|
||||
var/greyscale_colors = initial(item.greyscale_colors)
|
||||
if (greyscale_config && greyscale_colors)
|
||||
icon_file = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors)
|
||||
else
|
||||
icon_file = initial(item.icon)
|
||||
|
||||
icon_state = initial(item.icon_state)
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
// computers (and snowflakes) get their screen and keyboard sprites
|
||||
if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control))
|
||||
var/obj/machinery/computer/C = item
|
||||
var/screen = initial(C.icon_screen)
|
||||
var/keyboard = initial(C.icon_keyboard)
|
||||
var/all_states = icon_states(icon_file)
|
||||
if (screen && (screen in all_states))
|
||||
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
|
||||
if (keyboard && (keyboard in all_states))
|
||||
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
|
||||
|
||||
Insert(initial(D.id), I)
|
||||
|
||||
/datum/asset/spritesheet/vending
|
||||
name = "vending"
|
||||
|
||||
/datum/asset/spritesheet/vending/create_spritesheets()
|
||||
for (var/k in GLOB.vending_products)
|
||||
var/atom/item = k
|
||||
if (!ispath(item, /atom))
|
||||
continue
|
||||
|
||||
var/icon_file
|
||||
if (initial(item.greyscale_colors) && initial(item.greyscale_config))
|
||||
icon_file = SSgreyscale.GetColoredIconByType(initial(item.greyscale_config), initial(item.greyscale_colors))
|
||||
else
|
||||
icon_file = initial(item.icon)
|
||||
var/icon_state = initial(item.icon_state)
|
||||
var/icon/I
|
||||
|
||||
var/icon_states_list = icon_states(icon_file)
|
||||
if(icon_state in icon_states_list)
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
var/c = initial(item.color)
|
||||
if (!isnull(c) && c != "#FFFFFF")
|
||||
I.Blend(c, ICON_MULTIPLY)
|
||||
else
|
||||
var/icon_states_string
|
||||
for (var/an_icon_state in icon_states_list)
|
||||
if (!icon_states_string)
|
||||
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]")
|
||||
I = icon('icons/turf/floors.dmi', "", SOUTH)
|
||||
|
||||
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
|
||||
|
||||
Insert(imgid, I)
|
||||
|
||||
/datum/asset/simple/genetics
|
||||
assets = list(
|
||||
"dna_discovered.gif" = 'icons/ui_icons/dna/dna_discovered.gif',
|
||||
"dna_undiscovered.gif" = 'icons/ui_icons/dna/dna_undiscovered.gif',
|
||||
"dna_extra.gif" = 'icons/ui_icons/dna/dna_extra.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/orbit
|
||||
assets = list(
|
||||
"ghost.png" = 'icons/ui_icons/orbit/ghost.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/vv
|
||||
assets = list(
|
||||
"view_variables.css" = 'html/admin/view_variables.css'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/sheetmaterials
|
||||
name = "sheetmaterials"
|
||||
|
||||
/datum/asset/spritesheet/sheetmaterials/create_spritesheets()
|
||||
InsertAll("", 'icons/obj/stack_objects.dmi')
|
||||
|
||||
// Special case to handle Bluespace Crystals
|
||||
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
|
||||
|
||||
/datum/asset/spritesheet/mafia
|
||||
name = "mafia"
|
||||
|
||||
/datum/asset/spritesheet/mafia/create_spritesheets()
|
||||
InsertAll("", 'icons/obj/mafia.dmi')
|
||||
|
||||
/datum/asset/simple/portraits
|
||||
assets = list()
|
||||
|
||||
/datum/asset/simple/portraits/New()
|
||||
if(!length(SSpersistent_paintings.paintings))
|
||||
return
|
||||
for(var/datum/painting/portrait as anything in SSpersistent_paintings.paintings)
|
||||
var/png = "data/paintings/images/[portrait.md5].png"
|
||||
if(fexists(png))
|
||||
var/asset_name = "paintings_[portrait.md5]"
|
||||
assets[asset_name] = png
|
||||
..() //this is where it registers all these assets we added to the list
|
||||
|
||||
/datum/asset/simple/safe
|
||||
assets = list(
|
||||
"safe_dial.png" = 'icons/ui_icons/safe/safe_dial.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/contracts
|
||||
assets = list(
|
||||
"bluespace.png" = 'icons/ui_icons/contracts/bluespace.png',
|
||||
"destruction.png" = 'icons/ui_icons/contracts/destruction.png',
|
||||
"healing.png" = 'icons/ui_icons/contracts/healing.png',
|
||||
"robeless.png" = 'icons/ui_icons/contracts/robeless.png',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/fish
|
||||
name = "fish"
|
||||
|
||||
/datum/asset/spritesheet/fish/create_spritesheets()
|
||||
for (var/path in subtypesof(/datum/aquarium_behaviour/fish))
|
||||
var/datum/aquarium_behaviour/fish/fish_type = path
|
||||
var/fish_icon = initial(fish_type.icon)
|
||||
var/fish_icon_state = initial(fish_type.icon_state)
|
||||
var/id = sanitize_css_class_name("[fish_icon][fish_icon_state]")
|
||||
if(sprites[id]) //no dupes
|
||||
continue
|
||||
Insert(id, fish_icon, fish_icon_state)
|
||||
|
||||
/datum/asset/simple/adventure
|
||||
assets = list(
|
||||
"default" = 'icons/ui_icons/adventure/default.png',
|
||||
"grue" = 'icons/ui_icons/adventure/grue.png',
|
||||
"signal_lost" ='icons/ui_icons/adventure/signal_lost.png',
|
||||
"trade" = 'icons/ui_icons/adventure/trade.png',
|
||||
)
|
||||
|
||||
/datum/asset/simple/inventory
|
||||
assets = list(
|
||||
"inventory-glasses.png" = 'icons/ui_icons/inventory/glasses.png',
|
||||
"inventory-head.png" = 'icons/ui_icons/inventory/head.png',
|
||||
"inventory-neck.png" = 'icons/ui_icons/inventory/neck.png',
|
||||
"inventory-mask.png" = 'icons/ui_icons/inventory/mask.png',
|
||||
"inventory-ears.png" = 'icons/ui_icons/inventory/ears.png',
|
||||
"inventory-uniform.png" = 'icons/ui_icons/inventory/uniform.png',
|
||||
"inventory-suit.png" = 'icons/ui_icons/inventory/suit.png',
|
||||
"inventory-gloves.png" = 'icons/ui_icons/inventory/gloves.png',
|
||||
"inventory-hand_l.png" = 'icons/ui_icons/inventory/hand_l.png',
|
||||
"inventory-hand_r.png" = 'icons/ui_icons/inventory/hand_r.png',
|
||||
"inventory-shoes.png" = 'icons/ui_icons/inventory/shoes.png',
|
||||
"inventory-suit_storage.png" = 'icons/ui_icons/inventory/suit_storage.png',
|
||||
"inventory-id.png" = 'icons/ui_icons/inventory/id.png',
|
||||
"inventory-belt.png" = 'icons/ui_icons/inventory/belt.png',
|
||||
"inventory-back.png" = 'icons/ui_icons/inventory/back.png',
|
||||
"inventory-pocket.png" = 'icons/ui_icons/inventory/pocket.png',
|
||||
"inventory-collar.png" = 'icons/ui_icons/inventory/collar.png',
|
||||
)
|
||||
|
||||
/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
|
||||
/proc/sanitize_css_class_name(name)
|
||||
var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
|
||||
return replacetext(name, regex, "")
|
||||
|
||||
/datum/asset/simple/tutorial_advisors
|
||||
assets = list(
|
||||
"chem_help_advisor.gif" = 'icons/ui_icons/advisors/chem_help_advisor.gif',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/moods
|
||||
name = "moods"
|
||||
var/iconinserted = 1
|
||||
|
||||
/datum/asset/spritesheet/moods/create_spritesheets()
|
||||
for(var/i in 1 to 9)
|
||||
var/target_to_insert = "mood"+"[iconinserted]"
|
||||
Insert(target_to_insert, 'icons/hud/screen_gen.dmi', target_to_insert)
|
||||
iconinserted++
|
||||
|
||||
/datum/asset/spritesheet/moods/ModifyInserted(icon/pre_asset)
|
||||
var/blended_color
|
||||
switch(iconinserted)
|
||||
if(1)
|
||||
blended_color = "#f15d36"
|
||||
if(2 to 3)
|
||||
blended_color = "#f38943"
|
||||
if(4)
|
||||
blended_color = "#dfa65b"
|
||||
if(5)
|
||||
blended_color = "#4b96c4"
|
||||
if(6)
|
||||
blended_color = "#86d656"
|
||||
else
|
||||
blended_color = "#2eeb9a"
|
||||
pre_asset.Blend(blended_color, ICON_MULTIPLY)
|
||||
return pre_asset
|
||||
|
||||
/// Sends information needed for uplinks
|
||||
/datum/asset/json/uplink
|
||||
name = "uplink"
|
||||
|
||||
/datum/asset/json/uplink/generate()
|
||||
var/list/data = list()
|
||||
var/list/categories = list()
|
||||
var/list/items = list()
|
||||
for(var/datum/uplink_category/category as anything in subtypesof(/datum/uplink_category))
|
||||
categories += category
|
||||
categories = sortTim(categories, .proc/cmp_uplink_category_desc)
|
||||
|
||||
var/list/new_categories = list()
|
||||
for(var/datum/uplink_category/category as anything in categories)
|
||||
new_categories += initial(category.name)
|
||||
categories = new_categories
|
||||
|
||||
for(var/datum/uplink_item/item_path as anything in subtypesof(/datum/uplink_item))
|
||||
var/datum/uplink_item/item = new item_path()
|
||||
if(item.item) {
|
||||
items += list(list(
|
||||
"id" = item_path,
|
||||
"name" = item.name,
|
||||
"cost" = item.cost,
|
||||
"desc" = item.desc,
|
||||
"category" = item.category? initial(item.category.name) : null,
|
||||
"purchasable_from" = item.purchasable_from,
|
||||
"restricted" = item.restricted,
|
||||
"limited_stock" = item.limited_stock,
|
||||
"restricted_roles" = item.restricted_roles,
|
||||
"restricted_species" = item.restricted_species,
|
||||
"progression_minimum" = item.progression_minimum,
|
||||
))
|
||||
}
|
||||
SStraitor.uplink_items += item
|
||||
SStraitor.uplink_items_by_type[item_path] = item
|
||||
|
||||
data["items"] = items
|
||||
data["categories"] = categories
|
||||
return data
|
||||
@@ -0,0 +1,5 @@
|
||||
/datum/asset/spritesheet/simple/achievements
|
||||
name ="achievements"
|
||||
|
||||
/datum/asset/spritesheet/simple/achievements/create_spritesheets()
|
||||
InsertAll("", ACHIEVEMENTS_SET)
|
||||
@@ -0,0 +1,7 @@
|
||||
/datum/asset/simple/adventure
|
||||
assets = list(
|
||||
"default" = 'icons/ui_icons/adventure/default.png',
|
||||
"grue" = 'icons/ui_icons/adventure/grue.png',
|
||||
"signal_lost" ='icons/ui_icons/adventure/signal_lost.png',
|
||||
"trade" = 'icons/ui_icons/adventure/trade.png',
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
/datum/asset/simple/arcade
|
||||
assets = list(
|
||||
"boss1.gif" = 'icons/ui_icons/arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/ui_icons/arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/ui_icons/arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/ui_icons/arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/ui_icons/arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/ui_icons/arcade/boss6.gif',
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
/// Spritesheet for body zones. Necessary if your tgui uses BodyZoneSelector
|
||||
// This is a simple sheet instead of a spritesheet because spritesheets don't support
|
||||
// -ms-interpolation-mode when resized, since you need `transform: scale`.
|
||||
// Also spritesheets have some weird fudge on the edges of them because of an IE bug I can't track down.
|
||||
/datum/asset/simple/body_zones
|
||||
|
||||
/datum/asset/simple/body_zones/register()
|
||||
assets["body_zones.base.png"] = icon('icons/hud/screen_midnight.dmi', "zone_sel")
|
||||
|
||||
add_limb(BODY_ZONE_HEAD)
|
||||
add_limb(BODY_ZONE_CHEST)
|
||||
add_limb(BODY_ZONE_L_ARM)
|
||||
add_limb(BODY_ZONE_R_ARM)
|
||||
add_limb(BODY_ZONE_L_LEG)
|
||||
add_limb(BODY_ZONE_R_LEG)
|
||||
add_limb(BODY_ZONE_PRECISE_EYES)
|
||||
add_limb(BODY_ZONE_PRECISE_MOUTH)
|
||||
add_limb(BODY_ZONE_PRECISE_GROIN)
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/asset/simple/body_zones/proc/add_limb(limb)
|
||||
assets[SANITIZE_FILENAME("body_zones.[limb].png")] = icon('icons/hud/screen_gen.dmi', limb)
|
||||
@@ -0,0 +1,14 @@
|
||||
/datum/asset/spritesheet/chat
|
||||
name = "chat"
|
||||
|
||||
/datum/asset/spritesheet/chat/create_spritesheets()
|
||||
InsertAll("emoji", EMOJI_SET)
|
||||
// pre-loading all lanugage icons also helps to avoid meta
|
||||
InsertAll("language", 'icons/misc/language.dmi')
|
||||
// catch languages which are pulling icons from another file
|
||||
for(var/path in typesof(/datum/language))
|
||||
var/datum/language/L = path
|
||||
var/icon = initial(L.icon)
|
||||
if (icon != 'icons/misc/language.dmi')
|
||||
var/icon_state = initial(L.icon_state)
|
||||
Insert("language-[icon_state]", icon, icon_state=icon_state)
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/asset/simple/circuit_assets
|
||||
assets = list(
|
||||
"grid_background.png" = 'icons/ui_icons/tgui/grid_background.png'
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
/datum/asset/simple/namespaced/common
|
||||
assets = list("padlock.png" = 'icons/ui_icons/common/padlock.png')
|
||||
parents = list("common.css" = 'html/browser/common.css')
|
||||
@@ -0,0 +1,20 @@
|
||||
/datum/asset/spritesheet/simple/condiments
|
||||
name = "condiments"
|
||||
assets = list(
|
||||
CONDIMASTER_STYLE_FALLBACK = 'icons/ui_icons/condiments/emptycondiment.png',
|
||||
"enzyme" = 'icons/ui_icons/condiments/enzyme.png',
|
||||
"flour" = 'icons/ui_icons/condiments/flour.png',
|
||||
"mayonnaise" = 'icons/ui_icons/condiments/mayonnaise.png',
|
||||
"milk" = 'icons/ui_icons/condiments/milk.png',
|
||||
"blackpepper" = 'icons/ui_icons/condiments/peppermillsmall.png',
|
||||
"rice" = 'icons/ui_icons/condiments/rice.png',
|
||||
"sodiumchloride" = 'icons/ui_icons/condiments/saltshakersmall.png',
|
||||
"soymilk" = 'icons/ui_icons/condiments/soymilk.png',
|
||||
"soysauce" = 'icons/ui_icons/condiments/soysauce.png',
|
||||
"sugar" = 'icons/ui_icons/condiments/sugar.png',
|
||||
"ketchup" = 'icons/ui_icons/condiments/ketchup.png',
|
||||
"capsaicin" = 'icons/ui_icons/condiments/hotsauce.png',
|
||||
"frostoil" = 'icons/ui_icons/condiments/coldsauce.png',
|
||||
"bbqsauce" = 'icons/ui_icons/condiments/bbqsauce.png',
|
||||
"cornoil" = 'icons/ui_icons/condiments/oliveoil.png',
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
/datum/asset/simple/contracts
|
||||
assets = list(
|
||||
"bluespace.png" = 'icons/ui_icons/contracts/bluespace.png',
|
||||
"destruction.png" = 'icons/ui_icons/contracts/destruction.png',
|
||||
"healing.png" = 'icons/ui_icons/contracts/healing.png',
|
||||
"robeless.png" = 'icons/ui_icons/contracts/robeless.png',
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
/datum/asset/spritesheet/fish
|
||||
name = "fish"
|
||||
|
||||
/datum/asset/spritesheet/fish/create_spritesheets()
|
||||
for (var/path in subtypesof(/datum/aquarium_behaviour/fish))
|
||||
var/datum/aquarium_behaviour/fish/fish_type = path
|
||||
var/fish_icon = initial(fish_type.icon)
|
||||
var/fish_icon_state = initial(fish_type.icon_state)
|
||||
var/id = sanitize_css_class_name("[fish_icon][fish_icon_state]")
|
||||
if(sprites[id]) //no dupes
|
||||
continue
|
||||
Insert(id, fish_icon, fish_icon_state)
|
||||
@@ -0,0 +1,9 @@
|
||||
/datum/asset/simple/namespaced/fontawesome
|
||||
assets = list(
|
||||
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
|
||||
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
|
||||
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
|
||||
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css',
|
||||
)
|
||||
parents = list("font-awesome.css" = 'html/font-awesome/css/all.min.css')
|
||||
@@ -0,0 +1,6 @@
|
||||
/datum/asset/simple/genetics
|
||||
assets = list(
|
||||
"dna_discovered.gif" = 'icons/ui_icons/dna/dna_discovered.gif',
|
||||
"dna_undiscovered.gif" = 'icons/ui_icons/dna/dna_undiscovered.gif',
|
||||
"dna_extra.gif" = 'icons/ui_icons/dna/dna_extra.gif'
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
/datum/asset/simple/headers
|
||||
assets = list(
|
||||
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
|
||||
"alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
|
||||
"batt_5.gif" = 'icons/program_icons/batt_5.gif',
|
||||
"batt_20.gif" = 'icons/program_icons/batt_20.gif',
|
||||
"batt_40.gif" = 'icons/program_icons/batt_40.gif',
|
||||
"batt_60.gif" = 'icons/program_icons/batt_60.gif',
|
||||
"batt_80.gif" = 'icons/program_icons/batt_80.gif',
|
||||
"batt_100.gif" = 'icons/program_icons/batt_100.gif',
|
||||
"charging.gif" = 'icons/program_icons/charging.gif',
|
||||
"downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
|
||||
"downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
|
||||
"ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
|
||||
"ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
|
||||
"power_norm.gif" = 'icons/program_icons/power_norm.gif',
|
||||
"power_warn.gif" = 'icons/program_icons/power_warn.gif',
|
||||
"sig_high.gif" = 'icons/program_icons/sig_high.gif',
|
||||
"sig_low.gif" = 'icons/program_icons/sig_low.gif',
|
||||
"sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
|
||||
"sig_none.gif" = 'icons/program_icons/sig_none.gif',
|
||||
"smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
|
||||
"smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
|
||||
"smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
|
||||
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
|
||||
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
|
||||
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
|
||||
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif',
|
||||
"robotact.gif" = 'icons/program_icons/robotact.gif'
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
/datum/asset/simple/inventory
|
||||
assets = list(
|
||||
"inventory-glasses.png" = 'icons/ui_icons/inventory/glasses.png',
|
||||
"inventory-head.png" = 'icons/ui_icons/inventory/head.png',
|
||||
"inventory-neck.png" = 'icons/ui_icons/inventory/neck.png',
|
||||
"inventory-mask.png" = 'icons/ui_icons/inventory/mask.png',
|
||||
"inventory-ears.png" = 'icons/ui_icons/inventory/ears.png',
|
||||
"inventory-uniform.png" = 'icons/ui_icons/inventory/uniform.png',
|
||||
"inventory-suit.png" = 'icons/ui_icons/inventory/suit.png',
|
||||
"inventory-gloves.png" = 'icons/ui_icons/inventory/gloves.png',
|
||||
"inventory-hand_l.png" = 'icons/ui_icons/inventory/hand_l.png',
|
||||
"inventory-hand_r.png" = 'icons/ui_icons/inventory/hand_r.png',
|
||||
"inventory-shoes.png" = 'icons/ui_icons/inventory/shoes.png',
|
||||
"inventory-suit_storage.png" = 'icons/ui_icons/inventory/suit_storage.png',
|
||||
"inventory-id.png" = 'icons/ui_icons/inventory/id.png',
|
||||
"inventory-belt.png" = 'icons/ui_icons/inventory/belt.png',
|
||||
"inventory-back.png" = 'icons/ui_icons/inventory/back.png',
|
||||
"inventory-pocket.png" = 'icons/ui_icons/inventory/pocket.png',
|
||||
"inventory-collar.png" = 'icons/ui_icons/inventory/collar.png',
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
/datum/asset/simple/irv
|
||||
assets = list(
|
||||
"jquery-ui.custom-core-widgit-mouse-sortable.min.js" = 'html/jquery/jquery-ui.custom-core-widgit-mouse-sortable.min.js',
|
||||
)
|
||||
|
||||
/datum/asset/group/irv
|
||||
children = list(
|
||||
/datum/asset/simple/jquery,
|
||||
/datum/asset/simple/irv
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
/datum/asset/simple/jquery
|
||||
legacy = TRUE
|
||||
assets = list(
|
||||
"jquery.min.js" = 'html/jquery/jquery.min.js',
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
//this exists purely to avoid meta by pre-loading all language icons.
|
||||
/datum/asset/language
|
||||
|
||||
/datum/asset/language/register()
|
||||
set waitfor = FALSE
|
||||
|
||||
for(var/path in typesof(/datum/language))
|
||||
var/datum/language/language = new path()
|
||||
language.get_icon()
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/asset/simple/lobby
|
||||
assets = list(
|
||||
"playeroptions.css" = 'html/browser/playeroptions.css'
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
/datum/asset/spritesheet/mafia
|
||||
name = "mafia"
|
||||
|
||||
/datum/asset/spritesheet/mafia/create_spritesheets()
|
||||
InsertAll("", 'icons/obj/mafia.dmi')
|
||||
@@ -0,0 +1,27 @@
|
||||
/datum/asset/spritesheet/moods
|
||||
name = "moods"
|
||||
var/iconinserted = 1
|
||||
|
||||
/datum/asset/spritesheet/moods/create_spritesheets()
|
||||
for(var/i in 1 to 9)
|
||||
var/target_to_insert = "mood"+"[iconinserted]"
|
||||
Insert(target_to_insert, 'icons/hud/screen_gen.dmi', target_to_insert)
|
||||
iconinserted++
|
||||
|
||||
/datum/asset/spritesheet/moods/ModifyInserted(icon/pre_asset)
|
||||
var/blended_color
|
||||
switch(iconinserted)
|
||||
if(1)
|
||||
blended_color = "#f15d36"
|
||||
if(2 to 3)
|
||||
blended_color = "#f38943"
|
||||
if(4)
|
||||
blended_color = "#dfa65b"
|
||||
if(5)
|
||||
blended_color = "#4b96c4"
|
||||
if(6)
|
||||
blended_color = "#86d656"
|
||||
else
|
||||
blended_color = "#2eeb9a"
|
||||
pre_asset.Blend(blended_color, ICON_MULTIPLY)
|
||||
return pre_asset
|
||||
@@ -0,0 +1,7 @@
|
||||
/datum/asset/simple/notes
|
||||
assets = list(
|
||||
"high_button.png" = 'icons/ui_icons/notes/high_button.png',
|
||||
"medium_button.png" = 'icons/ui_icons/notes/medium_button.png',
|
||||
"minor_button.png" = 'icons/ui_icons/notes/minor_button.png',
|
||||
"none_button.png" = 'icons/ui_icons/notes/none_button.png',
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/asset/simple/orbit
|
||||
assets = list(
|
||||
"ghost.png" = 'icons/ui_icons/orbit/ghost.png'
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/asset/spritesheet/simple/paper
|
||||
name = "paper"
|
||||
assets = list(
|
||||
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
|
||||
"stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png',
|
||||
"stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png',
|
||||
"stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png',
|
||||
"stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png',
|
||||
"stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png',
|
||||
"stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png',
|
||||
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
|
||||
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
|
||||
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
|
||||
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png',
|
||||
"stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png',
|
||||
"stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
|
||||
"stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
|
||||
"stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
/datum/asset/spritesheet/simple/patches
|
||||
name = "patches"
|
||||
assets = list(
|
||||
"bandaid" = 'icons/ui_icons/patches/bandaid.png',
|
||||
"bandaid_brute" = 'icons/ui_icons/patches/bandaid_brute.png',
|
||||
"bandaid_burn" = 'icons/ui_icons/patches/bandaid_burn.png',
|
||||
"bandaid_both" = 'icons/ui_icons/patches/bandaid_both.png'
|
||||
)
|
||||
@@ -0,0 +1,34 @@
|
||||
/datum/asset/spritesheet/simple/pda
|
||||
name = "pda"
|
||||
assets = list(
|
||||
"atmos" = 'icons/pda_icons/pda_atmos.png',
|
||||
"back" = 'icons/pda_icons/pda_back.png',
|
||||
"bell" = 'icons/pda_icons/pda_bell.png',
|
||||
"blank" = 'icons/pda_icons/pda_blank.png',
|
||||
"boom" = 'icons/pda_icons/pda_boom.png',
|
||||
"bucket" = 'icons/pda_icons/pda_bucket.png',
|
||||
"medbot" = 'icons/pda_icons/pda_medbot.png',
|
||||
"floorbot" = 'icons/pda_icons/pda_floorbot.png',
|
||||
"cleanbot" = 'icons/pda_icons/pda_cleanbot.png',
|
||||
"crate" = 'icons/pda_icons/pda_crate.png',
|
||||
"cuffs" = 'icons/pda_icons/pda_cuffs.png',
|
||||
"eject" = 'icons/pda_icons/pda_eject.png',
|
||||
"flashlight" = 'icons/pda_icons/pda_flashlight.png',
|
||||
"honk" = 'icons/pda_icons/pda_honk.png',
|
||||
"mail" = 'icons/pda_icons/pda_mail.png',
|
||||
"medical" = 'icons/pda_icons/pda_medical.png',
|
||||
"menu" = 'icons/pda_icons/pda_menu.png',
|
||||
"mule" = 'icons/pda_icons/pda_mule.png',
|
||||
"notes" = 'icons/pda_icons/pda_notes.png',
|
||||
"power" = 'icons/pda_icons/pda_power.png',
|
||||
"rdoor" = 'icons/pda_icons/pda_rdoor.png',
|
||||
"reagent" = 'icons/pda_icons/pda_reagent.png',
|
||||
"refresh" = 'icons/pda_icons/pda_refresh.png',
|
||||
"scanner" = 'icons/pda_icons/pda_scanner.png',
|
||||
"signaler" = 'icons/pda_icons/pda_signaler.png',
|
||||
"skills" = 'icons/pda_icons/pda_skills.png',
|
||||
"status" = 'icons/pda_icons/pda_status.png',
|
||||
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
|
||||
"emoji" = 'icons/pda_icons/pda_emoji.png',
|
||||
"droneblacklist" = 'icons/pda_icons/pda_droneblacklist.png',
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
/datum/asset/simple/permissions
|
||||
assets = list(
|
||||
"search.js" = 'html/admin/search.js',
|
||||
"panels.css" = 'html/admin/panels.css'
|
||||
)
|
||||
|
||||
/datum/asset/group/permissions
|
||||
children = list(
|
||||
/datum/asset/simple/permissions,
|
||||
/datum/asset/simple/namespaced/common
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
/datum/asset/spritesheet/simple/pills
|
||||
name = "pills"
|
||||
assets = list(
|
||||
"pill1" = 'icons/ui_icons/pills/pill1.png',
|
||||
"pill2" = 'icons/ui_icons/pills/pill2.png',
|
||||
"pill3" = 'icons/ui_icons/pills/pill3.png',
|
||||
"pill4" = 'icons/ui_icons/pills/pill4.png',
|
||||
"pill5" = 'icons/ui_icons/pills/pill5.png',
|
||||
"pill6" = 'icons/ui_icons/pills/pill6.png',
|
||||
"pill7" = 'icons/ui_icons/pills/pill7.png',
|
||||
"pill8" = 'icons/ui_icons/pills/pill8.png',
|
||||
"pill9" = 'icons/ui_icons/pills/pill9.png',
|
||||
"pill10" = 'icons/ui_icons/pills/pill10.png',
|
||||
"pill11" = 'icons/ui_icons/pills/pill11.png',
|
||||
"pill12" = 'icons/ui_icons/pills/pill12.png',
|
||||
"pill13" = 'icons/ui_icons/pills/pill13.png',
|
||||
"pill14" = 'icons/ui_icons/pills/pill14.png',
|
||||
"pill15" = 'icons/ui_icons/pills/pill15.png',
|
||||
"pill16" = 'icons/ui_icons/pills/pill16.png',
|
||||
"pill17" = 'icons/ui_icons/pills/pill17.png',
|
||||
"pill18" = 'icons/ui_icons/pills/pill18.png',
|
||||
"pill19" = 'icons/ui_icons/pills/pill19.png',
|
||||
"pill20" = 'icons/ui_icons/pills/pill20.png',
|
||||
"pill21" = 'icons/ui_icons/pills/pill21.png',
|
||||
"pill22" = 'icons/ui_icons/pills/pill22.png',
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
/datum/asset/spritesheet/pipes
|
||||
name = "pipes"
|
||||
|
||||
/datum/asset/spritesheet/pipes/create_spritesheets()
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi'))
|
||||
InsertAll("", each, GLOB.alldirs)
|
||||
@@ -0,0 +1,12 @@
|
||||
/datum/asset/simple/portraits
|
||||
assets = list()
|
||||
|
||||
/datum/asset/simple/portraits/New()
|
||||
if(!length(SSpersistent_paintings.paintings))
|
||||
return
|
||||
for(var/datum/painting/portrait as anything in SSpersistent_paintings.paintings)
|
||||
var/png = "data/paintings/images/[portrait.md5].png"
|
||||
if(fexists(png))
|
||||
var/asset_name = "paintings_[portrait.md5]"
|
||||
assets[asset_name] = png
|
||||
..() //this is where it registers all these assets we added to the list
|
||||
@@ -0,0 +1,6 @@
|
||||
/datum/asset/simple/radar_assets
|
||||
assets = list(
|
||||
"ntosradarbackground.png" = 'icons/ui_icons/tgui/ntosradar_background.png',
|
||||
"ntosradarpointer.png" = 'icons/ui_icons/tgui/ntosradar_pointer.png',
|
||||
"ntosradarpointerS.png" = 'icons/ui_icons/tgui/ntosradar_pointer_S.png'
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
// Representative icons for each research design
|
||||
/datum/asset/spritesheet/research_designs
|
||||
name = "design"
|
||||
|
||||
/datum/asset/spritesheet/research_designs/create_spritesheets()
|
||||
for (var/path in subtypesof(/datum/design))
|
||||
var/datum/design/D = path
|
||||
|
||||
var/icon_file
|
||||
var/icon_state
|
||||
var/icon/I
|
||||
|
||||
if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest
|
||||
icon_file = initial(D.research_icon)
|
||||
icon_state = initial(D.research_icon_state)
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
else
|
||||
// construct the icon and slap it into the resource cache
|
||||
var/atom/item = initial(D.build_path)
|
||||
if (!ispath(item, /atom))
|
||||
// biogenerator outputs to beakers by default
|
||||
if (initial(D.build_type) & BIOGENERATOR)
|
||||
item = /obj/item/reagent_containers/glass/beaker/large
|
||||
else
|
||||
continue // shouldn't happen, but just in case
|
||||
|
||||
// circuit boards become their resulting machines or computers
|
||||
if (ispath(item, /obj/item/circuitboard))
|
||||
var/obj/item/circuitboard/C = item
|
||||
var/machine = initial(C.build_path)
|
||||
if (machine)
|
||||
item = machine
|
||||
|
||||
// Check for GAGS support where necessary
|
||||
var/greyscale_config = initial(item.greyscale_config)
|
||||
var/greyscale_colors = initial(item.greyscale_colors)
|
||||
if (greyscale_config && greyscale_colors)
|
||||
icon_file = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors)
|
||||
else
|
||||
icon_file = initial(item.icon)
|
||||
|
||||
icon_state = initial(item.icon_state)
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
// computers (and snowflakes) get their screen and keyboard sprites
|
||||
if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control))
|
||||
var/obj/machinery/computer/C = item
|
||||
var/screen = initial(C.icon_screen)
|
||||
var/keyboard = initial(C.icon_keyboard)
|
||||
var/all_states = icon_states(icon_file)
|
||||
if (screen && (screen in all_states))
|
||||
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
|
||||
if (keyboard && (keyboard in all_states))
|
||||
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
|
||||
|
||||
Insert(initial(D.id), I)
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/asset/simple/safe
|
||||
assets = list(
|
||||
"safe_dial.png" = 'icons/ui_icons/safe/safe_dial.png'
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
/datum/asset/spritesheet/sheetmaterials
|
||||
name = "sheetmaterials"
|
||||
|
||||
/datum/asset/spritesheet/sheetmaterials/create_spritesheets()
|
||||
InsertAll("", 'icons/obj/stack_objects.dmi')
|
||||
|
||||
// Special case to handle Bluespace Crystals
|
||||
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
|
||||
@@ -0,0 +1,27 @@
|
||||
/datum/asset/spritesheet/supplypods
|
||||
name = "supplypods"
|
||||
|
||||
/datum/asset/spritesheet/supplypods/create_spritesheets()
|
||||
for (var/style in 1 to length(GLOB.podstyles))
|
||||
if (style == STYLE_SEETHROUGH)
|
||||
Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi' , "seethrough-icon"))
|
||||
continue
|
||||
var/base = GLOB.podstyles[style][POD_BASE]
|
||||
if (!base)
|
||||
Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi', "invisible-icon"))
|
||||
continue
|
||||
var/icon/podIcon = icon('icons/obj/supplypods.dmi', base)
|
||||
var/door = GLOB.podstyles[style][POD_DOOR]
|
||||
if (door)
|
||||
door = "[base]_door"
|
||||
podIcon.Blend(icon('icons/obj/supplypods.dmi', door), ICON_OVERLAY)
|
||||
var/shape = GLOB.podstyles[style][POD_SHAPE]
|
||||
if (shape == POD_SHAPE_NORML)
|
||||
var/decal = GLOB.podstyles[style][POD_DECAL]
|
||||
if (decal)
|
||||
podIcon.Blend(icon('icons/obj/supplypods.dmi', decal), ICON_OVERLAY)
|
||||
var/glow = GLOB.podstyles[style][POD_GLOW]
|
||||
if (glow)
|
||||
glow = "pod_glow_[glow]"
|
||||
podIcon.Blend(icon('icons/obj/supplypods.dmi', glow), ICON_OVERLAY)
|
||||
Insert("pod_asset[style]", podIcon)
|
||||
@@ -0,0 +1,8 @@
|
||||
/datum/asset/simple/namespaced/tgfont
|
||||
assets = list(
|
||||
"tgfont.eot" = file("tgui/packages/tgfont/static/tgfont.eot"),
|
||||
"tgfont.woff2" = file("tgui/packages/tgfont/static/tgfont.woff2"),
|
||||
)
|
||||
parents = list(
|
||||
"tgfont.css" = file("tgui/packages/tgfont/static/tgfont.css"),
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
/datum/asset/simple/tgui
|
||||
keep_local_name = TRUE
|
||||
assets = list(
|
||||
"tgui.bundle.js" = file("tgui/public/tgui.bundle.js"),
|
||||
"tgui.bundle.css" = file("tgui/public/tgui.bundle.css"),
|
||||
)
|
||||
|
||||
/datum/asset/simple/tgui_panel
|
||||
keep_local_name = TRUE
|
||||
assets = list(
|
||||
"tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"),
|
||||
"tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"),
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/asset/simple/tutorial_advisors
|
||||
assets = list(
|
||||
"chem_help_advisor.gif" = 'icons/ui_icons/advisors/chem_help_advisor.gif',
|
||||
)
|
||||
@@ -0,0 +1,40 @@
|
||||
/// Sends information needed for uplinks
|
||||
/datum/asset/json/uplink
|
||||
name = "uplink"
|
||||
|
||||
/datum/asset/json/uplink/generate()
|
||||
var/list/data = list()
|
||||
var/list/categories = list()
|
||||
var/list/items = list()
|
||||
for(var/datum/uplink_category/category as anything in subtypesof(/datum/uplink_category))
|
||||
categories += category
|
||||
categories = sortTim(categories, .proc/cmp_uplink_category_desc)
|
||||
|
||||
var/list/new_categories = list()
|
||||
for(var/datum/uplink_category/category as anything in categories)
|
||||
new_categories += initial(category.name)
|
||||
categories = new_categories
|
||||
|
||||
for(var/datum/uplink_item/item_path as anything in subtypesof(/datum/uplink_item))
|
||||
var/datum/uplink_item/item = new item_path()
|
||||
if(item.item) {
|
||||
items += list(list(
|
||||
"id" = item_path,
|
||||
"name" = item.name,
|
||||
"cost" = item.cost,
|
||||
"desc" = item.desc,
|
||||
"category" = item.category? initial(item.category.name) : null,
|
||||
"purchasable_from" = item.purchasable_from,
|
||||
"restricted" = item.restricted,
|
||||
"limited_stock" = item.limited_stock,
|
||||
"restricted_roles" = item.restricted_roles,
|
||||
"restricted_species" = item.restricted_species,
|
||||
"progression_minimum" = item.progression_minimum,
|
||||
))
|
||||
}
|
||||
SStraitor.uplink_items += item
|
||||
SStraitor.uplink_items_by_type[item_path] = item
|
||||
|
||||
data["items"] = items
|
||||
data["categories"] = categories
|
||||
return data
|
||||
@@ -0,0 +1,36 @@
|
||||
/datum/asset/spritesheet/vending
|
||||
name = "vending"
|
||||
|
||||
/datum/asset/spritesheet/vending/create_spritesheets()
|
||||
for (var/k in GLOB.vending_products)
|
||||
var/atom/item = k
|
||||
if (!ispath(item, /atom))
|
||||
continue
|
||||
|
||||
var/icon_file
|
||||
if (initial(item.greyscale_colors) && initial(item.greyscale_config))
|
||||
icon_file = SSgreyscale.GetColoredIconByType(initial(item.greyscale_config), initial(item.greyscale_colors))
|
||||
else
|
||||
icon_file = initial(item.icon)
|
||||
var/icon_state = initial(item.icon_state)
|
||||
var/icon/I
|
||||
|
||||
var/icon_states_list = icon_states(icon_file)
|
||||
if(icon_state in icon_states_list)
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
var/c = initial(item.color)
|
||||
if (!isnull(c) && c != "#FFFFFF")
|
||||
I.Blend(c, ICON_MULTIPLY)
|
||||
else
|
||||
var/icon_states_string
|
||||
for (var/an_icon_state in icon_states_list)
|
||||
if (!icon_states_string)
|
||||
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]")
|
||||
I = icon('icons/turf/floors.dmi', "", SOUTH)
|
||||
|
||||
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
|
||||
|
||||
Insert(imgid, I)
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/asset/simple/vv
|
||||
assets = list(
|
||||
"view_variables.css" = 'html/admin/view_variables.css'
|
||||
)
|
||||
@@ -22,9 +22,9 @@
|
||||
var/requires_tech = FALSE //handles techweb-oriented surgeries, previously restricted to the /advanced subtype (You still need to add designs)
|
||||
var/replaced_by //type; doesn't show up if this type exists. Set to /datum/surgery if you want to hide a "base" surgery (useful for typing parents IE healing.dm just make sure to null it out again)
|
||||
/// Organ being directly manipulated, used for checking if the organ is still in the body after surgery has begun
|
||||
var/organ_to_manipulate
|
||||
var/organ_to_manipulate
|
||||
|
||||
/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart)
|
||||
/datum/surgery/New(atom/surgery_target, surgery_location, surgery_bodypart)
|
||||
..()
|
||||
if(!surgery_target)
|
||||
return
|
||||
@@ -39,6 +39,8 @@
|
||||
operated_wound = operated_bodypart.get_wound_type(targetable_wound)
|
||||
operated_wound.attached_surgery = src
|
||||
|
||||
SEND_SIGNAL(surgery_target, COMSIG_MOB_SURGERY_STARTED, src, surgery_location, surgery_bodypart)
|
||||
|
||||
/datum/surgery/Destroy()
|
||||
if(operated_wound)
|
||||
operated_wound.attached_surgery = null
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
|
||||
/obj/item/surgical_drapes/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/surgery_initiator)
|
||||
AddComponent(/datum/component/surgery_initiator)
|
||||
|
||||
|
||||
/obj/item/surgical_processor //allows medical cyborgs to scan and initiate advanced surgeries
|
||||
|
||||
+42
-2
@@ -207,6 +207,7 @@
|
||||
#include "code\__DEFINES\dcs\signals\signals_hydroponic.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_janitor.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_light_eater.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_medical.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_mind.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_mod.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_mood.dm"
|
||||
@@ -757,6 +758,7 @@
|
||||
#include "code\datums\components\strong_pull.dm"
|
||||
#include "code\datums\components\subtype_picker.dm"
|
||||
#include "code\datums\components\summoning.dm"
|
||||
#include "code\datums\components\surgery_initiator.dm"
|
||||
#include "code\datums\components\swabbing.dm"
|
||||
#include "code\datums\components\swarming.dm"
|
||||
#include "code\datums\components\tackle.dm"
|
||||
@@ -942,7 +944,6 @@
|
||||
#include "code\datums\elements\spooky.dm"
|
||||
#include "code\datums\elements\squish.dm"
|
||||
#include "code\datums\elements\strippable.dm"
|
||||
#include "code\datums\elements\surgery_initiator.dm"
|
||||
#include "code\datums\elements\swabbable.dm"
|
||||
#include "code\datums\elements\tenacious.dm"
|
||||
#include "code\datums\elements\tool_flash.dm"
|
||||
@@ -2123,7 +2124,46 @@
|
||||
#include "code\modules\asset_cache\asset_cache_client.dm"
|
||||
#include "code\modules\asset_cache\asset_cache_item.dm"
|
||||
#include "code\modules\asset_cache\asset_list.dm"
|
||||
#include "code\modules\asset_cache\asset_list_items.dm"
|
||||
#include "code\modules\asset_cache\assets\achievements.dm"
|
||||
#include "code\modules\asset_cache\assets\adventure.dm"
|
||||
#include "code\modules\asset_cache\assets\arcade.dm"
|
||||
#include "code\modules\asset_cache\assets\body_zones.dm"
|
||||
#include "code\modules\asset_cache\assets\chat.dm"
|
||||
#include "code\modules\asset_cache\assets\circuits.dm"
|
||||
#include "code\modules\asset_cache\assets\common.dm"
|
||||
#include "code\modules\asset_cache\assets\condiments.dm"
|
||||
#include "code\modules\asset_cache\assets\contracts.dm"
|
||||
#include "code\modules\asset_cache\assets\fish.dm"
|
||||
#include "code\modules\asset_cache\assets\fontawesome.dm"
|
||||
#include "code\modules\asset_cache\assets\genetics.dm"
|
||||
#include "code\modules\asset_cache\assets\headers.dm"
|
||||
#include "code\modules\asset_cache\assets\inventory.dm"
|
||||
#include "code\modules\asset_cache\assets\irv.dm"
|
||||
#include "code\modules\asset_cache\assets\jquery.dm"
|
||||
#include "code\modules\asset_cache\assets\language.dm"
|
||||
#include "code\modules\asset_cache\assets\lobby.dm"
|
||||
#include "code\modules\asset_cache\assets\mafia.dm"
|
||||
#include "code\modules\asset_cache\assets\moods.dm"
|
||||
#include "code\modules\asset_cache\assets\notes.dm"
|
||||
#include "code\modules\asset_cache\assets\orbit.dm"
|
||||
#include "code\modules\asset_cache\assets\paper.dm"
|
||||
#include "code\modules\asset_cache\assets\patches.dm"
|
||||
#include "code\modules\asset_cache\assets\pda.dm"
|
||||
#include "code\modules\asset_cache\assets\permissions.dm"
|
||||
#include "code\modules\asset_cache\assets\pills.dm"
|
||||
#include "code\modules\asset_cache\assets\pipes.dm"
|
||||
#include "code\modules\asset_cache\assets\portraits.dm"
|
||||
#include "code\modules\asset_cache\assets\radar.dm"
|
||||
#include "code\modules\asset_cache\assets\research_designs.dm"
|
||||
#include "code\modules\asset_cache\assets\safe.dm"
|
||||
#include "code\modules\asset_cache\assets\sheetmaterials.dm"
|
||||
#include "code\modules\asset_cache\assets\supplypods.dm"
|
||||
#include "code\modules\asset_cache\assets\tgfont.dm"
|
||||
#include "code\modules\asset_cache\assets\tgui.dm"
|
||||
#include "code\modules\asset_cache\assets\tutorial_advisors.dm"
|
||||
#include "code\modules\asset_cache\assets\uplink.dm"
|
||||
#include "code\modules\asset_cache\assets\vending.dm"
|
||||
#include "code\modules\asset_cache\assets\vv.dm"
|
||||
#include "code\modules\asset_cache\transports\asset_transport.dm"
|
||||
#include "code\modules\asset_cache\transports\webroot_transport.dm"
|
||||
#include "code\modules\atmospherics\environmental\LINDA_fire.dm"
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
import { Component, createRef } from "inferno";
|
||||
import { resolveAsset } from "../assets";
|
||||
import { Box } from "./Box";
|
||||
|
||||
export enum BodyZone {
|
||||
Head = "head",
|
||||
Chest = "chest",
|
||||
LeftArm = "l_arm",
|
||||
RightArm = "r_arm",
|
||||
LeftLeg = "l_leg",
|
||||
RightLeg = "r_leg",
|
||||
Eyes = "eyes",
|
||||
Mouth = "mouth",
|
||||
Groin = "groin",
|
||||
}
|
||||
|
||||
const bodyZonePixelToZone: (x: number, y: number) => (BodyZone | null)
|
||||
= (x, y) => {
|
||||
// TypeScript translation of /atom/movable/screen/zone_sel/proc/get_zone_at
|
||||
if (y < 1) {
|
||||
return null;
|
||||
} else if (y < 10) {
|
||||
if (x > 10 && x < 15) {
|
||||
return BodyZone.RightLeg;
|
||||
} else if (x > 17 && x < 22) {
|
||||
return BodyZone.LeftLeg;
|
||||
}
|
||||
} else if (y < 13) {
|
||||
if (x > 8 && x < 11) {
|
||||
return BodyZone.RightArm;
|
||||
} else if (x > 12 && x < 20) {
|
||||
return BodyZone.Groin;
|
||||
} else if (x > 21 && x < 24) {
|
||||
return BodyZone.LeftArm;
|
||||
}
|
||||
} else if (y < 22) {
|
||||
if (x > 8 && x < 11) {
|
||||
return BodyZone.RightArm;
|
||||
} else if (x > 12 && x < 20) {
|
||||
return BodyZone.Chest;
|
||||
} else if (x > 21 && x < 24) {
|
||||
return BodyZone.LeftArm;
|
||||
}
|
||||
} else if (y < 30 && (x > 12 && x < 20)) {
|
||||
if (y > 23 && y < 24 && (x > 15 && x < 17)) {
|
||||
return BodyZone.Mouth;
|
||||
} else if (y > 25 && y < 27 && (x > 14 && x < 18)) {
|
||||
return BodyZone.Eyes;
|
||||
} else {
|
||||
return BodyZone.Head;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
type BodyZoneSelectorProps = {
|
||||
onClick?: (zone: BodyZone) => void,
|
||||
scale?: number,
|
||||
selectedZone: BodyZone | null,
|
||||
}
|
||||
|
||||
type BodyZoneSelectorState = {
|
||||
hoverZone: BodyZone | null,
|
||||
}
|
||||
|
||||
export class BodyZoneSelector
|
||||
extends Component<BodyZoneSelectorProps, BodyZoneSelectorState>
|
||||
{
|
||||
ref = createRef<HTMLDivElement>();
|
||||
state: BodyZoneSelectorState = {
|
||||
hoverZone: null,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { hoverZone } = this.state;
|
||||
const { scale = 3, selectedZone } = this.props;
|
||||
|
||||
return (
|
||||
<div ref={this.ref} style={{
|
||||
width: `${32 * scale}px`,
|
||||
height: `${32 * scale}px`,
|
||||
position: "relative",
|
||||
}}>
|
||||
<Box
|
||||
as="img"
|
||||
src={resolveAsset("body_zones.base.png")}
|
||||
onClick={() => {
|
||||
const onClick = this.props.onClick;
|
||||
if (onClick && this.state.hoverZone) {
|
||||
onClick(this.state.hoverZone);
|
||||
}
|
||||
}}
|
||||
onMouseMove={(event) => {
|
||||
if (!this.props.onClick) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rect = this.ref.current?.getBoundingClientRect();
|
||||
if (!rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
const x = event.clientX - rect.left;
|
||||
const y = (32 * scale) - (event.clientY - rect.top);
|
||||
|
||||
this.setState({
|
||||
hoverZone: bodyZonePixelToZone(x / scale, y / scale),
|
||||
});
|
||||
}}
|
||||
style={{
|
||||
"-ms-interpolation-mode": "nearest-neighbor",
|
||||
"position": "absolute",
|
||||
"width": `${32 * scale}px`,
|
||||
"height": `${32 * scale}px`,
|
||||
}}
|
||||
/>
|
||||
|
||||
{selectedZone && (
|
||||
<Box
|
||||
as="img"
|
||||
src={resolveAsset(`body_zones.${selectedZone}.png`)}
|
||||
style={{
|
||||
"-ms-interpolation-mode": "nearest-neighbor",
|
||||
"pointer-events": "none",
|
||||
"position": "absolute",
|
||||
"width": `${32 * scale}px`,
|
||||
"height": `${32 * scale}px`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{hoverZone && (hoverZone !== selectedZone) && (
|
||||
<Box
|
||||
as="img"
|
||||
src={resolveAsset(`body_zones.${hoverZone}.png`)}
|
||||
style={{
|
||||
"-ms-interpolation-mode": "nearest-neighbor",
|
||||
"opacity": 0.5,
|
||||
"pointer-events": "none",
|
||||
"position": "absolute",
|
||||
"width": `${32 * scale}px`,
|
||||
"height": `${32 * scale}px`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
import { sortBy } from "common/collections";
|
||||
import { KEY_DOWN, KEY_ENTER, KEY_UP } from "common/keycodes";
|
||||
import { BooleanLike } from "common/react";
|
||||
import { Component } from "inferno";
|
||||
import { useBackend } from "../backend";
|
||||
import { Button, KeyListener, Stack } from "../components";
|
||||
import { BodyZone, BodyZoneSelector } from "../components/BodyZoneSelector";
|
||||
import { Window } from "../layouts";
|
||||
|
||||
type Surgery = {
|
||||
name: string,
|
||||
blocked?: BooleanLike,
|
||||
};
|
||||
|
||||
type SurgeryInitiatorData = {
|
||||
selected_zone: BodyZone,
|
||||
surgeries: Surgery[],
|
||||
target_name: string,
|
||||
};
|
||||
|
||||
const sortSurgeries
|
||||
= sortBy((surgery: Surgery) => surgery.name);
|
||||
|
||||
type SurgeryInitiatorInnerState = {
|
||||
selectedSurgeryIndex: number,
|
||||
};
|
||||
|
||||
class SurgeryInitiatorInner extends Component<
|
||||
SurgeryInitiatorData,
|
||||
SurgeryInitiatorInnerState
|
||||
> {
|
||||
state = {
|
||||
selectedSurgeryIndex: 0,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateSelectedSurgeryIndexState();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: SurgeryInitiatorData) {
|
||||
if (prevProps.selected_zone !== this.props.selected_zone) {
|
||||
this.updateSelectedSurgeryIndexState();
|
||||
}
|
||||
}
|
||||
|
||||
updateSelectedSurgeryIndexState() {
|
||||
this.setState({
|
||||
selectedSurgeryIndex: this.findSelectedSurgeryAfter(-1) || 0,
|
||||
});
|
||||
}
|
||||
|
||||
findSelectedSurgeryAfter(after: number): number | undefined {
|
||||
const foundIndex
|
||||
= this.props.surgeries.findIndex(
|
||||
(surgery, index) => index > after && !surgery.blocked
|
||||
);
|
||||
|
||||
return foundIndex === -1 ? undefined : foundIndex;
|
||||
}
|
||||
|
||||
findSelectedSurgeryBefore(before: number): number | undefined {
|
||||
for (let index = before; index >= 0; index--) {
|
||||
const surgery = this.props.surgeries[index];
|
||||
if (!surgery.blocked) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { act } = useBackend<SurgeryInitiatorData>(this.context);
|
||||
const { selected_zone, surgeries, target_name } = this.props;
|
||||
|
||||
return (
|
||||
<Window
|
||||
width={400}
|
||||
height={350}
|
||||
title={`Surgery on ${target_name}`}
|
||||
>
|
||||
<Window.Content>
|
||||
<Stack fill height="100%">
|
||||
<Stack.Item width="30%">
|
||||
<BodyZoneSelector
|
||||
onClick={(zone) => act("change_zone", { new_zone: zone })}
|
||||
selectedZone={selected_zone}
|
||||
/>
|
||||
</Stack.Item>
|
||||
|
||||
<Stack.Item width="95%">
|
||||
<Stack vertical height="100%">
|
||||
{surgeries.map((surgery, index) => (
|
||||
<Button
|
||||
onClick={() => {
|
||||
act("start_surgery", {
|
||||
surgery_name: surgery.name,
|
||||
});
|
||||
}}
|
||||
disabled={surgery.blocked}
|
||||
selected={index === this.state.selectedSurgeryIndex}
|
||||
tooltip={surgery.blocked ? "Their body is covered!" : undefined}
|
||||
key={surgery.name}
|
||||
fluid
|
||||
>
|
||||
{surgery.name}
|
||||
</Button>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
|
||||
<KeyListener
|
||||
onKeyDown={(event) => {
|
||||
const keyCode = event.code;
|
||||
const surgery = surgeries[this.state.selectedSurgeryIndex];
|
||||
|
||||
switch (keyCode) {
|
||||
case KEY_DOWN:
|
||||
this.setState((state) => {
|
||||
return {
|
||||
selectedSurgeryIndex:
|
||||
this.findSelectedSurgeryAfter(
|
||||
state.selectedSurgeryIndex
|
||||
) || this.findSelectedSurgeryAfter(-1) || 0,
|
||||
};
|
||||
});
|
||||
|
||||
break;
|
||||
case KEY_UP:
|
||||
this.setState((state) => {
|
||||
return {
|
||||
selectedSurgeryIndex:
|
||||
this.findSelectedSurgeryBefore(
|
||||
state.selectedSurgeryIndex - 1
|
||||
)
|
||||
?? this.findSelectedSurgeryBefore(
|
||||
this.props.surgeries.length - 1
|
||||
)
|
||||
?? 0,
|
||||
};
|
||||
});
|
||||
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
if (surgery) {
|
||||
act("start_surgery", {
|
||||
surgery_name: surgery.name,
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const SurgeryInitiator = (props, context) => {
|
||||
const { data } = useBackend<SurgeryInitiatorData>(context);
|
||||
|
||||
return (
|
||||
<SurgeryInitiatorInner
|
||||
selected_zone={data.selected_zone}
|
||||
surgeries={sortSurgeries(data.surgeries)}
|
||||
target_name={data.target_name}
|
||||
/>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user