mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
[MIRROR] Moving robot module and icon selection to tgui (#9492)
Co-authored-by: Heroman3003 <31296024+Heroman3003@users.noreply.github.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
3e9b15570f
commit
7f2914d757
@@ -628,3 +628,8 @@ GLOBAL_LIST_EMPTY(text_tag_cache)
|
||||
return json_decode(data)
|
||||
catch
|
||||
return null
|
||||
|
||||
/// 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, "")
|
||||
|
||||
@@ -118,7 +118,6 @@
|
||||
to speak with your team, and learn what their plan is for today."))
|
||||
|
||||
R.key = C.key
|
||||
// R.Namepick() // Apparnetly making someone a merc lets them pick a name, so this isn't needed.
|
||||
|
||||
spawn(1)
|
||||
mercs.add_antagonist(R.mind, FALSE, TRUE, FALSE, FALSE, FALSE)
|
||||
|
||||
@@ -225,7 +225,6 @@
|
||||
|
||||
feedback_inc("cyborg_birth",1)
|
||||
callHook("borgify", list(O))
|
||||
O.namepick()
|
||||
|
||||
qdel(src)
|
||||
else
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
from the pod is not a crewmember."))
|
||||
R.ckey = M.ckey
|
||||
visible_message(span_warning("As \the [src] opens, the eyes of the robot flicker as it is activated."))
|
||||
R.namepick()
|
||||
log_and_message_admins("successfully opened \a [src] and got a Lost Drone.")
|
||||
..()
|
||||
|
||||
@@ -57,7 +56,6 @@
|
||||
definiton of 'your gravesite' is where your pod is."))
|
||||
R.ckey = M.ckey
|
||||
visible_message(span_warning("As \the [src] opens, the eyes of the robot flicker as it is activated."))
|
||||
R.namepick()
|
||||
..()
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/swarm_drone
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
from the pod is not a crewmember."))
|
||||
R.ckey = M.ckey
|
||||
visible_message(span_warning("As \the [src] opens, the eyes of the robot flicker as it is activated."))
|
||||
R.namepick()
|
||||
log_and_message_admins("successfully opened \a [src] and got a Lost Drone.")
|
||||
used = TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -43,9 +43,16 @@
|
||||
qdel(source)
|
||||
. = ..()
|
||||
|
||||
/datum/eventkit/modify_robot/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/robot_icons)
|
||||
)
|
||||
|
||||
/datum/eventkit/modify_robot/tgui_data(mob/user)
|
||||
. = list()
|
||||
// Target section for general data
|
||||
var/datum/asset/spritesheet/robot_icons/spritesheet = get_asset_datum(/datum/asset/spritesheet/robot_icons)
|
||||
|
||||
if(target)
|
||||
.["target"] = list()
|
||||
.["target"]["name"] = target.name
|
||||
@@ -62,10 +69,8 @@
|
||||
// Target section for options once a module has been selected
|
||||
if(target.module)
|
||||
.["target"]["active"] = target.icon_selected
|
||||
.["target"]["front"] = icon2base64(get_flat_icon(target,dir=SOUTH,no_anim=TRUE))
|
||||
.["target"]["side"] = icon2base64(get_flat_icon(target,dir=WEST,no_anim=TRUE))
|
||||
.["target"]["side_alt"] = icon2base64(get_flat_icon(target,dir=EAST,no_anim=TRUE))
|
||||
.["target"]["back"] = icon2base64(get_flat_icon(target,dir=NORTH,no_anim=TRUE))
|
||||
.["target"]["sprite"] = sanitize_css_class_name("[target.sprite_datum.type]")
|
||||
.["target"]["sprite_size"] = spritesheet.icon_size_id(.["target"]["sprite"] + "S")
|
||||
.["target"]["modules"] = get_target_items(user)
|
||||
var/list/module_options = list()
|
||||
for(var/module in robot_modules)
|
||||
@@ -110,7 +115,7 @@
|
||||
.["access_options"] = access_options
|
||||
// Section for source data for the module we might want to salvage
|
||||
if(source)
|
||||
.["source"] += get_module_source(user)
|
||||
.["source"] += get_module_source(user, spritesheet)
|
||||
var/list/all_robots = list()
|
||||
for(var/mob/living/silicon/robot/R in silicon_mob_list)
|
||||
if(!R.loc)
|
||||
@@ -573,10 +578,11 @@
|
||||
target_items += list(list("name" = item.name, "ref" = "\ref[item]", "icon" = icon2html(item, user, sourceonly=TRUE), "desc" = item.desc))
|
||||
return target_items
|
||||
|
||||
/datum/eventkit/modify_robot/proc/get_module_source(var/mob/user)
|
||||
/datum/eventkit/modify_robot/proc/get_module_source(var/mob/user, var/datum/asset/spritesheet/robot_icons/spritesheet)
|
||||
var/list/source_list = list()
|
||||
source_list["model"] = source.module
|
||||
source_list["front"] = icon2base64(get_flat_icon(source,dir=SOUTH,no_anim=TRUE))
|
||||
source_list["sprite"] = sanitize_css_class_name("[source.sprite_datum.type]")
|
||||
source_list["sprite_size"] = spritesheet.icon_size_id(source_list["sprite"] + "S")
|
||||
var/list/source_items = list()
|
||||
for(var/obj/item in (source.module.modules | source.module.emag))
|
||||
var/exists
|
||||
|
||||
@@ -445,6 +445,45 @@
|
||||
for(var/i = 1 to 4) // CHOMPedit
|
||||
Insert("patch[i].png", 'icons/obj/chemical.dmi', "patch[i]") // CHOMPedit
|
||||
|
||||
// Robot UI sprites
|
||||
/datum/asset/spritesheet/robot_icons
|
||||
name = "robot_icons"
|
||||
|
||||
/datum/asset/spritesheet/robot_icons/create_spritesheets()
|
||||
for(var/datum/robot_sprite/S as anything in typesof(/datum/robot_sprite))
|
||||
if(!S.name || !S.sprite_icon_state) // snowflake out those customs... they suck
|
||||
continue
|
||||
var/icon/I_N = icon(S.sprite_icon, S.sprite_icon_state, NORTH)
|
||||
var/icon/I_S = icon(S.sprite_icon, S.sprite_icon_state, SOUTH)
|
||||
var/icon/I_W = icon(S.sprite_icon, S.sprite_icon_state, WEST)
|
||||
var/icon/I_E = icon(S.sprite_icon, S.sprite_icon_state, EAST)
|
||||
if(S.has_eye_sprites)
|
||||
var/icon/I_NE = icon(S.sprite_icon, "[S.sprite_icon_state]-eyes", NORTH)
|
||||
if(I_NE)
|
||||
I_N.Blend(I_NE, ICON_OVERLAY)
|
||||
if(S.has_eye_sprites)
|
||||
var/icon/I_SE = icon(S.sprite_icon, "[S.sprite_icon_state]-eyes", SOUTH)
|
||||
if(I_SE)
|
||||
I_S.Blend(I_SE, ICON_OVERLAY)
|
||||
if(S.has_eye_sprites)
|
||||
var/icon/I_WE = icon(S.sprite_icon, "[S.sprite_icon_state]-eyes", WEST)
|
||||
if(I_WE)
|
||||
I_W.Blend(I_WE, ICON_OVERLAY)
|
||||
if(S.has_eye_sprites)
|
||||
var/icon/I_EE = icon(S.sprite_icon, "[S.sprite_icon_state]-eyes", EAST)
|
||||
if(I_EE)
|
||||
I_E.Blend(I_EE, ICON_OVERLAY)
|
||||
var/imgid = sanitize_css_class_name("[S.type]")
|
||||
I_N.Scale(120, 120)
|
||||
I_S.Scale(120, 120)
|
||||
I_W.Scale(120, 120)
|
||||
I_E.Scale(120, 120)
|
||||
Insert(imgid + "N", I_N)
|
||||
Insert(imgid + "S", I_S)
|
||||
Insert(imgid + "W", I_W)
|
||||
Insert(imgid + "E", I_E)
|
||||
|
||||
|
||||
//Cloning pod sprites for UIs
|
||||
/datum/asset/simple/cloning
|
||||
assets = list(
|
||||
|
||||
@@ -203,9 +203,6 @@ var/list/mob_hat_cache = list()
|
||||
can_pick_shell = FALSE
|
||||
update_icon()
|
||||
|
||||
/mob/living/silicon/robot/drone/choose_icon()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/drone/pick_module()
|
||||
return
|
||||
|
||||
|
||||
@@ -11,11 +11,6 @@
|
||||
repick_laws()
|
||||
|
||||
// Forces synths to select an icon relevant to their module
|
||||
if(!icon_selected)
|
||||
icon_selection_tries = SSrobot_sprites.get_module_sprites_len(modtype, src) + 1
|
||||
choose_icon(icon_selection_tries)
|
||||
|
||||
if(sprite_datum && module)
|
||||
sprite_datum.do_equipment_glamour(module)
|
||||
pick_module()
|
||||
|
||||
plane_holder.set_vis(VIS_AUGMENTED, TRUE)
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
//Icon stuff
|
||||
|
||||
var/datum/robot_sprite/sprite_datum // Sprite datum, holding all our sprite data
|
||||
var/icon_selected = 1 // If icon selection has been completed yet
|
||||
var/icon_selection_tries = 0 // Remaining attempts to select icon before a selection is forced
|
||||
var/icon_selected = FALSE // If icon selection has been completed yet
|
||||
var/list/sprite_extra_customization = list()
|
||||
var/rest_style = "Default"
|
||||
var/notransform
|
||||
@@ -49,6 +48,9 @@
|
||||
var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not
|
||||
var/obj/screen/robot_modules_background
|
||||
|
||||
var/ui_theme
|
||||
var/selecting_module = FALSE
|
||||
|
||||
//3 Modules can be activated at any one time.
|
||||
var/obj/item/robot_module/module = null
|
||||
var/module_active = null
|
||||
@@ -339,50 +341,17 @@
|
||||
return module_sprites
|
||||
*/
|
||||
/mob/living/silicon/robot/proc/pick_module()
|
||||
if(icon_selected)
|
||||
return
|
||||
if(module)
|
||||
return
|
||||
var/list/modules = list()
|
||||
//VOREStatation Edit Start: shell restrictions //CHOMPstaton change to blacklist
|
||||
if(shell)
|
||||
if(restrict_modules_to.len > 0)
|
||||
modules.Add(restrict_modules_to)
|
||||
else
|
||||
modules.Add(robot_module_types)
|
||||
modules.Remove(GLOB.shell_module_blacklist) // CHOMPEdit - Managed Globals
|
||||
//CHOMPedit Add
|
||||
if(crisis || security_level == SEC_LEVEL_RED || crisis_override)
|
||||
to_chat(src, span_red("Crisis mode active. Combat module available."))
|
||||
modules |= emergency_module_types
|
||||
//CHOMPedit end
|
||||
else
|
||||
if(restrict_modules_to.len > 0)
|
||||
modules.Add(restrict_modules_to)
|
||||
else
|
||||
modules.Add(robot_module_types)
|
||||
if(crisis || security_level == SEC_LEVEL_RED || crisis_override)
|
||||
to_chat(src, span_red("Crisis mode active. Combat module available."))
|
||||
modules |= emergency_module_types
|
||||
for(var/module_name in whitelisted_module_types)
|
||||
if(is_borg_whitelisted(src, module_name))
|
||||
modules |= module_name
|
||||
//VOREStatation Edit End: shell restrictions
|
||||
modtype = tgui_input_list(usr, "Please, select a module!", "Robot module", modules)
|
||||
|
||||
if(module)
|
||||
return
|
||||
if(!(modtype in robot_modules))
|
||||
return
|
||||
|
||||
var/module_type = robot_modules[modtype]
|
||||
transform_with_anim() //VOREStation edit: sprite animation
|
||||
new module_type(src)
|
||||
|
||||
hands.icon_state = get_hud_module_icon()
|
||||
feedback_inc("cyborg_[lowertext(modtype)]",1)
|
||||
updatename()
|
||||
hud_used.update_robot_modules_display()
|
||||
notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name)
|
||||
robotact?.update_static_data_for_all_viewers()
|
||||
var/list/module_sprites = SSrobot_sprites.get_module_sprites(module, src)
|
||||
if(module_sprites.len == 1 || !client)
|
||||
sprite_datum = module_sprites[1]
|
||||
sprite_datum.do_equipment_glamour(module)
|
||||
return
|
||||
if(!selecting_module)
|
||||
var/datum/tgui_module/robot_ui_module/ui = new(src)
|
||||
ui.tgui_interact(src)
|
||||
|
||||
/mob/living/silicon/robot/proc/update_braintype()
|
||||
if(istype(mmi, /obj/item/mmi/digital/posibrain))
|
||||
@@ -448,15 +417,12 @@
|
||||
to_chat(usr, "You can't pick another custom name. [isshell(src) ? "" : "Go ask for a name change."]")
|
||||
return 0
|
||||
|
||||
spawn(0)
|
||||
var/newname
|
||||
newname = sanitizeSafe(tgui_input_text(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change","", MAX_NAME_LEN), MAX_NAME_LEN)
|
||||
if (newname)
|
||||
custom_name = newname
|
||||
sprite_name = newname
|
||||
var/newname = sanitizeSafe(tgui_input_text(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change","", MAX_NAME_LEN), MAX_NAME_LEN)
|
||||
if (newname)
|
||||
custom_name = newname
|
||||
sprite_name = newname
|
||||
|
||||
updatename()
|
||||
update_icon()
|
||||
updatename()
|
||||
|
||||
/mob/living/silicon/robot/verb/extra_customization()
|
||||
set name = "Customize Appearance"
|
||||
@@ -810,6 +776,7 @@
|
||||
notify_ai(ROBOT_NOTIFICATION_MODULE_RESET, module.name)
|
||||
module.Reset(src)
|
||||
qdel(module)
|
||||
icon_selected = FALSE
|
||||
module = null
|
||||
updatename("Default")
|
||||
has_recoloured = FALSE
|
||||
@@ -1126,82 +1093,6 @@
|
||||
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/proc/choose_icon(var/triesleft)
|
||||
var/robot_species = null
|
||||
if(!SSrobot_sprites)
|
||||
to_chat(src, "Robot Sprites have not been initialized yet. How are you choosing a sprite? Harass a coder.")
|
||||
return
|
||||
|
||||
var/list/module_sprites = SSrobot_sprites.get_module_sprites(modtype, src)
|
||||
if(!module_sprites || !module_sprites.len)
|
||||
to_chat(src, "Your module appears to have no sprite options. Harass a coder.")
|
||||
return
|
||||
|
||||
icon_selected = 0
|
||||
icon_selection_tries = triesleft
|
||||
if(module_sprites.len == 1 || !client)
|
||||
if(!(sprite_datum in module_sprites))
|
||||
sprite_datum = module_sprites[1]
|
||||
else
|
||||
var/selection = tgui_input_list(src, "Select an icon! [triesleft ? "You have [triesleft] more chance\s." : "This is your last try."]", "Robot Icon", module_sprites)
|
||||
sprite_datum = selection
|
||||
if(selection)
|
||||
sprite_datum = selection
|
||||
else
|
||||
sprite_datum = module_sprites[1]
|
||||
//CHOMPEdit Start, allow multi bellies
|
||||
vore_icon_bellies = list() //Clear any belly options that may not exist now
|
||||
vore_capacity_ex = list()
|
||||
vore_fullness_ex = list()
|
||||
if(sprite_datum.belly_capacity_list.len)
|
||||
for(var/belly in sprite_datum.belly_capacity_list) //vore icons list only contains a list of names with no associated data
|
||||
vore_capacity_ex[belly] = sprite_datum.belly_capacity_list[belly] //I dont know why but this wasnt working when I just
|
||||
vore_fullness_ex[belly] = 0 //set the lists equal to the old lists
|
||||
vore_icon_bellies += belly
|
||||
for(var/belly in sprite_datum.belly_light_list)
|
||||
vore_light_states[belly] = 0
|
||||
else if(sprite_datum.has_vore_belly_sprites)
|
||||
vore_capacity_ex = list("sleeper" = 1)
|
||||
vore_fullness_ex = list("sleeper" = 0)
|
||||
vore_icon_bellies = list("sleeper")
|
||||
if(sprite_datum.has_sleeper_light_indicator)
|
||||
vore_light_states = list("sleeepr" = 0)
|
||||
sprite_datum.belly_light_list = list("sleeper")
|
||||
update_fullness() //Set how full the newly defined bellies are, if they're already full
|
||||
//CHOMPEdit End
|
||||
if(!istype(src,/mob/living/silicon/robot/drone))
|
||||
robot_species = sprite_datum.name
|
||||
if(notransform)
|
||||
to_chat(src, "Your current transformation has not finished yet!")
|
||||
choose_icon(icon_selection_tries)
|
||||
return
|
||||
else
|
||||
transform_with_anim()
|
||||
|
||||
var/tempheight = vis_height
|
||||
update_icon()
|
||||
// This is bad but I dunno other way to 'reset' our resize offset based on vis_height changes other than resizing to normal and back.
|
||||
if(tempheight != vis_height)
|
||||
var/tempsize = size_multiplier
|
||||
resize(1)
|
||||
resize(tempsize)
|
||||
|
||||
|
||||
if (module_sprites.len > 1 && triesleft >= 1 && client)
|
||||
icon_selection_tries--
|
||||
var/choice = tgui_alert(usr, "Look at your icon - is this what you want?", "Icon Choice", list("Yes","No"))
|
||||
if(choice == "No")
|
||||
choose_icon(icon_selection_tries)
|
||||
return
|
||||
|
||||
|
||||
icon_selected = 1
|
||||
icon_selection_tries = 0
|
||||
sprite_type = robot_species
|
||||
if(hands)
|
||||
update_hud()
|
||||
to_chat(src, span_filter_notice("Your icon has been set. You now require a module reset to change it."))
|
||||
|
||||
/mob/living/silicon/robot/proc/set_default_module_icon()
|
||||
if(!SSrobot_sprites)
|
||||
return
|
||||
|
||||
@@ -74,7 +74,7 @@ var/global/list/robot_modules = list(
|
||||
R.radio.recalculateChannels()
|
||||
|
||||
R.set_default_module_icon()
|
||||
R.choose_icon(SSrobot_sprites.get_module_sprites_len(R.modtype, R) + 1)
|
||||
R.pick_module()
|
||||
if(!R.client)
|
||||
R.icon_selected = FALSE // It wasnt a player selecting icon? Let them do it later!
|
||||
|
||||
@@ -94,7 +94,7 @@ var/global/list/robot_modules = list(
|
||||
|
||||
if(R.radio)
|
||||
R.radio.recalculateChannels()
|
||||
R.choose_icon(0)
|
||||
R.set_default_module_icon()
|
||||
|
||||
R.scrubbing = FALSE
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
var/mob/living/silicon/robot/R = host
|
||||
|
||||
data["module_name"] = R.module ? "[R.module]" : null
|
||||
if(R.emagged)
|
||||
data["theme"] = "syndicate"
|
||||
else if (R.ui_theme)
|
||||
data["theme"] = R.ui_theme
|
||||
|
||||
if(!R.module)
|
||||
return data
|
||||
|
||||
186
code/modules/mob/living/silicon/robot/robot_ui_module.dm
Normal file
186
code/modules/mob/living/silicon/robot/robot_ui_module.dm
Normal file
@@ -0,0 +1,186 @@
|
||||
// Robot module selection
|
||||
/datum/tgui_module/robot_ui_module
|
||||
name = "Robot Module Configurator"
|
||||
tgui_id = "RobotChoose"
|
||||
var/selected_module
|
||||
var/new_name
|
||||
var/datum/robot_sprite/sprite_datum
|
||||
|
||||
/datum/tgui_module/robot_ui_module/tgui_state(mob/user)
|
||||
return GLOB.tgui_self_state
|
||||
|
||||
/datum/tgui_module/robot_ui_module/tgui_close(mob/user)
|
||||
. = ..()
|
||||
if(isrobot(user))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
R.selecting_module = FALSE
|
||||
|
||||
/datum/tgui_module/robot_ui_module/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
|
||||
. = ..()
|
||||
if(isrobot(user) && ui)
|
||||
var/mob/living/silicon/robot/R = user
|
||||
R.selecting_module = TRUE
|
||||
|
||||
/datum/tgui_module/robot_ui_module/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/robot_icons)
|
||||
)
|
||||
|
||||
/datum/tgui_module/robot_ui_module/tgui_static_data()
|
||||
var/list/data = ..()
|
||||
|
||||
var/mob/living/silicon/robot/R = host
|
||||
|
||||
var/list/modules = list()
|
||||
if(R.module)
|
||||
modules = list(R.modtype)
|
||||
selected_module = R.modtype
|
||||
else
|
||||
if(LAZYLEN(R.restrict_modules_to) > 0)
|
||||
modules.Add(R.restrict_modules_to)
|
||||
else if(R.shell)
|
||||
modules.Add(shell_module_types)
|
||||
// CHOMPAdd Start, shell blacklist and crisis mode for shells
|
||||
modules.Remove(GLOB.shell_module_blacklist)
|
||||
if(R.crisis || security_level == SEC_LEVEL_RED || R.crisis_override)
|
||||
to_chat(src, span_red("Crisis mode active. Combat module available."))
|
||||
modules |= emergency_module_types
|
||||
// CHOMPAdd End
|
||||
else
|
||||
modules.Add(robot_module_types)
|
||||
if(R.crisis || security_level == SEC_LEVEL_RED || R.crisis_override)
|
||||
to_chat(R, span_red("Crisis mode active. Combat module available."))
|
||||
modules |= emergency_module_types
|
||||
for(var/module_name in whitelisted_module_types)
|
||||
if(is_borg_whitelisted(R, module_name))
|
||||
modules |= module_name
|
||||
data["possible_modules"] = modules
|
||||
if(R.emagged)
|
||||
data["theme"] = "syndicate"
|
||||
else if (R.ui_theme)
|
||||
data["theme"] = R.ui_theme
|
||||
|
||||
return data
|
||||
|
||||
/datum/tgui_module/robot_ui_module/tgui_data()
|
||||
var/list/data = ..()
|
||||
|
||||
var/mob/living/silicon/robot/R = host
|
||||
var/datum/asset/spritesheet/robot_icons/spritesheet = get_asset_datum(/datum/asset/spritesheet/robot_icons)
|
||||
|
||||
data["currentName"] = new_name ? new_name : R.name
|
||||
data["isDefaultName"] = !new_name
|
||||
|
||||
if(selected_module)
|
||||
data["selected_module"] = selected_module
|
||||
if(!SSrobot_sprites)
|
||||
to_chat(R, span_warning("Robot Sprites have not been initialized yet. How are you choosing a sprite? Harass a coder."))
|
||||
selected_module = null
|
||||
return
|
||||
|
||||
var/list/module_sprites = SSrobot_sprites.get_module_sprites(selected_module, R)
|
||||
if(!module_sprites || !module_sprites.len)
|
||||
to_chat(R, span_warning("Your module appears to have no sprite options. Harass a coder."))
|
||||
selected_module = null
|
||||
return
|
||||
var/list/available_sprites = list()
|
||||
for(var/datum/robot_sprite/S in module_sprites)
|
||||
var/model_type = "def"
|
||||
if(istype(S, /datum/robot_sprite/dogborg))
|
||||
model_type = "wide"
|
||||
if(istype(S, /datum/robot_sprite/dogborg/tall))
|
||||
model_type = "tall"
|
||||
available_sprites += list(list("sprite" = S.name, "belly" = S.has_vore_belly_sprites, "type" = model_type))
|
||||
|
||||
data["possible_sprites"] = available_sprites
|
||||
data["sprite_datum"] = sprite_datum
|
||||
data["sprite_datum_class"] = null
|
||||
data["sprite_datum_size"] = null
|
||||
if(sprite_datum)
|
||||
data["sprite_datum_class"] = sanitize_css_class_name("[sprite_datum.type]")
|
||||
data["sprite_datum_size"] = spritesheet.icon_size_id(data["sprite_datum_class"] + "S") // just get the south icon's size, the rest will be the same
|
||||
|
||||
return data
|
||||
|
||||
/datum/tgui_module/robot_ui_module/tgui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = host
|
||||
|
||||
switch(action)
|
||||
if("pick_module")
|
||||
if(R.module)
|
||||
return
|
||||
var/new_module = params["value"]
|
||||
if(!(new_module in robot_modules))
|
||||
return
|
||||
if(!is_borg_whitelisted(R, new_module))
|
||||
return
|
||||
selected_module = new_module
|
||||
if(sprite_datum)
|
||||
var/new_datum
|
||||
var/list/module_sprites = SSrobot_sprites.get_module_sprites(selected_module, R)
|
||||
for(var/datum/robot_sprite/S in module_sprites)
|
||||
if(S.name == sprite_datum.name)
|
||||
new_datum = S
|
||||
break
|
||||
sprite_datum = new_datum
|
||||
. = TRUE
|
||||
if("pick_icon")
|
||||
var/sprite = params["value"]
|
||||
if(!sprite)
|
||||
return
|
||||
var/list/module_sprites = SSrobot_sprites.get_module_sprites(selected_module, R)
|
||||
for(var/datum/robot_sprite/S in module_sprites)
|
||||
if(S.name == sprite)
|
||||
sprite_datum = S
|
||||
break
|
||||
. = TRUE
|
||||
if("rename")
|
||||
var/name = params["value"]
|
||||
if(name)
|
||||
new_name = sanitizeSafe(name, MAX_NAME_LEN)
|
||||
. = TRUE
|
||||
if("confirm")
|
||||
R.apply_name(new_name)
|
||||
R.apply_module(sprite_datum, selected_module)
|
||||
R.update_multibelly() // CHOMPAdd Multibelly
|
||||
R.transform_module()
|
||||
close_ui()
|
||||
. = TRUE
|
||||
|
||||
/mob/living/silicon/robot/proc/apply_name(var/new_name)
|
||||
if(!custom_name)
|
||||
if (new_name)
|
||||
custom_name = new_name
|
||||
sprite_name = new_name
|
||||
|
||||
/mob/living/silicon/robot/proc/apply_module(var/datum/robot_sprite/new_datum, var/new_module)
|
||||
icon_selected = TRUE
|
||||
var/module_type = robot_modules[new_module]
|
||||
modtype = new_module
|
||||
module = new module_type(src)
|
||||
feedback_inc("cyborg_[lowertext(new_module)]",1)
|
||||
updatename()
|
||||
hud_used.update_robot_modules_display()
|
||||
notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name)
|
||||
robotact?.update_static_data_for_all_viewers()
|
||||
sprite_datum = new_datum
|
||||
if(!istype(src,/mob/living/silicon/robot/drone))
|
||||
sprite_type = sprite_datum.name
|
||||
|
||||
/mob/living/silicon/robot/proc/transform_module()
|
||||
transform_with_anim()
|
||||
var/tempheight = vis_height
|
||||
update_icon()
|
||||
// This is bad but I dunno other way to 'reset' our resize offset based on vis_height changes other than resizing to normal and back.
|
||||
if(tempheight != vis_height)
|
||||
var/tempsize = size_multiplier
|
||||
resize(1)
|
||||
resize(tempsize)
|
||||
if(hands)
|
||||
update_hud()
|
||||
sprite_datum.do_equipment_glamour(module)
|
||||
to_chat(src, span_filter_notice("Your icon has been set. You now require a module reset to change it."))
|
||||
@@ -9,6 +9,7 @@
|
||||
icon_selected = FALSE
|
||||
can_be_antagged = FALSE
|
||||
restrict_modules_to = list("Gravekeeper")
|
||||
ui_theme = "malfunction"
|
||||
|
||||
/mob/living/silicon/robot/gravekeeper/init()
|
||||
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
icon_selected = FALSE
|
||||
restrict_modules_to = list("Lost")
|
||||
var/law_retries = 5
|
||||
ui_theme = "malfunction"
|
||||
|
||||
/mob/living/silicon/robot/lost/init()
|
||||
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
idcard_type = /obj/item/card/id/syndicate
|
||||
icon_selected = FALSE
|
||||
restrict_modules_to = list("Protector", "Mechanist", "Combat Medic")
|
||||
ui_theme = "syndicate"
|
||||
|
||||
/mob/living/silicon/robot/syndicate/init()
|
||||
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
|
||||
|
||||
@@ -194,7 +194,6 @@
|
||||
O.custom_speech_bubble = B.custom_speech_bubble
|
||||
|
||||
callHook("borgify", list(O))
|
||||
O.namepick()
|
||||
|
||||
spawn(0) // Mobs still instantly del themselves, thus we need to spawn or O will never be returned
|
||||
qdel(src)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 72 KiB |
@@ -34,6 +34,26 @@
|
||||
else
|
||||
to_chat(src, span_filter_notice("Insufficient water reserves."))
|
||||
|
||||
/mob/living/silicon/robot/proc/update_multibelly()
|
||||
vore_icon_bellies = list() //Clear any belly options that may not exist now
|
||||
vore_capacity_ex = list()
|
||||
vore_fullness_ex = list()
|
||||
if(sprite_datum.belly_capacity_list.len)
|
||||
for(var/belly in sprite_datum.belly_capacity_list) //vore icons list only contains a list of names with no associated data
|
||||
vore_capacity_ex[belly] = sprite_datum.belly_capacity_list[belly] //I dont know why but this wasnt working when I just
|
||||
vore_fullness_ex[belly] = 0 //set the lists equal to the old lists
|
||||
vore_icon_bellies += belly
|
||||
for(var/belly in sprite_datum.belly_light_list)
|
||||
vore_light_states[belly] = 0
|
||||
else if(sprite_datum.has_vore_belly_sprites)
|
||||
vore_capacity_ex = list("sleeper" = 1)
|
||||
vore_fullness_ex = list("sleeper" = 0)
|
||||
vore_icon_bellies = list("sleeper")
|
||||
if(sprite_datum.has_sleeper_light_indicator)
|
||||
vore_light_states = list("sleeepr" = 0)
|
||||
sprite_datum.belly_light_list = list("sleeper")
|
||||
update_fullness() //Set how full the newly defined bellies are, if they're already full
|
||||
|
||||
/mob/living/silicon/robot/proc/reset_belly_lights(var/b_class)
|
||||
if(sprite_datum.belly_light_list.len && sprite_datum.belly_light_list.Find(b_class))
|
||||
vore_light_states[b_class] = 0
|
||||
|
||||
@@ -2,16 +2,17 @@ import { capitalize } from 'common/string';
|
||||
import { useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
Flex,
|
||||
Icon,
|
||||
Image,
|
||||
Input,
|
||||
Section,
|
||||
Stack,
|
||||
Tabs,
|
||||
} from 'tgui/components';
|
||||
import { classes } from 'tgui-core/react';
|
||||
|
||||
import { NoSpriteWarning } from '../components';
|
||||
import {
|
||||
@@ -163,15 +164,18 @@ export const ModifyRobotComponent = (props: {
|
||||
<Flex.Item width="30%" fill>
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<Image
|
||||
src={'data:image/jpeg;base64, ' + target.side_alt}
|
||||
style={{
|
||||
display: 'block',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
width: '200px',
|
||||
}}
|
||||
/>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box
|
||||
className={classes([
|
||||
target.sprite_size,
|
||||
target.sprite + 'E',
|
||||
])}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Tabs>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
Section,
|
||||
Stack,
|
||||
} from 'tgui/components';
|
||||
import { classes } from 'tgui-core/react';
|
||||
|
||||
import { NoSpriteWarning } from '../components';
|
||||
import { prepareSearch } from '../functions';
|
||||
@@ -47,7 +48,8 @@ export const ModifyRobotModules = (props: {
|
||||
/>
|
||||
{!!source && (
|
||||
<SelectionField
|
||||
previewImage={source.front}
|
||||
previewImage={source.sprite}
|
||||
previewImageSize={source.sprite_size}
|
||||
searchText={searchSourceText}
|
||||
onSearchText={setSearchSourceText}
|
||||
action="add_module"
|
||||
@@ -106,7 +108,8 @@ export const ModifyRobotModules = (props: {
|
||||
</Button.Confirm>
|
||||
<Divider />
|
||||
<SelectionField
|
||||
previewImage={target.front}
|
||||
previewImage={target.sprite}
|
||||
previewImageSize={target.sprite_size}
|
||||
searchText={searchModuleText}
|
||||
onSearchText={setSearchModulText}
|
||||
action="rem_module"
|
||||
@@ -123,6 +126,7 @@ export const ModifyRobotModules = (props: {
|
||||
|
||||
const SelectionField = (props: {
|
||||
previewImage: string | undefined;
|
||||
previewImageSize: string | undefined;
|
||||
searchText: string;
|
||||
onSearchText: Function;
|
||||
action: string;
|
||||
@@ -133,6 +137,7 @@ const SelectionField = (props: {
|
||||
const { act } = useBackend();
|
||||
const {
|
||||
previewImage,
|
||||
previewImageSize,
|
||||
searchText,
|
||||
onSearchText,
|
||||
action,
|
||||
@@ -144,15 +149,13 @@ const SelectionField = (props: {
|
||||
return (
|
||||
<>
|
||||
<Divider />
|
||||
<Image
|
||||
src={'data:image/jpeg;base64, ' + previewImage}
|
||||
style={{
|
||||
display: 'block',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
height: '200px',
|
||||
}}
|
||||
/>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box className={classes([previewImageSize, previewImage + 'S'])} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
<Divider />
|
||||
<Input
|
||||
fluid
|
||||
|
||||
@@ -2,15 +2,16 @@ import { capitalize } from 'common/string';
|
||||
import { useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
Flex,
|
||||
Icon,
|
||||
Image,
|
||||
Input,
|
||||
Section,
|
||||
Stack,
|
||||
} from 'tgui/components';
|
||||
import { classes } from 'tgui-core/react';
|
||||
|
||||
import { NoSpriteWarning } from '../components';
|
||||
import { prepareSearch } from '../functions';
|
||||
@@ -38,15 +39,15 @@ export const ModifyRobotRadio = (props: { target: Target }) => {
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item width="40%">
|
||||
<Image
|
||||
src={'data:image/jpeg;base64, ' + target.back}
|
||||
style={{
|
||||
display: 'block',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
width: '200px',
|
||||
}}
|
||||
/>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box
|
||||
className={classes([target.sprite_size, target.sprite + 'N'])}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
</Flex.Item>
|
||||
<Flex.Item width="30%" fill>
|
||||
<RadioSection
|
||||
|
||||
@@ -2,14 +2,15 @@ import { capitalize } from 'common/string';
|
||||
import { useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
Flex,
|
||||
Image,
|
||||
Input,
|
||||
Section,
|
||||
Stack,
|
||||
} from 'tgui/components';
|
||||
import { classes } from 'tgui-core/react';
|
||||
|
||||
import { NoSpriteWarning } from '../components';
|
||||
import { install2col } from '../constants';
|
||||
@@ -45,15 +46,15 @@ export const ModifyRobotUpgrades = (props: { target: Target }) => {
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item width="40%">
|
||||
<Image
|
||||
src={'data:image/jpeg;base64, ' + target.side}
|
||||
style={{
|
||||
display: 'block',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
width: '200px',
|
||||
}}
|
||||
/>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box
|
||||
className={classes([target.sprite_size, target.sprite + 'W'])}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
</Flex.Item>
|
||||
<Flex.Item width="30%" fill>
|
||||
<UpgradeSection
|
||||
|
||||
@@ -54,10 +54,8 @@ export type Target = {
|
||||
crisis_override: BooleanLike;
|
||||
active_restrictions: string[];
|
||||
possible_restrictions: string[];
|
||||
front: string | undefined;
|
||||
side: string | undefined;
|
||||
side_alt: string | undefined;
|
||||
back: string | undefined;
|
||||
sprite: string | undefined;
|
||||
sprite_size: string | undefined;
|
||||
modules: Module[];
|
||||
whitelisted_upgrades: Upgrade[];
|
||||
blacklisted_upgrades: Upgrade[];
|
||||
@@ -80,7 +78,8 @@ export type Upgrade = {
|
||||
|
||||
export type Source = {
|
||||
model: string;
|
||||
front: string;
|
||||
sprite: string | undefined;
|
||||
sprite_size: string | undefined;
|
||||
modules: Module[];
|
||||
} | null;
|
||||
|
||||
|
||||
88
tgui/packages/tgui/interfaces/RobotChoose/IconSection.tsx
Normal file
88
tgui/packages/tgui/interfaces/RobotChoose/IconSection.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Box, Button, Flex, Input, Section, Stack } from 'tgui-core/components';
|
||||
import { classes } from 'tgui-core/react';
|
||||
|
||||
import { Tooltip } from '../../components';
|
||||
|
||||
export const IconSection = (props: {
|
||||
currentName: string;
|
||||
isDefaultName: boolean;
|
||||
sprite?: string | null;
|
||||
size?: string | null;
|
||||
}) => {
|
||||
const { act } = useBackend();
|
||||
const { currentName, isDefaultName, sprite, size } = props;
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Sprite"
|
||||
fill
|
||||
scrollable
|
||||
width="40%"
|
||||
buttons={
|
||||
<Button disabled={!sprite} onClick={() => act('confirm')}>
|
||||
Confirm
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Stack.Item>
|
||||
<Stack fill>
|
||||
<Stack.Item>
|
||||
<Box>Name: </Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item basis="100%">
|
||||
<Tooltip content="Adjust your name">
|
||||
<Input
|
||||
fluid
|
||||
value={currentName}
|
||||
onChange={(e, value) => act('rename', { value })}
|
||||
maxLength={52}
|
||||
textColor={isDefaultName ? 'red' : undefined}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
{!!sprite && !!size && (
|
||||
<>
|
||||
<Stack.Item>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box className={classes([size, sprite + 'N'])} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box className={classes([size, sprite + 'S'])} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box className={classes([size, sprite + 'W'])} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Flex>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Box className={classes([size, sprite + 'E'])} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow />
|
||||
</Flex>
|
||||
</Stack.Item>
|
||||
</>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
47
tgui/packages/tgui/interfaces/RobotChoose/ModuleSection.tsx
Normal file
47
tgui/packages/tgui/interfaces/RobotChoose/ModuleSection.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { createSearch } from 'common/string';
|
||||
import { useState } from 'react';
|
||||
import { Input, Section, Stack } from 'tgui-core/components';
|
||||
|
||||
import { SelectorElement } from './SelectorElement';
|
||||
|
||||
export const ModuleSection = (props: {
|
||||
title: string;
|
||||
sortable?: string[];
|
||||
selected?: string;
|
||||
}) => {
|
||||
const { title, sortable, selected } = props;
|
||||
|
||||
const [searchText, setSearchText] = useState<string>('');
|
||||
|
||||
const searcher = createSearch(searchText, (element: string) => {
|
||||
return element;
|
||||
});
|
||||
|
||||
const filtered = sortable?.filter(searcher);
|
||||
|
||||
return (
|
||||
<Section title={title} fill scrollable width="30%">
|
||||
<Stack.Item mb={'10px'}>
|
||||
<Input
|
||||
fluid
|
||||
value={searchText}
|
||||
placeholder="Search for modules..."
|
||||
onInput={(e, value: string) => setSearchText(value)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Stack vertical fill>
|
||||
{!!filtered &&
|
||||
filtered.map((filter) => (
|
||||
<SelectorElement
|
||||
key={filter}
|
||||
option={filter}
|
||||
action="pick_module"
|
||||
selected={selected}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Button, Flex, Icon, Stack } from 'tgui-core/components';
|
||||
|
||||
export const SelectorElement = (props: {
|
||||
option: string;
|
||||
action: string;
|
||||
selected?: string | null;
|
||||
belly?: boolean;
|
||||
}) => {
|
||||
const { act } = useBackend();
|
||||
const { option, action, selected, belly } = props;
|
||||
|
||||
return (
|
||||
<Stack.Item>
|
||||
<Button
|
||||
fluid
|
||||
selected={option === selected}
|
||||
onClick={() => act(action, { value: option })}
|
||||
>
|
||||
<Flex>
|
||||
<Flex.Item>{option}</Flex.Item>
|
||||
{!!belly && (
|
||||
<>
|
||||
<Flex.Item grow />
|
||||
<Flex.Item>
|
||||
<Icon name="utensils" />
|
||||
</Flex.Item>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
);
|
||||
};
|
||||
80
tgui/packages/tgui/interfaces/RobotChoose/SpriteSection.tsx
Normal file
80
tgui/packages/tgui/interfaces/RobotChoose/SpriteSection.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, Input, Section, Stack } from 'tgui-core/components';
|
||||
|
||||
import { robotSpriteSearcher } from './functions';
|
||||
import { SelectorElement } from './SelectorElement';
|
||||
import { spriteOption } from './types';
|
||||
|
||||
export const SpriteSection = (props: {
|
||||
title: string;
|
||||
selected?: string | null;
|
||||
sortable?: spriteOption[];
|
||||
}) => {
|
||||
const { title, sortable, selected } = props;
|
||||
|
||||
const [searchText, setSearchText] = useState<string>('');
|
||||
const [includeDefault, setIncludeDefault] = useState<boolean>(false);
|
||||
const [includeWide, setInclideDog] = useState<boolean>(false);
|
||||
const [includeTall, setIncludeTall] = useState<boolean>(false);
|
||||
|
||||
const filtered = robotSpriteSearcher(
|
||||
searchText,
|
||||
includeDefault,
|
||||
includeWide,
|
||||
includeTall,
|
||||
sortable,
|
||||
);
|
||||
return (
|
||||
<Section
|
||||
title={title}
|
||||
fill
|
||||
scrollable
|
||||
width="30%"
|
||||
buttons={
|
||||
<>
|
||||
<Button.Checkbox
|
||||
checked={includeDefault}
|
||||
onClick={() => setIncludeDefault(!includeDefault)}
|
||||
>
|
||||
Def
|
||||
</Button.Checkbox>
|
||||
<Button.Checkbox
|
||||
checked={includeWide}
|
||||
onClick={() => setInclideDog(!includeWide)}
|
||||
>
|
||||
Wide
|
||||
</Button.Checkbox>
|
||||
<Button.Checkbox
|
||||
checked={includeTall}
|
||||
onClick={() => setIncludeTall(!includeTall)}
|
||||
>
|
||||
Tall
|
||||
</Button.Checkbox>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Stack.Item mb={'10px'}>
|
||||
<Input
|
||||
fluid
|
||||
value={searchText}
|
||||
placeholder="Search for sprites..."
|
||||
onInput={(e, value: string) => setSearchText(value)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Stack vertical>
|
||||
{!!filtered &&
|
||||
filtered.map((filter) => (
|
||||
<SelectorElement
|
||||
key={filter.sprite}
|
||||
option={filter.sprite}
|
||||
action="pick_icon"
|
||||
selected={selected}
|
||||
belly={filter.belly}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
47
tgui/packages/tgui/interfaces/RobotChoose/functions.ts
Normal file
47
tgui/packages/tgui/interfaces/RobotChoose/functions.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { filter } from 'common/collections';
|
||||
import { flow } from 'common/fp';
|
||||
import { createSearch } from 'common/string';
|
||||
|
||||
import { spriteOption } from './types';
|
||||
|
||||
export function robotSpriteSearcher(
|
||||
searchText: string,
|
||||
includeDefault: boolean,
|
||||
includeWide: boolean,
|
||||
includeTall: boolean,
|
||||
sprites?: spriteOption[],
|
||||
): spriteOption[] {
|
||||
const testSearch = createSearch(
|
||||
searchText,
|
||||
(sprite: spriteOption) => sprite.sprite,
|
||||
);
|
||||
if (!sprites) {
|
||||
return [];
|
||||
}
|
||||
let subtypes: string[] = [];
|
||||
if (includeDefault) {
|
||||
subtypes.push('def');
|
||||
}
|
||||
if (includeWide) {
|
||||
subtypes.push('wide');
|
||||
}
|
||||
if (includeTall) {
|
||||
subtypes.push('tall');
|
||||
}
|
||||
return flow([
|
||||
(sprites: spriteOption[]) => {
|
||||
if (!searchText) {
|
||||
return sprites;
|
||||
} else {
|
||||
return filter(sprites, testSearch);
|
||||
}
|
||||
},
|
||||
(sprites: spriteOption[]) => {
|
||||
if (!subtypes.length) {
|
||||
return sprites;
|
||||
} else {
|
||||
return filter(sprites, (sprite) => subtypes.includes(sprite.type));
|
||||
}
|
||||
},
|
||||
])(sprites);
|
||||
}
|
||||
49
tgui/packages/tgui/interfaces/RobotChoose/index.tsx
Normal file
49
tgui/packages/tgui/interfaces/RobotChoose/index.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import { Stack } from 'tgui-core/components';
|
||||
|
||||
import { IconSection } from './IconSection';
|
||||
import { ModuleSection } from './ModuleSection';
|
||||
import { SpriteSection } from './SpriteSection';
|
||||
import { Data } from './types';
|
||||
|
||||
export const RobotChoose = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
|
||||
const {
|
||||
possible_modules,
|
||||
possible_sprites,
|
||||
selected_module,
|
||||
sprite_datum,
|
||||
theme,
|
||||
currentName,
|
||||
isDefaultName,
|
||||
sprite_datum_class,
|
||||
sprite_datum_size,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Window width={800} height={600} theme={theme || 'ntos'}>
|
||||
<Window.Content>
|
||||
<Stack fill>
|
||||
<ModuleSection
|
||||
title="Modules"
|
||||
sortable={possible_modules}
|
||||
selected={selected_module}
|
||||
/>
|
||||
<SpriteSection
|
||||
title="Sprites"
|
||||
sortable={possible_sprites}
|
||||
selected={sprite_datum}
|
||||
/>
|
||||
<IconSection
|
||||
currentName={currentName}
|
||||
isDefaultName={isDefaultName}
|
||||
sprite={sprite_datum_class}
|
||||
size={sprite_datum_size}
|
||||
/>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
13
tgui/packages/tgui/interfaces/RobotChoose/types.ts
Normal file
13
tgui/packages/tgui/interfaces/RobotChoose/types.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export type Data = {
|
||||
possible_modules: string[];
|
||||
possible_sprites?: spriteOption[];
|
||||
currentName: string;
|
||||
isDefaultName: boolean;
|
||||
theme?: string;
|
||||
selected_module?: string;
|
||||
sprite_datum?: string | null;
|
||||
sprite_datum_class?: string | null;
|
||||
sprite_datum_size?: string | null;
|
||||
};
|
||||
|
||||
export type spriteOption = { sprite: string; belly: boolean; type: string };
|
||||
@@ -18,7 +18,7 @@ export const Robotact = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Window width={800} height={600} theme="ntos">
|
||||
<Window width={800} height={600} theme={data.theme || 'ntos'}>
|
||||
<Window.Content>{content}</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
|
||||
@@ -31,6 +31,7 @@ export type Data = {
|
||||
max_health: number;
|
||||
|
||||
light_color: string;
|
||||
theme?: string;
|
||||
|
||||
// Modules
|
||||
modules_static: Module[];
|
||||
|
||||
@@ -3362,6 +3362,7 @@
|
||||
#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_remote_control.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_ui.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_ui_module.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\dogborg\dog_modules_vr.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\dogborg\dog_modules_yw.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\dogborg\dog_sleeper_vr.dm"
|
||||
|
||||
Reference in New Issue
Block a user