mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-19 11:05:50 +01:00
Merge remote-tracking branch 'upstream/master' into Mob-TF-smite
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-fix %*
|
||||
@@ -341,6 +341,7 @@
|
||||
#define SPECIES_REPLICANT "Replicant"
|
||||
#define SPECIES_REPLICANT_ALPHA "Alpha Replicant"
|
||||
#define SPECIES_REPLICANT_BETA "Beta Replicant"
|
||||
#define SPECIES_REPLICANT_CREW "Gamma Replicant"
|
||||
|
||||
// Used to seperate simple animals by ""intelligence"".
|
||||
#define SA_PLANT 1
|
||||
|
||||
@@ -574,3 +574,22 @@
|
||||
continue
|
||||
if(!isnull(path))
|
||||
. += path
|
||||
|
||||
/proc/path2text_list(list/L)
|
||||
. = list()
|
||||
for(var/key in L)
|
||||
var/text = "[key]"
|
||||
if(!isnull(L[text]))
|
||||
.[text] = L[text]
|
||||
continue
|
||||
if(!isnull(L[key]))
|
||||
.[text] = L[key]
|
||||
continue
|
||||
if(!isnull(text))
|
||||
.[text] = ""
|
||||
|
||||
/proc/check_list_copy(var/i)
|
||||
if(islist(i))
|
||||
var/list/l = i
|
||||
return l.Copy()
|
||||
return i
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
if(direct)
|
||||
if(ismob(thing))
|
||||
var/mob/M = thing
|
||||
if(M.check_sound_preference(pref_check))
|
||||
if(!M.check_sound_preference(pref_check))
|
||||
continue
|
||||
SEND_SOUND(thing, S)
|
||||
else
|
||||
|
||||
@@ -330,6 +330,13 @@
|
||||
containertype = /obj/structure/closet/crate/einstein
|
||||
contains = list(/obj/item/weapon/circuitboard/fusion_fuel_compressor)
|
||||
|
||||
/datum/supply_pack/eng/deuterium
|
||||
name = "Deuterium crate"
|
||||
cost = 50
|
||||
containername = "Deuterium crate"
|
||||
containertype = /obj/structure/closet/crate/einstein
|
||||
contains = list(/obj/fiftyspawner/deuterium)
|
||||
|
||||
/datum/supply_pack/eng/tritium
|
||||
name = "Tritium crate"
|
||||
cost = 75
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
if(exact)
|
||||
return decls_repository.get_decl(path)
|
||||
else
|
||||
var/list/L = decls_repository.get_decls_of_type(path)
|
||||
var/list/L = decls_repository.get_decls_of_subtype(path) // Use get_decls_of_subtype instead of get_decls_of_type, or it will get the map placing icon_state
|
||||
return L[pick(L)]
|
||||
return null
|
||||
|
||||
|
||||
@@ -72,6 +72,13 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob
|
||||
return
|
||||
M = new_M
|
||||
|
||||
if(isrobot(M))
|
||||
var/mob/living/silicon/robot/R = M
|
||||
var/obj/item/device/dogborg/sleeper/S = locate() in R.module.modules
|
||||
if(S && S.patient)
|
||||
scan_mob(S.patient, user)
|
||||
return
|
||||
|
||||
if(ishuman(M))
|
||||
scan_mob(M, user)
|
||||
else
|
||||
|
||||
@@ -81,6 +81,13 @@
|
||||
health = 0
|
||||
healthcheck()
|
||||
return
|
||||
if(locate(/obj/item/organ/internal/xenos/resinspinner/replicant) in M.internal_organs)
|
||||
if(!do_after(M, 3 SECONDS))
|
||||
return
|
||||
visible_message ("<span class='warning'>[usr] strokes the [name] and it melts away!</span>", 1)
|
||||
health = 0
|
||||
healthcheck()
|
||||
return
|
||||
visible_message("<span class='warning'>[usr] claws at the [name]!</span>")
|
||||
health -= rand(5,10)
|
||||
healthcheck()
|
||||
|
||||
@@ -29,6 +29,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
|
||||
equippable_item_whitelist = typecacheof(list(
|
||||
/obj/item/weapon/storage/bag/trash,
|
||||
/obj/item/weapon/mop,
|
||||
/obj/item/weapon/mop/advanced,
|
||||
/obj/item/weapon/reagent_containers/spray,
|
||||
/obj/item/device/lightreplacer,
|
||||
/obj/item/clothing/suit/caution,
|
||||
@@ -49,7 +50,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
|
||||
mybag = I
|
||||
setTguiIcon("mybag", mybag)
|
||||
|
||||
else if(istype(I, /obj/item/weapon/mop))
|
||||
else if(istype(I, /obj/item/weapon/mop) || istype(I, /obj/item/weapon/mop/advanced))
|
||||
if(mymop)
|
||||
to_chat(user, "<span class='warning'>[src] already has \an [I].</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
return
|
||||
|
||||
var/datum/eventkit/modify_robot/modify_robot = new()
|
||||
modify_robot.target = target
|
||||
modify_robot.target = isrobot(target) ? target : null
|
||||
modify_robot.selected_ai = target.is_slaved()
|
||||
modify_robot.tgui_interact(src.mob)
|
||||
|
||||
/datum/eventkit/modify_robot
|
||||
var/mob/living/silicon/robot/target
|
||||
var/mob/living/silicon/robot/source
|
||||
var/mob/living/silicon/ai/selected_ai
|
||||
var/ion_law = "IonLaw"
|
||||
var/zeroth_law = "ZerothLaw"
|
||||
var/inherent_law = "InherentLaw"
|
||||
@@ -49,6 +51,7 @@
|
||||
.["target"]["name"] = target.name
|
||||
.["target"]["ckey"] = target.ckey
|
||||
.["target"]["module"] = target.module
|
||||
.["target"]["emagged"] = target.emagged
|
||||
.["target"]["crisis_override"] = target.crisis_override
|
||||
.["target"]["active_restrictions"] = target.restrict_modules_to
|
||||
var/list/possible_restrictions = list()
|
||||
@@ -121,6 +124,15 @@
|
||||
package_laws(., "supplied_laws", target.laws.supplied_laws)
|
||||
|
||||
.["isAI"] = isAI(target)
|
||||
.["isMalf"] = is_malf(user)
|
||||
.["isSlaved"] = target.is_slaved()
|
||||
var/list/active_ais = list()
|
||||
for(var/mob/living/silicon/ai/ai in active_ais())
|
||||
if(!ai.loc)
|
||||
continue
|
||||
active_ais += list(list("displayText" = "[ai]", "value" = "\ref[ai]"))
|
||||
.["active_ais"] = active_ais
|
||||
.["selected_ai"] = selected_ai ? selected_ai.name : null
|
||||
|
||||
var/list/channels = list()
|
||||
for(var/ch_name in target.law_channels())
|
||||
@@ -144,14 +156,16 @@
|
||||
target.real_name = params["new_name"]
|
||||
return TRUE
|
||||
if("select_target")
|
||||
target = locate(params["new_target"])
|
||||
log_and_message_admins("changed robot modifictation target to [target]")
|
||||
var/new_target = locate(params["new_target"])
|
||||
if(new_target != target)
|
||||
target = locate(params["new_target"])
|
||||
log_and_message_admins("changed robot modifictation target to [target]")
|
||||
return TRUE
|
||||
if("toggle_crisis")
|
||||
target.crisis_override = !target.crisis_override
|
||||
return TRUE
|
||||
if("add_restriction")
|
||||
target.restrict_modules_to += params["new_restriction"]
|
||||
target.restrict_modules_to |= params["new_restriction"]
|
||||
return TRUE
|
||||
if("remove_restriction")
|
||||
target.restrict_modules_to -= params["rem_restriction"]
|
||||
@@ -498,6 +512,41 @@
|
||||
if(usr != target)
|
||||
to_chat(usr, "<span class='notice'>Laws displayed.</span>")
|
||||
return TRUE
|
||||
if("select_ai")
|
||||
selected_ai = locate(params["new_ai"])
|
||||
return TRUE
|
||||
if("swap_sync")
|
||||
var/new_ai = selected_ai ? selected_ai : select_active_ai_with_fewest_borgs()
|
||||
if(new_ai)
|
||||
target.lawupdate = 1
|
||||
target.connect_to_ai(new_ai)
|
||||
return TRUE
|
||||
if("disconnect_ai")
|
||||
if(target.is_slaved())
|
||||
target.disconnect_from_ai()
|
||||
target.lawupdate = 0
|
||||
return TRUE
|
||||
if("toggle_emag")
|
||||
if(target.emagged)
|
||||
target.emagged = 0
|
||||
target.clear_supplied_laws()
|
||||
target.clear_inherent_laws()
|
||||
target.laws = new global.using_map.default_law_type
|
||||
target.laws.show_laws(target)
|
||||
target.hud_used.update_robot_modules_display()
|
||||
else
|
||||
target.emagged = 1
|
||||
target.lawupdate = 0
|
||||
target.disconnect_from_ai()
|
||||
target.clear_supplied_laws()
|
||||
target.clear_inherent_laws()
|
||||
target.laws = new /datum/ai_laws/syndicate_override
|
||||
if(target.bolt)
|
||||
if(!target.bolt.malfunction)
|
||||
target.bolt.malfunction = MALFUNCTION_PERMANENT
|
||||
target.laws.show_laws(target)
|
||||
target.hud_used.update_robot_modules_display()
|
||||
return TRUE
|
||||
|
||||
/datum/eventkit/modify_robot/proc/get_target_items(var/mob/user)
|
||||
var/list/target_items = list()
|
||||
@@ -650,3 +699,9 @@
|
||||
package_laws(packaged_laws, "supplied_laws", ALs.supplied_laws)
|
||||
law_sets[++law_sets.len] = list("name" = ALs.name, "header" = ALs.law_header, "ref" = "\ref[ALs]","laws" = packaged_laws)
|
||||
return law_sets
|
||||
|
||||
/datum/eventkit/modify_robot/proc/is_malf(var/mob/user)
|
||||
return (is_admin(user) && !target.is_slaved()) || is_special_role(user)
|
||||
|
||||
/datum/eventkit/modify_robot/proc/is_special_role(var/mob/user)
|
||||
return user.mind.special_role ? TRUE : FALSE
|
||||
|
||||
@@ -229,7 +229,7 @@
|
||||
var/selected_radio_channel = tgui_input_list(usr, "Please select the radio channel to add", "Channels", available_channels)
|
||||
if(!selected_radio_channel || selected_radio_channel == "Cancel")
|
||||
break
|
||||
if(selected_radio_channel == CHANNEL_SPECIAL_OPS)
|
||||
if(selected_radio_channel == CHANNEL_SPECIAL_OPS || selected_radio_channel == CHANNEL_RESPONSE_TEAM)
|
||||
target.radio.centComm = 1
|
||||
if(selected_radio_channel == CHANNEL_RAIDER)
|
||||
qdel(target.radio.keyslot)
|
||||
@@ -249,7 +249,7 @@
|
||||
var/selected_radio_channel = tgui_input_list(usr, "Please select the radio channel to remove", "Channels", target.radio.channels)
|
||||
if(!selected_radio_channel || selected_radio_channel == "Cancel")
|
||||
break
|
||||
if(selected_radio_channel == CHANNEL_SPECIAL_OPS)
|
||||
if(selected_radio_channel == CHANNEL_SPECIAL_OPS || selected_radio_channel == CHANNEL_RESPONSE_TEAM && !(target.module.channels[CHANNEL_SPECIAL_OPS] || target.module.channels[CHANNEL_RESPONSE_TEAM]))
|
||||
target.radio.centComm = 0
|
||||
target.module.channels -= selected_radio_channel
|
||||
if((selected_radio_channel == CHANNEL_MERCENARY || selected_radio_channel == CHANNEL_RAIDER) && !(target.module.channels[CHANNEL_RAIDER] || target.module.channels[CHANNEL_MERCENARY]))
|
||||
|
||||
@@ -20,10 +20,11 @@
|
||||
var/msg = "<span class='filter_pray'>" + span_blue("[icon2html(cross, GLOB.admins)] <b>" + span_purple("PRAY: ") + "[key_name(src, 1)] [ADMIN_QUE(src)] [ADMIN_PP(src)] [ADMIN_VV(src)] [ADMIN_SM(src)] ([admin_jump_link(src, src)]) [ADMIN_CA(src)] [ADMIN_SC(src)] [ADMIN_SMITE(src)]:</b> [raw_msg]") + "</span>"
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(R_ADMIN|R_EVENT & C.holder.rights)
|
||||
if(C.prefs?.read_preference(/datum/preference/toggle/show_chat_prayers))
|
||||
to_chat(C, msg, type = MESSAGE_TYPE_PRAYER, confidential = TRUE)
|
||||
C << 'sound/effects/ding.ogg'
|
||||
if(!check_rights(R_ADMIN, 0, C))
|
||||
continue
|
||||
if(C.prefs?.read_preference(/datum/preference/toggle/show_chat_prayers))
|
||||
to_chat(C, msg, type = MESSAGE_TYPE_PRAYER, confidential = TRUE)
|
||||
C << 'sound/effects/ding.ogg'
|
||||
to_chat(usr, "Your prayers have been received by the gods.", confidential = TRUE)
|
||||
|
||||
feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -32,13 +33,15 @@
|
||||
/proc/CentCom_announce(var/msg, var/mob/Sender, var/iamessage)
|
||||
msg = span_blue("<b>" + span_orange("[uppertext(using_map.boss_short)]M[iamessage ? " IA" : ""]:") + "[key_name(Sender, 1)] [ADMIN_PP(Sender)] [ADMIN_VV(Sender)] [ADMIN_SM(Sender)] ([admin_jump_link(Sender)]) [ADMIN_CA(Sender)] [ADMIN_BSA(Sender)] [ADMIN_CENTCOM_REPLY(Sender)]:</b> [msg]")
|
||||
for(var/client/C in GLOB.admins) //VOREStation Edit - GLOB admins
|
||||
if(R_ADMIN|R_EVENT & C.holder.rights)
|
||||
to_chat(C,msg)
|
||||
C << 'sound/machines/signal.ogg'
|
||||
if(!check_rights(R_ADMIN, 0, C))
|
||||
continue
|
||||
to_chat(C,msg)
|
||||
C << 'sound/machines/signal.ogg'
|
||||
|
||||
/proc/Syndicate_announce(var/msg, var/mob/Sender)
|
||||
msg = span_blue("<b>" + span_crimson("ILLEGAL:") + "[key_name(Sender, 1)] [ADMIN_PP(Sender)] [ADMIN_VV(Sender)] [ADMIN_SM(Sender)] ([admin_jump_link(Sender)]) [ADMIN_CA(Sender)] [ADMIN_BSA(Sender)] [ADMIN_SYNDICATE_REPLY(Sender)]:</b> [msg]")
|
||||
for(var/client/C in GLOB.admins) //VOREStation Edit - GLOB admins
|
||||
if(R_ADMIN|R_EVENT & C.holder.rights)
|
||||
to_chat(C,msg)
|
||||
C << 'sound/machines/signal.ogg'
|
||||
if(!check_rights(R_ADMIN, 0, C))
|
||||
continue
|
||||
to_chat(C,msg)
|
||||
C << 'sound/machines/signal.ogg'
|
||||
|
||||
@@ -1763,3 +1763,37 @@
|
||||
//todo; throw the ball in a random direction
|
||||
src.visible_message("\The [ball] bounces off \the [src]'s rim!")
|
||||
global_announcer.autosay("[ball.last_holder] threw the HYPERball and +missed!+ |Oooh!|","Laserdome Announcer","Entertainment")
|
||||
|
||||
/obj/structure/prop/machine/biosyphon/laserdome
|
||||
name = "Laserdome Orientation Holo"
|
||||
desc = {"This device is holoprojecting a wall of flickering text into the air. It seems to be incomprehensible gibberish at first, perhaps an alien language, but the longer you stare the more it starts to make sense, slowly coalescing into coherent sentences in your preferred language. The overall word choice is a little eclectic or unusual at times, and some words remain impossible for you to decipher, but you get the gist pretty quickly. It reads:<br>
|
||||
MANY GREETINGS, BRAVE VISITOR!
|
||||
THE (LIGHT AMPLIFIED BY STIMULATED EMISSION OF RADIATION) DOME IS FINEST PHYSICAL EXERCISE AND RECREATIONAL FACILITY LOCATED UPON THIS RELATIVE SIDE OF THE \[illegible\] SUPERMASSIVE OBSIDIAN VOID.
|
||||
OUR GREAT BRAINS HERE AT THE \[incomprehensible\] HAPPY FUN TIME CORPORATION ARE SURE YOU WILL DEFINITELY MUCH ENJOY PARTAKING IN THE SIGHTS AND SOUNDS OF OUR ESTABLISHMENT.
|
||||
EVEN IF YOU DO NOT WISH TO BE (OR ARE PHYSICALLY INCAPABLE OF) TAKING PART IN THE ACCELERATED LIGHT GAMES, PLEASE WITNESS OUR HEROIC GLADIATORS BATTLE FOR YOUR ENJOYMENT, AND VISIT LOCAL SERVICES SUCH AS THE \[incoherent\] ACCELERATED SUSTENANCE JOINT.
|
||||
PLEASE TO BE FOLLOWINGS FLOOR-BASED POINTED INDICATORS TOWARDS PLACEMENTS OF INTERESTING! AND BE SURE TO BE TAKINGS FREE RADIO HEADSET CHIP TO BE HEARING ARENA ANNOUNCER!
|
||||
THANKINGS YOU FOR YOUR PATRONAGE!!!
|
||||
(p.s. please to be cleanings up after selves, do not leave messes on concourse, thankings you again muchly)"}
|
||||
|
||||
/obj/structure/prop/machine/biosyphon/laserdome/hyperball
|
||||
name = "Laserdome HYPERball Orientation Holo"
|
||||
desc = {"This device is holoprojecting a wall of flickering text into the air. It seems to be incomprehensible gibberish at first, perhaps an alien language, but the longer you stare the more it starts to make sense, slowly coalescing into coherent sentences in your preferred language. The overall word choice is a little eclectic or unusual at times, and some words remain impossible for you to decipher, but you get the gist pretty quickly. It reads:<br>
|
||||
RULES OF HYPERBALL ARE SIMPLE!<br>
|
||||
TAKE BALL, SLAM-DUNKIFY INTO OPPOSING TEAM GOAL!
|
||||
THREE POINTS AWARD FOR THROW (BUT WATCH OUT, CAN MISS)!
|
||||
SEVEN POINTS IF ENDUNKENING IS BY HAND!
|
||||
POINTS AM DEDUCT IF OWN-DUNKING!
|
||||
FIRST TEAM TO TWENTY-AND-ONE POINTS IS WIN!
|
||||
MUST WEAR TEAM PLATINGS FOR SCORINGS TO COUNT!
|
||||
GOOD LUCK!!!"}
|
||||
|
||||
/obj/structure/prop/machine/biosyphon/laserdome/flagcap
|
||||
name = "Laserdome Capture-The-Flag Orientation Holo"
|
||||
desc = {"This device is holoprojecting a wall of flickering text into the air. It seems to be incomprehensible gibberish at first, perhaps an alien language, but the longer you stare the more it starts to make sense, slowly coalescing into coherent sentences in your preferred language. The overall word choice is a little eclectic or unusual at times, and some words remain impossible for you to decipher, but you get the gist pretty quickly. It reads:<br>
|
||||
RULES OF CAPTURING FLAG ARE SIMPLE!
|
||||
GO TO ENEMY BASE, TAKE THEIR FLAG, BRING BACK TO OWN BASE!
|
||||
NO SCORE IF ENEMY TEAM HAS FLAG, SO PROTECT OWN FLAG!
|
||||
RETURN OWN FLAG TO BASE BY TOUCHINGS!
|
||||
FIRST TEAM TO THREE CAPTURES IS WIN!
|
||||
MUST WEAR TEAM PLATINGS FOR SCORINGS TO COUNT!
|
||||
GOOD LUCK!!!"}
|
||||
|
||||
@@ -8,18 +8,19 @@
|
||||
var/static/list/forbidden_prefixes = list(";", ":", ".", "!", "*", "^", "-")
|
||||
|
||||
/datum/category_item/player_setup_item/general/language/load_character(list/save_data)
|
||||
pref.alternate_languages = save_data["language"]
|
||||
pref.alternate_languages = check_list_copy(save_data["language"])
|
||||
pref.extra_languages = save_data["extra_languages"]
|
||||
pref.language_prefixes = save_data["language_prefixes"]
|
||||
pref.species = save_data["species"]
|
||||
pref.preferred_language = save_data["preflang"]
|
||||
pref.language_custom_keys = save_data["language_custom_keys"]
|
||||
pref.language_custom_keys = check_list_copy(save_data["language_custom_keys"])
|
||||
|
||||
/datum/category_item/player_setup_item/general/language/save_character(list/save_data)
|
||||
save_data["language"] = pref.alternate_languages
|
||||
save_data["language"] = check_list_copy(pref.alternate_languages)
|
||||
save_data["extra_languages"] = pref.extra_languages
|
||||
save_data["language_prefixes"] = pref.language_prefixes
|
||||
save_data["language_custom_keys"] = pref.language_custom_keys
|
||||
save_data["preflang"] = pref.preferred_language
|
||||
save_data["preflang"] = check_list_copy(pref.preferred_language)
|
||||
|
||||
/datum/category_item/player_setup_item/general/language/sanitize_character()
|
||||
if(!islist(pref.alternate_languages))
|
||||
|
||||
@@ -113,16 +113,20 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
pref.b_eyes = save_data["eyes_blue"]
|
||||
pref.b_type = save_data["b_type"]
|
||||
pref.disabilities = save_data["disabilities"]
|
||||
pref.organ_data = save_data["organ_data"]
|
||||
pref.rlimb_data = save_data["rlimb_data"]
|
||||
pref.body_markings = save_data["body_markings"]
|
||||
pref.organ_data = check_list_copy(save_data["organ_data"])
|
||||
pref.rlimb_data = check_list_copy(save_data["rlimb_data"])
|
||||
pref.body_markings = check_list_copy(save_data["body_markings"])
|
||||
for(var/i in pref.body_markings)
|
||||
pref.body_markings[i] = check_list_copy(pref.body_markings[i])
|
||||
for(var/j in pref.body_markings[i])
|
||||
pref.body_markings[i][j] = check_list_copy(pref.body_markings[i][j])
|
||||
pref.synth_color = save_data["synth_color"]
|
||||
pref.r_synth = save_data["synth_red"]
|
||||
pref.g_synth = save_data["synth_green"]
|
||||
pref.b_synth = save_data["synth_blue"]
|
||||
pref.synth_markings = save_data["synth_markings"]
|
||||
pref.bgstate = save_data["bgstate"]
|
||||
pref.body_descriptors = save_data["body_descriptors"]
|
||||
pref.body_descriptors = check_list_copy(save_data["body_descriptors"])
|
||||
pref.ear_style = save_data["ear_style"]
|
||||
pref.r_ears = save_data["r_ears"]
|
||||
pref.g_ears = save_data["g_ears"]
|
||||
@@ -178,16 +182,21 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
save_data["eyes_blue"] = pref.b_eyes
|
||||
save_data["b_type"] = pref.b_type
|
||||
save_data["disabilities"] = pref.disabilities
|
||||
save_data["organ_data"] = pref.organ_data
|
||||
save_data["rlimb_data"] = pref.rlimb_data
|
||||
save_data["body_markings"] = pref.body_markings
|
||||
save_data["organ_data"] = check_list_copy(pref.organ_data)
|
||||
save_data["rlimb_data"] = check_list_copy(pref.rlimb_data)
|
||||
var/list/body_markings = check_list_copy(pref.body_markings)
|
||||
for(var/i in pref.body_markings)
|
||||
body_markings[i] = check_list_copy(body_markings[i])
|
||||
for(var/j in body_markings[i])
|
||||
body_markings[i][j] = check_list_copy(body_markings[i][j])
|
||||
save_data["body_markings"] = body_markings
|
||||
save_data["synth_color"] = pref.synth_color
|
||||
save_data["synth_red"] = pref.r_synth
|
||||
save_data["synth_green"] = pref.g_synth
|
||||
save_data["synth_blue"] = pref.b_synth
|
||||
save_data["synth_markings"] = pref.synth_markings
|
||||
save_data["bgstate"] = pref.bgstate
|
||||
save_data["body_descriptors"] = pref.body_descriptors
|
||||
save_data["body_descriptors"] = check_list_copy(pref.body_descriptors)
|
||||
save_data["ear_style"] = pref.ear_style
|
||||
save_data["r_ears"] = pref.r_ears
|
||||
save_data["g_ears"] = pref.g_ears
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
sort_order = 4
|
||||
|
||||
/datum/category_item/player_setup_item/general/equipment/load_character(list/save_data)
|
||||
pref.all_underwear = save_data["all_underwear"]
|
||||
pref.all_underwear_metadata = save_data["all_underwear_metadata"]
|
||||
pref.all_underwear = check_list_copy(save_data["all_underwear"])
|
||||
pref.all_underwear_metadata = check_list_copy(save_data["all_underwear_metadata"])
|
||||
for(var/i in pref.all_underwear_metadata)
|
||||
pref.all_underwear_metadata[i] = path2text_list(pref.all_underwear_metadata[i])
|
||||
pref.backbag = save_data["backbag"]
|
||||
pref.pdachoice = save_data["pdachoice"]
|
||||
pref.communicator_visibility = save_data["communicator_visibility"]
|
||||
@@ -17,7 +19,10 @@
|
||||
|
||||
/datum/category_item/player_setup_item/general/equipment/save_character(list/save_data)
|
||||
save_data["all_underwear"] = pref.all_underwear
|
||||
save_data["all_underwear_metadata"] = pref.all_underwear_metadata
|
||||
var/list/underwear = list()
|
||||
for(var/i in pref.all_underwear_metadata)
|
||||
underwear[i] = check_list_copy(pref.all_underwear_metadata[i])
|
||||
save_data["all_underwear_metadata"] = underwear
|
||||
save_data["backbag"] = pref.backbag
|
||||
save_data["pdachoice"] = pref.pdachoice
|
||||
save_data["communicator_visibility"] = pref.communicator_visibility
|
||||
|
||||
@@ -151,6 +151,11 @@ GLOBAL_DATUM_INIT(gear_tweak_free_matrix_recolor, /datum/gear_tweak/matrix_recol
|
||||
continue
|
||||
else
|
||||
path = contents[metadata[i]]
|
||||
if(!path)
|
||||
var/mob/user = ismob(I.loc) ? I.loc : I.loc?.loc
|
||||
if(istype(user))
|
||||
to_chat(user, span_warning("The content \"[metadata[i]]\" from \"[I]\" does no longer exist and has not been loaded. Please replace it in the character setup."))
|
||||
continue
|
||||
new path(I)
|
||||
|
||||
/*
|
||||
|
||||
@@ -46,17 +46,32 @@ var/list/gear_datums = list()
|
||||
var/current_tab = "General"
|
||||
|
||||
/datum/category_item/player_setup_item/loadout/load_character(list/save_data)
|
||||
pref.gear_list = save_data["gear_list"]
|
||||
pref.gear_list = list()
|
||||
var/all_gear = check_list_copy(save_data["gear_list"])
|
||||
for(var/i in all_gear)
|
||||
var/list/entries = check_list_copy(all_gear["[i]"])
|
||||
for(var/j in entries)
|
||||
entries["[j]"] = path2text_list(entries["[j]"])
|
||||
pref.gear_list["[i]"] = entries
|
||||
pref.gear_slot = save_data["gear_slot"]
|
||||
if(pref.gear_list!=null && pref.gear_slot!=null)
|
||||
pref.gear = pref.gear_list["[pref.gear_slot]"]
|
||||
else
|
||||
pref.gear = save_data["gear"]
|
||||
pref.gear = check_list_copy(save_data["gear"])
|
||||
pref.gear_slot = 1
|
||||
|
||||
/datum/category_item/player_setup_item/loadout/save_character(list/save_data)
|
||||
pref.gear_list["[pref.gear_slot]"] = pref.gear
|
||||
save_data["gear_list"] = pref.gear_list
|
||||
var/list/all_gear = list()
|
||||
var/worn_gear = check_list_copy(pref.gear_list)
|
||||
for(var/i in worn_gear)
|
||||
var/list/entries = check_list_copy(worn_gear["[i]"])
|
||||
if(!length(entries))
|
||||
entries = check_list_copy(worn_gear[i])
|
||||
for(var/j in entries)
|
||||
entries["[j]"] = check_list_copy(entries["[j]"])
|
||||
all_gear["[i]"] = entries
|
||||
save_data["gear_list"] = all_gear
|
||||
save_data["gear_slot"] = pref.gear_slot
|
||||
|
||||
/datum/category_item/player_setup_item/loadout/proc/valid_gear_choices(var/max_cost)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
pref.job_talon_med = save_data["job_talon_med"]
|
||||
pref.job_talon_high = save_data["job_talon_high"]
|
||||
//VOREStation Add End
|
||||
pref.player_alt_titles = save_data["player_alt_titles"]
|
||||
pref.player_alt_titles = check_list_copy(save_data["player_alt_titles"])
|
||||
|
||||
/datum/category_item/player_setup_item/occupation/save_character(list/save_data)
|
||||
save_data["alternate_option"] = pref.alternate_option
|
||||
@@ -36,7 +36,7 @@
|
||||
save_data["job_talon_med"] = pref.job_talon_med
|
||||
save_data["job_talon_high"] = pref.job_talon_high
|
||||
//VOREStation Add End
|
||||
save_data["player_alt_titles"] = pref.player_alt_titles
|
||||
save_data["player_alt_titles"] = check_list_copy(pref.player_alt_titles)
|
||||
|
||||
/datum/category_item/player_setup_item/occupation/sanitize_character()
|
||||
pref.alternate_option = sanitize_integer(pref.alternate_option, 0, 2, initial(pref.alternate_option))
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
sort_order = 1
|
||||
|
||||
/datum/category_item/player_setup_item/skills/load_character(list/save_data)
|
||||
pref.skills = save_data["skills"]
|
||||
pref.skills = check_list_copy(save_data["skills"])
|
||||
pref.used_skillpoints = save_data["used_skillpoints"]
|
||||
pref.skill_specialization = save_data["skill_specialization"]
|
||||
|
||||
/datum/category_item/player_setup_item/skills/save_character(list/save_data)
|
||||
save_data["skills"] = pref.skills
|
||||
save_data["skills"] = check_list_copy(pref.skills)
|
||||
save_data["used_skillpoints"] = pref.used_skillpoints
|
||||
save_data["skill_specialization"] = pref.skill_specialization
|
||||
|
||||
|
||||
@@ -125,15 +125,15 @@ var/global/list/valid_bloodreagents = list("default","iron","copper","phoron","s
|
||||
pref.custom_ask = save_data["custom_ask"]
|
||||
pref.custom_exclaim = save_data["custom_exclaim"]
|
||||
|
||||
pref.custom_heat = save_data["custom_heat"]
|
||||
pref.custom_cold = save_data["custom_cold"]
|
||||
pref.custom_heat = check_list_copy(save_data["custom_heat"])
|
||||
pref.custom_cold = check_list_copy(save_data["custom_cold"])
|
||||
|
||||
/datum/category_item/player_setup_item/vore/traits/save_character(list/save_data)
|
||||
save_data["custom_species"] = pref.custom_species
|
||||
save_data["custom_base"] = pref.custom_base
|
||||
save_data["pos_traits"] = pref.pos_traits
|
||||
save_data["neu_traits"] = pref.neu_traits
|
||||
save_data["neg_traits"] = pref.neg_traits
|
||||
save_data["pos_traits"] = check_list_copy(pref.pos_traits)
|
||||
save_data["neu_traits"] = check_list_copy(pref.neu_traits)
|
||||
save_data["neg_traits"] = check_list_copy(pref.neg_traits)
|
||||
save_data["blood_color"] = pref.blood_color
|
||||
save_data["blood_reagents"] = pref.blood_reagents
|
||||
|
||||
@@ -146,8 +146,8 @@ var/global/list/valid_bloodreagents = list("default","iron","copper","phoron","s
|
||||
save_data["custom_ask"] = pref.custom_ask
|
||||
save_data["custom_exclaim"] = pref.custom_exclaim
|
||||
|
||||
save_data["custom_heat"] = pref.custom_heat
|
||||
save_data["custom_cold"] = pref.custom_cold
|
||||
save_data["custom_heat"] = check_list_copy(pref.custom_heat)
|
||||
save_data["custom_cold"] = check_list_copy(pref.custom_cold)
|
||||
|
||||
/datum/category_item/player_setup_item/vore/traits/sanitize_character()
|
||||
if(!pref.pos_traits) pref.pos_traits = list()
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
pref.nif_path = save_data_file["nif_path"]
|
||||
pref.nif_durability = save_data_file["nif_durability"]
|
||||
pref.nif_savedata = save_data_file["nif_savedata"]
|
||||
pref.nif_savedata = check_list_copy(save_data_file["nif_savedata"])
|
||||
|
||||
/datum/category_item/player_setup_item/vore/nif/save_character()
|
||||
var/datum/json_savefile/savefile = new /datum/json_savefile(nif_savefile_path(pref.client_ckey))
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
save_data_file["nif_path"] = pref.nif_path
|
||||
save_data_file["nif_durability"] = pref.nif_durability
|
||||
save_data_file["nif_savedata"] = pref.nif_savedata
|
||||
save_data_file["nif_savedata"] = check_list_copy(pref.nif_savedata)
|
||||
|
||||
savefile.set_entry("character[pref.default_slot]", save_data_file)
|
||||
savefile.save()
|
||||
|
||||
@@ -19,17 +19,27 @@
|
||||
var/mob/living/carbon/M = user
|
||||
if(istype(M) && locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
|
||||
return TRUE
|
||||
if(istype(M) && locate(/obj/item/organ/internal/xenos/resinspinner/replicant) in M.internal_organs)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/material/resin/wall_touch_special(var/turf/simulated/wall/W, var/mob/living/L)
|
||||
var/mob/living/carbon/M = L
|
||||
if(istype(M) && locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
|
||||
to_chat(M, "<span class='alien'>\The [W] shudders under your touch, starting to become porous.</span>")
|
||||
to_chat(M, "\The [W] shudders under your touch, starting to become porous.")
|
||||
playsound(W, 'sound/effects/attackblob.ogg', 50, 1)
|
||||
if(do_after(L, 5 SECONDS))
|
||||
spawn(2)
|
||||
playsound(W, 'sound/effects/attackblob.ogg', 100, 1)
|
||||
W.dismantle_wall()
|
||||
if(!do_after(L, 5 SECONDS))
|
||||
return FALSE
|
||||
playsound(W, 'sound/effects/attackblob.ogg', 100, 1)
|
||||
W.dismantle_wall()
|
||||
return TRUE
|
||||
if(istype(M) && locate(/obj/item/organ/internal/xenos/resinspinner/replicant) in M.internal_organs)
|
||||
to_chat(M, "\The [W] shudders under your touch, starting to become porous.")
|
||||
playsound(W, 'sound/effects/attackblob.ogg', 50, 1)
|
||||
if(!do_after(L, 5 SECONDS))
|
||||
return FALSE
|
||||
playsound(W, 'sound/effects/attackblob.ogg', 100, 1)
|
||||
W.dismantle_wall()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/datum/species/shapeshifter/replicant/crew
|
||||
name = SPECIES_REPLICANT_CREW
|
||||
blurb = "Replicants are one of the few remaining living examples of precursor technology. \
|
||||
While their origins remain unknown, they are a facsimile of organic life held together by amalgamate, \
|
||||
rubbery flesh and anomalous organs. Whilst their original purpose is speculated to be used through cortical \
|
||||
mirrors as a way to 'wirelessly exist' in a different body via VR pods, this specific variant has had its \
|
||||
forking capabilities severed in exchange for a more stable, self-sufficient (albeit weaker) form."
|
||||
|
||||
min_age = 18
|
||||
max_age = 200
|
||||
blood_color = "#C0C0C0"
|
||||
|
||||
radiation_mod = 1.2 //Affected more by radiation
|
||||
siemens_coefficient = 1.5 //Don't get electrocuted
|
||||
|
||||
secondary_langs = list() // None by default
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart/replicant/rage/crew,
|
||||
O_LUNGS = /obj/item/organ/internal/lungs/replicant/mending/crew,
|
||||
O_VOICE = /obj/item/organ/internal/voicebox/replicant,
|
||||
O_LIVER = /obj/item/organ/internal/liver/replicant,
|
||||
O_KIDNEYS = /obj/item/organ/internal/kidneys/replicant,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/replicant/torso,
|
||||
O_EYES = /obj/item/organ/internal/eyes/replicant,
|
||||
O_AREJECT = /obj/item/organ/internal/immunehub/replicant,
|
||||
O_VENTC = /obj/item/organ/internal/metamorphgland/replicant,
|
||||
O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/replicant/crew,
|
||||
O_RESIN = /obj/item/organ/internal/xenos/resinspinner/replicant,
|
||||
O_STOMACH = /obj/item/organ/internal/stomach,
|
||||
O_INTESTINE = /obj/item/organ/internal/intestine
|
||||
)
|
||||
|
||||
appearance_flags = HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_HAIR_COLOR | HAS_UNDERWEAR | HAS_LIPS
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE
|
||||
color_mult = 1
|
||||
valid_transform_species = list(SPECIES_HUMAN, SPECIES_HUMAN_VATBORN, SPECIES_UNATHI, SPECIES_TAJ, SPECIES_SKRELL, SPECIES_ALTEVIAN, SPECIES_TESHARI, SPECIES_MONKEY, SPECIES_LLEILL, SPECIES_VULPKANIN, SPECIES_ZORREN_HIGH, SPECIES_RAPALA, SPECIES_NEVREAN, SPECIES_VASILISSAN, SPECIES_AKULA)
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_shape,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_colour,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_hair,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_hair_colors,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_gender,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_eye_colour,
|
||||
/mob/living/proc/set_size
|
||||
)
|
||||
@@ -354,14 +354,14 @@ I think I covered everything.
|
||||
body = pick(body_styles)
|
||||
overlay_colors["Body"] = pick(bodycolors)
|
||||
ears = pick(ear_styles)
|
||||
overlay_colors["Ears"] = "#[get_random_colour(0, 100, 150)]"
|
||||
overlay_colors["Ears"] = get_random_colour(0, 100, 150)
|
||||
mane = pick(mane_styles)
|
||||
overlay_colors["Mane"] = pick(bodycolors)
|
||||
horns = pick(horn_styles)
|
||||
var/list/horncolors = list("#000000","#151515","#303030","#606060","#808080","#AAAAAA","#CCCCCC","#EEEEEE","#FFFFFF")
|
||||
overlay_colors["Horns"] = pick(horncolors)
|
||||
eyes = pick(eye_styles)
|
||||
overlay_colors["Eyes"] = "#[get_random_colour(1)]"
|
||||
overlay_colors["Eyes"] = get_random_colour(1)
|
||||
|
||||
var/image/I = image(icon, "dragon_under[under][resting? "-rest" : (vore_fullness? "-[vore_fullness]" : null)]", pixel_x = -48)
|
||||
I.color = overlay_colors["Underbelly"]
|
||||
|
||||
@@ -398,7 +398,11 @@ var/list/organ_cache = list()
|
||||
rejecting = null
|
||||
|
||||
if(istype(owner))
|
||||
var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list
|
||||
// VOREstation edit begin - Posibrains don't have blood reagents, so they crash this
|
||||
var/datum/reagent/blood/organ_blood = null
|
||||
if(reagents)
|
||||
organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list
|
||||
// VOREstation edit end
|
||||
if(!organ_blood || !organ_blood.data["blood_DNA"])
|
||||
owner.vessel.trans_to(src, 5, 1, 1)
|
||||
|
||||
@@ -418,7 +422,11 @@ var/list/organ_cache = list()
|
||||
|
||||
if(!istype(target)) return
|
||||
|
||||
var/datum/reagent/blood/transplant_blood = locate(/datum/reagent/blood) in reagents.reagent_list
|
||||
// VOREstation edit begin - Posibrains don't have blood reagents, so they crash this
|
||||
var/datum/reagent/blood/transplant_blood = null
|
||||
if(reagents)
|
||||
transplant_blood = locate(/datum/reagent/blood) in reagents.reagent_list
|
||||
// VOREstation edit end
|
||||
transplant_data = list()
|
||||
if(!transplant_blood)
|
||||
transplant_data["species"] = target?.species.name
|
||||
|
||||
@@ -53,6 +53,20 @@
|
||||
can_reject = FALSE
|
||||
icon_state = "plasma_grey"
|
||||
|
||||
/obj/item/organ/internal/xenos/plasmavessel/replicant/crew/handle_organ_proc_special()
|
||||
if(!istype(owner))
|
||||
return
|
||||
|
||||
var/modifier = 1 - 0.5 * is_bruised()
|
||||
|
||||
if(owner.bloodstr.has_reagent("phoron"))
|
||||
adjust_plasma(round(4 * modifier))
|
||||
|
||||
if(owner.ingested.has_reagent("phoron"))
|
||||
adjust_plasma(round(2 * modifier))
|
||||
|
||||
adjust_plasma(2) //Make it a decent amount so people can actually build stuff without stealing all of medbays phoron
|
||||
|
||||
/obj/item/organ/internal/xenos/acidgland/replicant
|
||||
name = "replicant aerosol tubule"
|
||||
desc = "A long, rubbery tube that ends in a hard plastic-like bulb."
|
||||
@@ -152,6 +166,22 @@
|
||||
owner.add_modifier(/datum/modifier/berserk, 20 SECONDS)
|
||||
take_damage(5)
|
||||
|
||||
/obj/item/organ/internal/heart/replicant/rage/crew/handle_organ_proc_special()
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
var/damage_tally = 0
|
||||
var/pain_tally = 0
|
||||
damage_tally += owner.getBruteLoss()
|
||||
damage_tally += owner.getFireLoss()
|
||||
pain_tally += owner.getHalLoss()
|
||||
|
||||
if(((damage_tally >= 50 || prev_damage_tally >= 50) && prev_damage_tally - damage_tally < 0) || pain_tally >= 60)
|
||||
if(world.time > last_activation_time + 60 MINUTES) //Can only be activated once every 60 minutes to prevent it being able to be spammed
|
||||
last_activation_time = world.time
|
||||
owner.add_modifier(/datum/modifier/berserk, 40 SECONDS) //Lasts a little longer so that it can actually get some use seeing as it activates so infrequently
|
||||
take_damage(5)
|
||||
|
||||
/obj/item/organ/internal/lungs/replicant/mending
|
||||
name = "replicant hive lungs"
|
||||
desc = "A pair of rubbery sacs with large portions dedicated to honeycombed nanite filters."
|
||||
@@ -169,3 +199,15 @@
|
||||
var/obj/item/organ/O = owner.internal_organs_by_name[o_tag]
|
||||
if(O)
|
||||
O.take_damage(-1 * modifier)
|
||||
|
||||
/obj/item/organ/internal/lungs/replicant/mending/crew/handle_organ_proc_special()
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
var/modifier = 1 - (0.5 * is_bruised())
|
||||
|
||||
if(istype(owner))
|
||||
for(var/o_tag in repair_list)
|
||||
var/obj/item/organ/O = owner.internal_organs_by_name[o_tag]
|
||||
if(O)
|
||||
O.take_damage(-0.01 * modifier) //Very very slow regen, but still cool flavour
|
||||
|
||||
@@ -113,6 +113,8 @@
|
||||
for(var/atom/movable/A in affecting)
|
||||
if(istype(A,/obj/effect/abstract)) // Flashlight's lights are not physical objects
|
||||
continue
|
||||
if(istype(A,/obj/effect/decal/jan_hud)) // Ignore these too
|
||||
continue
|
||||
if(!A.anchored)
|
||||
if(A.loc == src.loc) // prevents the object from being affected if it's not currently here.
|
||||
step(A,movedir)
|
||||
|
||||
@@ -485,7 +485,17 @@
|
||||
"<span class='notice'>You have installed \the [tool] into [target]'s [affected.name].</span>")
|
||||
|
||||
var/obj/item/device/mmi/M = tool
|
||||
var/obj/item/organ/internal/mmi_holder/holder = new(target, 1)
|
||||
// VOREstation edit begin - Select the proper mmi holder subtype based on the brain inserted
|
||||
var/obj/item/organ/internal/mmi_holder/holder = null
|
||||
if(istype(M,/obj/item/device/mmi/digital/posibrain/nano))
|
||||
holder = new /obj/item/organ/internal/mmi_holder/posibrain/nano(target, 1)
|
||||
else if(istype(M,/obj/item/device/mmi/digital/posibrain))
|
||||
holder = new /obj/item/organ/internal/mmi_holder/posibrain(target, 1)
|
||||
else if(istype(M,/obj/item/device/mmi/digital/robot))
|
||||
holder = new /obj/item/organ/internal/mmi_holder/robot(target, 1)
|
||||
else
|
||||
holder = new /obj/item/organ/internal/mmi_holder(target, 1) // Fallback to old behavior if organic MMI or if no subtype exists.
|
||||
//VOREstation edit end
|
||||
target.internal_organs_by_name["brain"] = holder
|
||||
user.drop_from_inventory(tool)
|
||||
tool.loc = holder
|
||||
|
||||
@@ -192,7 +192,14 @@
|
||||
if(isnull(selected_surgery)) //They clicked 'cancel'
|
||||
return 1
|
||||
selected_surgery = available_surgeries[selected_surgery] //Sets the name they selected to be the datum.
|
||||
|
||||
// VOREstation edit start
|
||||
if(istype(selected_surgery,/datum/surgery_step/generic/amputate))
|
||||
var/obj/item/organ/external/affected = M.get_organ(zone)
|
||||
to_chat(user, "<span class='danger'>You are preparing to amputate \the [M]'s [affected.name]!</span>")
|
||||
if(!do_after(user, 3 SECONDS, M))
|
||||
to_chat(user, "<span class='warning'>You reconsider performing an amputation...</span>")
|
||||
return 0
|
||||
// VOREstation edit end
|
||||
M.op_stage.in_progress += zone
|
||||
selected_surgery.begin_step(user, M, zone, src) //start on it
|
||||
var/success = TRUE
|
||||
|
||||
@@ -90,6 +90,13 @@ var/list/ventcrawl_machinery = list(
|
||||
/mob/living/carbon/human/is_allowed_vent_crawl_item(var/obj/item/carried_item)
|
||||
if(carried_item in organs)
|
||||
return 1
|
||||
if(species.name == SPECIES_REPLICANT_CREW)
|
||||
if(istype(carried_item, /obj/item/clothing/under))
|
||||
return 1 //Allow them to not vent crawl naked
|
||||
if(istype(carried_item, /obj/item))
|
||||
var/obj/item/I = carried_item
|
||||
if(I.w_class <= 2)
|
||||
return 1 //Allow them to carry items that fit in pockets
|
||||
return ..()
|
||||
|
||||
/mob/living/proc/ventcrawl_carry()
|
||||
|
||||
@@ -117,6 +117,16 @@
|
||||
set category = "Abilities"
|
||||
|
||||
var/nuffin = TRUE
|
||||
|
||||
var/obj/belly/amprey = src.loc
|
||||
|
||||
if(istype(amprey))
|
||||
var/datum/digest_mode/selective/DM_S = GLOB.digest_modes[DM_SELECT]
|
||||
var/digest_mode = amprey.digest_mode == DM_SELECT ? DM_S.get_selective_mode(amprey, src) : amprey.digest_mode
|
||||
to_chat(src, "<span class='notice'>[digest_mode] - You are in [amprey.owner]'s [amprey.name]:</span>")
|
||||
src.chat_healthbar(src, TRUE, TRUE)
|
||||
nuffin = FALSE
|
||||
|
||||
for(var/obj/belly/b in vore_organs)
|
||||
if(!b.contents.len)
|
||||
continue
|
||||
@@ -127,10 +137,10 @@
|
||||
if(!belly_announce)
|
||||
var/datum/digest_mode/selective/DM_S = GLOB.digest_modes[DM_SELECT]
|
||||
var/digest_mode = b.digest_mode == DM_SELECT ? DM_S.get_selective_mode(b, thing) : b.digest_mode
|
||||
to_chat(src, "<span class='notice'>[digest_mode] - Within [b.name]:</span>") //We only want to announce the belly if we found something
|
||||
to_chat(src, "<span class='notice'>[digest_mode] - Within your [b.name]:</span>") //We only want to announce the belly if we found something
|
||||
belly_announce = TRUE
|
||||
var/mob/living/ourmob = thing
|
||||
ourmob.chat_healthbar(src, TRUE, TRUE)
|
||||
nuffin = FALSE
|
||||
if(nuffin)
|
||||
to_chat(src, "<span class='warning'>There are no mobs within any of your bellies to print health bars for.</span>")
|
||||
to_chat(src, "<span class='warning'>There are no mobs within any of your bellies to print health bars for, and you are not in a belly yourself.</span>")
|
||||
|
||||
@@ -737,10 +737,10 @@
|
||||
user.update_icon()
|
||||
|
||||
var/mob/living/carbon/victim = prey // Check for afk vore
|
||||
if(istype(victim) && !victim.client && !victim.ai_holder)
|
||||
if(istype(victim) && !victim.client && !victim.ai_holder && victim.ckey)
|
||||
log_and_message_admins("[key_name_admin(pred)] ate [key_name_admin(prey)] whilst the prey was AFK ([pred ? ADMIN_JMP(pred) : "null"])")
|
||||
var/mob/living/carbon/victim_pred = pred // Check for afk vore
|
||||
if(istype(victim_pred) && !victim_pred.client && !victim_pred.ai_holder)
|
||||
if(istype(victim_pred) && !victim_pred.client && !victim_pred.ai_holder && victim_pred.ckey)
|
||||
log_and_message_admins("[key_name_admin(pred)] ate [key_name_admin(prey)] whilst the pred was AFK ([pred ? ADMIN_JMP(pred) : "null"])")
|
||||
|
||||
// Inform Admins
|
||||
|
||||
@@ -127,6 +127,7 @@ ontejbjoav - Black-Eyed Shadekin
|
||||
ontejbjoav - Diona
|
||||
oreganovulgaris - Xenochimera
|
||||
oscarholmes - Protean
|
||||
oscarholmes - Gamma Replicant
|
||||
owwy - Black-Eyed Shadekin
|
||||
oxenfree - Protean
|
||||
ozyton - Black-Eyed Shadekin
|
||||
|
||||
+817
-380
File diff suppressed because it is too large
Load Diff
@@ -91,8 +91,20 @@ export const Button = (props: Props) => {
|
||||
|
||||
const toDisplay: ReactNode = content || children;
|
||||
|
||||
const ref = useRef(null);
|
||||
|
||||
function handleButtonClick(event) {
|
||||
if (!disabled && onClick) {
|
||||
onClick(event);
|
||||
if (ref?.current) {
|
||||
(ref.current as HTMLElement).blur();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let buttonContent = (
|
||||
<div
|
||||
ref={ref}
|
||||
className={classes([
|
||||
'Button',
|
||||
fluid && 'Button--fluid',
|
||||
@@ -114,9 +126,7 @@ export const Button = (props: Props) => {
|
||||
])}
|
||||
tabIndex={!disabled ? 0 : undefined}
|
||||
onClick={(event) => {
|
||||
if (!disabled && onClick) {
|
||||
onClick(event);
|
||||
}
|
||||
handleButtonClick(event);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (!captureKeys) {
|
||||
|
||||
@@ -29,7 +29,7 @@ export const ModifyRobotAccess = (props: {
|
||||
return (
|
||||
<>
|
||||
{!target.active && <NoSpriteWarning name={target.name} />}
|
||||
<Flex height={!target.active ? '80%' : '85%'}>
|
||||
<Flex height={!target.active ? '75%' : '80%'}>
|
||||
<Flex.Item width="30%" fill>
|
||||
<AccessSection
|
||||
title="Add Access"
|
||||
|
||||
@@ -38,7 +38,7 @@ export const ModifyRobotComponent = (props: {
|
||||
return (
|
||||
<>
|
||||
{!target.active && <NoSpriteWarning name={target.name} />}
|
||||
<Flex height={!target.active ? '80%' : '85%'}>
|
||||
<Flex height={!target.active ? '75%' : '80%'}>
|
||||
<Flex.Item width="35%" fill>
|
||||
<ComponentSection
|
||||
title="Repair Component"
|
||||
|
||||
@@ -31,7 +31,7 @@ export const ModifyRobotModules = (props: {
|
||||
return (
|
||||
<>
|
||||
{!target.active && <NoSpriteWarning name={target.name} />}
|
||||
<Flex height={!target.active ? '80%' : '85%'}>
|
||||
<Flex height={!target.active ? '75%' : '80%'}>
|
||||
<Flex.Item width="40%" fill>
|
||||
<Section title="Source Module" scrollable fill>
|
||||
<Box>Robot to salvage</Box>
|
||||
|
||||
@@ -27,7 +27,7 @@ export const ModifyRobotPKA = (props: { target: Target }) => {
|
||||
{!target.pka ? (
|
||||
<NoticeBox danger>{target.name} has no PKA installed.</NoticeBox>
|
||||
) : (
|
||||
<Flex height={!target.active ? '80%' : '85%'}>
|
||||
<Flex height={!target.active ? '75%' : '80%'}>
|
||||
<Flex.Item width="35%" fill>
|
||||
<Divider />
|
||||
<Box>Remaining Capacity: {target.pka.capacity}</Box>
|
||||
|
||||
@@ -25,7 +25,7 @@ export const ModifyRobotRadio = (props: { target: Target }) => {
|
||||
return (
|
||||
<>
|
||||
{!target.active && <NoSpriteWarning name={target.name} />}
|
||||
<Flex height={!target.active ? '80%' : '85%'}>
|
||||
<Flex height={!target.active ? '75%' : '80%'}>
|
||||
<Flex.Item width="30%" fill>
|
||||
<RadioSection
|
||||
title="Add Radio Channel"
|
||||
|
||||
@@ -65,7 +65,7 @@ export const ModifyRobotUpgrades = (props: { target: Target }) => {
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
<Flex height={!target.active ? '45%' : '50%'}>
|
||||
<Flex height={!target.active ? '40%' : '45%'}>
|
||||
<Flex.Item width="25%" fill>
|
||||
<UpgradeSection
|
||||
title="Utility Upgrade"
|
||||
|
||||
@@ -50,6 +50,10 @@ export const ModifyRobot = (props) => {
|
||||
has_inherent_laws,
|
||||
has_supplied_laws,
|
||||
isAI,
|
||||
isMalf,
|
||||
isSlaved,
|
||||
active_ais,
|
||||
selected_ai,
|
||||
channel,
|
||||
channels,
|
||||
law_sets,
|
||||
@@ -90,9 +94,8 @@ export const ModifyRobot = (props) => {
|
||||
tabs[6] = (
|
||||
<LawManagerLaws
|
||||
isAdmin
|
||||
isMalf
|
||||
hasScroll
|
||||
sectionHeight="85%"
|
||||
sectionHeight="80%"
|
||||
ion_law_nr={ion_law_nr}
|
||||
ion_law={ion_law}
|
||||
zeroth_law={zeroth_law}
|
||||
@@ -108,15 +111,16 @@ export const ModifyRobot = (props) => {
|
||||
has_inherent_laws={has_inherent_laws}
|
||||
has_supplied_laws={has_supplied_laws}
|
||||
isAI={isAI}
|
||||
isMalf={isMalf}
|
||||
channel={channel}
|
||||
channels={channels}
|
||||
/>
|
||||
);
|
||||
tabs[7] = (
|
||||
<Section scrollable fill height="85%">
|
||||
<Section scrollable fill height="80%">
|
||||
<LawManagerLawSets
|
||||
isAdmin
|
||||
isMalf
|
||||
isMalf={isMalf}
|
||||
law_sets={law_sets}
|
||||
ion_law_nr={ion_law_nr}
|
||||
searchLawName={searchLawName}
|
||||
@@ -154,7 +158,7 @@ export const ModifyRobot = (props) => {
|
||||
<>
|
||||
<Stack.Item>
|
||||
<Input
|
||||
width="300px"
|
||||
width="200px"
|
||||
value={robotName}
|
||||
onChange={(e, value) => setRobotName(value)}
|
||||
/>
|
||||
@@ -162,7 +166,7 @@ export const ModifyRobot = (props) => {
|
||||
<Stack.Item>
|
||||
<Button
|
||||
disabled={robotName.length < 3}
|
||||
onClick={(value) =>
|
||||
onClick={() =>
|
||||
act('rename', {
|
||||
new_name: robotName,
|
||||
})
|
||||
@@ -171,10 +175,63 @@ export const ModifyRobot = (props) => {
|
||||
Rename
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow />
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon={target.emagged ? 'sd-card' : 'bolt'}
|
||||
color={target.emagged ? 'green' : 'red'}
|
||||
onClick={() => act('toggle_emag')}
|
||||
tooltip={
|
||||
(target.emagged ? 'Disables' : 'Enables') +
|
||||
' hacked state'
|
||||
}
|
||||
>
|
||||
EMAG
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="AI Selection">
|
||||
{!!target?.module && (
|
||||
<Stack inline align="baseline">
|
||||
<Stack.Item>
|
||||
<Dropdown
|
||||
selected={selected_ai || ''}
|
||||
options={active_ais}
|
||||
onSelected={(value) =>
|
||||
act('select_ai', {
|
||||
new_ai: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="plug"
|
||||
disabled={selected_ai === isSlaved}
|
||||
color="green"
|
||||
tooltip="Connect the robot to an AI"
|
||||
onClick={() => act('swap_sync')}
|
||||
>
|
||||
{isSlaved ? isSlaved : 'Connect AI'}
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="plug-circle-minus"
|
||||
disabled={!isSlaved}
|
||||
color="red"
|
||||
tooltip="Disconnects the robot from the AI"
|
||||
onClick={() => act('disconnect_ai')}
|
||||
>
|
||||
DC
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
<Divider />
|
||||
{!!target &&
|
||||
|
||||
@@ -24,9 +24,13 @@ export type Data = {
|
||||
has_inherent_laws: number;
|
||||
has_supplied_laws: number;
|
||||
isAI: BooleanLike;
|
||||
isMalf: BooleanLike;
|
||||
isSlaved: string | null;
|
||||
channel: string;
|
||||
channels: { channel: string }[];
|
||||
law_sets: law_pack[];
|
||||
active_ais: DropdownEntry[];
|
||||
selected_ai: string | null;
|
||||
};
|
||||
|
||||
export type DropdownEntry = {
|
||||
@@ -38,6 +42,7 @@ export type Target = {
|
||||
name: string;
|
||||
ckey: string;
|
||||
module: string;
|
||||
emagged: BooleanLike;
|
||||
active: BooleanLike;
|
||||
crisis_override: BooleanLike;
|
||||
active_restrictions: string[];
|
||||
|
||||
@@ -417,6 +417,20 @@ export const TguiBenchTarget = new Juke.Target({
|
||||
executes: () => yarn('tgui:bench'),
|
||||
});
|
||||
|
||||
export const TguiPrettierFix = new Juke.Target({
|
||||
dependsOn: [YarnTarget],
|
||||
executes: () => yarn('tgui:prettier-fix'),
|
||||
});
|
||||
|
||||
export const TguiEslintFix = new Juke.Target({
|
||||
dependsOn: [YarnTarget],
|
||||
executes: () => yarn('tgui:eslint-fix'),
|
||||
});
|
||||
|
||||
export const TguiFix = new Juke.Target({
|
||||
dependsOn: [TguiPrettierFix, TguiEslintFix],
|
||||
});
|
||||
|
||||
export const TestTarget = new Juke.Target({
|
||||
dependsOn: [DmTestTarget, TguiTestTarget],
|
||||
});
|
||||
|
||||
@@ -3006,6 +3006,7 @@
|
||||
#include "code\modules\mob\living\carbon\human\species\station\prometheans.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\prometheans_vr.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\prommie_blob.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\replicant_crew.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\station.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\station_special_abilities_vr.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\station_special_vr.dm"
|
||||
|
||||
Reference in New Issue
Block a user