diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 246377eba32..d5a1ad8cbfd 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -161,12 +161,8 @@ GLOBAL_VAR(syndicate_code_response) //Code response for traitors. if(1)//1 and 2 can only be selected once each to prevent more than two specific names/places/etc. switch(rand(1,2))//Mainly to add more options later. if(1) - if(names.len&&prob(70)) + if(names.len) code_phrase += pick(names) - else - code_phrase += pick(pick(GLOB.first_names_male,GLOB.first_names_female)) - code_phrase += " " - code_phrase += pick(GLOB.last_names) if(2) code_phrase += pick(GLOB.joblist)//Returns a job. safety -= 1 diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index e5674a9b47b..f933105e13b 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -86,4 +86,6 @@ var/copier_max_items = 300 var/copier_items_printed_logged = FALSE -GLOBAL_VAR(map_name) // Self explanatory \ No newline at end of file +GLOBAL_VAR(map_name) // Self explanatory + +var/global/datum/datacore/data_core = null // Station datacore, manifest, etc \ No newline at end of file diff --git a/code/_globalvars/station.dm b/code/_globalvars/station.dm deleted file mode 100644 index ba8b70991c2..00000000000 --- a/code/_globalvars/station.dm +++ /dev/null @@ -1,2 +0,0 @@ -// TODO: Move this to be not in its own fucking file all alone on its own -var/global/datum/datacore/data_core = null \ No newline at end of file diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm index 6fe3a781642..1e8f99814df 100644 --- a/code/_onclick/hud/blob_overmind.dm +++ b/code/_onclick/hud/blob_overmind.dm @@ -126,7 +126,7 @@ /obj/screen/blob/Split icon_state = "ui_split" name = "Split consciousness (100)" - desc = "Creates another Blob Overmind at the nearest node. One use only.
Offsprings are be unable to use this ability." + desc = "Creates another Blob Overmind at the targeted node. One use only.
Offspring are unable to use this ability." /obj/screen/blob/Split/Click() if(isovermind(usr)) diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm index b43715ee598..a5586578b3f 100644 --- a/code/_onclick/hud/plane_master.dm +++ b/code/_onclick/hud/plane_master.dm @@ -34,7 +34,7 @@ /obj/screen/plane_master/game_world name = "game world plane master" plane = GAME_PLANE - appearance_flags = PLANE_MASTER //should use client color + appearance_flags = PLANE_MASTER blend_mode = BLEND_OVERLAY /obj/screen/plane_master/game_world/backdrop(mob/mymob) @@ -45,6 +45,7 @@ /obj/screen/plane_master/lighting name = "lighting plane master" plane = LIGHTING_PLANE + appearance_flags = PLANE_MASTER blend_mode = BLEND_MULTIPLY mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/datums/helper_datums/input.dm b/code/datums/helper_datums/input.dm new file mode 100644 index 00000000000..3bcf9509e37 --- /dev/null +++ b/code/datums/helper_datums/input.dm @@ -0,0 +1,115 @@ +/proc/input_async(mob/user=usr, prompt, list/choices) + var/datum/async_input/A = new(choices, prompt) + A.show(user) + return A + +/proc/input_ranked_async(mob/user=usr, prompt="Order by greatest to least preference", list/choices) + var/datum/async_input/ranked/A = new(choices, prompt) + A.show(user) + return A + +/datum/async_input + var/datum/browser/popup + var/list/choices + var/flash = TRUE + var/immediate_submit = FALSE + var/prompt + var/result = null + var/style = "text-align: center;" + var/window_id + var/height = 200 + var/width = 400 + +/datum/async_input/New(list/new_choices, new_prompt="Pick an option:", new_window_id="async_input") + choices = new_choices + prompt = new_prompt + window_id = new_window_id + +/datum/async_input/proc/close() + if(popup) + popup.close() + return result + +/datum/async_input/proc/show(mob/user) + var/dat = create_ui(user) + popup = new(user, window_id, , width, height, src) + popup.set_content(dat) + if(flash && result == null) + window_flash(user.client) + popup.open() + +/datum/async_input/proc/create_ui(mob/user) + var/dat = "
" + dat += render_prompt(user) + dat += render_choices(user) + dat += "
" + dat += "
" + dat += button("Submit", "submit=1", , result == null && !immediate_submit) + dat += "
" + return dat + +/datum/async_input/proc/render_prompt(mob/user) + return "

[prompt]

" + +/datum/async_input/proc/render_choices(mob/user) + var/dat = " " + for(var/choice in choices) + dat += button(choice, "choice=[choice]", choice == result) + dat += " " + return dat + +/datum/async_input/proc/button(label, topic, on=FALSE, disabled=FALSE) + var/class = "" + if(on) + class = "linkOn" + if(disabled) + class = "linkOff" + topic = "" + return "[label]" + +/datum/async_input/Topic(href, href_list) + if(href_list["submit"] || href_list["close"]) + close() + return + + if(href_list["choice"]) + result = href_list["choice"] + show(usr) + return + +/datum/async_input/ranked + height = 400 + immediate_submit = TRUE + +/datum/async_input/ranked/render_choices(mob/user) + var/dat = "
" + dat += "" + for(var/i = 1, i <= choices.len, i++) + var/choice = choices[i] + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
[button("+", i != 1 ? "upvote=[i]" : "", , i == 1)][button("-", i != choices.len ? "downvote=[i]" : "", , i == choices.len)][i]. [choice]
" + dat += "
" + return dat + +/datum/async_input/ranked/Topic(href, href_list) + if(!href_list["close"]) + // Mark that user interacted with interface + result = choices + + if(href_list["upvote"]) + var/index = text2num(href_list["upvote"]) + choices.Swap(index, index - 1) + show(usr) + return + + if(href_list["downvote"]) + var/index = text2num(href_list["downvote"]) + choices.Swap(index, index + 1) + show(usr) + return + + ..() diff --git a/code/datums/mind.dm b/code/datums/mind.dm index c20ded784a1..08c538c0462 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -18,6 +18,7 @@ However if you want that mind to have any special properties like being a traitor etc you will have to do that yourself. */ +#define SUMMON_POSSIBILITIES 3 /datum/mind var/key @@ -824,6 +825,11 @@ to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [SSticker.cultdat.entity_title2] above all else. Bring It back.") log_admin("[key_name(usr)] has culted [key_name(current)]") message_admins("[key_name_admin(usr)] has culted [key_name_admin(current)]") + if(!summon_spots.len) + while(summon_spots.len < SUMMON_POSSIBILITIES) + var/area/summon = pick(return_sorted_areas() - summon_spots) + if(summon && is_station_level(summon.z) && summon.valid_territory) + summon_spots += summon if("tome") var/mob/living/carbon/human/H = current if(istype(H)) @@ -900,9 +906,11 @@ if(src in SSticker.mode.changelings) SSticker.mode.changelings -= src special_role = null - current.remove_changeling_powers() + if(changeling) + current.remove_changeling_powers() + qdel(changeling) + changeling = null SSticker.mode.update_change_icons_removed(src) - if(changeling) qdel(changeling) to_chat(current, "You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!") log_admin("[key_name(usr)] has de-changelinged [key_name(current)]") message_admins("[key_name_admin(usr)] has de-changelinged [key_name_admin(current)]") diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 813604a1431..d8c7b26554c 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -62,6 +62,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges" + var/starts_charged = TRUE //Does this spell start ready to go? var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges" var/still_recharging_msg = "The spell is still recharging." @@ -167,6 +168,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin if("holdervar") adjust_var(user, holder_var_type, holder_var_amount) + if(action) + action.UpdateButtonIcon() return 1 /obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount @@ -193,9 +196,11 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin /obj/effect/proc_holder/spell/New() ..() action = new(src) - still_recharging_msg = "[name] is still recharging." - charge_counter = charge_max + if(starts_charged) + charge_counter = charge_max + else + start_recharge() /obj/effect/proc_holder/spell/Destroy() QDEL_NULL(action) @@ -212,9 +217,14 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin /obj/effect/proc_holder/spell/proc/start_recharge() if(action) action.UpdateButtonIcon() - while(charge_counter < charge_max) - sleep(1) - charge_counter++ + START_PROCESSING(SSfastprocess, src) + +/obj/effect/proc_holder/spell/process() + charge_counter += 2 + if(charge_counter < charge_max) + return + STOP_PROCESSING(SSfastprocess, src) + charge_counter = charge_max if(action) action.UpdateButtonIcon() @@ -235,6 +245,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin else cast(targets, user = user) after_cast(targets) + if(action) + action.UpdateButtonIcon() /obj/effect/proc_holder/spell/proc/before_cast(list/targets) if(overlay) @@ -291,8 +303,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin charge_counter++ if("holdervar") adjust_var(user, holder_var_type, -holder_var_amount) - - return + if(action) + action.UpdateButtonIcon() /obj/effect/proc_holder/spell/proc/updateButtonIcon() if(action) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f49cf05197a..889f32b3aee 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -337,6 +337,9 @@ if(AM && isturf(AM.loc)) step(AM, turn(AM.dir, 180)) +/atom/proc/get_spooked() + return + /atom/proc/add_hiddenprint(mob/living/M as mob) if(isnull(M)) return if(isnull(M.key)) return @@ -655,7 +658,7 @@ var/list/blood_splatter_icons = list() if(V.type == type) V.reagents.add_reagent(vomit_reagent, 5) return - + var/obj/effect/decal/cleanable/vomit/this = new type(src) // Make toxins vomit look different diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index 0482a8e19ae..91c6df639e5 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -105,7 +105,11 @@ spawn() if(!new_overmind) - candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1) + if(is_offspring) + candidates = pollCandidates("Do you want to play as a blob offspring?", ROLE_BLOB, 1) + else + candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1) + if(candidates.len) C = pick(candidates) else @@ -123,7 +127,6 @@ if(is_offspring) B.is_offspring = TRUE - /obj/structure/blob/core/proc/lateblobtimer() addtimer(CALLBACK(src, .proc/lateblobcheck), 50) diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index 5eb15759d99..2743277edb7 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -350,31 +350,32 @@ BS.Goto(pick(surrounding_turfs), BS.move_to_delay) return - /mob/camera/blob/verb/split_consciousness() set category = "Blob" set name = "Split consciousness (100) (One use)" set desc = "Expend resources to attempt to produce another sentient overmind." + var/turf/T = get_turf(src) + if(!T) + return if(split_used) to_chat(src, "You have already produced an offspring.") return if(is_offspring) to_chat(src, "You cannot split as an offspring of another Blob.") return - if(!blob_nodes || !blob_nodes.len) - to_chat(src, "A node is required to birth your offspring...") - return - var/obj/structure/blob/node/N = locate(/obj/structure/blob) in blob_nodes - if(!N) - to_chat(src, "A node is required to birth your offspring...") - return + var/obj/structure/blob/N = (locate(/obj/structure/blob) in T) + if(!N) + to_chat(src, "A node is required to birth your offspring.") + return + if(!istype(N, /obj/structure/blob/node)) + to_chat(src, "A node is required to birth your offspring.") + return if(!can_buy(100)) return split_used = TRUE - new /obj/structure/blob/core/ (get_turf(N), 200, null, blob_core.point_rate, "offspring") qdel(N) @@ -382,7 +383,6 @@ var/datum/game_mode/blob/BL = SSticker.mode BL.blobwincount += initial(BL.blobwincount) - /mob/camera/blob/verb/blob_broadcast() set category = "Blob" set name = "Blob Broadcast" diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index d0ac848d905..038f331f924 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -240,10 +240,10 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" var/geneticpoints = 10 var/purchasedpowers = list() var/mimicing = "" - var/canrespec = 0 + var/canrespec = FALSE //set to TRUE in absorb.dm var/changeling_speak = 0 var/datum/dna/chosen_dna - var/obj/effect/proc_holder/changeling/sting/chosen_sting + var/datum/action/changeling/sting/chosen_sting var/regenerating = FALSE /datum/changeling/New(gender=FEMALE) @@ -329,4 +329,4 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" return 1 /proc/can_absorb_species(datum/species/S) - return !(NO_DNA in S.species_traits) \ No newline at end of file + return !(NO_DNA in S.species_traits) diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm index 387e7ce9d61..69142049280 100644 --- a/code/game/gamemodes/changeling/changeling_power.dm +++ b/code/game/gamemodes/changeling/changeling_power.dm @@ -3,10 +3,10 @@ * TODO: combine atleast some of the functionality with /proc_holder/spell */ -/obj/effect/proc_holder/changeling - panel = "Changeling" +/datum/action/changeling name = "Prototype Sting" desc = "" // Fluff + background_icon_state = "bg_changeling" var/helptext = "" // Details var/chemical_cost = 0 // negative chemical cost is for passive abilities (chemical glands) var/dna_cost = -1 //cost of the sting in dna points. 0 = auto-purchase, -1 = cannot be purchased @@ -16,20 +16,26 @@ var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss. var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet. var/always_keep = 0 // important for abilities like regenerate that screw you if you lose them. + var/needs_button = TRUE // for passive abilities like hivemind that dont need a button + var/active = FALSE // used by a few powers that toggle -/obj/effect/proc_holder/changeling/proc/on_purchase(var/mob/user) - return +/* +changeling code now relies on on_purchase to grant powers. +if you override it, MAKE SURE you call parent or it will not be usable +the same goes for Remove(). if you override Remove(), call parent or else your power wont be removed on respec +*/ -/obj/effect/proc_holder/changeling/proc/on_refund(mob/user) - return +/datum/action/changeling/proc/on_purchase(var/mob/user) + if(needs_button) + Grant(user) -/obj/effect/proc_holder/changeling/Click() - var/mob/user = usr +/datum/action/changeling/Trigger() + var/mob/user = owner if(!user || !user.mind || !user.mind.changeling) return try_to_sting(user) -/obj/effect/proc_holder/changeling/proc/try_to_sting(var/mob/user, var/mob/target) +/datum/action/changeling/proc/try_to_sting(var/mob/user, var/mob/target) if(!user.mind || !user.mind.changeling) return if(!can_sting(user, target)) @@ -39,18 +45,18 @@ sting_feedback(user, target) take_chemical_cost(c) -/obj/effect/proc_holder/changeling/proc/sting_action(var/mob/user, var/mob/target) +/datum/action/changeling/proc/sting_action(var/mob/user, var/mob/target) return 0 -/obj/effect/proc_holder/changeling/proc/sting_feedback(var/mob/user, var/mob/target) +/datum/action/changeling/proc/sting_feedback(var/mob/user, var/mob/target) return 0 -/obj/effect/proc_holder/changeling/proc/take_chemical_cost(var/datum/changeling/changeling) +/datum/action/changeling/proc/take_chemical_cost(var/datum/changeling/changeling) changeling.chem_charges -= chemical_cost changeling.geneticdamage += genetic_damage //Fairly important to remember to return 1 on success >.< -/obj/effect/proc_holder/changeling/proc/can_sting(var/mob/user, var/mob/target) +/datum/action/changeling/proc/can_sting(var/mob/user, var/mob/target) if(!ishuman(user)) //typecast everything from mob to carbon from this point onwards return 0 if(req_human && (!ishuman(user) || issmall(user))) @@ -75,7 +81,7 @@ return 1 //used in /mob/Stat() -/obj/effect/proc_holder/changeling/proc/can_be_used_by(var/mob/user) +/datum/action/changeling/proc/can_be_used_by(var/mob/user) if(!ishuman(user)) return 0 if(req_human && !ishuman(user)) @@ -83,10 +89,10 @@ return 1 // Transform the target to the chosen dna. Used in transform.dm and tiny_prick.dm (handy for changes since it's the same thing done twice) -/obj/effect/proc_holder/changeling/proc/transform_dna(var/mob/living/carbon/human/H, var/datum/dna/D) +/datum/action/changeling/proc/transform_dna(var/mob/living/carbon/human/H, var/datum/dna/D) if(!D) return - + H.set_species(D.species.type, retain_damage = TRUE) H.dna = D.Clone() H.real_name = D.real_name diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index befdf899253..e8d266d2dd5 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -1,24 +1,25 @@ var/list/sting_paths // totally stolen from the new player panel. YAYY -/obj/effect/proc_holder/changeling/evolution_menu +/datum/action/changeling/evolution_menu name = "-Evolution Menu-" //Dashes are so it's listed before all the other abilities. desc = "Choose our method of subjugation." + button_icon_state = "changelingsting" dna_cost = 0 -/obj/effect/proc_holder/changeling/evolution_menu/Click() +/datum/action/changeling/evolution_menu/Trigger() if(!usr || !usr.mind || !usr.mind.changeling) return var/datum/changeling/changeling = usr.mind.changeling if(!sting_paths) - sting_paths = init_subtypes(/obj/effect/proc_holder/changeling) + sting_paths = init_subtypes(/datum/action/changeling) var/dat = create_menu(changeling) usr << browse(dat, "window=powers;size=600x700")//900x480 -/obj/effect/proc_holder/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling) +/datum/action/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling) var/dat dat +="Changeling Evolution Menu" @@ -230,7 +231,7 @@ var/list/sting_paths "} var/i = 1 - for(var/obj/effect/proc_holder/changeling/cling_power in sting_paths) + for(var/datum/action/changeling/cling_power in sting_paths) if(cling_power.dna_cost <= 0) //Let's skip the crap we start with. Keeps the evolution menu uncluttered. continue @@ -283,7 +284,7 @@ var/list/sting_paths return dat -/obj/effect/proc_holder/changeling/evolution_menu/Topic(href, href_list) +/datum/action/changeling/evolution_menu/Topic(href, href_list) ..() if(!(iscarbon(usr) && usr.mind && usr.mind.changeling)) return @@ -298,11 +299,11 @@ var/list/sting_paths /datum/changeling/proc/purchasePower(var/mob/living/carbon/user, var/sting_name) - var/obj/effect/proc_holder/changeling/thepower = null + var/datum/action/changeling/thepower = null if(!sting_paths) - sting_paths = init_subtypes(/obj/effect/proc_holder/changeling) - for(var/obj/effect/proc_holder/changeling/cling_sting in sting_paths) + sting_paths = init_subtypes(/datum/action/changeling) + for(var/datum/action/changeling/cling_sting in sting_paths) if(cling_sting.name == sting_name) thepower = cling_sting @@ -357,7 +358,7 @@ var/list/sting_paths if(!mind.changeling) mind.changeling = new /datum/changeling(gender) if(!sting_paths) - sting_paths = init_subtypes(/obj/effect/proc_holder/changeling) + sting_paths = init_subtypes(/datum/action/changeling) if(mind.changeling.purchasedpowers) remove_changeling_powers(1) @@ -367,8 +368,8 @@ var/list/sting_paths mind.changeling.absorbed_languages |= language // purchase free powers. - for(var/obj/effect/proc_holder/changeling/path in sting_paths) - //var/obj/effect/proc_holder/changeling/S = new path() + for(var/datum/action/changeling/path in sting_paths) + //var/datum/action/changeling/S = new path() if(!path.dna_cost) if(!mind.changeling.has_sting(path)) mind.changeling.purchasedpowers += path @@ -406,18 +407,18 @@ var/list/sting_paths digitalcamo = 0 mind.changeling.changeling_speak = 0 mind.changeling.reset() - for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers) + for(var/datum/action/changeling/p in mind.changeling.purchasedpowers) if((p.dna_cost == 0 && keep_free_powers) || p.always_keep) continue mind.changeling.purchasedpowers -= p - p.on_refund(src) + p.Remove(src) remove_language("Changeling") if(hud_used) hud_used.lingstingdisplay.icon_state = null hud_used.lingstingdisplay.invisibility = 101 -/datum/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power) - for(var/obj/effect/proc_holder/changeling/P in purchasedpowers) +/datum/changeling/proc/has_sting(datum/action/power) + for(var/datum/action/P in purchasedpowers) if(power.name == P.name) return 1 return 0 diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index b60cfee4718..b5ad5ab9f8a 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -1,12 +1,13 @@ -/obj/effect/proc_holder/changeling/absorbDNA +/datum/action/changeling/absorbDNA name = "Absorb DNA" - desc = "Absorb the DNA of our victim." + desc = "Absorb the DNA of our victim. Requires us to strangle them." + button_icon_state = "absorb_dna" chemical_cost = 0 dna_cost = 0 req_human = 1 max_genetic_damage = 100 -/obj/effect/proc_holder/changeling/absorbDNA/can_sting(var/mob/living/carbon/user) +/datum/action/changeling/absorbDNA/can_sting(mob/living/carbon/user) if(!..()) return @@ -26,7 +27,7 @@ var/mob/living/carbon/target = G.affecting return changeling.can_absorb_dna(user,target) -/obj/effect/proc_holder/changeling/absorbDNA/sting_action(var/mob/user) +/datum/action/changeling/absorbDNA/sting_action(var/mob/user) var/datum/changeling/changeling = user.mind.changeling var/obj/item/grab/G = user.get_active_hand() var/mob/living/carbon/human/target = G.affecting diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm index bf16d90d55e..b0b77a456d5 100644 --- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm +++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm @@ -1,36 +1,40 @@ //Augmented Eyesight: Gives you thermal and night vision - bye bye, flashlights. Also, high DNA cost because of how powerful it is. //Possible todo: make a custom message for directing a penlight/flashlight at the eyes - not sure what would display though. -/obj/effect/proc_holder/changeling/augmented_eyesight +/datum/action/changeling/augmented_eyesight name = "Augmented Eyesight" desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability." - helptext = "Grants us thermal vision or flash protection. We will become a lot more vulnerable to flash-based devices while thermal vision is active." + helptext = "Grants us thermal vision or flash protection. We will become a lot more vulnerable to flash based devices while thermal vision is active." + button_icon_state = "augmented_eyesight" chemical_cost = 0 dna_cost = 2 //Would be 1 without thermal vision + active = FALSE -/obj/effect/proc_holder/changeling/augmented_eyesight/sting_action(mob/living/carbon/human/user) +/datum/action/changeling/augmented_eyesight/on_purchase(mob/user) //The ability starts inactive, so we should be protected from flashes. + ..() + var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/shield/ling() + O.insert(user) + active = FALSE + +/datum/action/changeling/augmented_eyesight/sting_action(mob/living/carbon/user) if(!istype(user)) return - if(user.get_int_organ(/obj/item/organ/internal/cyberimp/eyes/thermals/ling)) - var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/shield/ling() - O.insert(user) - - else + if(!active) var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/thermals/ling() O.insert(user) - + active = TRUE + else + var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/shield/ling() + O.insert(user) + active = FALSE return 1 - -/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user) +/datum/action/changeling/augmented_eyesight/Remove(mob/user) var/obj/item/organ/internal/cyberimp/eyes/O = user.get_organ_slot("eye_ling") if(O) O.remove(user) qdel(O) - - - - + ..() /obj/item/organ/internal/cyberimp/eyes/shield/ling name = "protective membranes" @@ -53,7 +57,6 @@ S.reagents.add_reagent("oculine", 15) return S - /obj/item/organ/internal/cyberimp/eyes/thermals/ling name = "heat receptors" desc = "These heat receptors dramatically increases eyes light sensing ability." diff --git a/code/game/gamemodes/changeling/powers/biodegrade.dm b/code/game/gamemodes/changeling/powers/biodegrade.dm index 5142734183b..c8a7721a5f5 100644 --- a/code/game/gamemodes/changeling/powers/biodegrade.dm +++ b/code/game/gamemodes/changeling/powers/biodegrade.dm @@ -1,12 +1,13 @@ -/obj/effect/proc_holder/changeling/biodegrade +/datum/action/changeling/biodegrade name = "Biodegrade" - desc = "Dissolves restraints or other objects preventing free movement." + desc = "Dissolves restraints or other objects preventing free movement. Costs 30 chemicals." helptext = "This is obvious to nearby people, and can destroy standard restraints and closets." + button_icon_state = "biodegrade" chemical_cost = 30 //High cost to prevent spam dna_cost = 2 req_human = 1 -/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user) +/datum/action/changeling/biodegrade/sting_action(mob/living/carbon/human/user) var/used = FALSE // only one form of shackles removed per use if(!user.restrained() && !istype(user.loc, /obj/structure/closet) && !istype(user.loc, /obj/structure/spider/cocoon)) to_chat(user, "We are already free!") @@ -30,7 +31,6 @@ addtimer(CALLBACK(src, .proc/dissolve_straightjacket, user, S), 30) used = TRUE - if(istype(user.loc, /obj/structure/closet) && !used) var/obj/structure/closet/C = user.loc if(!istype(C)) @@ -53,21 +53,21 @@ feedback_add_details("changeling_powers","BD") return TRUE -/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O) +/datum/action/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O) if(O && user.handcuffed == O) user.unEquip(O) O.visible_message("[O] dissolves into a puddle of sizzling goop.") O.forceMove(get_turf(user)) qdel(O) -/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S) +/datum/action/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S) if(S && user.wear_suit == S) user.unEquip(S) S.visible_message("[S] dissolves into a puddle of sizzling goop.") S.forceMove(get_turf(user)) qdel(S) -/obj/effect/proc_holder/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C) +/datum/action/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C) if(C && user.loc == C) C.visible_message("[C]'s door breaks and opens!") C.welded = FALSE @@ -76,7 +76,7 @@ C.open() to_chat(user, "We open the container restraining us!") -/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C) +/datum/action/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C) if(C && user.loc == C) qdel(C) //The cocoon's destroy will move the changeling outside of it without interference to_chat(user, "We dissolve the cocoon!") diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm index 07340cf3e84..7de16801153 100644 --- a/code/game/gamemodes/changeling/powers/chameleon_skin.dm +++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm @@ -1,12 +1,13 @@ -/obj/effect/proc_holder/changeling/chameleon_skin +/datum/action/changeling/chameleon_skin name = "Chameleon Skin" - desc = "Our skin pigmentation rapidly changes to suit our current environment." + desc = "Our skin pigmentation rapidly changes to suit our current environment. Costs 25 chemicals." helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off." + button_icon_state = "chameleon_skin" dna_cost = 2 chemical_cost = 25 req_human = 1 -/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user) +/datum/action/changeling/chameleon_skin/sting_action(mob/user) var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 if(!istype(H)) // req_human could be done in can_sting stuff. return @@ -20,8 +21,9 @@ feedback_add_details("changeling_powers","CS") return TRUE -/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user) +/datum/action/changeling/chameleon_skin/Remove(mob/user) var/mob/living/carbon/C = user if(C.dna.GetSEState(CHAMELEONBLOCK)) C.dna.SetSEState(CHAMELEONBLOCK, 0) genemutcheck(C, CHAMELEONBLOCK, null, MUTCHK_FORCED) + ..() diff --git a/code/game/gamemodes/changeling/powers/digitalcamo.dm b/code/game/gamemodes/changeling/powers/digitalcamo.dm index bc5879f67be..dd309b55060 100644 --- a/code/game/gamemodes/changeling/powers/digitalcamo.dm +++ b/code/game/gamemodes/changeling/powers/digitalcamo.dm @@ -1,11 +1,12 @@ -/obj/effect/proc_holder/changeling/digitalcamo +/datum/action/changeling/digitalcamo name = "Digital Camouflage" desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras." helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny." + button_icon_state = "digital_camo" dna_cost = 1 //Prevents AIs tracking you but makes you easily detectable to the human-eye. -/obj/effect/proc_holder/changeling/digitalcamo/sting_action(var/mob/user) +/datum/action/changeling/digitalcamo/sting_action(var/mob/user) if(user.digitalcamo) to_chat(user, "We return to normal.") diff --git a/code/game/gamemodes/changeling/powers/epinephrine.dm b/code/game/gamemodes/changeling/powers/epinephrine.dm index 4e783f111cc..786ad0660ee 100644 --- a/code/game/gamemodes/changeling/powers/epinephrine.dm +++ b/code/game/gamemodes/changeling/powers/epinephrine.dm @@ -1,19 +1,21 @@ -/obj/effect/proc_holder/changeling/epinephrine +/datum/action/changeling/epinephrine name = "Epinephrine Overdose" - desc = "We evolve additional sacs of adrenaline throughout our body." - helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body." + desc = "We evolve additional sacs of adrenaline throughout our body. Costs 30 chemicals." + helptext = "Removes all stuns instantly and adds a short term reduction in further stuns. Can be used while unconscious. Continued use poisons the body." + button_icon_state = "adrenaline" chemical_cost = 30 dna_cost = 2 req_human = 1 req_stat = UNCONSCIOUS //Recover from stuns. -/obj/effect/proc_holder/changeling/epinephrine/sting_action(var/mob/living/user) +/datum/action/changeling/epinephrine/sting_action(var/mob/living/user) if(user.lying) to_chat(user, "We arise.") else to_chat(user, "Adrenaline rushes through us.") + user.SetSleeping(0) user.stat = 0 user.SetParalysis(0) user.SetStunned(0) diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm index 19cbbbdc3bd..d403059b0c7 100644 --- a/code/game/gamemodes/changeling/powers/fakedeath.dm +++ b/code/game/gamemodes/changeling/powers/fakedeath.dm @@ -1,6 +1,7 @@ -/obj/effect/proc_holder/changeling/fakedeath +/datum/action/changeling/fakedeath name = "Regenerative Stasis" - desc = "We fall into a stasis, allowing us to regenerate." + desc = "We fall into a stasis, allowing us to regenerate and trick our enemies. Costs 15 chemicals." + button_icon_state = "fake_death" chemical_cost = 15 dna_cost = 0 req_dna = 1 @@ -8,7 +9,7 @@ max_genetic_damage = 100 //Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. -/obj/effect/proc_holder/changeling/fakedeath/sting_action(var/mob/living/user) +/datum/action/changeling/fakedeath/sting_action(var/mob/living/user) to_chat(user, "We begin our stasis, preparing energy to arise once more.") if(user.stat != DEAD) @@ -26,12 +27,13 @@ feedback_add_details("changeling_powers","FD") return 1 -/obj/effect/proc_holder/changeling/fakedeath/proc/ready_to_regenerate(mob/user) +/datum/action/changeling/fakedeath/proc/ready_to_regenerate(mob/user) if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers) to_chat(user, "We are ready to regenerate.") - user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null) + var/datum/action/changeling/revive/R = new + R.Grant(user) -/obj/effect/proc_holder/changeling/fakedeath/can_sting(var/mob/user) +/datum/action/changeling/fakedeath/can_sting(var/mob/user) if(user.status_flags & FAKEDEATH) to_chat(user, "We are already regenerating.") return diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm index f6f7c16fd21..f7475090660 100644 --- a/code/game/gamemodes/changeling/powers/fleshmend.dm +++ b/code/game/gamemodes/changeling/powers/fleshmend.dm @@ -1,7 +1,8 @@ -/obj/effect/proc_holder/changeling/fleshmend +/datum/action/changeling/fleshmend name = "Fleshmend" - desc = "Our flesh rapidly regenerates, healing our wounds." - helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious." + desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath. Costs 20 chemicals." + helptext = "If we are on fire, the healing effect will not function. Does not regrow limbs or restore lost blood. Functions while unconscious." + button_icon_state = "fleshmend" chemical_cost = 20 dna_cost = 2 req_stat = UNCONSCIOUS @@ -11,20 +12,20 @@ // divided by healing_ticks to get heal/tick var/total_healing = 100 -/obj/effect/proc_holder/changeling/fleshmend/New() +/datum/action/changeling/fleshmend/New() ..() START_PROCESSING(SSobj, src) -/obj/effect/proc_holder/changeling/fleshmend/Destroy() +/datum/action/changeling/fleshmend/Destroy() STOP_PROCESSING(SSobj, src) return ..() -/obj/effect/proc_holder/changeling/fleshmend/process() +/datum/action/changeling/fleshmend/process() if(recent_uses > 1) recent_uses = max(1, recent_uses - (1 / healing_ticks)) //Starts healing you every second for 10 seconds. Can be used whilst unconscious. -/obj/effect/proc_holder/changeling/fleshmend/sting_action(var/mob/living/user) +/datum/action/changeling/fleshmend/sting_action(var/mob/living/user) to_chat(user, "We begin to heal rapidly.") if(recent_uses > 1) to_chat(user, "Our healing's effectiveness is reduced \ @@ -35,7 +36,7 @@ feedback_add_details("changeling_powers","RR") return TRUE -/obj/effect/proc_holder/changeling/fleshmend/proc/fleshmend(mob/living/user) +/datum/action/changeling/fleshmend/proc/fleshmend(mob/living/user) // The healing itself - doesn't heal toxin damage // (that's anatomic panacea) and the effectiveness decreases with diff --git a/code/game/gamemodes/changeling/powers/headcrab.dm b/code/game/gamemodes/changeling/powers/headcrab.dm index a950ec7a9c9..b39a2bba0d5 100644 --- a/code/game/gamemodes/changeling/powers/headcrab.dm +++ b/code/game/gamemodes/changeling/powers/headcrab.dm @@ -1,17 +1,18 @@ -/obj/effect/proc_holder/changeling/headcrab +/datum/action/changeling/headcrab name = "Last Resort" - desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel." + desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel that can plant our likeness in a new host. Costs 20 chemicals." helptext = "We will be placed in control of a small, fragile creature. We may attack a corpse like this to plant an egg which will slowly mature into a new form for us." + button_icon_state = "last_resort" chemical_cost = 20 dna_cost = 1 req_human = 1 -/obj/effect/proc_holder/changeling/headcrab/try_to_sting(mob/user, mob/target) +/datum/action/changeling/headcrab/try_to_sting(mob/user, mob/target) if(alert("Are you sure you wish to do this? This action cannot be undone.",,"Yes","No")=="No") return ..() -/obj/effect/proc_holder/changeling/headcrab/sting_action(mob/user) +/datum/action/changeling/headcrab/sting_action(mob/user) var/datum/mind/M = user.mind var/list/organs = user.get_organs_zone("head", 1) @@ -42,4 +43,4 @@ to_chat(crab, "You burst out of the remains of your former body in a shower of gore!") user.gib() feedback_add_details("changeling_powers","LR") - return 1 \ No newline at end of file + return 1 diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm index 0976f0da36d..af375cad368 100644 --- a/code/game/gamemodes/changeling/powers/hivemind.dm +++ b/code/game/gamemodes/changeling/powers/hivemind.dm @@ -1,34 +1,38 @@ //HIVEMIND COMMUNICATION (:g) -/obj/effect/proc_holder/changeling/hivemind_comms +/datum/action/changeling/hivemind_comms name = "Hivemind Communication" desc = "We tune our senses to the airwaves to allow us to discreetly communicate and exchange DNA with other changelings." helptext = "We will be able to talk with other changelings with :g. Exchanged DNA do not count towards absorb objectives." dna_cost = 0 chemical_cost = -1 + needs_button = FALSE -/obj/effect/proc_holder/changeling/hivemind_comms/on_purchase(var/mob/user) +/datum/action/changeling/hivemind_comms/on_purchase(var/mob/user) ..() var/datum/changeling/changeling=user.mind.changeling changeling.changeling_speak = 1 to_chat(user, "Use say \":g message\" to communicate with the other changelings.") - var/obj/effect/proc_holder/changeling/hivemind_upload/S1 = new + var/datum/action/changeling/hivemind_upload/S1 = new if(!changeling.has_sting(S1)) changeling.purchasedpowers+=S1 - var/obj/effect/proc_holder/changeling/hivemind_download/S2 = new + S1.Grant(user) + var/datum/action/changeling/hivemind_download/S2 = new if(!changeling.has_sting(S2)) + S2.Grant(user) changeling.purchasedpowers+=S2 return // HIVE MIND UPLOAD/DOWNLOAD DNA var/list/datum/dna/hivemind_bank = list() -/obj/effect/proc_holder/changeling/hivemind_upload +/datum/action/changeling/hivemind_upload name = "Hive Channel DNA" - desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it." + desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it. Costs 10 chemicals." + button_icon_state = "hivemind_channel" chemical_cost = 10 dna_cost = -1 -/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user) +/datum/action/changeling/hivemind_upload/sting_action(var/mob/user) var/datum/changeling/changeling = user.mind.changeling var/list/names = list() for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna)) @@ -52,13 +56,14 @@ var/list/datum/dna/hivemind_bank = list() feedback_add_details("changeling_powers","HU") return 1 -/obj/effect/proc_holder/changeling/hivemind_download +/datum/action/changeling/hivemind_download name = "Hive Absorb DNA" - desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives." + desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives. Costs 10 chemicals." + button_icon_state = "hive_absorb" chemical_cost = 10 dna_cost = -1 -/obj/effect/proc_holder/changeling/hivemind_download/can_sting(var/mob/living/carbon/user) +/datum/action/changeling/hivemind_download/can_sting(var/mob/living/carbon/user) if(!..()) return var/datum/changeling/changeling = user.mind.changeling @@ -67,7 +72,7 @@ var/list/datum/dna/hivemind_bank = list() return return 1 -/obj/effect/proc_holder/changeling/hivemind_download/sting_action(var/mob/user) +/datum/action/changeling/hivemind_download/sting_action(var/mob/user) var/datum/changeling/changeling = user.mind.changeling var/list/names = list() for(var/datum/dna/DNA in hivemind_bank) @@ -87,4 +92,4 @@ var/list/datum/dna/hivemind_bank = list() changeling.store_dna(chosen_dna, user) to_chat(user, "We absorb the DNA of [S] from the air.") feedback_add_details("changeling_powers","HD") - return 1 \ No newline at end of file + return 1 diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index 72b0e821e66..f9b214c513c 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -1,14 +1,14 @@ -/obj/effect/proc_holder/changeling/humanform +/datum/action/changeling/humanform name = "Human form" - desc = "We change into a human." + desc = "We change into a human. Costs 5 chemicals." + button_icon_state = "human_form" chemical_cost = 5 genetic_damage = 3 req_dna = 1 max_genetic_damage = 3 - //Transform into a human. -/obj/effect/proc_holder/changeling/humanform/sting_action(var/mob/living/carbon/human/user) +/datum/action/changeling/humanform/sting_action(var/mob/living/carbon/human/user) var/datum/changeling/changeling = user.mind.changeling var/list/names = list() for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna)) @@ -38,7 +38,7 @@ user.UpdateAppearance() changeling.purchasedpowers -= src - //O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/lesserform(null) + //O.mind.changeling.purchasedpowers += new /datum/action/changeling/lesserform(null) + src.Remove(user) feedback_add_details("changeling_powers","LFT") return 1 - diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index 2197163cbd5..0dd112b66dd 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -1,13 +1,15 @@ -/obj/effect/proc_holder/changeling/lesserform +/datum/action/changeling/lesserform name = "Lesser form" - desc = "We debase ourselves and become lesser. We become a monkey." + desc = "We debase ourselves and become lesser. We become a monkey. Costs 5 chemicals." + helptext = "The transformation greatly reduces our size, allowing us to slip out of cuffs and climb through vents." + button_icon_state = "lesser_form" chemical_cost = 5 dna_cost = 1 genetic_damage = 3 req_human = 1 //Transform into a monkey. -/obj/effect/proc_holder/changeling/lesserform/sting_action(var/mob/living/carbon/human/user) +/datum/action/changeling/lesserform/sting_action(var/mob/living/carbon/human/user) var/datum/changeling/changeling = user.mind.changeling if(!user) return 0 @@ -25,6 +27,10 @@ changeling.geneticdamage = 30 to_chat(H, "Our genes cry out!") H.monkeyize() - changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) + + var/datum/action/changeling/humanform/HF = new + changeling.purchasedpowers += HF + HF.Grant(user) + feedback_add_details("changeling_powers","LF") return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/linglink.dm b/code/game/gamemodes/changeling/powers/linglink.dm index b9f984b57c0..ba203a3e71f 100644 --- a/code/game/gamemodes/changeling/powers/linglink.dm +++ b/code/game/gamemodes/changeling/powers/linglink.dm @@ -1,12 +1,14 @@ -/obj/effect/proc_holder/changeling/linglink +/datum/action/changeling/linglink name = "Hivemind Link" - desc = "Link your victim's mind into the hivemind for personal interrogation" + desc = "We link our victim's mind into the hivemind for personal interrogation." + helptext = "If we find a human mad enough to support our cause, this can be a helpful tool to stay in touch." + button_icon_state = "hivemind_link" chemical_cost = 0 dna_cost = 0 req_human = 1 max_genetic_damage = 100 -/obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user) +/datum/action/changeling/linglink/can_sting(mob/living/carbon/user) if(!..()) return var/datum/changeling/changeling = user.mind.changeling @@ -34,7 +36,7 @@ return return changeling.can_absorb_dna(user,target) -/obj/effect/proc_holder/changeling/linglink/sting_action(mob/user) +/datum/action/changeling/linglink/sting_action(mob/user) var/datum/changeling/changeling = user.mind.changeling var/obj/item/grab/G = user.get_active_hand() var/mob/living/carbon/target = G.affecting diff --git a/code/game/gamemodes/changeling/powers/mimic_voice.dm b/code/game/gamemodes/changeling/powers/mimic_voice.dm index 21693a84c3a..27211bd8a79 100644 --- a/code/game/gamemodes/changeling/powers/mimic_voice.dm +++ b/code/game/gamemodes/changeling/powers/mimic_voice.dm @@ -1,14 +1,15 @@ -/obj/effect/proc_holder/changeling/mimicvoice +/datum/action/changeling/mimicvoice name = "Mimic Voice" - desc = "We shape our vocal glands to sound like a desired voice." + desc = "We shape our vocal glands to sound like a desired voice. Maintaining this power slows chemical production." helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this." + button_icon_state = "mimic_voice" chemical_cost = 0 //constant chemical drain hardcoded dna_cost = 1 req_human = 1 // Fake Voice -/obj/effect/proc_holder/changeling/mimicvoice/sting_action(var/mob/user) +/datum/action/changeling/mimicvoice/sting_action(var/mob/user) var/datum/changeling/changeling=user.mind.changeling if(changeling.mimicing) changeling.mimicing = "" diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index e23a3bff415..59e93e2d513 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -9,7 +9,7 @@ //Parent to shields and blades because muh copypasted code. -/obj/effect/proc_holder/changeling/weapon +/datum/action/changeling/weapon name = "Organic Weapon" desc = "Go tell a coder if you see this" helptext = "Yell at coderbus" @@ -21,7 +21,7 @@ var/weapon_type var/weapon_name_simple -/obj/effect/proc_holder/changeling/weapon/try_to_sting(var/mob/user, var/mob/target) +/datum/action/changeling/weapon/try_to_sting(var/mob/user, var/mob/target) if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh qdel(user.l_hand) if(!silent) @@ -36,7 +36,7 @@ return ..(user, target) -/obj/effect/proc_holder/changeling/weapon/sting_action(var/mob/user) +/datum/action/changeling/weapon/sting_action(var/mob/user) if(!user.drop_item()) to_chat(user, "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!") return @@ -45,7 +45,7 @@ return W //Parent to space suits and armor. -/obj/effect/proc_holder/changeling/suit +/datum/action/changeling/suit name = "Organic Suit" desc = "Go tell a coder if you see this" helptext = "Yell at coderbus" @@ -60,7 +60,7 @@ var/recharge_slowdown = 0 var/blood_on_castoff = 0 -/obj/effect/proc_holder/changeling/suit/try_to_sting(var/mob/user, var/mob/target) +/datum/action/changeling/suit/try_to_sting(var/mob/user, var/mob/target) var/datum/changeling/changeling = user.mind.changeling if(!ishuman(user) || !changeling) return @@ -84,7 +84,7 @@ return ..(H, target) -/obj/effect/proc_holder/changeling/suit/sting_action(var/mob/living/carbon/human/user) +/datum/action/changeling/suit/sting_action(var/mob/living/carbon/human/user) if(!user.unEquip(user.wear_suit)) to_chat(user, "\the [user.wear_suit] is stuck to your body, you cannot grow a [suit_name_simple] over it!") return @@ -107,10 +107,11 @@ /***************************************\ |***************ARM BLADE***************| \***************************************/ -/obj/effect/proc_holder/changeling/weapon/arm_blade +/datum/action/changeling/weapon/arm_blade name = "Arm Blade" - desc = "We reform one of our arms into a deadly blade." - helptext = "Cannot be used while in lesser form." + desc = "We reform one of our arms into a deadly blade. Costs 25 chemicals." + helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form." + button_icon_state = "armblade" chemical_cost = 25 dna_cost = 2 genetic_damage = 10 @@ -168,12 +169,13 @@ |***********COMBAT TENTACLES*************| \***************************************/ -/obj/effect/proc_holder/changeling/weapon/tentacle +/datum/action/changeling/weapon/tentacle name = "Tentacle" - desc = "We ready a tentacle to grab items or victims with." + desc = "We ready a tentacle to grab items or victims with. Costs 10 chemicals." helptext = "We can use it once to retrieve a distant item. If used on living creatures, the effect depends on the intent: \ Help will simply drag them closer, Disarm will grab whatever they are holding instead of them, Grab will put the victim in our hold after catching it, \ and Harm will stun it, and stab it if we are also holding a sharp weapon. Cannot be used while in lesser form." + button_icon_state = "tentacle" chemical_cost = 10 dna_cost = 2 genetic_damage = 5 @@ -341,10 +343,11 @@ /***************************************\ |****************SHIELD*****************| \***************************************/ -/obj/effect/proc_holder/changeling/weapon/shield +/datum/action/changeling/weapon/shield name = "Organic Shield" - desc = "We reform one of our arms into a hard shield." - helptext = "Organic tissue cannot resist damage forever, the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form." + desc = "We reform one of our arms into a hard shield. Costs 20 chemicals." + helptext = "Organic tissue cannot resist damage forever. The shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form." + button_icon_state = "organic_shield" chemical_cost = 20 dna_cost = 1 genetic_damage = 12 @@ -354,7 +357,7 @@ weapon_type = /obj/item/shield/changeling weapon_name_simple = "shield" -/obj/effect/proc_holder/changeling/weapon/shield/sting_action(var/mob/user) +/datum/action/changeling/weapon/shield/sting_action(var/mob/user) var/datum/changeling/changeling = user.mind.changeling //So we can read the absorbedcount. if(!changeling) return @@ -395,10 +398,11 @@ /***************************************\ |*********SPACE SUIT + HELMET***********| \***************************************/ -/obj/effect/proc_holder/changeling/suit/organic_space_suit +/datum/action/changeling/suit/organic_space_suit name = "Organic Space Suit" - desc = "We grow an organic suit to protect ourselves from space exposure." - helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form." + desc = "We grow an organic suit to protect ourselves from space exposure. Costs 20 chemicals." + helptext = "We must constantly repair our form to make it space proof, reducing chemical production while we are protected. Cannot be used in lesser form." + button_icon_state = "organic_suit" chemical_cost = 20 dna_cost = 2 genetic_damage = 8 @@ -442,10 +446,11 @@ /***************************************\ |*****************ARMOR*****************| \***************************************/ -/obj/effect/proc_holder/changeling/suit/armor +/datum/action/changeling/suit/armor name = "Chitinous Armor" - desc = "We turn our skin into tough chitin to protect us from damage." - helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form." + desc = "We turn our skin into tough chitin to protect us from damage. Costs 25 chemicals." + helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form." + button_icon_state = "chitinous_armor" chemical_cost = 25 dna_cost = 2 genetic_damage = 11 diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm index 8f4fe0ac394..6e6d69cc1dd 100644 --- a/code/game/gamemodes/changeling/powers/panacea.dm +++ b/code/game/gamemodes/changeling/powers/panacea.dm @@ -1,13 +1,14 @@ -/obj/effect/proc_holder/changeling/panacea +/datum/action/changeling/panacea name = "Anatomic Panacea" - desc = "Expels impurifications from our form; curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely." + desc = "Expels impurifications from our form, curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely. Costs 20 chemicals." helptext = "Can be used while unconscious." + button_icon_state = "panacea" chemical_cost = 20 dna_cost = 1 req_stat = UNCONSCIOUS //Heals the things that the other regenerative abilities don't. -/obj/effect/proc_holder/changeling/panacea/sting_action(var/mob/user) +/datum/action/changeling/panacea/sting_action(var/mob/user) to_chat(user, "We cleanse impurities from our form.") diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 1fef93d0f13..740d9fb25dc 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -1,11 +1,12 @@ -/obj/effect/proc_holder/changeling/revive +/datum/action/changeling/revive name = "Regenerate" desc = "We regenerate, healing all damage from our form." + button_icon_state = "revive" req_stat = DEAD always_keep = 1 //Revive from regenerative stasis -/obj/effect/proc_holder/changeling/revive/sting_action(var/mob/living/carbon/user) +/datum/action/changeling/revive/sting_action(var/mob/living/carbon/user) user.setToxLoss(0, FALSE) user.setOxyLoss(0, FALSE) user.setCloneLoss(0, FALSE) @@ -62,7 +63,7 @@ user.regenerate_icons() user.update_revive() //Handle waking up the changeling after the regenerative stasis has completed. - user.mind.changeling.purchasedpowers -= src + src.Remove(user) user.med_hud_set_status() user.med_hud_set_health() feedback_add_details("changeling_powers","CR") diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm index 1c60013fbb8..068092dde0d 100644 --- a/code/game/gamemodes/changeling/powers/shriek.dm +++ b/code/game/gamemodes/changeling/powers/shriek.dm @@ -1,13 +1,14 @@ -/obj/effect/proc_holder/changeling/resonant_shriek +/datum/action/changeling/resonant_shriek name = "Resonant Shriek" - desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded." - helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors." + desc = "Our lungs and vocal cords shift, allowing us to briefly emit a noise that deafens and confuses the weak minded. Costs 30 chemicals." + helptext = "Emits a high frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors." + button_icon_state = "resonant_shriek" chemical_cost = 30 dna_cost = 1 req_human = 1 -//A flashy ability, good for crowd control and sewing chaos. -/obj/effect/proc_holder/changeling/resonant_shriek/sting_action(var/mob/user) +//A flashy ability, good for crowd control and sowing chaos. +/datum/action/changeling/resonant_shriek/sting_action(var/mob/user) for(var/mob/living/M in get_mobs_in_view(4, user)) if(iscarbon(M)) if(!M.mind || !M.mind.changeling) @@ -28,14 +29,15 @@ feedback_add_details("changeling_powers","RS") return 1 -/obj/effect/proc_holder/changeling/dissonant_shriek +/datum/action/changeling/dissonant_shriek name = "Dissonant Shriek" - desc = "We shift our vocal cords to release a high-frequency sound that overloads nearby electronics." + desc = "We shift our vocal cords to release a high frequency sound that overloads nearby electronics. Costs 30 chemicals." + button_icon_state = "dissonant_shriek" chemical_cost = 30 dna_cost = 1 //A flashy ability, good for crowd control and sewing chaos. -/obj/effect/proc_holder/changeling/dissonant_shriek/sting_action(var/mob/user) +/datum/action/changeling/dissonant_shriek/sting_action(var/mob/user) for(var/obj/machinery/light/L in range(5, usr)) L.on = 1 L.broken() diff --git a/code/game/gamemodes/changeling/powers/spiders.dm b/code/game/gamemodes/changeling/powers/spiders.dm index 348924c7d7b..82b2db6ac7b 100644 --- a/code/game/gamemodes/changeling/powers/spiders.dm +++ b/code/game/gamemodes/changeling/powers/spiders.dm @@ -1,13 +1,14 @@ -/obj/effect/proc_holder/changeling/spiders +/datum/action/changeling/spiders name = "Spread Infestation" desc = "Our form divides, creating arachnids which will grow into deadly beasts." helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 DNA absorptions." + button_icon_state = "spread_infestation" chemical_cost = 45 dna_cost = 1 req_dna = 5 //Makes some spiderlings. Good for setting traps and causing general trouble. -/obj/effect/proc_holder/changeling/spiders/sting_action(var/mob/user) +/datum/action/changeling/spiders/sting_action(var/mob/user) for(var/i=0, i<2, i++) var/obj/structure/spider/spiderling/S = new(user.loc) S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/hunter diff --git a/code/game/gamemodes/changeling/powers/strained_muscles.dm b/code/game/gamemodes/changeling/powers/strained_muscles.dm index 28884c2653a..10f8a5a5d77 100644 --- a/code/game/gamemodes/changeling/powers/strained_muscles.dm +++ b/code/game/gamemodes/changeling/powers/strained_muscles.dm @@ -1,17 +1,18 @@ //Strained Muscles: Temporary speed boost at the cost of rapid damage //Limited because of hardsuits and such; ideally, used for a quick getaway -/obj/effect/proc_holder/changeling/strained_muscles +/datum/action/changeling/strained_muscles name = "Strained Muscles" desc = "We evolve the ability to reduce the acid buildup in our muscles, allowing us to move much faster." helptext = "The strain will make us tired, and we will rapidly become fatigued. Standard weight restrictions, like hardsuits, still apply. Cannot be used in lesser form." + button_icon_state = "strained_muscles" chemical_cost = 0 dna_cost = 1 req_human = 1 var/stacks = 0 //Increments every 5 seconds; damage increases over time var/enabled = 0 //Whether or not you are a hedgehog -/obj/effect/proc_holder/changeling/strained_muscles/sting_action(var/mob/living/carbon/user) +/datum/action/changeling/strained_muscles/sting_action(var/mob/living/carbon/user) enabled = !enabled if(enabled) to_chat(user, "Our muscles tense and strengthen.") diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm index 7f0164535c2..e0fc1107729 100644 --- a/code/game/gamemodes/changeling/powers/swap_form.dm +++ b/code/game/gamemodes/changeling/powers/swap_form.dm @@ -1,12 +1,13 @@ -/obj/effect/proc_holder/changeling/swap_form +/datum/action/changeling/swap_form name = "Swap Forms" - desc = "We force ourselves into the body of another form, pushing their consciousness into the form we left behind." + desc = "We force ourselves into the body of another form, pushing their consciousness into the form we left behind. Costs 40 chemicals." helptext = "We will bring all our abilities with us, but we will lose our old form DNA in exchange for the new one. The process will seem suspicious to any observers." + button_icon_state = "mindswap" chemical_cost = 40 dna_cost = 1 req_human = 1 //Monkeys can't grab -/obj/effect/proc_holder/changeling/swap_form/can_sting(var/mob/living/carbon/user) +/datum/action/changeling/swap_form/can_sting(var/mob/living/carbon/user) if(!..()) return var/obj/item/grab/G = user.get_active_hand() @@ -20,10 +21,12 @@ if(!istype(target) || issmall(target) || NO_DNA in target.dna.species.species_traits) to_chat(user, "[target] is not compatible with this ability.") return + if(target.mind.changeling) + to_chat(user, "We are unable to swap forms with another changeling!") + return return 1 - -/obj/effect/proc_holder/changeling/swap_form/sting_action(var/mob/living/carbon/user) +/datum/action/changeling/swap_form/sting_action(var/mob/living/carbon/user) var/obj/item/grab/G = user.get_active_hand() var/mob/living/carbon/human/target = G.affecting var/datum/changeling/changeling = user.mind.changeling @@ -38,6 +41,10 @@ to_chat(target, "[user] tightens [user.p_their()] grip as a painful sensation invades your body.") + var/lingpowers = list() + for(var/power in changeling.purchasedpowers) + lingpowers += power + changeling.absorbed_dna -= changeling.find_dna(user.dna) changeling.protected_dna -= changeling.find_dna(user.dna) changeling.absorbedcount -= 1 @@ -55,6 +62,13 @@ user.Paralyse(2) target.add_language("Changeling") user.remove_language("Changeling") + user.regenerate_icons() + + for(var/power in lingpowers) + var/datum/action/changeling/S = power + target.mind.changeling.purchasedpowers += S + if(istype(S) && S.needs_button) + S.Grant(target) to_chat(target, "Our genes cry out as we swap our [user] form for [target].") return 1 diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 58afbb73dfe..94bde26674b 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -1,10 +1,10 @@ -/obj/effect/proc_holder/changeling/sting +/datum/action/changeling/sting name = "Tiny Prick" desc = "Stabby stabby" var/sting_icon = null -/obj/effect/proc_holder/changeling/sting/Click() - var/mob/user = usr +/datum/action/changeling/sting/Trigger() + var/mob/user = owner if(!user || !user.mind || !user.mind.changeling) return if(!(user.mind.changeling.chosen_sting)) @@ -13,13 +13,13 @@ unset_sting(user) return -/obj/effect/proc_holder/changeling/sting/proc/set_sting(var/mob/user) +/datum/action/changeling/sting/proc/set_sting(var/mob/user) to_chat(user, "We prepare our sting, use alt+click or middle mouse button on target to sting them.") user.mind.changeling.chosen_sting = src user.hud_used.lingstingdisplay.icon_state = sting_icon user.hud_used.lingstingdisplay.invisibility = 0 -/obj/effect/proc_holder/changeling/sting/proc/unset_sting(var/mob/user) +/datum/action/changeling/sting/proc/unset_sting(var/mob/user) to_chat(user, "We retract our sting, we can't sting anyone for now.") user.mind.changeling.chosen_sting = null user.hud_used.lingstingdisplay.icon_state = null @@ -29,7 +29,7 @@ if(mind && mind.changeling && mind.changeling.chosen_sting) mind.changeling.chosen_sting.unset_sting(src) -/obj/effect/proc_holder/changeling/sting/can_sting(var/mob/user, var/mob/target) +/datum/action/changeling/sting/can_sting(var/mob/user, var/mob/target) if(!..()) return if(!user.mind.changeling.chosen_sting) @@ -51,7 +51,7 @@ return return 1 -/obj/effect/proc_holder/changeling/sting/sting_feedback(var/mob/user, var/mob/target) +/datum/action/changeling/sting/sting_feedback(var/mob/user, var/mob/target) if(!target) return to_chat(user, "We stealthily sting [target.name].") @@ -60,18 +60,18 @@ add_attack_logs(user, target, "Unsuccessful sting (changeling)") return 1 - -/obj/effect/proc_holder/changeling/sting/transformation +/datum/action/changeling/sting/transformation name = "Transformation Sting" - desc = "We silently sting a human, injecting a retrovirus that forces them to transform." + desc = "We silently sting a human, injecting a retrovirus that forces them to transform. Costs 50 chemicals." helptext = "The victim will transform much like a changeling would. The effects will be obvious to the victim, and the process will damage our genomes." + button_icon_state = "sting_transform" sting_icon = "sting_transform" chemical_cost = 50 dna_cost = 3 genetic_damage = 100 var/datum/dna/selected_dna = null -/obj/effect/proc_holder/changeling/sting/transformation/Click() +/datum/action/changeling/sting/transformation/Trigger() var/mob/user = usr var/datum/changeling/changeling = user.mind.changeling if(changeling.chosen_sting) @@ -85,7 +85,7 @@ return ..() -/obj/effect/proc_holder/changeling/sting/transformation/can_sting(var/mob/user, var/mob/target) +/datum/action/changeling/sting/transformation/can_sting(var/mob/user, var/mob/target) if(!..()) return if((HUSK in target.mutations) || (!ishuman(target))) @@ -98,7 +98,7 @@ return FALSE return TRUE -/obj/effect/proc_holder/changeling/sting/transformation/sting_action(var/mob/user, var/mob/target) +/datum/action/changeling/sting/transformation/sting_action(var/mob/user, var/mob/target) add_attack_logs(user, target, "Transformation sting (changeling) (new identity is [selected_dna.real_name])") if(issmall(target)) to_chat(user, "Our genes cry out as we sting [target.name]!") @@ -114,48 +114,51 @@ feedback_add_details("changeling_powers","TS") return TRUE -obj/effect/proc_holder/changeling/sting/extract_dna +datum/action/changeling/sting/extract_dna name = "Extract DNA Sting" - desc = "We stealthily sting a target and extract their DNA." + desc = "We stealthily sting a target and extract their DNA. Costs 25 chemicals." helptext = "Will give you the DNA of your target, allowing you to transform into them." + button_icon_state = "sting_extract" sting_icon = "sting_extract" chemical_cost = 25 dna_cost = 0 -/obj/effect/proc_holder/changeling/sting/extract_dna/can_sting(var/mob/user, var/mob/target) +/datum/action/changeling/sting/extract_dna/can_sting(var/mob/user, var/mob/target) if(..()) return user.mind.changeling.can_absorb_dna(user, target) -/obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(var/mob/user, var/mob/living/carbon/human/target) +/datum/action/changeling/sting/extract_dna/sting_action(var/mob/user, var/mob/living/carbon/human/target) add_attack_logs(user, target, "Extraction sting (changeling)") if(!(user.mind.changeling.has_dna(target.dna))) user.mind.changeling.absorb_dna(target, user) feedback_add_details("changeling_powers","ED") return 1 -obj/effect/proc_holder/changeling/sting/mute +datum/action/changeling/sting/mute name = "Mute Sting" - desc = "We silently sting a human, completely silencing them for a short time." + desc = "We silently sting a human, completely silencing them for a short time. Costs 20 chemicals." helptext = "Does not provide a warning to the victim that they have been stung, until they try to speak and cannot." + button_icon_state = "sting_mute" sting_icon = "sting_mute" chemical_cost = 20 dna_cost = 2 -/obj/effect/proc_holder/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target) +/datum/action/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target) add_attack_logs(user, target, "Mute sting (changeling)") target.AdjustSilence(30) feedback_add_details("changeling_powers","MS") return 1 -obj/effect/proc_holder/changeling/sting/blind +datum/action/changeling/sting/blind name = "Blind Sting" - desc = "Temporarily blinds the target." - helptext = "This sting completely blinds a target for a short time." + desc = "We temporarily blind our victim. Costs 25 chemicals." + helptext = "This sting completely blinds a target for a short time, and leaves them with blurred vision for a long time." + button_icon_state = "sting_blind" sting_icon = "sting_blind" chemical_cost = 25 dna_cost = 1 -/obj/effect/proc_holder/changeling/sting/blind/sting_action(var/mob/living/user, var/mob/living/target) +/datum/action/changeling/sting/blind/sting_action(var/mob/living/user, var/mob/living/target) add_attack_logs(user, target, "Blind sting (changeling)") to_chat(target, "Your eyes burn horrifically!") target.BecomeNearsighted() @@ -164,15 +167,16 @@ obj/effect/proc_holder/changeling/sting/blind feedback_add_details("changeling_powers","BS") return 1 -obj/effect/proc_holder/changeling/sting/LSD +datum/action/changeling/sting/LSD name = "Hallucination Sting" - desc = "Causes terror in the target." + desc = "We cause mass terror to our victim. Costs 10 chemicals." helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung, and the effect occurs after 30 to 60 seconds." + button_icon_state = "sting_lsd" sting_icon = "sting_lsd" chemical_cost = 10 dna_cost = 1 -/obj/effect/proc_holder/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target) +/datum/action/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target) add_attack_logs(user, target, "LSD sting (changeling)") spawn(rand(300,600)) if(target) @@ -180,15 +184,16 @@ obj/effect/proc_holder/changeling/sting/LSD feedback_add_details("changeling_powers","HS") return 1 -obj/effect/proc_holder/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry. +datum/action/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry. name = "Cryogenic Sting" - desc = "We silently sting a human with a cocktail of chemicals that freeze them." + desc = "We silently sting our victim with a cocktail of chemicals that freezes them from the inside. Costs 15 chemicals." helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing." + button_icon_state = "sting_cryo" sting_icon = "sting_cryo" chemical_cost = 15 dna_cost = 2 -/obj/effect/proc_holder/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target) +/datum/action/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target) add_attack_logs(user, target, "Cryo sting (changeling)") if(target.reagents) target.reagents.add_reagent("frostoil", 30) diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index eb50ae0b750..417fbaa052d 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -1,6 +1,7 @@ -/obj/effect/proc_holder/changeling/transform +/datum/action/changeling/transform name = "Transform" - desc = "We take on the appearance and voice of one we have absorbed." + desc = "We take on the appearance and voice of one we have absorbed. Costs 5 chemicals." + button_icon_state = "transform" chemical_cost = 5 dna_cost = 0 req_dna = 1 @@ -8,7 +9,7 @@ max_genetic_damage = 3 //Change our DNA to that of somebody we've absorbed. -/obj/effect/proc_holder/changeling/transform/sting_action(var/mob/living/carbon/human/user) +/datum/action/changeling/transform/sting_action(var/mob/living/carbon/human/user) var/datum/changeling/changeling = user.mind.changeling var/datum/dna/chosen_dna = changeling.select_dna("Select the target DNA: ", "Target DNA") diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index c9524458975..5eb4b3f0242 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -156,6 +156,7 @@ user.SetWeakened(0) user.SetStunned(0) user.SetParalysis(0) + user.SetSleeping(0) U.adjustStaminaLoss(-75) to_chat(user, "You flush your system with clean blood and remove any incapacitating effects.") spawn(1) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 679af70526e..b7e24014f1e 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -459,8 +459,8 @@ organData["germ_level"] = I.germ_level organData["damage"] = I.damage organData["maxHealth"] = I.max_damage - organData["bruised"] = I.min_broken_damage - organData["broken"] = I.min_bruised_damage + organData["bruised"] = I.min_bruised_damage + organData["broken"] = I.min_broken_damage organData["robotic"] = I.is_robotic() organData["dead"] = (I.status & ORGAN_DEAD) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 0ab3d01ddf1..17965c12f4c 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -231,9 +231,9 @@ /obj/item/reagent_containers/hypospray/CMO, /obj/item/clothing/accessory/medal/gold/captain, /obj/item/clothing/gloves/color/black/krav_maga/sec, - /obj/item/storage/internal, /obj/item/spacepod_key, - /obj/item/nullrod + /obj/item/nullrod, + /obj/item/key ) // These items will NOT be preserved var/list/do_not_preserve_items = list ( diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 91dcb43ab57..072281cb188 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -595,3 +595,11 @@ Class Procs: emp_act(EMP_LIGHT) else ex_act(EXPLODE_HEAVY) + +/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8 + var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot. + for (var/i in 1 to 32) + . += hex2num(md5[i]) + . = . % 9 + AM.pixel_x = -8 + ((.%3)*8) + AM.pixel_y = -8 + (round( . / 3)*8) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 05545e6a3d1..642676c6eff 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -78,6 +78,9 @@ set_picture("ai_bsod") ..(severity) +/obj/machinery/status_display/get_spooked() + spookymode = TRUE + // set what is displayed /obj/machinery/status_display/proc/update() if(friendc && !ignore_friendc) @@ -227,6 +230,9 @@ set_picture("ai_bsod") ..(severity) +/obj/machinery/ai_status_display/get_spooked() + spookymode = TRUE + /obj/machinery/ai_status_display/proc/update() if(mode==0) //Blank overlays.Cut() diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 45bfb37f035..3c5fea2a967 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -14,7 +14,6 @@ var/global/list/image/splatter_cache = list() icon = 'icons/effects/blood.dmi' icon_state = "mfloor1" random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7") - appearance_flags = NO_CLIENT_COLOR blood_DNA = list() var/base_icon = 'icons/effects/blood.dmi' var/blood_state = BLOOD_STATE_HUMAN @@ -155,7 +154,6 @@ var/global/list/image/splatter_cache = list() layer = TURF_LAYER random_icon_states = null blood_DNA = list() - appearance_flags = NO_CLIENT_COLOR var/list/existing_dirs = list() /obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in() diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm index 742f5b3d0c0..912212d19c7 100644 --- a/code/game/objects/items/weapons/soap.dm +++ b/code/game/objects/items/weapons/soap.dm @@ -4,6 +4,8 @@ gender = PLURAL icon = 'icons/obj/items.dmi' icon_state = "soap" + lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi' w_class = WEIGHT_CLASS_TINY throwforce = 0 throw_speed = 4 diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index cd65ba0fcb7..0ff7678a52e 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -51,6 +51,7 @@ desc = "A backpack that opens into a localized pocket of Blue Space." origin_tech = "bluespace=5;materials=4;engineering=4;plasmatech=5" icon_state = "holdingpack" + item_state = "holdingpack" max_w_class = WEIGHT_CLASS_HUGE max_combined_w_class = 35 burn_state = FIRE_PROOF diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 03b5ac86870..603a86b072b 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -62,6 +62,7 @@ /obj/item/storage/fancy/egg_box icon_state = "eggbox" icon_type = "egg" + item_state = "eggbox" name = "egg box" storage_slots = 12 can_hold = list(/obj/item/reagent_containers/food/snacks/egg) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 5e214e87d80..993cb458777 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -299,6 +299,10 @@ /turf/proc/Bless() flags |= NOJAUNT +/turf/get_spooked() + for(var/atom/movable/AM in contents) + AM.get_spooked() + /turf/proc/burn_down() return diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index e9d813c1439..caa051f8748 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -88,7 +88,9 @@ //get message text, limit it's length.and clean/escape html if(!msg) + set_typing(C, TRUE) msg = input(src,"Message:", "Private message to [holder ? key_name(C, FALSE) : key_name_hidden(C, FALSE)]") as text|null + set_typing(C, FALSE) if(!msg) return @@ -130,6 +132,9 @@ var/recieve_message = "" + pm_tracker.add_message(C, src, msg, mob) + C.pm_tracker.add_message(src, src, msg, C.mob) + if(holder && !C.holder) recieve_message = "-- Click the [recieve_pm_type]'s name to reply --\n" if(C.adminhelped) @@ -233,3 +238,141 @@ continue if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob)) to_chat(X, "PM: [key_name(src, TRUE, 0)]->IRC-Admins: [msg]") + +/client/verb/open_pms_ui() + set name = "My PMs" + set category = "OOC" + pm_tracker.show_ui(usr) + +/client/proc/set_typing(client/target, value) + if(!target) + return + var/datum/pm_convo/convo = target.pm_tracker.pms[key] + if(!convo) + return + convo.typing = value + if(target.pm_tracker.open && target.pm_tracker.current_title == key) + target.pm_tracker.show_ui(target.mob) + +/datum/pm_tracker + var/current_title = "" + var/open = FALSE + var/list/pms = list() + var/show_archived = FALSE + var/window_id = "pms_window" + +/datum/pm_convo + var/list/messages = list() + var/archived = FALSE + var/client/client + var/read = FALSE + var/typing = FALSE + +/datum/pm_convo/New(client/C) + client = C + +/datum/pm_convo/proc/add(client/sender, message) + messages.Add("[sender]: [message]") + archived = FALSE + read = FALSE + +/datum/pm_tracker/proc/add_message(client/title, client/sender, message, mob/user) + if(!pms[title.key]) + pms[title.key] = new /datum/pm_convo(title) + pms[title.key].add(sender, message) + + if(!open) + // The next time the window's opened, it'll be open to the most recent message + current_title = title.key + return + + // If it's already opened, it'll refresh + show_ui(user) + +/datum/pm_tracker/proc/show_ui(mob/user) + var/dat = "" + + dat += "Refresh" + dat += "[show_archived ? "Hide" : "Show"] Archived" + dat += "
" + for(var/title in pms) + if(pms[title].archived && !show_archived) + continue + var/label = "[title]" + var/class = "" + if(title == current_title) + label = "[label]" + class = "linkOn" + else if(!pms[title].read) + label = "*[label]" + dat += "[label]" + + var/datum/pm_convo/convo = pms[current_title] + if(convo) + convo.read = TRUE + dat += "

[check_rights(R_ADMIN, FALSE, user) ? fancy_title(current_title) : current_title]

" + dat += "

" + dat += "

" + + for(var/message in convo.messages) + dat += "" + + dat += "
[message]
" + if(convo.typing) + dat += "[current_title] is typing" + dat += "
" + dat += "" + dat += "Reply" + dat += "[convo.archived ? "Unarchive" : "Archive"]" + if(check_rights(R_ADMIN, FALSE, user)) + dat += "Ping" + + var/datum/browser/popup = new(user, window_id, "Messages", 1000, 600, src) + popup.set_content(dat) + popup.open() + open = TRUE + +/datum/pm_tracker/proc/fancy_title(title) + var/client/C = pms[title].client + if(!C) + return "[title] (Disconnected)" + return "[key_name(C, FALSE)] ([ADMIN_QUE(C.mob,"?")]) ([ADMIN_PP(C.mob,"PP")]) ([ADMIN_VV(C.mob,"VV")]) ([ADMIN_SM(C.mob,"SM")]) ([admin_jump_link(C.mob)]) (CA)" + +/datum/pm_tracker/Topic(href, href_list) + if(href_list["archive"]) + pms[href_list["archive"]].archived = !pms[href_list["archive"]].archived + show_ui(usr) + return + + if(href_list["refresh"]) + show_ui(usr) + return + + if(href_list["newtitle"]) + current_title = href_list["newtitle"] + show_ui(usr) + return + + if(href_list["ping"]) + var/client/C = pms[href_list["ping"]].client + if(C) + C.pm_tracker.current_title = usr.key + window_flash(C) + C.pm_tracker.show_ui(C.mob) + to_chat(usr, "Forced open [C]'s messages window.") + show_ui(usr) + return + + if(href_list["reply"]) + usr.client.cmd_admin_pm(ckey(href_list["reply"]), null) + show_ui(usr) + return + + if(href_list["showarchived"]) + show_archived = !show_archived + show_ui(usr) + return + + if(href_list["close"]) + open = FALSE + return diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 170b93a50f6..2d076b4e90f 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -177,6 +177,11 @@ client/proc/one_click_antag() H = pick(candidates) SSticker.mode.add_cultist(H.mind) candidates.Remove(H) + if(!summon_spots.len) + while(summon_spots.len < SUMMON_POSSIBILITIES) + var/area/summon = pick(return_sorted_areas() - summon_spots) + if(summon && is_station_level(summon.z) && summon.valid_territory) + summon_spots += summon return 1 return 0 diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index c15ea50c93e..a6bc558842b 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -7,6 +7,7 @@ var/last_message = "" //contains the last message sent by this client - used to protect against copy-paste spamming. var/last_message_count = 0 //contains a number of how many times a message identical to last_message was sent. var/last_message_time = 0 //holds the last time (based on world.time) a message was sent + var/datum/pm_tracker/pm_tracker = new() ///////// //OTHER// diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 00a9137fe05..c6ab57bae4d 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -688,8 +688,8 @@ message += " (RESTRICTED)" to_chat(world, "[message]") -/client/proc/colour_transition(var/list/colour_to = null, var/time = 10) //Call this with no parameters to reset to default. - animate(src, color=colour_to, time=time, easing=SINE_EASING) +/client/proc/colour_transition(list/colour_to = null, time = 10) //Call this with no parameters to reset to default. + animate(src, color = colour_to, time = time, easing = SINE_EASING) /client/proc/on_varedit() var_edited = TRUE diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 632c5053b48..4b24d267f29 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -436,9 +436,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts // LEFT SIDE OF THE PAGE dat += "
" dat += "

General Settings

" - dat += "Attack Animations: [(show_ghostitem_attack) ? "Yes" : "No"]
" if(user.client.holder) dat += "Adminhelp sound: [(sound & SOUND_ADMINHELP)?"On":"Off"]
" + dat += "Ambient Occlusion: [toggles & AMBIENT_OCCLUSION ? "Enabled" : "Disabled"]
" + dat += "Attack Animations: [(show_ghostitem_attack) ? "Yes" : "No"]
" if(unlock_content) dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" dat += "Custom UI settings:
" @@ -449,11 +450,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(user.client.donator_level > 0) dat += "Donator Publicity: [(toggles & DONATOR_PUBLIC) ? "Public" : "Hidden"]
" dat += "Fancy NanoUI: [(nanoui_fancy) ? "Yes" : "No"]
" - dat += "FPS: [clientfps]
" - dat += "Ambient Occlusion: [toggles & AMBIENT_OCCLUSION ? "Enabled" : "Disabled"]
" + dat += "FPS: [clientfps]
" dat += "Ghost Ears: [(toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
" - dat += "Ghost Sight: [(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
" dat += "Ghost Radio: [(toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]
" + dat += "Ghost Sight: [(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
" if(check_rights(R_ADMIN,0)) dat += "OOC Color:     Change
" if(config.allow_Metadata) diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 091f1522b72..d965166fdb2 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -256,16 +256,16 @@ desc = "Somehow these seem even more out-of-date than normal sunglasses." actions_types = list(/datum/action/item_action/noir) -/obj/item/clothing/glasses/sunglasses/noir/attack_self() - toggle_noir() +/obj/item/clothing/glasses/sunglasses/noir/attack_self(mob/user) + toggle_noir(user) /obj/item/clothing/glasses/sunglasses/noir/item_action_slot_check(slot) if(slot == slot_glasses) return 1 -/obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir() +/obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir(mob/user) color_view = color_view ? null : MATRIX_GREYSCALE //Toggles between null and grayscale, with null being the default option. - usr.update_client_colour() + user.update_client_colour() /obj/item/clothing/glasses/sunglasses/yeah name = "agreeable glasses" diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index 84c6d9394c5..df229f5b9c3 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -10,14 +10,14 @@ permeability_coefficient = 0.50 actions_types = list(/datum/action/item_action/adjust) burn_state = FIRE_PROOF - sprite_sheets = list( "Vox" = 'icons/mob/species/vox/mask.dmi', "Unathi" = 'icons/mob/species/unathi/mask.dmi', "Tajaran" = 'icons/mob/species/tajaran/mask.dmi', "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi', "Grey" = 'icons/mob/species/grey/mask.dmi', - "Drask" = 'icons/mob/species/drask/mask.dmi' + "Drask" = 'icons/mob/species/drask/mask.dmi', + "Plasmaman" = 'icons/mob/species/plasmaman/mask.dmi' ) /obj/item/clothing/mask/breath/attack_self(var/mob/user) diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 9fbf2506edd..3b0912a5004 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -10,14 +10,14 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 burn_state = FIRE_PROOF - sprite_sheets = list( "Vox" = 'icons/mob/species/vox/mask.dmi', "Unathi" = 'icons/mob/species/unathi/mask.dmi', "Tajaran" = 'icons/mob/species/tajaran/mask.dmi', "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi', "Drask" = 'icons/mob/species/drask/mask.dmi', - "Grey" = 'icons/mob/species/grey/mask.dmi' + "Grey" = 'icons/mob/species/grey/mask.dmi', + "Plasmaman" = 'icons/mob/species/plasmaman/mask.dmi' ) // **** Welding gas mask **** @@ -194,6 +194,7 @@ name = "security gas mask" desc = "A standard issue Security gas mask with integrated 'Compli-o-nator 3000' device, plays over a dozen pre-recorded compliance phrases designed to get scumbags to stand still whilst you taze them. Do not tamper with the device." icon_state = "sechailer" + item_state = "sechailer" var/phrase = 1 var/aggressiveness = 1 var/safety = 1 diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 8283bbdad62..d70db0658e8 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -373,6 +373,7 @@ for(var/obj/O in contents) if(O.name == K) O.forceMove(loc) + adjust_item_drop_location(O) update_icon() i-- if(i <= 0) diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 4f0196473c7..5b20aad5047 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -207,19 +207,26 @@ /datum/action/innate/minedrone/toggle_meson_vision name = "Toggle Meson Vision" button_icon_state = "meson" + var/sight_flags = SEE_TURFS + var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE /datum/action/innate/minedrone/toggle_meson_vision/Activate() - var/mob/living/simple_animal/hostile/mining_drone/user = owner - if(user.sight & SEE_TURFS) - user.sight &= ~SEE_TURFS - user.lighting_alpha = initial(user.lighting_alpha) + var/mob/living/user = owner + var/is_active = user.sight & SEE_TURFS + + if(is_active) + UnregisterSignal(user, COMSIG_MOB_UPDATE_SIGHT) + user.update_sight() else - user.sight |= SEE_TURFS - user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE + RegisterSignal(user, COMSIG_MOB_UPDATE_SIGHT, .proc/update_user_sight) + user.update_sight() - user.sync_lighting_plane_alpha() + to_chat(user, "You toggle your meson vision [!is_active ? "on" : "off"].") - to_chat(user, "You toggle your meson vision [(user.sight & SEE_TURFS) ? "on" : "off"].") +/datum/action/innate/minedrone/toggle_meson_vision/proc/update_user_sight(mob/living/user) + user.sight |= sight_flags + if(!isnull(lighting_alpha)) + user.lighting_alpha = min(user.lighting_alpha, lighting_alpha) /datum/action/innate/minedrone/toggle_mode name = "Toggle Mode" diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 12b9421423a..9be4f92a0b8 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -720,7 +720,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/proc/updateghostimages() if(!client) return - if(!ghostvision) + if(seedarkness || !ghostvision) client.images -= ghost_images else //add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now diff --git a/code/modules/mob/dead/observer/spells.dm b/code/modules/mob/dead/observer/spells.dm index 620c1854e73..916ff9aa9b8 100644 --- a/code/modules/mob/dead/observer/spells.dm +++ b/code/modules/mob/dead/observer/spells.dm @@ -1,6 +1,4 @@ - - -var/global/list/boo_phrases=list( +GLOBAL_LIST_INIT(boo_phrases, list( "You feel a chill run down your spine.", "You think you see a figure in your peripheral vision.", "What was that?", @@ -9,16 +7,17 @@ var/global/list/boo_phrases=list( "Something doesn't feel right...", "You feel a presence in the room.", "It feels like someone's standing behind you.", -) +)) /obj/effect/proc_holder/spell/aoe_turf/boo name = "Boo!" desc = "Fuck with the living." - ghost = 1 + ghost = TRUE school = "transmutation" charge_max = 600 + starts_charged = FALSE clothes_req = 0 stat_allowed = 1 invocation = "" @@ -27,26 +26,4 @@ var/global/list/boo_phrases=list( /obj/effect/proc_holder/spell/aoe_turf/boo/cast(list/targets, mob/user = usr) for(var/turf/T in targets) - for(var/atom/A in T.contents) - - // Bug humans - if(ishuman(A)) - var/mob/living/carbon/human/H = A - if(H && H.client) - to_chat(H, "[pick(boo_phrases)]") - - // Flicker unblessed lights in range - if(istype(A,/obj/machinery/light)) - var/obj/machinery/light/L = A - if(L) - L.flicker() - - // OH GOD BLUE APC (single animation cycle) - if(istype(A, /obj/machinery/power/apc)) - A:spookify() - - if(istype(A, /obj/machinery/status_display)) - A:spookymode=1 - - if(istype(A, /obj/machinery/ai_status_display)) - A:spookymode=1 \ No newline at end of file + T.get_spooked() diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 416fd911777..52636efb896 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -206,9 +206,13 @@ if("hiss", "hisses") var/M = handle_emote_param(param) - message = "[src] hisses[M ? " at [M]" : ""]." - playsound(loc, 'sound/effects/unathihiss.ogg', 50, 0) //Credit to Jamius (freesound.org) for the sound. - m_type = 2 + if(!muzzled) + message = "[src] hisses[M ? " at [M]" : ""]." + playsound(loc, 'sound/effects/unathihiss.ogg', 50, 0) //Credit to Jamius (freesound.org) for the sound. + m_type = 2 + else + message = "[src] makes a weak hissing noise." + m_type = 2 if("quill", "quills") var/M = handle_emote_param(param) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index e497fd04814..2cd524f8a15 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -2003,6 +2003,9 @@ Eyes need to have significantly high darksight to shine unless the mob has the X genemutcheck(src, block, null, MUTCHK_FORCED) dna.UpdateSE() +/mob/living/carbon/human/get_spooked() + to_chat(src, "[pick(GLOB.boo_phrases)]") + /mob/living/carbon/human/extinguish_light() // Parent function handles stuff the human may be holding ..() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index e68f5652b01..47dd5622379 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -44,9 +44,9 @@ return has_organ("chest") if(slot_wear_id) // the only relevant check for this is the uniform check - return 1 + return TRUE if(slot_wear_pda) - return 1 + return TRUE if(slot_l_ear) return has_organ("head") if(slot_r_ear) @@ -70,9 +70,9 @@ if(slot_s_store) return has_organ("chest") if(slot_in_backpack) - return 1 + return TRUE if(slot_tie) - return 1 + return TRUE // The actual dropping happens at the mob level - checks to prevent drops should // come here @@ -421,56 +421,34 @@ /mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0) switch(dna.species.handle_can_equip(I, slot, disable_warning, src)) - if(1) return 1 - if(2) return 0 //if it returns 2, it wants no normal handling - + if(1) return TRUE + if(2) return FALSE //if it returns 2, it wants no normal handling + if(!has_organ_for_slot(slot)) + return FALSE + if(istype(I, /obj/item/clothing/under) || istype(I, /obj/item/clothing/suit)) if(FAT in mutations) //testing("[M] TOO FAT TO WEAR [src]!") if(!(I.flags_size & ONESIZEFITSALL)) if(!disable_warning) to_chat(src, "You're too fat to wear the [I].") - return 0 + return FALSE switch(slot) if(slot_l_hand) - if(l_hand) - return 0 - return !incapacitated() + return !l_hand && !incapacitated() if(slot_r_hand) - if(r_hand) - return 0 - return !incapacitated() + return !r_hand && !incapacitated() if(slot_wear_mask) - if(wear_mask) - return 0 - if(!(I.slot_flags & SLOT_MASK)) - return 0 - return 1 + return !wear_mask && (I.slot_flags & SLOT_MASK) if(slot_back) - if(back) - return 0 - if(!(I.slot_flags & SLOT_BACK)) - return 0 - return 1 + return !back && (I.slot_flags & SLOT_BACK) if(slot_wear_suit) - if(wear_suit) - return 0 - if(!(I.slot_flags & SLOT_OCLOTHING)) - return 0 - return 1 + return !wear_suit && (I.slot_flags & SLOT_OCLOTHING) if(slot_gloves) - if(gloves) - return 0 - if(!(I.slot_flags & SLOT_GLOVES)) - return 0 - return 1 + return !gloves && (I.slot_flags & SLOT_GLOVES) if(slot_shoes) - if(shoes) - return 0 - if(!(I.slot_flags & SLOT_FEET)) - return 0 - return 1 + return !shoes && (I.slot_flags & SLOT_FEET) if(slot_belt) if(belt) return 0 @@ -482,39 +460,15 @@ return return 1 if(slot_glasses) - if(glasses) - return 0 - if(!(I.slot_flags & SLOT_EYES)) - return 0 - return 1 + return !glasses && (I.slot_flags & SLOT_EYES) if(slot_head) - if(head) - return 0 - if(!(I.slot_flags & SLOT_HEAD)) - return 0 - return 1 + return !head && (I.slot_flags & SLOT_HEAD) if(slot_l_ear) - if(l_ear) - return 0 - if(!(I.slot_flags & SLOT_EARS)) - return 0 - if((I.slot_flags & SLOT_TWOEARS) && r_ear ) - return 0 - return 1 + return !l_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && r_ear) if(slot_r_ear) - if(r_ear) - return 0 - if(!(I.slot_flags & SLOT_EARS)) - return 0 - if((I.slot_flags & SLOT_TWOEARS) && l_ear) - return 0 - return 1 + return !r_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && l_ear) if(slot_w_uniform) - if(w_uniform) - return 0 - if(!(I.slot_flags & SLOT_ICLOTHING)) - return 0 - return 1 + return !w_uniform && (I.slot_flags & SLOT_ICLOTHING) if(slot_wear_id) if(wear_id) return 0 @@ -583,17 +537,9 @@ return 1 return 0 if(slot_handcuffed) - if(handcuffed) - return 0 - if(!istype(I, /obj/item/restraints/handcuffs)) - return 0 - return 1 + return !handcuffed && istype(I, /obj/item/restraints/handcuffs) if(slot_legcuffed) - if(legcuffed) - return 0 - if(!istype(I, /obj/item/restraints/legcuffs)) - return 0 - return 1 + return !legcuffed && istype(I, /obj/item/restraints/legcuffs) if(slot_in_backpack) if(back && istype(back, /obj/item/storage/backpack)) var/obj/item/storage/backpack/B = back diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index cac42a29cd2..7eedf2520a3 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -59,6 +59,8 @@ genemutcheck(H, MONKEYBLOCK, null, MUTCHK_FORCED) /datum/species/monkey/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user) + if(!user.has_organ_for_slot(slot)) + return 2 switch(slot) if(slot_l_hand) if(user.l_hand) diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 90af0fba3c4..84c467b1549 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -619,12 +619,14 @@ /datum/pai_software/flashlight/toggle(mob/living/silicon/pai/user) var/atom/movable/actual_location = istype(user.loc, /obj/item/paicard) ? user.loc : user - if(user.flashlight_on) + if(!user.flashlight_on) actual_location.set_light(2) user.card.set_light(2) - return - actual_location.set_light(2) - user.card.set_light(0) + else + actual_location.set_light(0) + user.card.set_light(0) + + user.flashlight_on = !user.flashlight_on /datum/pai_software/flashlight/is_active(mob/living/silicon/pai/user) return user.flashlight_on diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index 48c7a24f855..c82a0ee7806 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -59,9 +59,6 @@ return target.attack_animal(src) - - - /obj/item/organ/internal/body_egg/changeling_egg name = "changeling egg" desc = "Twitching and disgusting." @@ -91,7 +88,12 @@ if(origin.changeling.can_absorb_dna(M, owner)) origin.changeling.absorb_dna(owner, M) - origin.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) + var/datum/action/changeling/humanform/HF = new + HF.Grant(M) + for(var/power in origin.changeling.purchasedpowers) + var/datum/action/changeling/S = power + if(istype(S) && S.needs_button) + S.Grant(M) M.key = origin.key owner.gib() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e7ea036fed1..3e49f8a79a2 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -956,9 +956,6 @@ var/list/slot_equipment_priority = list( \ statpanel("Status") // We only want alt-clicked turfs to come before Status - if(mind && mind.changeling) - add_stings_to_statpanel(mind.changeling.purchasedpowers) - if(mob_spell_list && mob_spell_list.len) for(var/obj/effect/proc_holder/spell/S in mob_spell_list) add_spell_to_statpanel(S) @@ -1025,12 +1022,6 @@ var/list/slot_equipment_priority = list( \ statpanel_things += A statpanel(listed_turf.name, null, statpanel_things) - -/mob/proc/add_stings_to_statpanel(var/list/stings) - for(var/obj/effect/proc_holder/changeling/S in stings) - if(S.chemical_cost >=0 && S.can_be_used_by(src)) - statpanel("[S.panel]",((S.chemical_cost > 0) ? "[S.chemical_cost]" : ""),S) - /mob/proc/add_spell_to_statpanel(var/obj/effect/proc_holder/spell/S) switch(S.charge_type) if("recharge") @@ -1040,7 +1031,6 @@ var/list/slot_equipment_priority = list( \ if("holdervar") statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S) - // facing verbs /mob/proc/canface() if(!canmove) return 0 diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index f0b6c0a5d7a..436911d30fa 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -377,8 +377,9 @@ else data_core.manifest_inject(character) SSticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn - AnnounceArrival(character, rank, join_message) - AddEmploymentContract(character) + if(!IsAdminJob(rank)) + AnnounceArrival(character, rank, join_message) + AddEmploymentContract(character) if(!thisjob.is_position_available() && thisjob in SSjobs.prioritized_jobs) SSjobs.prioritized_jobs -= thisjob diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0adec3f6baa..451687cd38c 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -403,8 +403,8 @@ /obj/item/paper/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE) ..() - if(burn_state >= FLAMMABLE) //Only render paper that's burnable to be hard to read. - info = "[stars(info)]" + if(burn_state >= FLAMMABLE) //Renders paper that has been lit on fire to be illegible. + info = "Heat-curled corners and sooty words offer little insight. Whatever was once written on this page has been rendered illegible through fire." /obj/item/paper/proc/stamp(var/obj/item/stamp/S) stamps += (!stamps || stamps == "" ? "
" : "") + "" diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index a3186b115a4..4b88ba41ef8 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -49,7 +49,6 @@ use_power = NO_POWER_USE req_access = list(access_engine_equip) siemens_strength = 1 - var/spooky=0 var/area/area var/areastring = null var/obj/item/stock_parts/cell/cell @@ -248,9 +247,9 @@ // update the APC icon to show the three base states // also add overlays for indicator lights -/obj/machinery/power/apc/update_icon() +/obj/machinery/power/apc/update_icon(force_update = FALSE) - if(!status_overlays) + if(!status_overlays || force_update) status_overlays = 1 status_overlays_lock = new status_overlays_charging = new @@ -291,10 +290,10 @@ var/update = check_updates() //returns 0 if no need to update icons. // 1 if we need to update the icon_state // 2 if we need to update the overlays - if(!update) + if(!update && !force_update) return - if(update & 1) // Updating the icon state + if(force_update || update & 1) // Updating the icon state if(update_state & UPSTATE_ALLGOOD) icon_state = "apc0" else if(update_state & (UPSTATE_OPENED1|UPSTATE_OPENED2)) @@ -322,7 +321,7 @@ - if(update & 2) + if(force_update || update & 2) if(overlays.len) overlays.len = 0 @@ -412,14 +411,17 @@ update_icon() updating_icon = 0 -/obj/machinery/power/apc/proc/spookify() - if(spooky) return // Fuck you we're already spooky - spooky=1 - update_icon() - spawn(10) - spooky=0 - update_icon() - +/obj/machinery/power/apc/get_spooked(second_pass = FALSE) + if(opened || wiresexposed) + return + if(stat & (NOPOWER | BROKEN)) + return + if(!second_pass) //The first time, we just cut overlays + addtimer(CALLBACK(src, .get_spooked, TRUE), 1) + cut_overlays() + else + flick("apcemag", src) //Second time we cause the APC to update its icon, then add a timer to update icon later + addtimer(CALLBACK(src, .proc/update_icon, TRUE), 10) //attack with an item - open/close cover, insert cell, or (un)lock interface /obj/machinery/power/apc/attackby(obj/item/W, mob/living/user, params) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index a0bee89e0be..b186e862f01 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -232,6 +232,9 @@ on = FALSE return +/obj/machinery/light/get_spooked() + flicker() + // update the icon_state and luminosity of the light depending on its state /obj/machinery/light/proc/update(var/trigger = TRUE) switch(status) diff --git a/code/modules/reagents/chemistry/recipes/toxins.dm b/code/modules/reagents/chemistry/recipes/toxins.dm index 99f33d625a6..6d93a575240 100644 --- a/code/modules/reagents/chemistry/recipes/toxins.dm +++ b/code/modules/reagents/chemistry/recipes/toxins.dm @@ -181,4 +181,5 @@ id = "Rotatium" result = "rotatium" required_reagents = list("lsd" = 1, "teslium" = 1, "methamphetamine" = 1) + result_amount = 3 mix_message = "After sparks, fire, and the smell of LSD, the mix is constantly spinning with no stop in sight." \ No newline at end of file diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 239cb71328e..ae2d3da87ae 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -10,7 +10,6 @@ var/giftwrapped = 0 var/sortTag = 0 - /obj/structure/bigDelivery/attack_hand(mob/user as mob) playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1) if(wrapped) @@ -24,7 +23,6 @@ qdel(src) - /obj/structure/bigDelivery/attackby(obj/item/W as obj, mob/user as mob, params) if(istype(W, /obj/item/destTagger)) var/obj/item/destTagger/O = W @@ -67,17 +65,16 @@ else to_chat(user, "You need more paper.") - /obj/item/smallDelivery name = "small parcel" desc = "A small wrapped package." icon = 'icons/obj/storage.dmi' icon_state = "deliverycrateSmall" + item_state = "deliverypackage" var/obj/item/wrapped = null var/giftwrapped = 0 var/sortTag = 0 - /obj/item/smallDelivery/attack_self(mob/user as mob) if(wrapped && wrapped.loc) //sometimes items can disappear. For example, bombs. --rastaf0 wrapped.loc = user.loc @@ -88,7 +85,6 @@ playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1) qdel(src) - /obj/item/smallDelivery/attackby(obj/item/W as obj, mob/user as mob, params) if(istype(W, /obj/item/destTagger)) var/obj/item/destTagger/O = W @@ -128,8 +124,6 @@ else to_chat(user, "You need more paper.") - - /obj/item/stack/packageWrap name = "package wrapper" icon = 'icons/obj/items.dmi' @@ -140,7 +134,6 @@ max_amount = 25 burn_state = FLAMMABLE - /obj/item/stack/packageWrap/afterattack(var/obj/target as obj, mob/user as mob, proximity) if(!proximity) return if(!istype(target)) //this really shouldn't be necessary (but it is). -Pete @@ -153,8 +146,6 @@ if(target in user) return - - if(istype(target, /obj/item) && !(istype(target, /obj/item/storage) && !istype(target,/obj/item/storage/box) && !istype(target, /obj/item/shippingPackage))) var/obj/item/O = target if(use(1)) @@ -364,7 +355,6 @@ to_chat(user, "You need more welding fuel to complete this task.") return - /obj/item/shippingPackage name = "Shipping package" desc = "A pre-labeled package for shipping an item to coworkers." diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm index 2a86d4a4a54..cdc81a9e759 100644 --- a/code/modules/response_team/ert.dm +++ b/code/modules/response_team/ert.dm @@ -55,13 +55,9 @@ var/ert_request_answered = FALSE to_chat(src, "Upon using the antagHUD you forfeited the ability to join the round.") return 0 - if(response_team_members.len > 6) - to_chat(src, "The emergency response team is already full!") - return 0 - return 1 -/proc/trigger_armed_response_team(var/datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) +/proc/trigger_armed_response_team(datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) response_team_members = list() active_team = response_team_type active_team.setSlots(commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) @@ -71,7 +67,7 @@ var/ert_request_answered = FALSE if(!ert_candidates.len) active_team.cannot_send_team() send_emergency_team = FALSE - return 0 + return // Respawnable players get first dibs for(var/mob/dead/observer/M in ert_candidates) @@ -87,38 +83,58 @@ var/ert_request_answered = FALSE if(!response_team_members.len) active_team.cannot_send_team() send_emergency_team = FALSE - return 0 + return - var/index = 1 + var/list/ert_gender_prefs = list() for(var/mob/M in response_team_members) - if(index > emergencyresponseteamspawn.len) - index = 1 + ert_gender_prefs.Add(input_async(M, "Please select a gender (10 seconds):", list("Male", "Female"))) + addtimer(CALLBACK(GLOBAL_PROC, .proc/get_ert_role_prefs, response_team_members, ert_gender_prefs), 100) +/proc/get_ert_role_prefs(list/response_team_members, list/ert_gender_prefs) + var/list/ert_role_prefs = list() + for(var/datum/async_input/A in ert_gender_prefs) + A.close() + for(var/mob/M in response_team_members) + ert_role_prefs.Add(input_ranked_async(M, "Please order ERT roles from most to least preferred (15 seconds):", active_team.get_slot_list())) + addtimer(CALLBACK(GLOBAL_PROC, .proc/dispatch_response_team, response_team_members, ert_gender_prefs, ert_role_prefs), 150) + +/proc/dispatch_response_team(list/response_team_members, list/ert_gender_prefs, list/ert_role_prefs) + var/spawn_index = 1 + + for(var/i = 1, i <= response_team_members.len, i++) + if(spawn_index > emergencyresponseteamspawn.len) + break + if(!active_team.get_slot_list().len) + break + var/gender_pref = ert_gender_prefs[i].result + var/role_pref = ert_role_prefs[i].close() + var/mob/M = response_team_members[i] if(!M || !M.client) continue - log_debug("Spawning as ERT: [M.ckey] ([M])") - var/client/C = M.client - var/mob/living/new_commando = C.create_response_team(emergencyresponseteamspawn[index]) - if(!M || !new_commando) + if(!gender_pref || !role_pref) + // Player was afk and did not select continue - new_commando.mind.key = M.key - new_commando.key = M.key - new_commando.update_icons() - index++ - + for(var/role in role_pref) + if(active_team.check_slot_available(role)) + var/mob/living/new_commando = M.client.create_response_team(gender_pref, role, emergencyresponseteamspawn[spawn_index]) + active_team.reduceSlots(role) + spawn_index++ + if(!M || !new_commando) + break + new_commando.mind.key = M.key + new_commando.key = M.key + new_commando.update_icons() + break send_emergency_team = FALSE - active_team.announce_team() - return 1 -/client/proc/create_response_team(var/turf/spawn_location) - var/class = 0 - while(!class) - class = input(src, "Which loadout would you like to choose?") in active_team.get_slot_list() - if(!active_team.check_slot_available(class)) // Because the prompt does not update automatically when a slot gets filled. - class = 0 + if(active_team.count) + active_team.announce_team() + return + // Everyone who said yes was afk + active_team.cannot_send_team() - if(class == "Cyborg") - active_team.reduceCyborgSlots() +/client/proc/create_response_team(new_gender, role, turf/spawn_location) + if(role == "Cyborg") var/cyborg_unlock = active_team.getCyborgUnlock() var/mob/living/silicon/robot/ert/R = new /mob/living/silicon/robot/ert(spawn_location, cyborg_unlock) return R @@ -126,8 +142,6 @@ var/ert_request_answered = FALSE var/mob/living/carbon/human/M = new(null) var/obj/item/organ/external/head/head_organ = M.get_organ("head") - var/new_gender = alert(src, "Please select your gender.", "ERT Character Generation", "Male", "Female") - if(new_gender) if(new_gender == "Male") M.change_gender(MALE) @@ -169,21 +183,24 @@ var/ert_request_answered = FALSE SSticker.mode.ert += M.mind M.forceMove(spawn_location) - SSjobs.CreateMoneyAccount(M, class, null) + SSjobs.CreateMoneyAccount(M, role, null) - active_team.equip_officer(class, M) + active_team.equip_officer(role, M) return M /datum/response_team - var/command_slots = 1 - var/engineer_slots = 3 - var/medical_slots = 3 - var/security_slots = 3 - var/janitor_slots = 0 - var/paranormal_slots = 0 - var/cyborg_slots = 0 + var/list/slots = list( + Commander = 0, + Security = 0, + Engineer = 0, + Medic = 0, + Janitor = 0, + Paranormal = 0, + Cyborg = 0 + ) + var/count = 0 var/command_outfit var/engineering_outfit @@ -193,88 +210,56 @@ var/ert_request_answered = FALSE var/paranormal_outfit var/cyborg_unlock = 0 -/datum/response_team/proc/setSlots(com, sec, med, eng, jan, par, cyb) - command_slots = com == null ? command_slots : com - security_slots = sec == null ? security_slots : sec - medical_slots = med == null ? medical_slots : med - engineer_slots = eng == null ? engineer_slots : eng - janitor_slots = jan == null ? janitor_slots : jan - paranormal_slots = par == null ? paranormal_slots : par - cyborg_slots = cyb == null ? cyborg_slots : cyb +/datum/response_team/proc/setSlots(com=1, sec=3, med=3, eng=3, jan=0, par=0, cyb=0) + slots["Commander"] = com + slots["Security"] = sec + slots["Medic"] = med + slots["Engineer"] = eng + slots["Janitor"] = jan + slots["Paranormal"] = par + slots["Cyborg"] = cyb -/datum/response_team/proc/reduceCyborgSlots() - cyborg_slots-- +/datum/response_team/proc/reduceSlots(role) + slots[role]-- + count++ /datum/response_team/proc/getCyborgUnlock() return cyborg_unlock /datum/response_team/proc/get_slot_list() var/list/slots_available = list() - if(command_slots) - slots_available |= "Commander" - if(security_slots) - slots_available |= "Security" - if(engineer_slots) - slots_available |= "Engineer" - if(medical_slots) - slots_available |= "Medic" - if(janitor_slots) - slots_available |= "Janitor" - if(paranormal_slots) - slots_available |= "Paranormal" - if(cyborg_slots) - slots_available |= "Cyborg" + for(var/role in slots) + if(slots[role]) + slots_available.Add(role) return slots_available -/datum/response_team/proc/check_slot_available(var/slot) - switch(slot) - if("Commander") - return command_slots - if("Security") - return security_slots - if("Engineer") - return engineer_slots - if("Medic") - return medical_slots - if("Janitor") - return janitor_slots - if("Paranormal") - return paranormal_slots - if("Cyborg") - return cyborg_slots - return 0 +/datum/response_team/proc/check_slot_available(role) + return slots[role] /datum/response_team/proc/equip_officer(var/officer_type, var/mob/living/carbon/human/M) switch(officer_type) if("Engineer") - engineer_slots -= 1 M.equipOutfit(engineering_outfit) M.job = "ERT Engineering" if("Security") - security_slots -= 1 M.equipOutfit(security_outfit) M.job = "ERT Security" if("Medic") - medical_slots -= 1 M.equipOutfit(medical_outfit) M.job = "ERT Medical" if("Janitor") - janitor_slots -= 1 M.equipOutfit(janitor_outfit) M.job = "ERT Janitor" if("Paranormal") - paranormal_slots -= 1 M.equipOutfit(paranormal_outfit) M.job = "ERT Paranormal" M.mind.isholy = TRUE if("Commander") - command_slots = 0 - // Override name and age for the commander M.rename_character(null, "[pick("Lieutenant", "Captain", "Major")] [pick(GLOB.last_names)]") M.age = rand(35,45) diff --git a/html/browser/common.css b/html/browser/common.css index 23b675f7fa2..3480183d129 100644 --- a/html/browser/common.css +++ b/html/browser/common.css @@ -345,4 +345,22 @@ div.notice -ms-interpolation-mode: nearest-neighbor; width: 64px; height:64px; -} \ No newline at end of file +} + +.typing:after +{ + overflow: hidden; + display: inline-block; + vertical-align: bottom; + animation: ellipsis steps(4,end) 900ms infinite; + content: "\2026"; + width: 0px; +} + +@keyframes ellipsis +{ + to + { + width: 1.25em; + } +} diff --git a/html/changelogs/AutoChangeLog-pr-11438.yml b/html/changelogs/AutoChangeLog-pr-11438.yml new file mode 100644 index 00000000000..a276198bfa9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11438.yml @@ -0,0 +1,4 @@ +author: "EmanTheAlmighty" +delete-after: True +changes: + - tweak: "Admin made cultists can now properly summon their Gods if the gamemode wasn't initially Cult." diff --git a/html/changelogs/AutoChangeLog-pr-11439.yml b/html/changelogs/AutoChangeLog-pr-11439.yml new file mode 100644 index 00000000000..c5352502c88 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11439.yml @@ -0,0 +1,6 @@ +author: "Arkatos" +delete-after: True +changes: + - rscadd: "Changeling verbs replaced with action buttons" + - tweak: "Changeling ability descriptions updated" + - imageadd: "Added custom icons for changeling action buttons" diff --git a/html/changelogs/AutoChangeLog-pr-11460.yml b/html/changelogs/AutoChangeLog-pr-11460.yml new file mode 100644 index 00000000000..b4fd18328dd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11460.yml @@ -0,0 +1,4 @@ +author: "Arkatos" +delete-after: True +changes: + - imageadd: "Added movement animation for mice, chickens and killer tomatoes" diff --git a/html/changelogs/AutoChangeLog-pr-11472.yml b/html/changelogs/AutoChangeLog-pr-11472.yml new file mode 100644 index 00000000000..acfaebf6e7f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11472.yml @@ -0,0 +1,5 @@ +author: "Couls" +delete-after: True +changes: + - rscadd: "Only names from the manifest will be used for syndicate code phrases" + - rscdel: "randomly generated people names from syndicate code phrases" diff --git a/html/changelogs/AutoChangeLog-pr-11476.yml b/html/changelogs/AutoChangeLog-pr-11476.yml new file mode 100644 index 00000000000..540d77e7bf3 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11476.yml @@ -0,0 +1,8 @@ +author: "Arkatos" +delete-after: True +changes: + - imageadd: "Added inhand sprite for eggbox" + - imageadd: "Added inhand sprites for all types of soaps" + - imageadd: "Added inhand sprite for small parcel" + - imageadd: "Added inhand sprite for sechailer" + - imageadd: "Added inhand sprite for bag of holding" diff --git a/html/changelogs/AutoChangeLog-pr-11477.yml b/html/changelogs/AutoChangeLog-pr-11477.yml new file mode 100644 index 00000000000..756b6c1e4e4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11477.yml @@ -0,0 +1,4 @@ +author: "Arkatos" +delete-after: True +changes: + - tweak: "Added new system for outputting contents of smartfridges" diff --git a/html/changelogs/AutoChangeLog-pr-11479.yml b/html/changelogs/AutoChangeLog-pr-11479.yml new file mode 100644 index 00000000000..efa34ac077d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11479.yml @@ -0,0 +1,5 @@ +author: "TDSSS" +delete-after: True +changes: + - tweak: "Vampire rejuv wakes you up if you're asleep now" + - tweak: "Cling epinephrine wakes you up if you're asleep now" diff --git a/html/changelogs/AutoChangeLog-pr-11480.yml b/html/changelogs/AutoChangeLog-pr-11480.yml new file mode 100644 index 00000000000..a4fcc50ceaa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11480.yml @@ -0,0 +1,4 @@ +author: "Tayyyyyyy" +delete-after: True +changes: + - rscadd: "Messages window (My PMs in OOC tab)" diff --git a/html/changelogs/AutoChangeLog-pr-11486.yml b/html/changelogs/AutoChangeLog-pr-11486.yml new file mode 100644 index 00000000000..c854e1f9c4c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11486.yml @@ -0,0 +1,4 @@ +author: "Tayyyyyyy" +delete-after: True +changes: + - tweak: "You no longer have to wait on others for ERT spawning" diff --git a/html/changelogs/AutoChangeLog-pr-11511.yml b/html/changelogs/AutoChangeLog-pr-11511.yml new file mode 100644 index 00000000000..c32d89bc2fc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11511.yml @@ -0,0 +1,5 @@ +author: "Markolie" +delete-after: True +changes: + - bugfix: "Lighting now respects color blindness again." + - bugfix: "pAI flashlights now work properly." diff --git a/html/changelogs/AutoChangeLog-pr-11518.yml b/html/changelogs/AutoChangeLog-pr-11518.yml new file mode 100644 index 00000000000..0ad85e1e84a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11518.yml @@ -0,0 +1,4 @@ +author: "farie82" +delete-after: True +changes: + - bugfix: "can_equip now checks if you have the limbs required to equip something" diff --git a/html/changelogs/AutoChangeLog-pr-11520.yml b/html/changelogs/AutoChangeLog-pr-11520.yml new file mode 100644 index 00000000000..ffc477deba7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11520.yml @@ -0,0 +1,5 @@ +author: "Citinited" +delete-after: True +changes: + - bugfix: "Boo affects APCs again" + - bugfix: "Boo no longer fully charges when you enter your corpse" diff --git a/html/changelogs/AutoChangeLog-pr-11521.yml b/html/changelogs/AutoChangeLog-pr-11521.yml new file mode 100644 index 00000000000..48a73a71cac --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11521.yml @@ -0,0 +1,5 @@ +author: "Arkatos" +delete-after: True +changes: + - tweak: "Blob split consciousness ability now requires you to directly target a node you want to turn into another sentient overmind instead of selecting a nearest one" + - spellcheck: "Fixed and improved some descriptions regarding Blob offspring" diff --git a/html/changelogs/AutoChangeLog-pr-11533.yml b/html/changelogs/AutoChangeLog-pr-11533.yml new file mode 100644 index 00000000000..e1708e5901c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11533.yml @@ -0,0 +1,4 @@ +author: "Markolie" +delete-after: True +changes: + - bugfix: "Rotatium can now be created properly." diff --git a/html/changelogs/AutoChangeLog-pr-11536.yml b/html/changelogs/AutoChangeLog-pr-11536.yml new file mode 100644 index 00000000000..0fba2aa34e5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11536.yml @@ -0,0 +1,5 @@ +author: "dovydas12345" +delete-after: True +changes: + - bugfix: "Fixes cryopod removing ambulance, secway keys" + - bugfix: "Fixes cryopod recovering the invisible headpocket item" diff --git a/html/changelogs/AutoChangeLog-pr-11541.yml b/html/changelogs/AutoChangeLog-pr-11541.yml new file mode 100644 index 00000000000..a317a29455f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11541.yml @@ -0,0 +1,4 @@ +author: "Tayyyyyyy" +delete-after: True +changes: + - bugfix: "Admin jobs no longer announced" diff --git a/html/changelogs/AutoChangeLog-pr-11546.yml b/html/changelogs/AutoChangeLog-pr-11546.yml new file mode 100644 index 00000000000..33a522e1d19 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11546.yml @@ -0,0 +1,4 @@ +author: "Shadeykins" +delete-after: True +changes: + - bugfix: "Fixes a paper exploit." diff --git a/html/changelogs/AutoChangeLog-pr-11547.yml b/html/changelogs/AutoChangeLog-pr-11547.yml new file mode 100644 index 00000000000..d3cd23d8632 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11547.yml @@ -0,0 +1,4 @@ +author: "AffectedArc07" +delete-after: True +changes: + - tweak: "Tweaks some preference orders" diff --git a/html/changelogs/AutoChangeLog-pr-11551.yml b/html/changelogs/AutoChangeLog-pr-11551.yml new file mode 100644 index 00000000000..5770e7a1488 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11551.yml @@ -0,0 +1,5 @@ +author: "Arkatos" +delete-after: True +changes: + - bugfix: "Fixed a case where ghosts had an extra ghost icon visible on them" + - bugfix: "Fixed a case where some ghosts were too bright" diff --git a/html/changelogs/AutoChangeLog-pr-11554.yml b/html/changelogs/AutoChangeLog-pr-11554.yml new file mode 100644 index 00000000000..4923c690400 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11554.yml @@ -0,0 +1,4 @@ +author: "Arkatos" +delete-after: True +changes: + - bugfix: "You are now unable to swap forms with another changeling" diff --git a/html/changelogs/AutoChangeLog-pr-11555.yml b/html/changelogs/AutoChangeLog-pr-11555.yml new file mode 100644 index 00000000000..63ff2434d6e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11555.yml @@ -0,0 +1,4 @@ +author: "Arkatos" +delete-after: True +changes: + - bugfix: "You can no longer hiss while muzzled" diff --git a/html/changelogs/AutoChangeLog-pr-11556.yml b/html/changelogs/AutoChangeLog-pr-11556.yml new file mode 100644 index 00000000000..246cc070f24 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11556.yml @@ -0,0 +1,4 @@ +author: "AffectedArc07" +delete-after: True +changes: + - tweak: "Moved a global define" diff --git a/html/changelogs/AutoChangeLog-pr-11559.yml b/html/changelogs/AutoChangeLog-pr-11559.yml new file mode 100644 index 00000000000..5bb8465ec94 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11559.yml @@ -0,0 +1,8 @@ +author: "Arkatos" +delete-after: True +changes: + - tweak: "Upon purchasing Augmented Eyesight changeling ability, changeling immediately receives passive version of the ability" + - tweak: "Changelings in the lesser form can now toggle Augmented Eyesight ability" + - bugfix: "Changelings are now removed properly via Traitor Panel" + - bugfix: "Changelings do not get their action buttons bugged when using Swap Forms ability now" + - bugfix: "Action buttons should update their cooldown statuses more reliably" diff --git a/html/changelogs/AutoChangeLog-pr-11567.yml b/html/changelogs/AutoChangeLog-pr-11567.yml new file mode 100644 index 00000000000..8e0769768f9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11567.yml @@ -0,0 +1,4 @@ +author: "Couls" +delete-after: True +changes: + - bugfix: "t-t-t-typo!" diff --git a/html/changelogs/AutoChangeLog-pr-11573.yml b/html/changelogs/AutoChangeLog-pr-11573.yml new file mode 100644 index 00000000000..bb4c67a6cc3 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11573.yml @@ -0,0 +1,4 @@ +author: "Shadeykins" +delete-after: True +changes: + - bugfix: "Fixes rogue pixels on breath masks/gas masks for Plasmamen." diff --git a/html/changelogs/AutoChangeLog-pr-11574.yml b/html/changelogs/AutoChangeLog-pr-11574.yml new file mode 100644 index 00000000000..0acc59e9621 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11574.yml @@ -0,0 +1,4 @@ +author: "Christasmurf" +delete-after: True +changes: + - bugfix: "Fixes a random pixel on the leather shoes" diff --git a/html/changelogs/AutoChangeLog-pr-11582.yml b/html/changelogs/AutoChangeLog-pr-11582.yml new file mode 100644 index 00000000000..455dfcea14e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11582.yml @@ -0,0 +1,4 @@ +author: "uc_guy" +delete-after: True +changes: + - bugfix: "Fixed \"Venus Human Traps\" being invisible." diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index 44fd328e6a2..e02bb48ac46 100644 Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index 1e321d40058..26cc4faf2ee 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index 7fa7b78561d..db20e9a2a79 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi index 06b2934ebde..11a962c579d 100644 Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing_righthand.dmi b/icons/mob/inhands/clothing_righthand.dmi index 3a558b90140..bda8c4a8e00 100644 Binary files a/icons/mob/inhands/clothing_righthand.dmi and b/icons/mob/inhands/clothing_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/custodial_lefthand.dmi b/icons/mob/inhands/equipment/custodial_lefthand.dmi new file mode 100644 index 00000000000..a707c315cfa Binary files /dev/null and b/icons/mob/inhands/equipment/custodial_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/custodial_righthand.dmi b/icons/mob/inhands/equipment/custodial_righthand.dmi new file mode 100644 index 00000000000..f42d427a82d Binary files /dev/null and b/icons/mob/inhands/equipment/custodial_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 35bd70efd28..0fb5935dc0e 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 0f2b8b0996d..614ddfd6e5a 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/species/plasmaman/mask.dmi b/icons/mob/species/plasmaman/mask.dmi new file mode 100644 index 00000000000..1acdc5e581f Binary files /dev/null and b/icons/mob/species/plasmaman/mask.dmi differ diff --git a/paradise.dme b/paradise.dme index 22cb443fac8..dd0f171e6f1 100644 --- a/paradise.dme +++ b/paradise.dme @@ -103,7 +103,6 @@ #include "code\_globalvars\logging.dm" #include "code\_globalvars\mapping.dm" #include "code\_globalvars\misc.dm" -#include "code\_globalvars\station.dm" #include "code\_globalvars\unused.dm" #include "code\_globalvars\lists\flavor_misc.dm" #include "code\_globalvars\lists\fortunes.dm" @@ -336,6 +335,7 @@ #include "code\datums\helper_datums\global_iterator.dm" #include "code\datums\helper_datums\hotkey_modes.dm" #include "code\datums\helper_datums\icon_snapshot.dm" +#include "code\datums\helper_datums\input.dm" #include "code\datums\helper_datums\map_template.dm" #include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\topic_input.dm"