Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into stacks
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
else
|
||||
logs_missing += "[subject] (empty)"
|
||||
|
||||
var/list/combined = sortList(logs_present) + sortList(logs_missing)
|
||||
var/list/combined = sort_list(logs_present) + sort_list(logs_missing)
|
||||
|
||||
var/selected = input("Investigate what?", "Investigate") as null|anything in combined
|
||||
|
||||
|
||||
@@ -694,7 +694,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
// if(!SStrading_card_game.loaded)
|
||||
// message_admins("The card subsystem is not currently loaded")
|
||||
// return
|
||||
// var/pack = input("Which pack should we test?", "You fucked it didn't you") as null|anything in sortList(SStrading_card_game.card_packs)
|
||||
// var/pack = input("Which pack should we test?", "You fucked it didn't you") as null|anything in sort_list(SStrading_card_game.card_packs)
|
||||
// var/batchCount = input("How many times should we open it?", "Don't worry, I understand") as null|num
|
||||
// var/batchSize = input("How many cards per batch?", "I hope you remember to check the validation") as null|num
|
||||
// var/guar = input("Should we use the pack's guaranteed rarity? If so, how many?", "We've all been there. Man you should have seen the old system") as null|num
|
||||
@@ -714,7 +714,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
var/type_length = length_char("/obj/effect/proc_holder/spell") + 2
|
||||
for(var/A in GLOB.spells)
|
||||
spell_list[copytext_char("[A]", type_length)] = A
|
||||
var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in sortList(spell_list)
|
||||
var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in sort_list(spell_list)
|
||||
if(!S)
|
||||
return
|
||||
|
||||
@@ -735,7 +735,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
set desc = "Remove a spell from the selected mob."
|
||||
|
||||
if(T?.mind)
|
||||
var/obj/effect/proc_holder/spell/S = input("Choose the spell to remove", "NO ABRAKADABRA") as null|anything in sortList(T.mind.spell_list)
|
||||
var/obj/effect/proc_holder/spell/S = input("Choose the spell to remove", "NO ABRAKADABRA") as null|anything in sort_list(T.mind.spell_list)
|
||||
if(S)
|
||||
T.mind.RemoveSpell(S)
|
||||
log_admin("[key_name(usr)] removed the spell [S] from [key_name(T)].")
|
||||
@@ -749,7 +749,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
if(!istype(T))
|
||||
to_chat(src, "<span class='notice'>You can only give a disease to a mob of type /mob/living.</span>", confidential = TRUE)
|
||||
return
|
||||
var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in sortList(SSdisease.diseases, /proc/cmp_typepaths_asc)
|
||||
var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in sort_list(SSdisease.diseases, /proc/cmp_typepaths_asc)
|
||||
if(!D)
|
||||
return
|
||||
T.ForceContractDisease(new D, FALSE, TRUE)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
clients += list(client)
|
||||
|
||||
clients = sortList(clients, /proc/cmp_playtime)
|
||||
clients = sort_list(clients, /proc/cmp_playtime)
|
||||
data["clients"] = clients
|
||||
return data
|
||||
|
||||
|
||||
@@ -403,7 +403,7 @@
|
||||
if (SSstickyban.dbcacheexpire)
|
||||
return SSstickyban.dbcache.Copy()
|
||||
|
||||
return sortList(world.GetConfig("ban"))
|
||||
return sort_list(world.GetConfig("ban"))
|
||||
|
||||
|
||||
/proc/get_stickyban_from_ckey(ckey)
|
||||
|
||||
@@ -1351,7 +1351,7 @@
|
||||
for (var/rule in subtypesof(/datum/dynamic_ruleset/roundstart))
|
||||
var/datum/dynamic_ruleset/roundstart/newrule = new rule()
|
||||
roundstart_rules[newrule.name] = newrule
|
||||
var/added_rule = input(usr,"What ruleset do you want to force? This will bypass threat level and population restrictions.", "Rigging Roundstart", null) as null|anything in sortList(roundstart_rules)
|
||||
var/added_rule = input(usr,"What ruleset do you want to force? This will bypass threat level and population restrictions.", "Rigging Roundstart", null) as null|anything in sort_list(roundstart_rules)
|
||||
if (added_rule)
|
||||
GLOB.dynamic_forced_roundstart_ruleset += roundstart_rules[added_rule]
|
||||
log_admin("[key_name(usr)] set [added_rule] to be a forced roundstart ruleset.")
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
targets["[T.mob.real_name](as [T.mob.name]) - [T]"] = T
|
||||
else
|
||||
targets["(No Mob) - [T]"] = T
|
||||
var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
|
||||
var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sort_list(targets)
|
||||
cmd_admin_pm(targets[target],null)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin PM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
@@ -259,11 +259,11 @@
|
||||
if (!istype(chosensilicon, /mob/living/silicon))
|
||||
to_chat(usr, "<span class='warning'>Silicon is required for law changes</span>", confidential=TRUE)
|
||||
return
|
||||
var/chosen = pick_closest_path(null, make_types_fancy(typesof(/obj/item/aiModule)))
|
||||
var/chosen = pick_closest_path(null, make_types_fancy(typesof(/obj/item/ai_module)))
|
||||
if (!chosen)
|
||||
return
|
||||
var/new_board = new chosen(src)
|
||||
var/obj/item/aiModule/chosenboard = new_board
|
||||
var/obj/item/ai_module/chosenboard = new_board
|
||||
var/mob/living/silicon/beepboop = chosensilicon
|
||||
chosenboard.install(beepboop.laws, usr)
|
||||
message_admins("[key_name_admin(usr)] added [chosenboard] to [ADMIN_LOOKUPFLW(beepboop)].")
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
if(M.ckey)
|
||||
if(alert("This mob is being controlled by [M.key]. Are you sure you wish to give someone else control of it? [M.key] will be made a ghost.",,"Yes","No") != "Yes")
|
||||
return
|
||||
var/client/newkey = input(src, "Pick the player to put in control.", "New player") as null|anything in sortList(GLOB.clients)
|
||||
var/client/newkey = input(src, "Pick the player to put in control.", "New player") as null|anything in sort_list(GLOB.clients)
|
||||
var/mob/oldmob = newkey.mob
|
||||
var/delmob = FALSE
|
||||
if((isobserver(oldmob) || alert("Do you want to delete [newkey]'s old mob?","Delete?","Yes","No") != "No"))
|
||||
@@ -494,7 +494,7 @@
|
||||
var/datum/outfit/O = path //not much to initalize here but whatever
|
||||
outfits[initial(O.name)] = path
|
||||
|
||||
var/dresscode = input("Select outfit", "Robust quick dress shop") as null|anything in baseoutfits + sortList(outfits)
|
||||
var/dresscode = input("Select outfit", "Robust quick dress shop") as null|anything in baseoutfits + sort_list(outfits)
|
||||
if (isnull(dresscode))
|
||||
return
|
||||
|
||||
@@ -508,7 +508,7 @@
|
||||
var/datum/outfit/O = path
|
||||
job_outfits[initial(O.name)] = path
|
||||
|
||||
dresscode = input("Select job equipment", "Robust quick dress shop") as null|anything in sortList(job_outfits)
|
||||
dresscode = input("Select job equipment", "Robust quick dress shop") as null|anything in sort_list(job_outfits)
|
||||
dresscode = job_outfits[dresscode]
|
||||
if(isnull(dresscode))
|
||||
return
|
||||
@@ -520,7 +520,7 @@
|
||||
var/datum/outfit/O = path
|
||||
plasmaman_outfits[initial(O.name)] = path
|
||||
|
||||
dresscode = input("Select plasmeme equipment", "Robust quick dress shop") as null|anything in sortList(plasmaman_outfits)
|
||||
dresscode = input("Select plasmeme equipment", "Robust quick dress shop") as null|anything in sort_list(plasmaman_outfits)
|
||||
dresscode = plasmaman_outfits[dresscode]
|
||||
if(isnull(dresscode))
|
||||
return
|
||||
@@ -529,7 +529,7 @@
|
||||
var/list/custom_names = list()
|
||||
for(var/datum/outfit/D in GLOB.custom_outfits)
|
||||
custom_names[D.name] = D
|
||||
var/selected_name = input("Select outfit", "Robust quick dress shop") as null|anything in sortList(custom_names)
|
||||
var/selected_name = input("Select outfit", "Robust quick dress shop") as null|anything in sort_list(custom_names)
|
||||
dresscode = custom_names[selected_name]
|
||||
if(isnull(dresscode))
|
||||
return
|
||||
@@ -828,15 +828,15 @@
|
||||
set name = "Show Line Profiling"
|
||||
set desc = "Shows tracked profiling info from code lines that support it"
|
||||
|
||||
var/sortlist = list(
|
||||
var/sort_list = list(
|
||||
"Avg time" = /proc/cmp_profile_avg_time_dsc,
|
||||
"Total Time" = /proc/cmp_profile_time_dsc,
|
||||
"Call Count" = /proc/cmp_profile_count_dsc
|
||||
)
|
||||
var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist
|
||||
var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sort_list
|
||||
if (!sort)
|
||||
return
|
||||
sort = sortlist[sort]
|
||||
sort = sort_list[sort]
|
||||
profile_show(src, sort)
|
||||
|
||||
/client/proc/reload_configuration()
|
||||
|
||||
@@ -1672,7 +1672,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
var/name = GLOB.trait_name_map[trait] || trait
|
||||
availible_traits[name] = trait
|
||||
|
||||
var/chosen_trait = input("Select trait to modify", "Trait") as null|anything in sortList(availible_traits)
|
||||
var/chosen_trait = input("Select trait to modify", "Trait") as null|anything in sort_list(availible_traits)
|
||||
if(!chosen_trait)
|
||||
return
|
||||
chosen_trait = availible_traits[chosen_trait]
|
||||
@@ -1689,7 +1689,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
if("All")
|
||||
source = null
|
||||
if("Specific")
|
||||
source = input("Source to be removed","Trait Remove/Add") as null|anything in sortList(D.status_traits[chosen_trait])
|
||||
source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D.status_traits[chosen_trait])
|
||||
if(!source)
|
||||
return
|
||||
REMOVE_TRAIT(D,chosen_trait,source)
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
var/datum/round_event_control/disease_outbreak/DC = locate(/datum/round_event_control/disease_outbreak) in SSevents.control
|
||||
E = DC.runEvent()
|
||||
if("Choose")
|
||||
var/virus = input("Choose the virus to spread", "BIOHAZARD") as null|anything in sortList(typesof(/datum/disease), /proc/cmp_typepaths_asc)
|
||||
var/virus = input("Choose the virus to spread", "BIOHAZARD") as null|anything in sort_list(typesof(/datum/disease), /proc/cmp_typepaths_asc)
|
||||
var/datum/round_event_control/disease_outbreak/DC = locate(/datum/round_event_control/disease_outbreak) in SSevents.control
|
||||
var/datum/round_event/disease_outbreak/DO = DC.runEvent()
|
||||
DO.virus_type = virus
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
for (var/V in O.vars)
|
||||
names += V
|
||||
|
||||
names = sortList(names)
|
||||
names = sort_list(names)
|
||||
|
||||
variable = input("Which var?", "Var") as null|anything in names
|
||||
else
|
||||
|
||||
@@ -306,7 +306,7 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
for (var/V in O.vars)
|
||||
names += V
|
||||
|
||||
names = sortList(names)
|
||||
names = sort_list(names)
|
||||
|
||||
variable = input("Which var?","Var") as null|anything in names
|
||||
if(!variable)
|
||||
|
||||
@@ -65,11 +65,11 @@
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/names = list()
|
||||
var/list/componentsubtypes = sortList(subtypesof(/datum/component), /proc/cmp_typepaths_asc)
|
||||
var/list/componentsubtypes = sort_list(subtypesof(/datum/component), /proc/cmp_typepaths_asc)
|
||||
names += "---Components---"
|
||||
names += componentsubtypes
|
||||
names += "---Elements---"
|
||||
names += sortList(subtypesof(/datum/element), /proc/cmp_typepaths_asc)
|
||||
names += sort_list(subtypesof(/datum/element), /proc/cmp_typepaths_asc)
|
||||
var/result = input(usr, "Choose a component/element to add","better know what ur fuckin doin pal") as null|anything in names
|
||||
if(!usr || !result || result == "---Components---" || result == "---Elements---")
|
||||
return
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
value = L[key]
|
||||
variable_html += debug_variable(i, value, 0, L)
|
||||
else
|
||||
names = sortList(names)
|
||||
names = sort_list(names)
|
||||
for(var/V in names)
|
||||
if(D.can_vv_get(V))
|
||||
variable_html += D.vv_get_var(V)
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
..()
|
||||
|
||||
/obj/item/projectile/tentacle/proc/reset_throw(mob/living/carbon/human/H)
|
||||
if(H.in_throw_mode)
|
||||
if(H.throw_mode)
|
||||
H.throw_mode_off() //Don't annoy the changeling if he doesn't catch the item
|
||||
|
||||
/obj/item/projectile/tentacle/proc/tentacle_grab(mob/living/carbon/human/H, mob/living/carbon/C)
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
return
|
||||
if(isitem(M))
|
||||
var/obj/item/I = M
|
||||
if(is_servant_of_ratvar(I.thrownby)) //nice try!
|
||||
if(is_servant_of_ratvar(I.thrownby?.resolve())) //nice try!
|
||||
return
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/proc/generate_all_scripture()
|
||||
if(GLOB.all_scripture.len)
|
||||
return
|
||||
for(var/V in sortList(subtypesof(/datum/clockwork_scripture) - list(/datum/clockwork_scripture/channeled, /datum/clockwork_scripture/create_object, /datum/clockwork_scripture/create_object/construct), /proc/cmp_clockscripture_priority))
|
||||
for(var/V in sort_list(subtypesof(/datum/clockwork_scripture) - list(/datum/clockwork_scripture/channeled, /datum/clockwork_scripture/create_object, /datum/clockwork_scripture/create_object/construct), /proc/cmp_clockscripture_priority))
|
||||
var/datum/clockwork_scripture/S = new V
|
||||
GLOB.all_scripture[S.type] = S
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
density = TRUE //Skewers are one-use only
|
||||
desc = "A vicious brass spike protruding from the ground like a stala[pick("gm", "ct")]ite. It makes you sick to look at." //is stalagmite the ground one? or the ceiling one? who can ever remember?
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob()
|
||||
/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob(check_loc)
|
||||
return
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/brass_skewer/post_buckle_mob(mob/living/L)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, silent = FALSE)
|
||||
/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, invdrop, silent = FALSE)
|
||||
if(..())
|
||||
update_inv_hands()
|
||||
return 1
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
to_chat(user, "<span class='warning'>These items don't possess the required fingerprints or DNA.</span>")
|
||||
return FALSE
|
||||
|
||||
var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sortList(compiled_list, /proc/cmp_mob_realname_dsc)
|
||||
var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sort_list(compiled_list, /proc/cmp_mob_realname_dsc)
|
||||
if(!chosen_mob)
|
||||
return FALSE
|
||||
curse(compiled_list[chosen_mob])
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
var/datum/component/uplink/uplink = uplink_holder.GetComponent(/datum/component/uplink)
|
||||
uplink.telecrystals = INITIAL_CRYSTALS
|
||||
// Give AI hacking board
|
||||
var/obj/item/aiModule/core/full/overthrow/O = new(H)
|
||||
var/obj/item/ai_module/core/full/overthrow/O = new(H)
|
||||
var/list/slots = list (
|
||||
"backpack" = ITEM_SLOT_BACKPACK,
|
||||
"left pocket" = ITEM_SLOT_LPOCKET,
|
||||
|
||||
@@ -331,7 +331,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
if (legacy)
|
||||
assets |= parents
|
||||
var/list/hashlist = list()
|
||||
var/list/sorted_assets = sortList(assets)
|
||||
var/list/sorted_assets = sort_list(assets)
|
||||
|
||||
for (var/asset_name in sorted_assets)
|
||||
var/datum/asset_cache_item/ACI = new(asset_name, sorted_assets[asset_name])
|
||||
|
||||
@@ -388,7 +388,7 @@
|
||||
return
|
||||
switch(action)
|
||||
if("relabel")
|
||||
var/label = input("New canister label:", name) as null|anything in sortList(label2types)
|
||||
var/label = input("New canister label:", name) as null|anything in sort_list(label2types)
|
||||
if(label && !..())
|
||||
var/newtype = label2types[label]
|
||||
if(newtype)
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
if (temp_pod.effectShrapnel == TRUE) //If already doing custom damage, set back to default (no shrapnel)
|
||||
temp_pod.effectShrapnel = FALSE
|
||||
return
|
||||
var/shrapnelInput = input("Please enter the type of pellet cloud you'd like to create on landing (Can be any projectile!)", "Projectile Typepath", 0) in sortList(subtypesof(/obj/item/projectile), /proc/cmp_typepaths_asc)
|
||||
var/shrapnelInput = input("Please enter the type of pellet cloud you'd like to create on landing (Can be any projectile!)", "Projectile Typepath", 0) in sort_list(subtypesof(/obj/item/projectile), /proc/cmp_typepaths_asc)
|
||||
if (isnull(shrapnelInput))
|
||||
return
|
||||
var/shrapnelMagnitude = input("Enter the magnitude of the pellet cloud. This is usually a value around 1-5. Please note that Ryll-Ryll has asked me to tell you that if you go too crazy with the projectiles you might crash the server. So uh, be gentle!", "Shrapnel Magnitude", 0) as null|num
|
||||
|
||||
@@ -1429,7 +1429,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
//The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows.
|
||||
var/datum/job/lastJob
|
||||
|
||||
for(var/datum/job/job in sortList(SSjob.occupations, /proc/cmp_job_display_asc))
|
||||
for(var/datum/job/job in sort_list(SSjob.occupations, /proc/cmp_job_display_asc))
|
||||
|
||||
index += 1
|
||||
if((index >= limit) || (job.title in splitJobs))
|
||||
@@ -2981,7 +2981,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(!length(key_bindings[old_key]))
|
||||
key_bindings -= old_key
|
||||
key_bindings[full_key] += list(kb_name)
|
||||
key_bindings[full_key] = sortList(key_bindings[full_key])
|
||||
key_bindings[full_key] = sort_list(key_bindings[full_key])
|
||||
if(href_list["special"]) // special keys need a full reset
|
||||
user.client.ensure_keys_set(src)
|
||||
user << browse(null, "window=capturekeypress")
|
||||
|
||||
@@ -237,7 +237,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
|
||||
choices["[C.mob]([C])"] = C
|
||||
else
|
||||
choices[C] = C
|
||||
choices = sortList(choices)
|
||||
choices = sort_list(choices)
|
||||
var/selection = input("Please, select a player!", "Ignore", null, null) as null|anything in choices
|
||||
if(!selection || !(selection in choices))
|
||||
return
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
else
|
||||
Lines += "[C.key] ([round(C.avgping, 1)]ms)"
|
||||
|
||||
for(var/line in sortList(Lines))
|
||||
for(var/line in sort_list(Lines))
|
||||
msg += "[line]\n"
|
||||
|
||||
msg += "<b>Total Players: [length(Lines)]</b>"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
var/suggested = pick(strings(REDPILL_FILE, "redpill_questions"))
|
||||
|
||||
forced_secret = (input(usr, "What horrifying truth will you reveal?", "Curse of Madness", sortList(suggested)) as text|null) || suggested
|
||||
forced_secret = (input(usr, "What horrifying truth will you reveal?", "Curse of Madness", sort_list(suggested)) as text|null) || suggested
|
||||
|
||||
/datum/round_event/wizard/madness/start()
|
||||
var/datum/round_event_control/wizard/madness/C = control
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
listofitems[md5name]["amount"]++ // The good news is, #30519 made smartfridge UIs non-auto-updating
|
||||
else
|
||||
listofitems[md5name] = list("name" = O.name, "type" = O.type, "amount" = 1)
|
||||
sortList(listofitems)
|
||||
sort_list(listofitems)
|
||||
|
||||
.["contents"] = listofitems
|
||||
.["name"] = name
|
||||
|
||||
@@ -425,9 +425,10 @@
|
||||
for(var/datum/reagent/A in reagents.reagent_list)
|
||||
R += A.type + " ("
|
||||
R += num2text(A.volume) + "),"
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(isturf(target) && reagents.reagent_list.len && thrown_by)
|
||||
log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
reagents.reaction(M, TOUCH)
|
||||
log_combat(user, M, "splashed", R)
|
||||
reagents.clear_reagents()
|
||||
|
||||
@@ -626,7 +626,7 @@
|
||||
for(var/muties in myseed.mutatelist)
|
||||
var/obj/item/seeds/another_mut = new muties
|
||||
fresh_mut_list[another_mut.plantname] = muties
|
||||
var/locked_mutation = (input(user, "Select a mutation to lock.", "Plant Mutation Locks") as null|anything in sortList(fresh_mut_list))
|
||||
var/locked_mutation = (input(user, "Select a mutation to lock.", "Plant Mutation Locks") as null|anything in sort_list(fresh_mut_list))
|
||||
if(!user.canUseTopic(src, BE_CLOSE) || !locked_mutation)
|
||||
return
|
||||
myseed.mutatelist = list(fresh_mut_list[locked_mutation])
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
/datum/job/ai/after_spawn(mob/H, client/C, latejoin)
|
||||
. = ..()
|
||||
if(latejoin)
|
||||
var/obj/structure/AIcore/latejoin_inactive/lateJoinCore
|
||||
for(var/obj/structure/AIcore/latejoin_inactive/P in GLOB.latejoin_ai_cores)
|
||||
var/obj/structure/ai_core/latejoin_inactive/lateJoinCore
|
||||
for(var/obj/structure/ai_core/latejoin_inactive/P in GLOB.latejoin_ai_cores)
|
||||
if(P.is_available())
|
||||
lateJoinCore = P
|
||||
GLOB.latejoin_ai_cores -= P
|
||||
@@ -60,7 +60,7 @@
|
||||
if(!do_special_check)
|
||||
return TRUE
|
||||
for(var/i in GLOB.latejoin_ai_cores)
|
||||
var/obj/structure/AIcore/latejoin_inactive/LAI = i
|
||||
var/obj/structure/ai_core/latejoin_inactive/LAI = i
|
||||
if(istype(LAI))
|
||||
if(LAI.is_available())
|
||||
return TRUE
|
||||
|
||||
@@ -28,7 +28,7 @@ GLOBAL_LIST(labor_sheet_values)
|
||||
if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet_type)) //ignore no-value sheets and x/fifty subtypes
|
||||
continue
|
||||
sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value)))
|
||||
GLOB.labor_sheet_values = sortList(sheet_list, /proc/cmp_sheet_list)
|
||||
GLOB.labor_sheet_values = sort_list(sheet_list, /proc/cmp_sheet_list)
|
||||
|
||||
/proc/cmp_sheet_list(list/a, list/b)
|
||||
return a["value"] - b["value"]
|
||||
|
||||
@@ -292,10 +292,18 @@
|
||||
|
||||
//The following functions are the same save for one small difference
|
||||
|
||||
//for when you want the item to end up on the ground
|
||||
//will force move the item to the ground and call the turf's Entered
|
||||
/mob/proc/dropItemToGround(obj/item/I, force = FALSE)
|
||||
return doUnEquip(I, force, drop_location(), FALSE)
|
||||
/**
|
||||
* Used to drop an item (if it exists) to the ground.
|
||||
* * Will pass as TRUE is successfully dropped, or if there is no item to drop.
|
||||
* * Will pass FALSE if the item can not be dropped due to TRAIT_NODROP via doUnEquip()
|
||||
* If the item can be dropped, it will be forceMove()'d to the ground and the turf's Entered() will be called.
|
||||
*/
|
||||
/mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE)
|
||||
if (isnull(I))
|
||||
return TRUE
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MOB_DROPPING_ITEM)
|
||||
. = doUnEquip(I, force, drop_location(), FALSE, invdrop = invdrop, silent = silent)
|
||||
|
||||
//for when the item will be immediately placed in a loc other than the ground
|
||||
/mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE, silent = TRUE)
|
||||
|
||||
@@ -47,8 +47,20 @@
|
||||
if(brain)
|
||||
to_chat(user, "<span class='warning'>There's already a brain in the MMI!</span>")
|
||||
return
|
||||
if(!newbrain.brainmob)
|
||||
to_chat(user, "<span class='warning'>You aren't sure where this brain came from, but you're pretty sure it's a useless brain!</span>")
|
||||
if(newbrain.brainmob?.suiciding)
|
||||
to_chat(user, span_warning("[newbrain] is completely useless."))
|
||||
return
|
||||
if(!newbrain.brainmob?.mind || !newbrain.brainmob)
|
||||
var/install = tgui_alert(user, "[newbrain] is inactive, slot it in anyway?", "Installing Brain", list("Yes", "No"))
|
||||
if(install != "Yes")
|
||||
return
|
||||
if(!user.transferItemToLoc(newbrain, src))
|
||||
return
|
||||
user.visible_message(span_notice("[user] sticks [newbrain] into [src]."), span_notice("[src]'s indicator light turns red as you insert [newbrain]. Its brainwave activity alarm buzzes."))
|
||||
brain = newbrain
|
||||
brain.organ_flags |= ORGAN_FROZEN
|
||||
name = "[initial(name)]: [copytext(newbrain.name, 1, -8)]"
|
||||
update_appearance()
|
||||
return
|
||||
|
||||
if(!user.transferItemToLoc(O, src))
|
||||
@@ -97,15 +109,15 @@
|
||||
name = initial(name)
|
||||
|
||||
/obj/item/mmi/proc/eject_brain(mob/user)
|
||||
brainmob.container = null //Reset brainmob mmi var.
|
||||
brainmob.forceMove(brain) //Throw mob into brain.
|
||||
brainmob.stat = DEAD
|
||||
brainmob.emp_damage = 0
|
||||
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
|
||||
brainmob.remove_from_alive_mob_list() //Get outta here
|
||||
brainmob.add_to_dead_mob_list()
|
||||
brain.brainmob = brainmob //Set the brain to use the brainmob
|
||||
brainmob = null //Set mmi brainmob var to null
|
||||
if(brain.brainmob)
|
||||
brainmob.container = null //Reset brainmob mmi var.
|
||||
brainmob.forceMove(brain) //Throw mob into brain.
|
||||
brainmob.stat = DEAD
|
||||
brainmob.emp_damage = 0
|
||||
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
|
||||
brain.brainmob = brainmob //Set the brain to use the brainmob
|
||||
log_game("[key_name(user)] has ejected the brain of [key_name(brainmob)] from an MMI at [AREACOORD(src)]")
|
||||
brainmob = null //Set mmi brainmob var to null
|
||||
if(user)
|
||||
user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf
|
||||
else
|
||||
@@ -210,6 +222,38 @@
|
||||
/obj/item/mmi/relaymove(mob/user)
|
||||
return //so that the MMI won't get a warning about not being able to move if it tries to move
|
||||
|
||||
/obj/item/mmi/proc/brain_check(mob/user)
|
||||
var/mob/living/brain/B = brainmob
|
||||
if(!B)
|
||||
if(user)
|
||||
to_chat(user, span_warning("\The [src] indicates that there is no mind present!"))
|
||||
return FALSE
|
||||
if(brain?.decoy_override)
|
||||
if(user)
|
||||
to_chat(user, span_warning("This [name] does not seem to fit!"))
|
||||
return FALSE
|
||||
if(!B.key || !B.mind)
|
||||
if(user)
|
||||
to_chat(user, span_warning("\The [src] indicates that their mind is completely unresponsive!"))
|
||||
return FALSE
|
||||
if(!B.client)
|
||||
if(user)
|
||||
to_chat(user, span_warning("\The [src] indicates that their mind is currently inactive."))
|
||||
return FALSE
|
||||
if(B.suiciding)
|
||||
if(user)
|
||||
to_chat(user, span_warning("\The [src] indicates that their mind has no will to live!"))
|
||||
return FALSE
|
||||
if(B.stat == DEAD)
|
||||
if(user)
|
||||
to_chat(user, span_warning("\The [src] indicates that the brain is dead!"))
|
||||
return FALSE
|
||||
if(brain?.organ_flags & ORGAN_FAILING)
|
||||
if(user)
|
||||
to_chat(user, span_warning("\The [src] indicates that the brain is damaged!"))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mmi/syndie
|
||||
name = "Syndicate Man-Machine Interface"
|
||||
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs and AIs created with it."
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
//can't unequip since it can't equip anything
|
||||
/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, silent = FALSE)
|
||||
/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, invdrop, silent = FALSE)
|
||||
return
|
||||
|
||||
@@ -125,8 +125,8 @@
|
||||
take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5)
|
||||
victim.DefaultCombatKnockdown(20)
|
||||
DefaultCombatKnockdown(20)
|
||||
visible_message("<span class='danger'>[src] crashes into [victim] [extra_speed ? "really hard" : ""], knocking them both over!</span>",\
|
||||
"<span class='userdanger'>You violently crash into [victim] [extra_speed ? "extra hard" : ""]!</span>")
|
||||
visible_message("<span class='danger'>[src] crashes into [victim][extra_speed ? " really hard" : ""], knocking them both over!</span>",\
|
||||
"<span class='userdanger'>You violently crash into [victim][extra_speed ? " extra hard" : ""]!</span>")
|
||||
playsound(src,'sound/weapons/punch1.ogg',50,1)
|
||||
|
||||
|
||||
@@ -134,33 +134,35 @@
|
||||
/mob/living/carbon/proc/toggle_throw_mode()
|
||||
if(stat)
|
||||
return
|
||||
if(in_throw_mode)
|
||||
if(throw_mode)
|
||||
throw_mode_off()
|
||||
else
|
||||
throw_mode_on()
|
||||
|
||||
|
||||
/mob/living/carbon/proc/throw_mode_off()
|
||||
in_throw_mode = 0
|
||||
throw_mode = FALSE
|
||||
if(client && hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw_off"
|
||||
|
||||
|
||||
/mob/living/carbon/proc/throw_mode_on()
|
||||
in_throw_mode = 1
|
||||
throw_mode = TRUE
|
||||
if(client && hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw_on"
|
||||
|
||||
/mob/proc/throw_item(atom/target)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_THROW, target)
|
||||
return
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CARBON_THROW_THING, src, target)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/throw_item(atom/target)
|
||||
. = ..()
|
||||
throw_mode_off()
|
||||
if(!target || !isturf(loc))
|
||||
return
|
||||
return FALSE
|
||||
if(istype(target, /atom/movable/screen))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
//CIT CHANGES - makes it impossible to throw while in stamina softcrit
|
||||
if(IS_STAMCRIT(src))
|
||||
@@ -170,59 +172,56 @@
|
||||
var/random_turn = a_intent == INTENT_HARM
|
||||
//END OF CIT CHANGES
|
||||
|
||||
var/obj/item/I = get_active_held_item()
|
||||
|
||||
var/atom/movable/thrown_thing
|
||||
var/mob/living/throwable_mob
|
||||
var/obj/item/held_item = get_active_held_item()
|
||||
var/verb_text = pick("throw", "toss", "hurl", "chuck", "fling")
|
||||
if(prob(0.5))
|
||||
verb_text = "yeet"
|
||||
|
||||
if(istype(I, /obj/item/clothing/head/mob_holder))
|
||||
var/obj/item/clothing/head/mob_holder/holder = I
|
||||
if(holder.held_mob)
|
||||
throwable_mob = holder.held_mob
|
||||
holder.release()
|
||||
|
||||
if(!I || throwable_mob)
|
||||
if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
|
||||
throwable_mob = pulling
|
||||
|
||||
if(throwable_mob && !throwable_mob.buckled)
|
||||
thrown_thing = throwable_mob
|
||||
if(pulling)
|
||||
var/neckgrab_throw = FALSE
|
||||
if(!held_item)
|
||||
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
|
||||
var/mob/living/throwable_mob = pulling
|
||||
if(!throwable_mob.buckled)
|
||||
thrown_thing = throwable_mob
|
||||
if(grab_state >= GRAB_NECK)
|
||||
neckgrab_throw = TRUE
|
||||
stop_pulling()
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM))
|
||||
to_chat(src, "<span class='notice'>You gently let go of [throwable_mob].</span>")
|
||||
return
|
||||
if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE))
|
||||
return
|
||||
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
|
||||
var/turf/end_T = get_turf(target)
|
||||
if(start_T && end_T)
|
||||
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
|
||||
|
||||
else if(!(I.item_flags & ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
|
||||
thrown_thing = I
|
||||
dropItemToGround(I)
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM) && I.throwforce)
|
||||
to_chat(src, "<span class='notice'>You set [I] down gently on the ground.</span>")
|
||||
return
|
||||
|
||||
if(!UseStaminaBuffer(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST), warn = TRUE))
|
||||
return
|
||||
|
||||
if(thrown_thing)
|
||||
var/power_throw = 0
|
||||
if(HAS_TRAIT(src, TRAIT_HULK))
|
||||
power_throw++
|
||||
if(pulling && grab_state >= GRAB_NECK)
|
||||
power_throw++
|
||||
visible_message("<span class='danger'>[src] throws [thrown_thing][power_throw ? " really hard!" : "."]</span>", \
|
||||
"<span class='danger'>You throw [thrown_thing][power_throw ? " really hard!" : "."]</span>")
|
||||
log_message("has thrown [thrown_thing] [power_throw ? "really hard" : ""]", LOG_ATTACK)
|
||||
do_attack_animation(target, no_effect = 1)
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1)
|
||||
newtonian_move(get_dir(target, src))
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed + power_throw, src, null, null, null, move_force, random_turn)
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM))
|
||||
to_chat(src, span_notice("You gently let go of [throwable_mob]."))
|
||||
return FALSE
|
||||
if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE))
|
||||
return FALSE
|
||||
else
|
||||
thrown_thing = held_item.on_thrown(src, target)
|
||||
if(!thrown_thing)
|
||||
return FALSE
|
||||
if(isliving(thrown_thing))
|
||||
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
|
||||
var/turf/end_T = get_turf(target)
|
||||
if(start_T && end_T)
|
||||
log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
|
||||
var/power_throw = 0
|
||||
if(HAS_TRAIT(src, TRAIT_HULK))
|
||||
power_throw++
|
||||
if(HAS_TRAIT(src, TRAIT_DWARF))
|
||||
power_throw--
|
||||
if(HAS_TRAIT(thrown_thing, TRAIT_DWARF))
|
||||
power_throw++
|
||||
if(neckgrab_throw)
|
||||
power_throw++
|
||||
if(isitem(thrown_thing))
|
||||
var/obj/item/thrown_item = thrown_thing
|
||||
if(thrown_item.throw_verb)
|
||||
verb_text = thrown_item.throw_verb
|
||||
visible_message(span_danger("[src] [verb_text][plural_s(verb_text)] [thrown_thing][power_throw ? " really hard!" : "."]"), \
|
||||
span_danger("You [verb_text] [thrown_thing][power_throw ? " really hard!" : "."]"))
|
||||
log_message("has thrown [thrown_thing] [power_throw > 0 ? "really hard" : ""]", LOG_ATTACK)
|
||||
do_attack_animation(target, no_effect = 1)
|
||||
var/extra_throw_range = 0 // HAS_TRAIT(src, TRAIT_THROWINGARM) ? 2 : 0
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1)
|
||||
newtonian_move(get_dir(target, src))
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force, random_turn)
|
||||
|
||||
/mob/living/carbon/restrained(ignore_grab)
|
||||
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
|
||||
|
||||
@@ -48,22 +48,30 @@
|
||||
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
|
||||
affecting.dismember(P.damtype)
|
||||
|
||||
/mob/living/carbon/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
. = ..()
|
||||
if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !in_throw_mode)
|
||||
/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check)
|
||||
. = FALSE
|
||||
if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !throw_mode)
|
||||
return
|
||||
if(incapacitated())
|
||||
if(get_active_held_item())
|
||||
return
|
||||
if (get_active_held_item())
|
||||
if (HAS_TRAIT_FROM(src, TRAIT_AUTO_CATCH_ITEM,RISING_BASS_TRAIT))
|
||||
visible_message("<span class='warning'>[src] chops [I] out of the air!</span>")
|
||||
if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED))
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(!skipcatch && can_catch_item() && isitem(AM) && isturf(AM.loc))
|
||||
var/obj/item/I = AM
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message(span_warning("[src] catches [I]!"), \
|
||||
span_userdanger("You catch [I] in mid-air!"))
|
||||
throw_mode_off()
|
||||
return TRUE
|
||||
return
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
if(isitem(AM) && HAS_TRAIT_FROM(src, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT))
|
||||
visible_message(span_warning("[src] chops [AM] out of the air!"), \
|
||||
span_userdanger("You chop [AM] out of the air!"))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier
|
||||
|
||||
@@ -68,12 +68,16 @@
|
||||
|
||||
/mob/living/carbon/human/proc/check_martial_melee_block()
|
||||
if(mind)
|
||||
if(mind.martial_art && prob(mind.martial_art.block_chance) && mind.martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE))
|
||||
if(mind.martial_art && prob(mind.martial_art.block_chance) && mind.martial_art.can_use(src) && throw_mode && !incapacitated(FALSE, TRUE))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
return dna?.species?.spec_hitby(AM, src) || ..()
|
||||
if(dna?.species)
|
||||
var/spec_return = dna.species.spec_hitby(AM, src)
|
||||
if(spec_return)
|
||||
return spec_return
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (HAS_TRAIT(src, TRAIT_FAT)) && ismonkey(pulling))
|
||||
@@ -817,7 +821,7 @@
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
|
||||
else
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
|
||||
if(damage_type != BRUTE && damage_type != BURN)
|
||||
|
||||
@@ -419,7 +419,8 @@
|
||||
var/obj/item/I
|
||||
if(istype(AM, /obj/item))
|
||||
I = AM
|
||||
if(I.thrownby == H) //No throwing stuff at yourself to trigger the teleport
|
||||
var/mob/thrown_by = I.thrownby?.resolve()
|
||||
if(thrown_by == H) //No throwing stuff at yourself to trigger the teleport
|
||||
return 0
|
||||
else
|
||||
reactive_teleport(H)
|
||||
|
||||
@@ -396,12 +396,13 @@
|
||||
retaliate(Proj.firer)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby))
|
||||
var/mob/living/carbon/human/H = I.thrownby
|
||||
retaliate(H)
|
||||
/mob/living/carbon/monkey/hitby(atom/movable/hitting_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(hitting_atom, /obj/item))
|
||||
var/obj/item/item_hitby = hitting_atom
|
||||
var/mob/thrown_by = item_hitby.thrownby?.resolve()
|
||||
if(item_hitby.throwforce < src.health && thrown_by && ishuman(thrown_by))
|
||||
var/mob/living/carbon/human/human_throwee = thrown_by
|
||||
retaliate(human_throwee)
|
||||
..()
|
||||
|
||||
/mob/living/carbon/monkey/Crossed(atom/movable/AM)
|
||||
|
||||
@@ -489,7 +489,7 @@
|
||||
if(E.can_run_emote(user, status_check = FALSE))
|
||||
keys += E.key
|
||||
|
||||
keys = sortList(keys)
|
||||
keys = sort_list(keys)
|
||||
|
||||
for(var/emote in keys)
|
||||
if(LAZYLEN(message) > 1)
|
||||
|
||||
@@ -106,48 +106,51 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
return FALSE
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
// Throwingdatum can be null if someone had an accident() while slipping with an item in hand.
|
||||
var/obj/item/I
|
||||
var/throwpower = 30
|
||||
if(isitem(AM))
|
||||
I = AM
|
||||
throwpower = I.throwforce
|
||||
var/impacting_zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
|
||||
var/list/block_return = list()
|
||||
var/total_damage = AM.throwforce
|
||||
if(mob_run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone, block_return) & BLOCK_SUCCESS)
|
||||
if(!isitem(AM))
|
||||
// Filled with made up numbers for non-items.
|
||||
if(mob_run_block(AM, 30, "\the [AM.name]", ATTACK_TYPE_PROJECTILE, 0, throwingdatum.thrower, throwingdatum.thrower.zone_selected, list()))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
else
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1) //Item sounds are handled in the item itself
|
||||
return ..()
|
||||
|
||||
var/obj/item/thrown_item = AM
|
||||
if(thrown_item.thrownby == WEAKREF(src)) //No throwing stuff at yourself to trigger hit reactions
|
||||
return ..()
|
||||
|
||||
if(mob_run_block(AM, thrown_item.throwforce, "\the [thrown_item.name]", ATTACK_TYPE_PROJECTILE, 0, throwingdatum.thrower, throwingdatum.thrower.zone_selected, list()))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
total_damage = block_calculate_resultant_damage(total_damage, block_return)
|
||||
if(I)
|
||||
var/nosell_hit = SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone, throwingdatum, FALSE, blocked)
|
||||
if(nosell_hit)
|
||||
skipcatch = TRUE
|
||||
hitpush = FALSE
|
||||
if(!skipcatch && isturf(I.loc) && catch_item(I))
|
||||
return TRUE
|
||||
var/dtype = BRUTE
|
||||
|
||||
dtype = I.damtype
|
||||
var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
|
||||
var/nosell_hit = SEND_SIGNAL(thrown_item, COMSIG_MOVABLE_IMPACT_ZONE, src, zone, blocked, throwingdatum) // TODO: find a better way to handle hitpush and skipcatch for humans
|
||||
if(nosell_hit)
|
||||
skipcatch = TRUE
|
||||
hitpush = FALSE
|
||||
|
||||
if(!blocked)
|
||||
if(!nosell_hit)
|
||||
visible_message("<span class='danger'>[src] is hit by [I]!</span>", \
|
||||
"<span class='userdanger'>You're hit by [I]!</span>")
|
||||
if(!I.throwforce)
|
||||
return
|
||||
var/armor = run_armor_check(impacting_zone, MELEE, "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
|
||||
apply_damage(I.throwforce, dtype, impacting_zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND))
|
||||
else
|
||||
return 1
|
||||
else
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
|
||||
..()
|
||||
if(blocked)
|
||||
return TRUE
|
||||
|
||||
var/mob/thrown_by = thrown_item.thrownby?.resolve()
|
||||
if(thrown_by)
|
||||
log_combat(thrown_by, src, "threw and hit", thrown_item)
|
||||
if(nosell_hit)
|
||||
return ..()
|
||||
visible_message(span_danger("[src] is hit by [thrown_item]!"), \
|
||||
span_userdanger("You're hit by [thrown_item]!"))
|
||||
if(!thrown_item.throwforce)
|
||||
return
|
||||
var/armor = run_armor_check(zone, MELEE, "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", thrown_item.armour_penetration, "", FALSE)
|
||||
apply_damage(thrown_item.throwforce, thrown_item.damtype, zone, armor, sharpness = thrown_item.get_sharpness(), wound_bonus = (nosell_hit * CANT_WOUND))
|
||||
if(QDELETED(src)) //Damage can delete the mob.
|
||||
return
|
||||
if(lying) // physics says it's significantly harder to push someone by constantly chucking random furniture at them if they are down on the floor.
|
||||
hitpush = FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/fire_act()
|
||||
adjust_fire_stacks(3)
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
has_field_of_vision = FALSE //Vision through cameras.
|
||||
var/battery = 200 //emergency power if the AI's APC is off
|
||||
var/list/network = list("ss13")
|
||||
var/obj/machinery/camera/current
|
||||
var/list/connected_robots = list()
|
||||
@@ -46,7 +47,7 @@
|
||||
var/obj/item/multitool/aiMulti
|
||||
var/mob/living/simple_animal/bot/Bot
|
||||
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
|
||||
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
|
||||
var/datum/effect_system/spark_spread/spark_system //So they can initialize sparks whenever/N
|
||||
var/obj/machinery/status_display/controlled_display
|
||||
|
||||
//MALFUNCTION
|
||||
@@ -83,7 +84,7 @@
|
||||
var/cooldown = 0
|
||||
var/acceleration = 1
|
||||
|
||||
var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
|
||||
var/obj/structure/ai_core/deactivated/linked_core //For exosuit control
|
||||
var/mob/living/silicon/robot/deployed_shell = null //For shell control
|
||||
var/datum/action/innate/deploy_shell/deploy_action = new
|
||||
var/datum/action/innate/deploy_last_shell/redeploy_action = new
|
||||
@@ -105,11 +106,17 @@
|
||||
///remember AI's last location
|
||||
var/atom/lastloc
|
||||
interaction_range = INFINITY
|
||||
///whether its mmi is a posibrain or regular mmi when going ai mob to ai core structure
|
||||
var/posibrain_inside = TRUE
|
||||
///whether its cover is opened, so you can wirecut it for deconstruction
|
||||
var/opened = FALSE
|
||||
///whether AI is anchored or not, used for checks
|
||||
var/is_anchored = TRUE
|
||||
|
||||
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
|
||||
. = ..()
|
||||
if(!target_ai) //If there is no player/brain inside.
|
||||
new/obj/structure/AIcore/deactivated(loc) //New empty terminal.
|
||||
new/obj/structure/ai_core/deactivated(loc) //New empty terminal.
|
||||
return INITIALIZE_HINT_QDEL //Delete AI.
|
||||
|
||||
ADD_TRAIT(src, TRAIT_NO_TELEPORT, src)
|
||||
@@ -125,6 +132,8 @@
|
||||
mind.store_memory("As an AI, you must obey your silicon laws above all else. Your objectives will consider you to be dead.")
|
||||
to_chat(src, "<span class='userdanger'>You have been installed as an AI! </span>")
|
||||
to_chat(src, "<span class='danger'>You must obey your silicon laws above all else. Your objectives will consider you to be dead.</span>")
|
||||
if(!mind.has_ever_been_ai)
|
||||
mind.has_ever_been_ai = TRUE
|
||||
|
||||
to_chat(src, "<B>You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).</B>")
|
||||
to_chat(src, "<B>To look at other parts of the station, click on yourself to get a camera menu.</B>")
|
||||
@@ -237,6 +246,8 @@
|
||||
. += text("Systems nonfunctional")
|
||||
return
|
||||
. += text("System integrity: [(health + 100) * 0.5]%")
|
||||
if(isturf(loc)) //only show if we're "in" a core
|
||||
. += "Backup Power: [battery * 0.5]%"
|
||||
. += text("Connected cyborgs: [length(connected_robots)]")
|
||||
for(var/r in connected_robots)
|
||||
var/mob/living/silicon/robot/connected_robot = r
|
||||
@@ -333,18 +344,64 @@
|
||||
if(!isturf(loc)) // if their location isn't a turf
|
||||
return // stop
|
||||
if(incapacitated())
|
||||
return
|
||||
var/is_anchored = FALSE
|
||||
if(move_resist == MOVE_FORCE_OVERPOWERING)
|
||||
if(battery < 50)
|
||||
to_chat(src, span_warning("Insufficient backup power!"))
|
||||
return
|
||||
battery = battery - 50
|
||||
to_chat(src, span_notice("You route power from your backup battery to move the bolts."))
|
||||
flip_anchored()
|
||||
to_chat(src, "<b>You are now [is_anchored ? "" : "un"]anchored.</b>")
|
||||
|
||||
/mob/living/silicon/ai/proc/flip_anchored()
|
||||
if(is_anchored)
|
||||
is_anchored = !is_anchored
|
||||
move_resist = MOVE_FORCE_NORMAL
|
||||
status_flags |= CANPUSH
|
||||
REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src)
|
||||
else
|
||||
is_anchored = TRUE
|
||||
is_anchored = !is_anchored
|
||||
move_resist = MOVE_FORCE_OVERPOWERING
|
||||
status_flags &= ~CANPUSH
|
||||
ADD_TRAIT(src, TRAIT_NO_TELEPORT, src)
|
||||
|
||||
to_chat(src, "<b>You are now [is_anchored ? "" : "un"]anchored.</b>")
|
||||
// the message in the [] will change depending whether or not the AI is anchored
|
||||
/mob/living/silicon/ai/proc/ai_mob_to_structure()
|
||||
disconnect_shell()
|
||||
ShutOffDoomsdayDevice()
|
||||
var/obj/structure/ai_core/deactivated/ai_core = new(get_turf(src), /* skip_mmi_creation = */ TRUE)
|
||||
if(make_mmi_drop_and_transfer(ai_core.core_mmi, the_core = ai_core))
|
||||
qdel(src)
|
||||
return ai_core
|
||||
|
||||
/mob/living/silicon/ai/proc/make_mmi_drop_and_transfer(obj/item/mmi/the_mmi, the_core)
|
||||
var/mmi_type
|
||||
if(posibrain_inside)
|
||||
mmi_type = new/obj/item/mmi/posibrain(src, /* autoping = */ FALSE)
|
||||
else
|
||||
mmi_type = new/obj/item/mmi(src)
|
||||
if(hack_software)
|
||||
new/obj/item/malf_upgrade(get_turf(src))
|
||||
the_mmi = mmi_type
|
||||
the_mmi.brain = new /obj/item/organ/brain(the_mmi)
|
||||
the_mmi.brain.organ_flags |= ORGAN_FROZEN
|
||||
the_mmi.brain.name = "[real_name]'s brain"
|
||||
the_mmi.name = "[initial(the_mmi.name)]: [real_name]"
|
||||
the_mmi.brainmob = new /mob/living/brain(the_mmi)
|
||||
the_mmi.brainmob.name = src.real_name
|
||||
the_mmi.brainmob.real_name = src.real_name
|
||||
the_mmi.brainmob.container = the_mmi
|
||||
the_mmi.brainmob.suiciding = suiciding
|
||||
if(the_core)
|
||||
var/obj/structure/ai_core/core = the_core
|
||||
core.core_mmi = the_mmi
|
||||
the_mmi.forceMove(the_core)
|
||||
else
|
||||
the_mmi.forceMove(get_turf(src))
|
||||
if(the_mmi.brainmob.stat == DEAD && !suiciding)
|
||||
the_mmi.brainmob.stat = CONSCIOUS
|
||||
if(mind)
|
||||
mind.transfer_to(the_mmi.brainmob)
|
||||
the_mmi.update_appearance()
|
||||
return TRUE
|
||||
|
||||
// AIs are immobile
|
||||
/mob/living/silicon/ai/update_mobility()
|
||||
@@ -427,18 +484,30 @@
|
||||
return
|
||||
|
||||
if (href_list["ai_take_control"]) //Mech domination
|
||||
var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"])
|
||||
var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"]) in GLOB.mechas_list
|
||||
if (!M)
|
||||
return
|
||||
|
||||
var/mech_has_controlbeacon = FALSE
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/ai_control/A in M.trackers)
|
||||
mech_has_controlbeacon = TRUE
|
||||
break
|
||||
if(!can_dominate_mechs && !mech_has_controlbeacon)
|
||||
message_admins("Warning: possible href exploit by [key_name(usr)] - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.")
|
||||
usr.log_message("possibly attempting href exploit - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.", LOG_ADMIN)
|
||||
return
|
||||
|
||||
if(controlled_equipment)
|
||||
to_chat(src, "<span class='warning'>You are already loaded into an onboard computer!</span>")
|
||||
to_chat(src, span_warning("You are already loaded into an onboard computer!"))
|
||||
return
|
||||
if(!GLOB.cameranet.checkCameraVis(M))
|
||||
to_chat(src, "<span class='warning'>Exosuit is no longer near active cameras.</span>")
|
||||
to_chat(src, span_warning("Exosuit is no longer near active cameras."))
|
||||
return
|
||||
if(!isturf(loc))
|
||||
to_chat(src, "<span class='warning'>You aren't in your core!</span>")
|
||||
to_chat(src, span_warning("You aren't in your core!"))
|
||||
return
|
||||
if(M)
|
||||
M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself.
|
||||
M.transfer_ai(AI_MECH_HACK, src, usr) //Called on the mech itself.
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C)
|
||||
@@ -825,10 +894,12 @@
|
||||
to_chat(user, "<span class='warning'>No intelligence patterns detected.</span>" )
|
||||
return
|
||||
ShutOffDoomsdayDevice()
|
||||
new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location.
|
||||
var/obj/structure/ai_core/new_core = new /obj/structure/ai_core/deactivated(loc, posibrain_inside)//Spawns a deactivated terminal at AI location.
|
||||
new_core.circuit.battery = battery
|
||||
ai_restore_power()//So the AI initially has power.
|
||||
control_disabled = 1//Can't control things remotely if you're stuck in a card!
|
||||
radio_enabled = 0 //No talking on the built-in radio for you either!
|
||||
control_disabled = TRUE //Can't control things remotely if you're stuck in a card!
|
||||
interaction_range = 0
|
||||
radio_enabled = FALSE //No talking on the built-in radio for you either!
|
||||
forceMove(card)
|
||||
card.AI = src
|
||||
to_chat(src, "You have been downloaded to a mobile storage device. Remote device connection severed.")
|
||||
@@ -1063,7 +1134,7 @@
|
||||
// Sends an announcement the AI has cryoed.
|
||||
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
|
||||
announcer.announce("CRYOSTORAGE", src.real_name, announce_rank, list())
|
||||
new /obj/structure/AIcore/latejoin_inactive(loc)
|
||||
new /obj/structure/ai_core/latejoin_inactive(loc)
|
||||
if(src.mind)
|
||||
//Handle job slot/tater cleanup.
|
||||
if(src.mind.assigned_role == "AI")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
|
||||
if(I.force && I.damtype != STAMINA && stat != DEAD && !QDELETED(src)) //only sparks if real damage is dealt.
|
||||
spark_system.start()
|
||||
|
||||
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
|
||||
@@ -48,3 +48,105 @@
|
||||
|
||||
/mob/living/silicon/ai/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
|
||||
return // no eyes, no flashing
|
||||
|
||||
/mob/living/silicon/ai/emag_act(mob/user, obj/item/card/emag/emag_card) ///emags access panel lock, so you can crowbar it without robotics access or consent
|
||||
. = ..()
|
||||
if(emagged)
|
||||
balloon_alert(user, "access panel lock already shorted!")
|
||||
return
|
||||
balloon_alert(user, "access panel lock shorted")
|
||||
var/message = (user ? "[user] shorts out your access panel lock!" : "Your access panel lock was short circuited!")
|
||||
to_chat(src, span_warning(message))
|
||||
do_sparks(3, FALSE, src) // just a bit of extra "oh shit" to the ai - might grab its attention
|
||||
emagged = TRUE
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/wrench_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return
|
||||
balloon_alert(user, "[!is_anchored ? "tightening" : "loosening"] bolts...")
|
||||
balloon_alert(src, "bolts being [!is_anchored ? "tightened" : "loosened"]...")
|
||||
if(!tool.use_tool(src, user, 4 SECONDS))
|
||||
return TRUE
|
||||
flip_anchored()
|
||||
balloon_alert(user, "bolts [is_anchored ? "tightened" : "loosened"]")
|
||||
balloon_alert(src, "bolts [is_anchored ? "tightened" : "loosened"]")
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/crowbar_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return
|
||||
if(!is_anchored)
|
||||
balloon_alert(user, "bolt it down first!")
|
||||
return TRUE
|
||||
if(opened)
|
||||
if(emagged)
|
||||
balloon_alert(user, "access panel lock damaged!")
|
||||
return TRUE
|
||||
balloon_alert(user, "closing access panel...")
|
||||
balloon_alert(src, "access panel being closed...")
|
||||
if(!tool.use_tool(src, user, 5 SECONDS))
|
||||
return TRUE
|
||||
balloon_alert(src, "access panel closed")
|
||||
balloon_alert(user, "access panel closed")
|
||||
opened = FALSE
|
||||
return TRUE
|
||||
if(stat == DEAD)
|
||||
to_chat(user, span_warning("The access panel looks damaged, you try dislodging the cover."))
|
||||
else
|
||||
var/consent
|
||||
var/consent_override = FALSE
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(human_user.wear_id)
|
||||
var/list/access = human_user.wear_id.GetAccess()
|
||||
if(ACCESS_ROBOTICS in access)
|
||||
consent_override = TRUE
|
||||
if(mind)
|
||||
consent = tgui_alert(src, "[user] is attempting to open your access panel, unlock the cover?", "AI Access Panel", list("Yes", "No"))
|
||||
if(consent == "No" && !consent_override && !emagged)
|
||||
to_chat(user, span_notice("[src] refuses to unlock its access panel."))
|
||||
return TRUE
|
||||
if(consent != "Yes" && (consent_override || emagged))
|
||||
to_chat(user, span_warning("[src] refuses to unlock its access panel...so you[!emagged ? " swipe your ID and " : " "]open it anyway!"))
|
||||
else
|
||||
if(!consent_override && !emagged)
|
||||
to_chat(user, span_notice("[src] did not respond to your request to unlock its access panel cover lock."))
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, span_notice("[src] did not respond to your request to unlock its access panel cover lock. You[!emagged ? " swipe your ID and " : " "]open it anyway."))
|
||||
|
||||
balloon_alert(user, "prying open access panel...")
|
||||
balloon_alert(src, "access panel being pried open...")
|
||||
if(!tool.use_tool(src, user, (stat == DEAD ? 40 SECONDS : 5 SECONDS)))
|
||||
return TRUE
|
||||
balloon_alert(src, "access panel opened")
|
||||
balloon_alert(user, "access panel opened")
|
||||
opened = TRUE
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/wirecutter_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return
|
||||
if(!is_anchored)
|
||||
balloon_alert(user, "bolt it down first!")
|
||||
return TRUE
|
||||
if(!opened)
|
||||
balloon_alert(user, "open the access panel first!")
|
||||
return TRUE
|
||||
balloon_alert(src, "neural network being disconnected...")
|
||||
balloon_alert(user, "disconnecting neural network...")
|
||||
if(!tool.use_tool(src, user, (stat == DEAD ? 40 SECONDS : 5 SECONDS)))
|
||||
return TRUE
|
||||
if(IS_MALF_AI(src))
|
||||
to_chat(user, span_userdanger("The voltage inside the wires rises dramatically!"))
|
||||
user.electrocute_act(120, src)
|
||||
opened = FALSE
|
||||
return TRUE
|
||||
to_chat(src, span_danger("You feel incredibly confused and disorientated."))
|
||||
var/atom/ai_structure = ai_mob_to_structure()
|
||||
ai_structure.balloon_alert(user, "disconnected neural network")
|
||||
return TRUE
|
||||
|
||||
@@ -28,11 +28,15 @@
|
||||
// Handle power damage (oxy)
|
||||
if(aiRestorePowerRoutine)
|
||||
// Lost power
|
||||
adjustOxyLoss(1)
|
||||
if (!battery)
|
||||
to_chat(src, span_warning("Your backup battery's output drops below usable levels. It takes only a moment longer for your systems to fail, corrupted and unusable."))
|
||||
adjustOxyLoss(200)
|
||||
else
|
||||
battery--
|
||||
else
|
||||
// Gain Power
|
||||
if(getOxyLoss())
|
||||
adjustOxyLoss(-1)
|
||||
if (battery < 200)
|
||||
battery++
|
||||
|
||||
if(!lacks_power())
|
||||
var/area/home = get_area(src)
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
if(BORG_SEC_AVAILABLE)
|
||||
modulelist["Security"] = /obj/item/robot_module/security
|
||||
|
||||
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in sortList(modulelist)
|
||||
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in sort_list(modulelist)
|
||||
if(!input_module || module.type != /obj/item/robot_module)
|
||||
return
|
||||
|
||||
@@ -379,8 +379,8 @@
|
||||
to_chat(user, span_warning("You can't reach the wiring!"))
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/aiModule))
|
||||
var/obj/item/aiModule/MOD = W
|
||||
if(istype(W, /obj/item/ai_module))
|
||||
var/obj/item/ai_module/MOD = W
|
||||
if(!opened)
|
||||
to_chat(user, span_warning("You need access to the robot's insides to do that!"))
|
||||
return
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high ///If this is a path, this gets created as an object in Initialize.
|
||||
|
||||
var/opened = FALSE
|
||||
var/emagged = FALSE
|
||||
var/emag_cooldown = 0
|
||||
var/wiresexposed = FALSE
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-med")
|
||||
bad_snowflake.pixel_x = -16
|
||||
med_icons["Alina"] = bad_snowflake
|
||||
med_icons = sortList(med_icons)
|
||||
med_icons = sort_list(med_icons)
|
||||
var/med_borg_icon = show_radial_menu(R, R , med_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
|
||||
switch(med_borg_icon)
|
||||
if("Default")
|
||||
@@ -498,7 +498,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-eng")
|
||||
bad_snowflake.pixel_x = -16
|
||||
engi_icons["Alina"] = bad_snowflake
|
||||
engi_icons = sortList(engi_icons)
|
||||
engi_icons = sort_list(engi_icons)
|
||||
var/engi_borg_icon = show_radial_menu(R, R , engi_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
|
||||
switch(engi_borg_icon)
|
||||
if("Default")
|
||||
@@ -595,7 +595,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
|
||||
bad_snowflake.pixel_x = -16
|
||||
sec_icons["Alina"] = bad_snowflake
|
||||
sec_icons = sortList(sec_icons)
|
||||
sec_icons = sort_list(sec_icons)
|
||||
var/sec_borg_icon = show_radial_menu(R, R , sec_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
|
||||
switch(sec_borg_icon)
|
||||
if("Default")
|
||||
@@ -681,7 +681,7 @@
|
||||
|
||||
/obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module)
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
var/static/list/peace_icons = sortList(list(
|
||||
var/static/list/peace_icons = sort_list(list(
|
||||
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"),
|
||||
"Borgi" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "borgi"),
|
||||
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider")
|
||||
@@ -852,7 +852,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
|
||||
bad_snowflake.pixel_x = -16
|
||||
service_icons["Alina"] = bad_snowflake
|
||||
service_icons = sortList(service_icons)
|
||||
service_icons = sort_list(service_icons)
|
||||
var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
|
||||
switch(service_robot_icon)
|
||||
if("(Service) Waitress")
|
||||
@@ -966,7 +966,7 @@
|
||||
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
|
||||
wide.pixel_x = -16
|
||||
mining_icons[a] = wide
|
||||
mining_icons = sortList(mining_icons)
|
||||
mining_icons = sort_list(mining_icons)
|
||||
var/mining_borg_icon = show_radial_menu(R, R , mining_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
|
||||
switch(mining_borg_icon)
|
||||
if("Lavaland")
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
var/obj/machinery/camera/builtInCamera = null
|
||||
var/updating = FALSE //portable camera camerachunk update
|
||||
|
||||
///Whether we have been emagged
|
||||
var/emagged = FALSE
|
||||
var/hack_software = FALSE //Will be able to use hacking actions
|
||||
var/interaction_range = 7 //wireless control range
|
||||
|
||||
|
||||
@@ -138,13 +138,14 @@
|
||||
bike_horn(A)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(AM, /obj/item))
|
||||
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/hitting_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(hitting_atom, /obj/item))
|
||||
playsound(src, honksound, 50, TRUE, -1)
|
||||
var/obj/item/I = AM
|
||||
if(I.throwforce < health && I.thrownby && (istype(I.thrownby, /mob/living/carbon/human)))
|
||||
var/mob/living/carbon/human/H = I.thrownby
|
||||
retaliate(H)
|
||||
var/obj/item/item_hitby = hitting_atom
|
||||
var/mob/thrown_by = item_hitby.thrownby?.resolve()
|
||||
if(item_hitby.throwforce < src.health && thrown_by && ishuman(thrown_by))
|
||||
var/mob/living/carbon/human/human_throwee = thrown_by
|
||||
retaliate(human_throwee)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/bike_horn() //use bike_horn
|
||||
|
||||
@@ -351,12 +351,13 @@
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby))
|
||||
var/mob/living/carbon/human/H = I.thrownby
|
||||
retaliate(H)
|
||||
/mob/living/simple_animal/bot/secbot/hitby(atom/movable/hitting_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(hitting_atom, /obj/item))
|
||||
var/obj/item/item_hitby = hitting_atom
|
||||
var/mob/thrown_by = item_hitby.thrownby?.resolve()
|
||||
if(item_hitby.throwforce < src.health && thrown_by && ishuman(thrown_by))
|
||||
var/mob/living/carbon/human/human_throwee = thrown_by
|
||||
retaliate(human_throwee)
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
..() //lose items, then return
|
||||
|
||||
//SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE
|
||||
/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, silent = FALSE)
|
||||
/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, invdrop, silent = FALSE)
|
||||
if(..())
|
||||
update_inv_hands()
|
||||
if(I == internal_storage)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
if(!stat)
|
||||
Aggro()
|
||||
if(T.throwforce <= 20)
|
||||
visible_message("<span class='notice'>The [T.name] [throw_message] [src.name]!</span>")
|
||||
visible_message(span_notice("The [T.name] [throw_message] [src.name]!"))
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
@@ -587,7 +587,7 @@
|
||||
|
||||
//ANIMAL RIDING
|
||||
|
||||
/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user)
|
||||
/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user, check_loc)
|
||||
var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding)
|
||||
if(riding_datum)
|
||||
if(user.incapacitated())
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
Feedon(Food)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/slime/doUnEquip(obj/item/W, silent = FALSE)
|
||||
/mob/living/simple_animal/slime/doUnEquip(obj/item/W, invdrop, silent = FALSE)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
|
||||
var/research_scanner = 0 //For research scanner equipped mobs. Enable to show research data when examining.
|
||||
|
||||
var/in_throw_mode = 0
|
||||
var/throw_mode = 0
|
||||
|
||||
var/job = null//Living
|
||||
|
||||
|
||||
@@ -454,7 +454,7 @@
|
||||
var/obj/item/computer_hardware/H = all_components[h]
|
||||
component_names.Add(H.name)
|
||||
|
||||
var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sortList(component_names)
|
||||
var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sort_list(component_names)
|
||||
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
auto.Remove(buckled_mob)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user)
|
||||
/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc)
|
||||
if(user.incapacitated() || !istype(user))
|
||||
return
|
||||
for(var/atom/movable/A in get_turf(src))
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
burst_size = 1
|
||||
|
||||
sortList(fire_select_modes, /proc/cmp_numeric_asc)
|
||||
sort_list(fire_select_modes, /proc/cmp_numeric_asc)
|
||||
|
||||
if(fire_select_modes.len > 1)
|
||||
firemode_action = new(src)
|
||||
|
||||
@@ -94,16 +94,16 @@
|
||||
|
||||
/obj/machinery/chem_dispenser/Initialize(mapload)
|
||||
. = ..()
|
||||
dispensable_reagents = sortList(dispensable_reagents, /proc/cmp_reagents_asc)
|
||||
dispensable_reagents = sort_list(dispensable_reagents, /proc/cmp_reagents_asc)
|
||||
if(emagged_reagents)
|
||||
emagged_reagents = sortList(emagged_reagents, /proc/cmp_reagents_asc)
|
||||
emagged_reagents = sort_list(emagged_reagents, /proc/cmp_reagents_asc)
|
||||
if(upgrade_reagents)
|
||||
upgrade_reagents = sortList(upgrade_reagents, /proc/cmp_reagents_asc)
|
||||
upgrade_reagents = sort_list(upgrade_reagents, /proc/cmp_reagents_asc)
|
||||
if(upgrade_reagents2)
|
||||
upgrade_reagents2 = sortList(upgrade_reagents2, /proc/cmp_reagents_asc)
|
||||
upgrade_reagents2 = sort_list(upgrade_reagents2, /proc/cmp_reagents_asc)
|
||||
if(upgrade_reagents3)
|
||||
upgrade_reagents3 = sortList(upgrade_reagents3, /proc/cmp_reagents_asc)
|
||||
dispensable_reagents = sortList(dispensable_reagents, /proc/cmp_reagents_asc)
|
||||
upgrade_reagents3 = sort_list(upgrade_reagents3, /proc/cmp_reagents_asc)
|
||||
dispensable_reagents = sort_list(dispensable_reagents, /proc/cmp_reagents_asc)
|
||||
create_reagents(200, NO_REACT)
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -106,9 +106,10 @@
|
||||
/obj/item/reagent_containers/proc/bartender_check(atom/target)
|
||||
. = FALSE
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T || !target.CanPass(src, T) || !thrownby || !thrownby.actions)
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(!T || !target.CanPass(src, T) || !thrown_by || !thrown_by.actions)
|
||||
return
|
||||
var/datum/action/innate/D = get_action_of_type(thrownby, /datum/action/innate/drink_fling)
|
||||
var/datum/action/innate/D = get_action_of_type(thrown_by, /datum/action/innate/drink_fling)
|
||||
if(D?.active)
|
||||
return TRUE
|
||||
|
||||
@@ -118,6 +119,7 @@
|
||||
/obj/item/reagent_containers/proc/SplashReagents(atom/target, thrown = FALSE)
|
||||
if(!reagents || !reagents.total_volume || !spillable)
|
||||
return
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
|
||||
if(ismob(target) && target.reagents)
|
||||
if(thrown)
|
||||
@@ -128,10 +130,10 @@
|
||||
"<span class='userdanger'>[M] has been splashed with something!</span>")
|
||||
var/turf/TT = get_turf(target)
|
||||
var/throwerstring
|
||||
if(thrownby && thrown)
|
||||
log_combat(thrownby, M, "splashed", R)
|
||||
var/turf/AT = get_turf(thrownby)
|
||||
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]"
|
||||
if(thrown_by && thrown)
|
||||
log_combat(thrown_by, M, "splashed", R)
|
||||
var/turf/AT = get_turf(thrown_by)
|
||||
throwerstring = " THROWN BY [key_name(thrown_by)] at [AT] (AREACOORD(AT)]"
|
||||
log_reagent("SPLASH: [src] mob SplashReagents() onto [key_name(target)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]")
|
||||
reagents.reaction(target, TOUCH)
|
||||
reagents.clear_reagents()
|
||||
@@ -142,15 +144,15 @@
|
||||
addtimer(CALLBACK(src, .proc/ForceResetRotation), 1)
|
||||
|
||||
else
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
|
||||
log_game("[key_name(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].")
|
||||
if(isturf(target) && reagents.reagent_list.len && thrown_by)
|
||||
log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
|
||||
log_game("[key_name(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].")
|
||||
var/turf/T = get_turf(target)
|
||||
var/throwerstring
|
||||
if(thrownby && thrown)
|
||||
var/turf/AT = get_turf(thrownby)
|
||||
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] ([AREACOORD(AT)])"
|
||||
if(thrown_by && thrown)
|
||||
var/turf/AT = get_turf(thrown_by)
|
||||
throwerstring = " THROWN BY [key_name(thrown_by)] at [AT] ([AREACOORD(AT)])"
|
||||
log_reagent("SPLASH - [src] object SplashReagents() onto [target] at [T] ([AREACOORD(T)])[throwerstring] - [reagents.log_list()]")
|
||||
visible_message("<span class='notice'>[src] spills its contents all over [target].</span>")
|
||||
reagents.reaction(target, TOUCH)
|
||||
|
||||
@@ -29,9 +29,10 @@
|
||||
M.visible_message("<span class='danger'>[user] splashes the contents of [src] onto [M]!</span>", \
|
||||
"<span class='userdanger'>[user] splashes the contents of [src] onto [M]!</span>")
|
||||
var/R = reagents?.log_list()
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(isturf(target) && reagents.reagent_list.len && thrown_by)
|
||||
log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
reagents.reaction(M, TOUCH)
|
||||
log_combat(user, M, "splashed", R)
|
||||
var/turf/UT = get_turf(user)
|
||||
|
||||
@@ -359,10 +359,10 @@
|
||||
if(isitem(AM) && AM.CanEnterDisposals())
|
||||
if(prob(75))
|
||||
AM.forceMove(src)
|
||||
visible_message("<span class='notice'>[AM] lands in [src].</span>")
|
||||
update_icon()
|
||||
visible_message(span_notice("[AM] lands in [src]."))
|
||||
update_appearance()
|
||||
else
|
||||
visible_message("<span class='notice'>[AM] bounces off of [src]'s rim!</span>")
|
||||
visible_message(span_notice("[AM] bounces off of [src]'s rim!"))
|
||||
return ..()
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
desc = "Allows for the construction of a Safeguard AI Module."
|
||||
id = "safeguard_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/gold = 2000)
|
||||
build_path = /obj/item/aiModule/supplied/safeguard
|
||||
build_path = /obj/item/ai_module/supplied/safeguard
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
desc = "Allows for the construction of a OneCrew AI Module."
|
||||
id = "onehuman_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 6000)
|
||||
build_path = /obj/item/aiModule/zeroth/oneHuman
|
||||
build_path = /obj/item/ai_module/zeroth/oneHuman
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
desc = "Allows for the construction of a ProtectStation AI Module."
|
||||
id = "protectstation_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/gold = 2000)
|
||||
build_path = /obj/item/aiModule/supplied/protectStation
|
||||
build_path = /obj/item/ai_module/supplied/protectStation
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
desc = "Allows for the construction of a Quarantine AI Module."
|
||||
id = "quarantine_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/gold = 2000)
|
||||
build_path = /obj/item/aiModule/supplied/quarantine
|
||||
build_path = /obj/item/ai_module/supplied/quarantine
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
desc = "Allows for the construction of a Safeguard AI Module."
|
||||
id = "oxygen_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/gold = 2000)
|
||||
build_path = /obj/item/aiModule/supplied/oxygen
|
||||
build_path = /obj/item/ai_module/supplied/oxygen
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
desc = "Allows for the construction of a Freeform AI Module."
|
||||
id = "freeform_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/gold = 10000)//Custom inputs should be more expensive to get
|
||||
build_path = /obj/item/aiModule/supplied/freeform
|
||||
build_path = /obj/item/ai_module/supplied/freeform
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
desc = "Allows for the construction of a Reset AI Module."
|
||||
id = "reset_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/gold = 2000)
|
||||
build_path = /obj/item/aiModule/reset
|
||||
build_path = /obj/item/ai_module/reset
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
desc = "Allows for the construction of a Purge AI Module."
|
||||
id = "purge_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 2000)
|
||||
build_path = /obj/item/aiModule/reset/purge
|
||||
build_path = /obj/item/ai_module/reset/purge
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
desc = "Allows for the construction of a Law Removal AI Core Module."
|
||||
id = "remove_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 2000)
|
||||
build_path = /obj/item/aiModule/remove
|
||||
build_path = /obj/item/ai_module/remove
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
desc = "Allows for the construction of a Freeform AI Core Module."
|
||||
id = "freeformcore_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 10000)//Ditto
|
||||
build_path = /obj/item/aiModule/core/freeformcore
|
||||
build_path = /obj/item/ai_module/core/freeformcore
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
desc = "Allows for the construction of an Asimov AI Core Module."
|
||||
id = "asimov_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 2000)
|
||||
build_path = /obj/item/aiModule/core/full/asimov
|
||||
build_path = /obj/item/ai_module/core/full/asimov
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
id = "paladin_module"
|
||||
build_type = IMPRINTER
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 2000)
|
||||
build_path = /obj/item/aiModule/core/full/paladin
|
||||
build_path = /obj/item/ai_module/core/full/paladin
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
desc = "Allows for the construction of a T.Y.R.A.N.T. AI Module."
|
||||
id = "tyrant_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 2000)
|
||||
build_path = /obj/item/aiModule/core/full/tyrant
|
||||
build_path = /obj/item/ai_module/core/full/tyrant
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
desc = "Allows for the construction of a Corporate AI Core Module."
|
||||
id = "corporate_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 2000)
|
||||
build_path = /obj/item/aiModule/core/full/corp
|
||||
build_path = /obj/item/ai_module/core/full/corp
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -142,6 +142,6 @@
|
||||
desc = "Allows for the construction of a Default AI Core Module."
|
||||
id = "default_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/diamond = 2000)
|
||||
build_path = /obj/item/aiModule/core/full/custom
|
||||
build_path = /obj/item/ai_module/core/full/custom
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
@@ -145,13 +145,13 @@
|
||||
name = "Hacked AI Law Upload Module"
|
||||
desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. \
|
||||
Be careful with wording, as artificial intelligences may look for loopholes to exploit."
|
||||
item = /obj/item/aiModule/syndicate
|
||||
item = /obj/item/ai_module/syndicate
|
||||
cost = 9
|
||||
|
||||
/datum/uplink_item/device_tools/damaged_module
|
||||
name = "Damaged AI Law Upload Module"
|
||||
desc = "This AI law upload module has been laying around our warehouse for god knows how long. We do not know why you would ever use this."
|
||||
item = /obj/item/aiModule/core/full/damaged
|
||||
item = /obj/item/ai_module/core/full/damaged
|
||||
cost = 5
|
||||
|
||||
/datum/uplink_item/device_tools/headsetupgrade
|
||||
|
||||
@@ -198,7 +198,8 @@
|
||||
|
||||
/obj/vehicle/sealed/mecha/Destroy()
|
||||
for(var/ejectee in occupants)
|
||||
mob_exit(ejectee, TRUE, TRUE)
|
||||
mob_exit(ejectee, silent = TRUE)
|
||||
|
||||
if(LAZYLEN(equipment))
|
||||
for(var/obj/item/mecha_parts/mecha_equipment/equip as anything in equipment)
|
||||
equip.detach(loc)
|
||||
@@ -215,6 +216,8 @@
|
||||
QDEL_NULL(cabin_air)
|
||||
QDEL_NULL(spark_system)
|
||||
QDEL_NULL(smoke_system)
|
||||
QDEL_NULL(trackers)
|
||||
QDEL_NULL(wires)
|
||||
|
||||
GLOB.poi_list -= src
|
||||
GLOB.mechas_list -= src //global mech list
|
||||
@@ -223,14 +226,39 @@
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/sealed/mecha/obj_destruction()
|
||||
spark_system?.start()
|
||||
loc.assume_air(cabin_air)
|
||||
air_update_turf(FALSE, FALSE)
|
||||
|
||||
var/mob/living/silicon/ai/unlucky_ai
|
||||
for(var/mob/living/occupant as anything in occupants)
|
||||
if(isAI(occupant))
|
||||
occupant.gib() //No wreck, no AI to recover
|
||||
var/mob/living/silicon/ai/ai = occupant
|
||||
if(!ai.linked_core) // we probably shouldnt gib AIs with a core
|
||||
unlucky_ai = occupant
|
||||
ai.investigate_log("has been gibbed by having their mech destroyed.", INVESTIGATE_DEATHS)
|
||||
ai.gib() //No wreck, no AI to recover
|
||||
else
|
||||
mob_exit(ai,silent = TRUE, forced = TRUE) // so we dont ghost the AI
|
||||
continue
|
||||
mob_exit(occupant, FALSE, TRUE)
|
||||
occupant.SetSleeping(destruction_sleep_duration)
|
||||
mob_exit(occupant, forced = TRUE)
|
||||
if(!isbrain(occupant)) // who would win.. 1 brain vs 1 sleep proc..
|
||||
occupant.SetSleeping(destruction_sleep_duration)
|
||||
|
||||
if(wreckage)
|
||||
var/obj/structure/mecha_wreckage/WR = new wreckage(loc, unlucky_ai)
|
||||
for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
|
||||
if(E.detachable && prob(30))
|
||||
WR.crowbar_salvage += E
|
||||
E.detach(WR) //detaches from src into WR
|
||||
else
|
||||
E.detach(loc)
|
||||
qdel(E)
|
||||
if(cell)
|
||||
WR.crowbar_salvage += cell
|
||||
cell.forceMove(WR)
|
||||
cell.use(rand(0, cell.charge), TRUE)
|
||||
cell = null
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/sealed/mecha/update_icon()
|
||||
@@ -480,7 +508,7 @@
|
||||
var/mob/living/occupant = b
|
||||
if(!enclosed && occupant?.incapacitated()) //no sides mean it's easy to just sorta fall out if you're incapacitated.
|
||||
visible_message("<span class='warning'>[occupant] tumbles out of the cockpit!</span>")
|
||||
mob_try_exit(occupant, TRUE, TRUE) //bye bye
|
||||
mob_exit(occupant, randomstep = TRUE) //bye bye
|
||||
|
||||
//Diagnostic HUD updates
|
||||
diag_hud_set_mechhealth()
|
||||
@@ -796,19 +824,31 @@
|
||||
to_chat(user, "<a href='?src=[REF(user)];ai_take_control=[REF(src)]'><span class='boldnotice'>Take control of exosuit?</span></a><br>")
|
||||
|
||||
/obj/vehicle/sealed/mecha/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
|
||||
if(!..())
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
//Transfer from core or card to mech. Proc is called by mech.
|
||||
switch(interaction)
|
||||
if(AI_TRANS_TO_CARD) //Upload AI from mech to AI card.
|
||||
if(!construction_state) //Mech must be in maint mode to allow carding.
|
||||
to_chat(user, "<span class='warning'>[name] must have maintenance protocols active in order to allow a transfer.</span>")
|
||||
to_chat(user, span_warning("[name] must have maintenance protocols active in order to allow a transfer."))
|
||||
return
|
||||
if(!locate(AI) in occupants) //Mech does not have an AI for a pilot
|
||||
to_chat(user, "<span class='warning'>No AI detected in the [name] onboard computer.</span>")
|
||||
var/list/ai_pilots = list()
|
||||
for(var/mob/living/silicon/ai/aipilot in occupants)
|
||||
ai_pilots += aipilot
|
||||
if(!length(ai_pilots)) //Mech does not have an AI for a pilot
|
||||
to_chat(user, span_warning("No AI detected in the [name] onboard computer."))
|
||||
return
|
||||
for(var/mob/living/silicon/ai in occupants)
|
||||
if(length(ai_pilots) > 1) //Input box for multiple AIs, but if there's only one we'll default to them.
|
||||
AI = tgui_input_list(user, "Which AI do you wish to card?", "AI Selection", sort_list(ai_pilots))
|
||||
else
|
||||
AI = ai_pilots[1]
|
||||
if(isnull(AI))
|
||||
return
|
||||
if(!(AI in occupants) || !user.Adjacent(src))
|
||||
return //User sat on the selection window and things changed.
|
||||
|
||||
AI.ai_restore_power()//So the AI initially has power.
|
||||
AI.control_disabled = TRUE
|
||||
AI.radio_enabled = FALSE
|
||||
@@ -819,36 +859,37 @@
|
||||
card.AI = AI
|
||||
AI.controlled_equipment = null
|
||||
AI.remote_control = null
|
||||
to_chat(AI, "<span class='notice'>You have been downloaded to a mobile storage device. Wireless connection offline.</span>")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
|
||||
to_chat(AI, span_notice("You have been downloaded to a mobile storage device. Wireless connection offline."))
|
||||
to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
|
||||
return
|
||||
|
||||
if(AI_MECH_HACK) //Called by AIs on the mech
|
||||
AI.linked_core = new /obj/structure/AIcore/deactivated(AI.loc)
|
||||
if(AI.can_dominate_mechs)
|
||||
if(LAZYLEN(occupants)) //Oh, I am sorry, were you using that?
|
||||
to_chat(AI, "<span class='warning'>Occupants detected! Forced ejection initiated!</span>")
|
||||
to_chat(occupants, "<span class='danger'>You have been forcibly ejected!</span>")
|
||||
ejectall() //IT IS MINE, NOW. SUCK IT, RD!
|
||||
ai_enter_mech(AI, interaction)
|
||||
AI.linked_core = new /obj/structure/ai_core/deactivated(AI.loc)
|
||||
if(AI.can_dominate_mechs && LAZYLEN(occupants)) //Oh, I am sorry, were you using that?
|
||||
to_chat(AI, span_warning("Occupants detected! Forced ejection initiated!"))
|
||||
to_chat(occupants, span_danger("You have been forcibly ejected!"))
|
||||
for(var/ejectee in occupants)
|
||||
mob_exit(ejectee, silent = TRUE, randomstep = TRUE, forced = TRUE) //IT IS MINE, NOW. SUCK IT, RD!
|
||||
AI.can_shunt = FALSE //ONE AI ENTERS. NO AI LEAVES.
|
||||
|
||||
if(AI_TRANS_FROM_CARD) //Using an AI card to upload to a mech.
|
||||
AI = card.AI
|
||||
if(!AI)
|
||||
to_chat(user, "<span class='warning'>There is no AI currently installed on this device.</span>")
|
||||
to_chat(user, span_warning("There is no AI currently installed on this device."))
|
||||
return
|
||||
if(AI.deployed_shell) //Recall AI if shelled so it can be checked for a client
|
||||
AI.disconnect_shell()
|
||||
if(AI.stat || !AI.client)
|
||||
to_chat(user, "<span class='warning'>[AI.name] is currently unresponsive, and cannot be uploaded.</span>")
|
||||
to_chat(user, span_warning("[AI.name] is currently unresponsive, and cannot be uploaded."))
|
||||
return
|
||||
if((LAZYLEN(occupants) >= max_occupants) || dna_lock) //Normal AIs cannot steal mechs!
|
||||
to_chat(user, "<span class='warning'>Access denied. [name] is [LAZYLEN(occupants) >= max_occupants ? "currently fully occupied" : "secured with a DNA lock"].</span>")
|
||||
to_chat(user, span_warning("Access denied. [name] is [LAZYLEN(occupants) >= max_occupants ? "currently fully occupied" : "secured with a DNA lock"]."))
|
||||
return
|
||||
AI.control_disabled = FALSE
|
||||
AI.radio_enabled = TRUE
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
|
||||
to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
|
||||
card.AI = null
|
||||
ai_enter_mech(AI, interaction)
|
||||
ai_enter_mech(AI)
|
||||
|
||||
//Hack and From Card interactions share some code, so leave that here for both to use.
|
||||
/obj/vehicle/sealed/mecha/proc/ai_enter_mech(mob/living/silicon/ai/AI, interaction)
|
||||
@@ -865,7 +906,6 @@
|
||||
"<span class='notice'>You have been uploaded to a mech's onboard computer.</span>")
|
||||
to_chat(AI, "<span class='reallybig boldnotice'>Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.</span>")
|
||||
|
||||
|
||||
///Handles an actual AI (simple_animal mecha pilot) entering the mech
|
||||
/obj/vehicle/sealed/mecha/proc/aimob_enter_mech(mob/living/simple_animal/hostile/syndicate/mecha_pilot/pilot_mob)
|
||||
if(pilot_mob && pilot_mob.Adjacent(src))
|
||||
@@ -1042,47 +1082,45 @@
|
||||
if(isAI(user))
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(!AI.can_shunt)
|
||||
to_chat(AI, "<span class='notice'>You can't leave a mech after dominating it!.</span>")
|
||||
to_chat(AI, span_notice("You can't leave a mech after dominating it!."))
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You begin the ejection procedure. Equipment is disabled during this process. Hold still to finish ejecting.</span>")
|
||||
to_chat(user, span_notice("You begin the ejection procedure. Equipment is disabled during this process. Hold still to finish ejecting."))
|
||||
is_currently_ejecting = TRUE
|
||||
if(do_after(user, exit_delay , target = src))
|
||||
to_chat(user, "<span class='notice'>You exit the mech.</span>")
|
||||
mob_try_exit(user, silent = FALSE)
|
||||
if(do_after(user, has_gravity() ? exit_delay : 0 , target = src))
|
||||
to_chat(user, span_notice("You exit the mech."))
|
||||
mob_exit(user, silent = TRUE)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You stop exiting the mech. Weapons are enabled again.</span>")
|
||||
to_chat(user, span_notice("You stop exiting the mech. Weapons are enabled again."))
|
||||
is_currently_ejecting = FALSE
|
||||
|
||||
/obj/vehicle/sealed/mecha/proc/ejectall()
|
||||
for(var/ejectee in occupants)
|
||||
mob_try_exit(ejectee, TRUE, TRUE)
|
||||
|
||||
/obj/vehicle/sealed/mecha/mob_try_exit(mob/M, silent, randomstep)
|
||||
mob_exit(M, silent, randomstep)
|
||||
|
||||
/obj/vehicle/sealed/mecha/mob_exit(mob/M, silent, forced)
|
||||
var/newloc = get_turf(src)
|
||||
/obj/vehicle/sealed/mecha/mob_exit(mob/M, silent = FALSE, randomstep = FALSE, forced = FALSE)
|
||||
var/atom/movable/mob_container
|
||||
var/turf/newloc = get_turf(src)
|
||||
if(ishuman(M))
|
||||
remove_occupant(M)
|
||||
..()
|
||||
return
|
||||
mob_container = M
|
||||
else if(isbrain(M))
|
||||
var/mob/living/brain/brain = M
|
||||
mob_container = brain.container
|
||||
else if(isAI(M))
|
||||
var/mob/living/silicon/ai/AI = M
|
||||
//stop listening to this signal, as the static update is now handled by the eyeobj's setLoc
|
||||
AI.eyeobj?.UnregisterSignal(src, COMSIG_MOVABLE_MOVED)
|
||||
AI.eyeobj?.forceMove(newloc) //kick the eye out as well
|
||||
if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf.
|
||||
AI.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
|
||||
if(!AI.linked_core) //if the victim AI has no core
|
||||
AI.investigate_log("has been gibbed by being forced out of their mech by another AI.", INVESTIGATE_DEATHS)
|
||||
AI.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
|
||||
AI = null
|
||||
mecha_flags &= ~SILICON_PILOT
|
||||
return
|
||||
else
|
||||
if(!AI.linked_core)
|
||||
to_chat(AI, "<span class='userdanger'>Inactive core destroyed. Unable to return.</span>")
|
||||
if(!silent)
|
||||
to_chat(AI, span_userdanger("Inactive core destroyed. Unable to return."))
|
||||
AI.linked_core = null
|
||||
return
|
||||
to_chat(AI, "<span class='notice'>Returning to core...</span>")
|
||||
if(!silent)
|
||||
to_chat(AI, span_notice("Returning to core..."))
|
||||
AI.controlled_equipment = null
|
||||
AI.remote_control = null
|
||||
mob_container = AI
|
||||
@@ -1090,21 +1128,20 @@
|
||||
qdel(AI.linked_core)
|
||||
else
|
||||
return ..()
|
||||
var/mob/living/L = M
|
||||
var/mob/living/ejector = M
|
||||
mecha_flags &= ~SILICON_PILOT
|
||||
if(mob_container.forceMove(newloc))
|
||||
log_message("[mob_container] moved out.", LOG_MECHA)
|
||||
L << browse(null, "window=exosuit")
|
||||
mob_container.forceMove(newloc)//ejecting mob container
|
||||
log_message("[mob_container] moved out.", LOG_MECHA)
|
||||
SStgui.close_user_uis(M, src)
|
||||
if(istype(mob_container, /obj/item/mmi))
|
||||
var/obj/item/mmi/mmi = mob_container
|
||||
if(mmi.brainmob)
|
||||
L.forceMove(mmi)
|
||||
L.reset_perspective()
|
||||
remove_occupant(L)
|
||||
ejector.forceMove(mmi)
|
||||
ejector.reset_perspective()
|
||||
remove_occupant(ejector)
|
||||
mmi.mecha = null
|
||||
mmi.update_icon()
|
||||
L.mobility_flags = NONE
|
||||
setDir(dir_in)
|
||||
mmi.update_appearance()
|
||||
setDir(SOUTH)
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
else
|
||||
add_control_flags(M, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
|
||||
|
||||
/obj/vehicle/sealed/mecha/combat/neovgre/mob_exit(mob/M, silent, forced)
|
||||
/obj/vehicle/sealed/mecha/combat/neovgre/mob_exit(mob/M, silent, randomstep, forced)
|
||||
if(forced)
|
||||
..()
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
/obj/vehicle/sealed/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper
|
||||
log_message("Hit by [AM].", LOG_MECHA, color="red")
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/sealed/mecha/bullet_act(obj/item/projectile/Proj) //wrapper
|
||||
if(!enclosed && LAZYLEN(occupants) && !(mecha_flags & SILICON_PILOT) && !Proj.force_hit && (Proj.def_zone == BODY_ZONE_HEAD || Proj.def_zone == BODY_ZONE_CHEST)) //allows bullets to hit the pilot of open-canopy mechs
|
||||
|
||||
Reference in New Issue
Block a user