diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 98686aee07d..b5564f3f6b0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -21,7 +21,7 @@ reporting bugs in the code. Refer to ISSUE_TEMPLATE for the exact format that yo should be in. #### Guidelines: - - Issue reports should be as detailed as possible, and if applicable, should include + * Issue reports should be as detailed as possible, and if applicable, should include instructions on how to reproduce the bug. ## Pull requests @@ -31,119 +31,491 @@ strongly recommended you get approval/traction for it from our forums before sta actual development. #### Guidelines: - - Pull requests should be atomic; Make one commit for each distinct change, so if a part + * Pull requests should be atomic; Make one commit for each distinct change, so if a part of a pull request needs to be removed/changed, you may simply modify that single commit. Due to limitations of the engine, this may not always be possible; but do try your best. - - Document and explain your pull requests thoroughly. Detail what each commit changes, + * Document and explain your pull requests thoroughly. Detail what each commit changes, and why it changes it. We do not want to have to read all of you commit names to figure out what your pull request is about. - - Any pull request that is not solely composed of fixes or non gameplay-affecting + * Any pull request that is not solely composed of fixes or non gameplay-affecting refactors must have a changelog. Inline changelogs are supported through the format described [here](https://github.com/ParadiseSS13/Paradise/pull/3291#issuecomment-172950466) and should be used rather than manually edited .yml file changelogs. - - Pull requests should not have any merge commits except in the case of fixing merge + * Pull requests should not have any merge commits except in the case of fixing merge conflicts for an existing pull request. New pull requests should not have any merge commits. Use `git rebase` or `git reset` to update your branches, not `git pull`. -#### BYOND Specific Guidelines: - - Any `type` or `proc` paths **must** use absolute pathing unless the file you are - working in primarily utilizes relative pathing. - - Paths must begin with `/`. It should be `/obj/machinery/fancy_robot`, - not `obj/machinery/fancy_robot`. - - New bases of datum must begin with `/datum/`. `/datum/arbitrary_datum`, - not `/arbitrary_datum`. - - Don't use strings in combination with `text2path()` unless the paths are being - dynamically created. Variables can contain normal paths just fine. - - Don't duplicate code. If you have identical code in two places, it should probably - be a new proc that they both can use. - - No magic numbers/strings. If you have a number or text that is important and used in - your code, make a `#DEFINE` statement with a name that clearly indicates it's use. - - `if(condition)` must be used over `if (condition)` or any other variation. - - The same applies for `while` and `for` loops, they must have no space between the - keyword and condition brackets. `while(condition)`, `for(condition)` - - If you want to output a message to a player's chat - (this includes text sent to `world`), use `to_chat(mob/client/world, "message")`. - Do not use `mob/client/world << "message"`. - - Do not use one-line control statements (if, else, for, while, etc). The space saved - is not worth the decreased readability. - - Control statements comparing a variable to a constant should be formatted `variable`, - `operator`, `constant`. This means `if(count <= 10)` is preferred over - `if(10 >= count)`. - - **Never** use a colon `:` operator to bypass type safety checks, unless you are doing - something where the tiny performance increase is incredibly noticeable (eg, a loop for - a huge list). You should properly typecast everything and use the period `.` - operator. - - Use early returns, and avoid far-indented if blocks. This means that you should not - do this: +#### Using Changelog + * Tags used in changelog include add/rscadd, del/rscdel, fix/fixes, typo/spellcheck. + * Without specifying a name it will default to using your GitHub name. + Some examples +``` +:cl: +add: The ability to change the color of wires +del: Deleted depreciated wire merging now handled in parent +fix: Moving wires now follows the user input instead of moving the stack +/:cl: +``` +``` +:cl: N3X15 +typo: Fixes some misspelled words under Using Changelog +/:cl: +``` + + +## Specifications + +As mentioned before, you are expected to follow these specifications in order to make everyone's lives easier. It'll save both your time and ours, by making +sure you don't have to make any changes and we don't have to ask you to. Thank you for reading this section! + +### Object Oriented Code +As BYOND's Dream Maker (henceforth "DM") is an object-oriented language, code must be object-oriented when possible in order to be more flexible when adding +content to it. If you don't know what "object-oriented" means, we highly recommend you do some light research to grasp the basics. + +### All BYOND paths must contain the full path +(i.e. absolute pathing) + +DM will allow you nest almost any type keyword into a block, such as: + +```DM +datum + datum1 + var + varname1 = 1 + varname2 + static + varname3 + varname4 + proc + proc1() + code + proc2() + code + + datum2 + varname1 = 0 + proc + proc3() + code + proc2() + ..() + code +``` + +The use of this is not allowed in this project *unless the majority of the file is already relatively pathed* as it makes finding definitions via full text +searching next to impossible. The only exception is the variables of an object may be nested to the object, but must not nest further. + +The previous code made compliant: + +```DM +/datum/datum1 + var/varname1 + var/varname2 + var/static/varname3 + var/static/varname4 + +/datum/datum1/proc/proc1() + code +/datum/datum1/proc/proc2() + code +/datum/datum1/datum2 + varname1 = 0 +/datum/datum1/datum2/proc/proc3() + code +/datum/datum1/datum2/proc2() + ..() + code +``` + +### No overriding type safety checks +The use of the : operator to override type safety checks is not allowed. You must cast the variable to the proper type. + +### Type paths must begin with a / +eg: `/datum/thing`, not `datum/thing` + +### Datum type paths must began with "datum" +In DM, this is optional, but omitting it makes finding definitions harder. To be specific, you can declare the path `/arbitrary`, but it +will still be, in actuality, `/datum/arbitrary`. Write your code to reflect this. + +### Do not use text/string based type paths +It is rarely allowed to put type paths in a text format, as there are no compile errors if the type path no longer exists. Here is an example: + +```DM +//Good +var/path_type = /obj/item/baseball_bat + +//Bad +var/path_type = "/obj/item/baseball_bat" +``` + +### Do not use `\The`. +The `\The` macro doesn't actually do anything when used in the format `\The [atom reference]`. Directly referencing an atom in an embedded string +will automatically prefix `The` or `the` to it as appropriate. As an extension, when referencing an atom, don't use `[atom.name]`, use `[atom]`. +The only exception to this rule is when dealing with items "belonging" to a mob, in which case you should use `[mob]'s [atom.name]` to avoid `The` +ever forming. + +```DM +//Good +var/atom/A +"[A]" + +//Bad +"\The [A]" +``` + +### Use the pronoun library instead of `\his` macros. +We have a system in code/\_\_HELPERS/pronouns.dm for addressing all forms of pronouns. This is useful in a number of ways; + * BYOND's \his macro can be unpredictable on what object it references. + Take this example: `"[user] waves \his [user.weapon] around, hitting \his opponents!"`. + This will end up referencing the user's gender in the first occurence, but what about the second? + It'll actually print the gender set on the weapon he's carrying, which is unintended - and there's no way around this. + * It always prints the real `gender` variable of the atom it's referencing. This can lead to exposing a mob's gender even when their face is covered, + which would normally prevent it's gender from being printed. + +The way to avoid these problems is to use the pronoun system. Instead of `"[user] waves \his arms."`, you can do `"[user] waves [user.p_their()] arms."` + +``` +//Good +"[H] waves [H.p_their()] hands!" +"[user] waves [H.p_their()] [user.weapon] around, hitting [H.p_their()] opponents!"` + +//Bad +"[H] waves \his hands!" +"[user] waves \his [user.weapon] around, hitting \his opponents!" +``` + +### Use `[A.UID()]` over `\ref[A]` +BYOND has a system to pass "soft references" to datums, using the format `"\ref[datum]"` inside a string. This allows you to find the object just based +off of a text string, which is especially useful when dealing with the bridge between BYOND code and HTML/JS in UIs. It's resolved back into an object +reference by using `locate("\ref[datum]")` when the code comes back to BYOND. The issue with this is that locate() can return a unexpected datum +if the original datum has been deleted - BYOND recycles the references. + +UID's are actually unique; they work off of a global counter and are not recycled. Each datum has one assigned to it when it's created, which can be +accessed by `[datum.UID()]`. You can use this as a snap-in replacement for `\ref` by changing any `locate(ref)` calls in your code to `locateUID(ref)`. +Usage of this system is mandatory for any /Topic( calls, and will produce errors in Dream Daemon if it's not used. ``, not `Remove|Implanted
" else - text = "Mindshield Implant:No Implant|Implant him!
" + text = "Mindshield Implant:No Implant|Implant [H.p_them()]!
" sections["implant"] = text /** REVOLUTION ***/ text = "revolution" @@ -467,9 +482,11 @@ var/new_memo = copytext(input("Write new memory", "Memory", memory) as null|message,1,MAX_MESSAGE_LEN) if(isnull(new_memo)) return - memory = new_memo - log_admin("[key_name(usr)] has edited [key_name(current)]'s memory") - message_admins("[key_name_admin(usr)] has edited [key_name_admin(current)]'s memory") + var/confirmed = alert(usr, "Are you sure?", "Edit Memory", "Yes", "No") + if(confirmed == "Yes") // Because it is too easy to accidentally wipe someone's memory + memory = new_memo + log_admin("[key_name(usr)] has edited [key_name(current)]'s memory") + message_admins("[key_name_admin(usr)] has edited [key_name_admin(current)]'s memory") else if(href_list["obj_edit"] || href_list["obj_add"]) var/datum/objective/objective @@ -525,8 +542,8 @@ new_objective = new objective_path new_objective.owner = src new_objective:target = new_target:mind - //Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops. - new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role=="MODE" ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]." + //Will display as special role if assigned mode is equal to special role.. Ninjas/commandos/nuke ops. + new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role == new_target:mind:special_role ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]." if("destroy") var/list/possible_targets = active_ais(1) @@ -614,7 +631,7 @@ new_objective = new /datum/objective/escape/escape_with_identity new_objective.owner = src new_objective.target = new_target - new_objective.explanation_text = "Escape on the shuttle or an escape pod with the identity of [targ.current.real_name], the [targ.assigned_role] while wearing their identification card." + new_objective.explanation_text = "Escape on the shuttle or an escape pod with the identity of [targ.current.real_name], the [targ.assigned_role] while wearing [targ.current.p_their()] identification card." if("custom") var/expl = sanitize(copytext(input("Custom objective:", "Objective", objective ? objective.explanation_text : "") as text|null,1,MAX_MESSAGE_LEN)) if(!expl) @@ -726,7 +743,7 @@ if(src in ticker.mode.revolutionaries) ticker.mode.revolutionaries -= src ticker.mode.update_rev_icons_removed(src) - to_chat(current, "\red You have proven your devotion to revolution! You are a head revolutionary now!") + to_chat(current, "You have proven your devotion to revolution! You are a head revolutionary now!") else if(!(src in ticker.mode.head_revolutionaries)) to_chat(current, "You are a member of the revolutionaries' leadership now!") else @@ -1114,14 +1131,17 @@ log_admin("[key_name(usr)] turned [current] into abductor.") ticker.mode.update_abductor_icons_added(src) if("equip") + if(!ishuman(current)) + to_chat(usr, "This only works on humans!") + return + + var/mob/living/carbon/human/H = current var/gear = alert("Agent or Scientist Gear","Gear","Agent","Scientist") if(gear) - var/datum/game_mode/abduction/temp = new - temp.equip_common(current) if(gear=="Agent") - temp.equip_agent(current) + H.equipOutfit(/datum/outfit/abductor/agent) else - temp.equip_scientist(current) + H.equipOutfit(/datum/outfit/abductor/scientist) else if(href_list["silicon"]) switch(href_list["silicon"]) @@ -1201,17 +1221,75 @@ message_admins("[key_name_admin(usr)] has given [key_name_admin(current)] an uplink") else if(href_list["obj_announce"]) - var/obj_count = 1 - to_chat(current, "
Your current objectives:") - for(var/datum/objective/objective in objectives) - to_chat(current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - current << 'sound/ambience/alarm4.ogg' + announce_objectives() + SEND_SOUND(current, sound('sound/ambience/alarm4.ogg')) log_admin("[key_name(usr)] has announced [key_name(current)]'s objectives") message_admins("[key_name_admin(usr)] has announced [key_name_admin(current)]'s objectives") edit_memory() + +// Datum antag mind procs +/datum/mind/proc/add_antag_datum(datum_type_or_instance, team) + if(!datum_type_or_instance) + return + var/datum/antagonist/A + if(!ispath(datum_type_or_instance)) + A = datum_type_or_instance + if(!istype(A)) + return + else + A = new datum_type_or_instance() + //Choose snowflake variation if antagonist handles it + var/datum/antagonist/S = A.specialization(src) + if(S && S != A) + qdel(A) + A = S + if(!A.can_be_owned(src)) + qdel(A) + return + A.owner = src + LAZYADD(antag_datums, A) + A.create_team(team) + var/datum/team/antag_team = A.get_team() + if(antag_team) + antag_team.add_member(src) + A.on_gain() + return A + +/datum/mind/proc/remove_antag_datum(datum_type) + if(!datum_type) + return + var/datum/antagonist/A = has_antag_datum(datum_type) + if(A) + A.on_removal() + return TRUE + + +/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us. + for(var/a in antag_datums) + var/datum/antagonist/A = a + A.on_removal() + +/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE) + if(!datum_type) + return + . = FALSE + for(var/a in antag_datums) + var/datum/antagonist/A = a + if(check_subtypes && istype(A, datum_type)) + return A + else if(A.type == datum_type) + return A + +/datum/mind/proc/announce_objectives() + var/obj_count = 1 + to_chat(current, "Your current objectives:") + for(var/objective in objectives) + var/datum/objective/O = objective + to_chat(current, "Objective #[obj_count]: [O.explanation_text]") + obj_count++ + /datum/mind/proc/find_syndicate_uplink() var/list/L = current.get_contents() for(var/obj/item/I in L) @@ -1224,7 +1302,7 @@ if(H) qdel(H) -/datum/mind/proc/make_Tratior() +/datum/mind/proc/make_Traitor() if(!(src in ticker.mode.traitors)) ticker.mode.traitors += src special_role = SPECIAL_ROLE_TRAITOR @@ -1242,7 +1320,7 @@ else current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" special_role = SPECIAL_ROLE_NUKEOPS - assigned_role = "MODE" + assigned_role = SPECIAL_ROLE_NUKEOPS to_chat(current, "You are a [syndicate_name()] agent!") ticker.mode.forge_syndicate_objectives(src) ticker.mode.greet_syndicate(src) @@ -1264,7 +1342,16 @@ ticker.mode.equip_syndicate(current) -/datum/mind/proc/make_Changling() +/datum/mind/proc/make_Vampire() + if(!(src in ticker.mode.vampires)) + ticker.mode.vampires += src + ticker.mode.grant_vampire_powers(current) + special_role = SPECIAL_ROLE_VAMPIRE + ticker.mode.forge_vampire_objectives(src) + ticker.mode.greet_vampire(src) + ticker.mode.update_change_icons_added(src) + +/datum/mind/proc/make_Changeling() if(!(src in ticker.mode.changelings)) ticker.mode.changelings += src ticker.mode.grant_changeling_powers(current) @@ -1277,7 +1364,7 @@ if(!(src in ticker.mode.wizards)) ticker.mode.wizards += src special_role = SPECIAL_ROLE_WIZARD - assigned_role = "MODE" + assigned_role = SPECIAL_ROLE_WIZARD //ticker.mode.learn_basic_spells(current) if(!wizardstart.len) current.loc = pick(latejoin) @@ -1293,42 +1380,6 @@ ticker.mode.greet_wizard(src) ticker.mode.update_wiz_icons_added(src) - -/datum/mind/proc/make_Cultist() - if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_cult_icons_added(src) - special_role = SPECIAL_ROLE_CULTIST - to_chat(current, "You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title2]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].") - to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") - var/datum/game_mode/cult/cult = ticker.mode - if(GAMEMODE_IS_CULT) - cult.memorize_cult_objectives(src) - else - var/explanation = "Summon [ticker.cultdat.entity_name] via the use of the appropriate rune. It will only work if nine cultists stand on and around it." - to_chat(current, "Objective #1: [explanation]") - current.memory += "Objective #1: [explanation]
" - - - var/mob/living/carbon/human/H = current - if(istype(H)) - var/obj/item/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if(!where) - else - to_chat(H, "A tome, a message from your new master, appears in your [where].") - - if(!ticker.mode.equip_cultist(current)) - to_chat(H, "Summoning an amulet from your Master failed.") - /datum/mind/proc/make_Rev() if(ticker.mode.head_revolutionaries.len>0) // copy targets @@ -1375,36 +1426,32 @@ var/mob/living/carbon/human/H = current - H.set_species("Abductor") + H.set_species(/datum/species/abductor) + var/datum/species/abductor/S = H.dna.species - switch(role) - if("Agent") - H.mind.abductor.agent = 1 - if("Scientist") - H.mind.abductor.scientist = 1 - H.mind.abductor.team = team + if(role == "Scientist") + S.scientist = TRUE + + S.team = team var/list/obj/effect/landmark/abductor/agent_landmarks = new var/list/obj/effect/landmark/abductor/scientist_landmarks = new agent_landmarks.len = 4 scientist_landmarks.len = 4 for(var/obj/effect/landmark/abductor/A in landmarks_list) - if(istype(A,/obj/effect/landmark/abductor/agent)) + if(istype(A, /obj/effect/landmark/abductor/agent)) agent_landmarks[text2num(A.team)] = A - else if(istype(A,/obj/effect/landmark/abductor/scientist)) + else if(istype(A, /obj/effect/landmark/abductor/scientist)) scientist_landmarks[text2num(A.team)] = A var/obj/effect/landmark/L - if(teleport=="Yes") + if(teleport == "Yes") switch(role) if("Agent") - H.mind.abductor.agent = 1 L = agent_landmarks[team] - H.loc = L.loc if("Scientist") - H.mind.abductor.scientist = 1 L = agent_landmarks[team] - H.loc = L.loc + H.forceMove(L.loc) // check whether this mind's mob has been brigged for the given duration @@ -1479,11 +1526,11 @@ ticker.mode.implanter[ref] = implanters ticker.mode.traitors += src special_role = "traitor" - to_chat(current, "You're now a loyal zealot of [missionary.name]! You now must lay down your life to protect them and assist in their goals at any cost.") + to_chat(current, "You're now a loyal zealot of [missionary.name]! You now must lay down your life to protect [missionary.p_them()] and assist in [missionary.p_their()] goals at any cost.") var/datum/objective/protect/mindslave/MS = new MS.owner = src MS.target = missionary.mind - MS.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role=="MODE" ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]." + MS.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role == missionary.mind.special_role ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]." objectives += MS for(var/datum/objective/objective in objectives) to_chat(current, "Objective #1: [objective.explanation_text]") diff --git a/code/datums/modules.dm b/code/datums/modules.dm deleted file mode 100644 index d01bded3254..00000000000 --- a/code/datums/modules.dm +++ /dev/null @@ -1,63 +0,0 @@ -// module datum. -// this is per-object instance, and shows the condition of the modules in the object -// actual modules needed is referenced through modulestypes and the object type - -/datum/module - var/status // bits set if working, 0 if broken - var/installed // bits set if installed, 0 if missing - -// moduletypes datum -// this is per-object type, and shows the modules needed for a type of object - -/datum/moduletypes - var/list/modcount = list() // assoc list of the count of modules for a type - - -var/list/modules = list( // global associative list -"/obj/machinery/power/apc" = "card_reader,power_control,id_auth,cell_power,cell_charge") - - -/datum/module/New(var/obj/O) - - var/type = O.type // the type of the creating object - - var/mneed = mods.inmodlist(type) // find if this type has modules defined - - if(!mneed) // not found in module list? - qdel(src) // delete self, thus ending proc - return - - var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object - status = needed - installed = needed - -/datum/moduletypes/proc/addmod(var/type, var/modtextlist) - modules += type // index by type text - modules[type] = modtextlist - -/datum/moduletypes/proc/inmodlist(var/type) - return ("[type]" in modules) - -/datum/moduletypes/proc/getbitmask(var/type) - var/count = modcount["[type]"] - if(count) - return 2**count-1 - - var/modtext = modules["[type]"] - var/num = 1 - var/pos = 1 - - while(1) - pos = findtext(modtext, ",", pos, 0) - if(!pos) - break - else - pos++ - num++ - - modcount += "[type]" - modcount["[type]"] = num - - return 2**num-1 - - diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm index 9e4bba0515c..edb254203bf 100644 --- a/code/datums/outfits/outfit_admin.dm +++ b/code/datums/outfits/outfit_admin.dm @@ -371,7 +371,7 @@ ) /datum/outfit/admin/vox/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(H.get_species() == "Vox Armalis") + if(isvoxarmalis(H)) . = ..() else H.equip_vox_raider() @@ -1063,6 +1063,7 @@ /datum/outfit/admin/wizard + name = "Blue Wizard" uniform = /obj/item/clothing/under/color/lightpurple suit = /obj/item/clothing/suit/wizrobe back = /obj/item/storage/backpack @@ -1086,10 +1087,6 @@ if(istype(I)) apply_to_card(I, H, get_all_accesses(), "Wizard") -/datum/outfit/admin/wizard/blue - name = "Blue Wizard" - // the default wizard clothes are blue - /datum/outfit/admin/wizard/red name = "Red Wizard" diff --git a/code/datums/pipe_datums.dm b/code/datums/pipe_datums.dm new file mode 100644 index 00000000000..cf2ec79fe85 --- /dev/null +++ b/code/datums/pipe_datums.dm @@ -0,0 +1,390 @@ +GLOBAL_LIST_EMPTY(construction_pipe_list) //List of all pipe datums +GLOBAL_LIST_EMPTY(rpd_pipe_list) //Some pipes we don't want to be dispensable by the RPD, so we have a separate thing + +/datum/pipes + var/pipe_name //What the pipe is called in the interface + var/pipe_id //Use the pipe define for this + var/pipe_type //Atmos, disposals etc. + var/pipe_category //What category of pipe + var/bendy = FALSE //Is this pipe bendy? + var/orientations //Number of orientations (for interface purposes) + var/pipe_icon //icon_state of the dispensed pipe (for interface purposes) + var/rpd_dispensable = FALSE + +/datum/pipes/atmospheric + pipe_type = PIPETYPE_ATMOS + pipe_category = PIPETYPE_ATMOS + +/datum/pipes/disposal + pipe_type = PIPETYPE_DISPOSAL + +//Normal pipes + +/datum/pipes/atmospheric/simple + pipe_name = "straight pipe" + pipe_id = PIPE_SIMPLE_STRAIGHT + orientations = 2 + pipe_icon = "simple" + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/bent //Why is this not atmospheric/simple/bent you ask? Because otherwise the ordering of the pipes in the UI menu gets weird + pipe_name = "bent pipe" + pipe_id = PIPE_SIMPLE_BENT + orientations = 4 + bendy = TRUE + pipe_icon = "simple" + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/manifold + pipe_name = "t-manifold" + pipe_id = PIPE_MANIFOLD + orientations = 4 + pipe_icon = "manifold" + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/manifold4w + pipe_name = "4-way manifold" + pipe_id = PIPE_MANIFOLD4W + orientations = 1 + pipe_icon = "manifold4w" + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/cap + pipe_name = "pipe cap" + pipe_id = PIPE_CAP + orientations = 4 + pipe_icon = "cap" + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/valve + pipe_name = "manual valve" + pipe_id = PIPE_MVALVE + orientations = 2 + pipe_icon = "mvalve" + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/valve/digital + pipe_name = "digital valve" + pipe_id = PIPE_DVALVE + pipe_icon = "dvalve" + +/datum/pipes/atmospheric/tvalve + pipe_name = "manual t-valve" + pipe_id = PIPE_TVALVE + orientations = 4 + pipe_icon = "tvalve" + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/tvalve/digital + pipe_name = "digital t-valve" + pipe_id = PIPE_DTVALVE + pipe_icon = "dtvalve" + +//Supply pipes + +/datum/pipes/atmospheric/simple/supply + pipe_name = "straight supply pipe" + pipe_id = PIPE_SUPPLY_STRAIGHT + pipe_category = RPD_SUPPLY_PIPING + +/datum/pipes/atmospheric/bent/supply + pipe_name = "bent supply pipe" + pipe_id = PIPE_SUPPLY_BENT + pipe_category = RPD_SUPPLY_PIPING + +/datum/pipes/atmospheric/manifold/supply + pipe_name = "supply T-manifold" + pipe_id = PIPE_SUPPLY_MANIFOLD + pipe_category = RPD_SUPPLY_PIPING + +/datum/pipes/atmospheric/manifold4w/supply + pipe_name = "4-way supply manifold" + pipe_id = PIPE_SUPPLY_MANIFOLD4W + pipe_category = RPD_SUPPLY_PIPING + +/datum/pipes/atmospheric/cap/supply + pipe_name = "supply pipe cap" + pipe_id = PIPE_SUPPLY_CAP + pipe_category = RPD_SUPPLY_PIPING + +//Scrubbers pipes + +/datum/pipes/atmospheric/simple/scrubbers + pipe_name = "straight scrubbers pipe" + pipe_id = PIPE_SCRUBBERS_STRAIGHT + pipe_category = RPD_SCRUBBERS_PIPING + +/datum/pipes/atmospheric/bent/scrubbers + pipe_name = "bent scrubbers pipe" + pipe_id = PIPE_SCRUBBERS_BENT + pipe_category = RPD_SCRUBBERS_PIPING + +/datum/pipes/atmospheric/manifold/scrubbers + pipe_name = "scrubbers t-manifold" + pipe_id = PIPE_SCRUBBERS_MANIFOLD + pipe_category = RPD_SCRUBBERS_PIPING + +/datum/pipes/atmospheric/manifold4w/scrubbers + pipe_name = "4-way scrubbers manifold" + pipe_id = PIPE_SCRUBBERS_MANIFOLD4W + pipe_category = RPD_SCRUBBERS_PIPING + +/datum/pipes/atmospheric/cap/scrubbers + pipe_name = "scrubbers pipe cap" + pipe_id = PIPE_SCRUBBERS_CAP + pipe_category = RPD_SCRUBBERS_PIPING + +//Devices + +/datum/pipes/atmospheric/upa + pipe_name = "universal pipe adapter" + pipe_id = PIPE_UNIVERSAL + orientations = 2 + pipe_icon = "universal" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/connector + pipe_name = "connector" + pipe_id = PIPE_CONNECTOR + orientations = 4 + pipe_icon = "connector" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/unaryvent + pipe_name = "unary vent" + pipe_id = PIPE_UVENT + orientations = 4 + pipe_icon = "uvent" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/scrubber + pipe_name = "scrubber" + pipe_id = PIPE_SCRUBBER + orientations = 4 + pipe_icon = "scrubber" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/pump + pipe_name = "pump" + pipe_id = PIPE_PUMP + orientations = 4 + pipe_icon = "pump" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/volume_pump + pipe_name = "volume pump" + pipe_id = PIPE_VOLUME_PUMP + orientations = 4 + pipe_icon = "volumepump" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/gate + pipe_name = "passive gate" + pipe_id = PIPE_PASSIVE_GATE + orientations = 4 + pipe_icon = "passivegate" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/filter + pipe_name = "gas filter" + pipe_id = PIPE_GAS_FILTER + orientations = 4 + pipe_icon = "filter" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/mixer + pipe_name = "gas mixer" + pipe_id = PIPE_GAS_MIXER + orientations = 4 + pipe_icon = "mixer" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/sensor + pipe_name = "gas sensor" + pipe_id = PIPE_GAS_SENSOR + orientations = 1 + pipe_icon = "sensor" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/meter + pipe_name = "meter" + pipe_id = PIPE_METER + orientations = 1 + pipe_icon = "meter" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/passive_vent + pipe_name = "passive vent" + pipe_id = PIPE_PASV_VENT + orientations = 4 + pipe_icon = "passive vent" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/dual_vent_pump + pipe_name = "dual-port vent pump" + pipe_id = PIPE_DP_VENT + orientations = 2 + pipe_icon = "dual-port vent" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/injector + pipe_name = "air injector" + pipe_id = PIPE_INJECTOR + orientations = 4 + pipe_icon = "injector" + pipe_category = RPD_DEVICES + rpd_dispensable = TRUE + +//Heat exchange pipes + +/datum/pipes/atmospheric/simple/he + pipe_name = "straight h/e pipe" + pipe_id = PIPE_HE_STRAIGHT + pipe_icon = "he" + pipe_category = RPD_HEAT_PIPING + +/datum/pipes/atmospheric/bent/he + pipe_name = "bent h/e pipe" + pipe_id = PIPE_HE_BENT + pipe_icon = "he" + bendy = TRUE + pipe_category = RPD_HEAT_PIPING + +/datum/pipes/atmospheric/he_junction + pipe_name = "junction" + pipe_id = PIPE_JUNCTION + orientations = 4 + pipe_icon = "junction" + pipe_category = RPD_HEAT_PIPING + rpd_dispensable = TRUE + +/datum/pipes/atmospheric/heat_exchanger + pipe_name = "heat exchanger" + pipe_id = PIPE_HEAT_EXCHANGE + orientations = 4 + pipe_icon = "heunary" + pipe_category = RPD_HEAT_PIPING + rpd_dispensable = TRUE + +//DISPOSALS PIPES + +/datum/pipes/disposal/straight + pipe_name = "straight disposals pipe" + pipe_id = PIPE_DISPOSALS_STRAIGHT + orientations = 2 + pipe_icon = "pipe-s" + rpd_dispensable = TRUE + +/datum/pipes/disposal/bent + pipe_name = "bent disposals pipe" + pipe_id = PIPE_DISPOSALS_BENT + orientations = 4 + pipe_icon = "pipe-c" + rpd_dispensable = TRUE + +/datum/pipes/disposal/junction + pipe_name = "disposals junction" + pipe_id = PIPE_DISPOSALS_JUNCTION_RIGHT + orientations = 4 + pipe_icon = "pipe-j1" + rpd_dispensable = TRUE + +/datum/pipes/disposal/y_junction + pipe_name = "disposals y-junction" + pipe_id = PIPE_DISPOSALS_Y_JUNCTION + orientations = 4 + pipe_icon = "pipe-y" + rpd_dispensable = TRUE + +/datum/pipes/disposal/trunk + pipe_name = "disposals trunk" + pipe_id = PIPE_DISPOSALS_TRUNK + orientations = 4 + pipe_icon = "pipe-t" + rpd_dispensable = TRUE + +/datum/pipes/disposal/bin + pipe_name = "disposals pipe bin" + pipe_id = PIPE_DISPOSALS_BIN + orientations = 1 + pipe_icon = "disposal" + rpd_dispensable = TRUE + +/datum/pipes/disposal/outlet + pipe_name = "disposals outlet" + pipe_id = PIPE_DISPOSALS_OUTLET + orientations = 4 + pipe_icon = "outlet" + rpd_dispensable = TRUE + +/datum/pipes/disposal/chute + pipe_name = "disposals chute" + pipe_id = PIPE_DISPOSALS_CHUTE + orientations = 4 + pipe_icon = "intake" + rpd_dispensable = TRUE + +//Pipes the RPD can't dispense. Since these don't use an interface, we don't need to bother with setting an icon. We do, however, want to name these for other purposes + +/datum/pipes/atmospheric/circulator + pipe_name = "circulator / heat exchanger" + pipe_id = PIPE_CIRCULATOR + pipe_icon = "circ" + +/datum/pipes/atmospheric/omni_filter + pipe_name = "omni filter" + pipe_id = PIPE_OMNI_FILTER + pipe_icon = "omni_filter" + +/datum/pipes/atmospheric/omni_mixer + pipe_name = "omni mixer" + pipe_id = PIPE_OMNI_MIXER + pipe_icon = "omni_mixer" + +/datum/pipes/atmospheric/insulated + pipe_name = "insulated pipe" + pipe_id = PIPE_INSULATED_STRAIGHT + pipe_icon = "insulated" + +/datum/pipes/atmospheric/insulated/bent + pipe_name = "bent insulated pipe" + pipe_id = PIPE_INSULATED_BENT + +/datum/pipes/disposal/sortjunction + pipe_name = "disposals sort junction" + pipe_id = PIPE_DISPOSALS_SORT_RIGHT + pipe_icon = "pipe-j1s" + +/datum/pipes/disposal/sortjunction/left + pipe_id = PIPE_DISPOSALS_SORT_LEFT + pipe_icon = "pipe-j2s" + +/datum/pipes/disposal/left_junction + pipe_name = "disposals junction" + pipe_id = PIPE_DISPOSALS_JUNCTION_LEFT + pipe_icon = "pipe-j2" + +/proc/get_pipe_name(var/pipe_id, var/pipe_type) + for(var/datum/pipes/P in GLOB.construction_pipe_list) + if(P.pipe_id == pipe_id && P.pipe_type == pipe_type) + return P.pipe_name + return "unknown pipe" + +/proc/get_pipe_icon(var/pipe_id) + for(var/datum/pipes/P in GLOB.construction_pipe_list) + if(P.pipe_id == pipe_id) + return P.pipe_icon + return "unknown icon" diff --git a/code/datums/spell.dm b/code/datums/spell.dm index cc3b85bf94e..f251fed2951 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -115,7 +115,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin caster.reset_perspective(0) return 0 - if(is_admin_level(user.z) && (!centcom_cancast || ticker.mode.name == "ragin' mages")) //Certain spells are not allowed on the centcom zlevel + if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel return 0 if(!skipcharge) @@ -171,10 +171,13 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin /obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount switch(invocation_type) if("shout") - if(prob(50))//Auto-mute? Fuck that noise - user.say(invocation) + if(!user.IsVocal()) + user.emote("makes frantic gestures!") else - user.say(replacetext(invocation," ","`")) + if(prob(50))//Auto-mute? Fuck that noise + user.say(invocation) + else + user.say(replacetext(invocation," ","`")) if("whisper") if(prob(50)) user.whisper(invocation) @@ -418,7 +421,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list)) return 0 - if(is_admin_level(user.z) && (!centcom_cancast || ticker.mode.name == "ragin' mages")) //Certain spells are not allowed on the centcom zlevel + if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel return 0 switch(charge_type) diff --git a/code/datums/spells/emplosion.dm b/code/datums/spells/emplosion.dm index 1ba430ad27e..b2f0a228282 100644 --- a/code/datums/spells/emplosion.dm +++ b/code/datums/spells/emplosion.dm @@ -10,6 +10,6 @@ /obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets, mob/user = usr) for(var/mob/living/target in targets) - empulse(target.loc, emp_heavy, emp_light) + empulse(target.loc, emp_heavy, emp_light, 1) - return \ No newline at end of file + return diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm index 84c3a552c03..f1744e22550 100644 --- a/code/datums/spells/lichdom.dm +++ b/code/datums/spells/lichdom.dm @@ -68,7 +68,7 @@ lich.real_name = M.mind.name M.mind.transfer_to(lich) - lich.set_species("Skeleton") + lich.set_species(/datum/species/skeleton) to_chat(lich, "Your bones clatter and shutter as they're pulled back into this world!") charge_max += 600 var/mob/old_body = current_body @@ -122,7 +122,7 @@ current_body = M.mind.current if(ishuman(M)) var/mob/living/carbon/human/H = M - H.set_species("Skeleton") + H.set_species(/datum/species/skeleton) H.unEquip(H.wear_suit) H.unEquip(H.head) H.unEquip(H.shoes) diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm index 296521405a0..19b30674bf6 100644 --- a/code/datums/spells/mime.dm +++ b/code/datums/spells/mime.dm @@ -21,7 +21,7 @@ if(!usr.mind.miming) to_chat(usr, "You must dedicate yourself to silence first.") return - invocation = "[usr.real_name] looks as if a wall is in front of them." + invocation = "[usr.real_name] looks as if a wall is in front of [usr.p_them()]." else invocation_type ="none" ..() diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm index 2a8408dfe4a..d6a48d25c68 100644 --- a/code/datums/spells/mind_transfer.dm +++ b/code/datums/spells/mind_transfer.dm @@ -32,7 +32,7 @@ Also, you never added distance checking after target is selected. I've went ahea return if(!target.key || !target.mind) - to_chat(user, "They appear to be catatonic. Not even magic can affect their vacant mind.") + to_chat(user, "[target.p_they(TRUE)] appear[target.p_s()] to be catatonic. Not even magic can affect [target.p_their()] vacant mind.") return if(user.suiciding) diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index b82fc629eef..eaa14c4d0b0 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -2,8 +2,8 @@ /datum/status_effect/high_five id = "high_five" - duration = 25 + duration = 40 alert_type = null /datum/status_effect/high_five/on_timeout() - owner.visible_message("[owner] was left hanging....") \ No newline at end of file + owner.visible_message("[owner] was left hanging....") diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 353d38a6932..628b754a5ae 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -1236,8 +1236,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine /datum/supply_packs/materials/plastic30 name = "30 Plastic Sheets Crate" contains = list(/obj/item/stack/sheet/plastic) - amount = 50 - cost = 10 + amount = 30 + cost = 20 containername = "plastic sheets crate" ////////////////////////////////////////////////////////////////////////////// diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 9a5bf86665c..952711f3063 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -97,6 +97,7 @@ var/list/uplink_items = list() if(I) if(ishuman(user)) var/mob/living/carbon/human/A = user + log_game("[key_name(user)] purchased [I.name]") A.put_in_any_hand_if_possible(I) if(istype(I,/obj/item/storage/box/) && I.contents.len>0) @@ -128,6 +129,14 @@ var/list/uplink_items = list() cost = 5 job = list("Clown") +/datum/uplink_item/jobspecific/clownmagboots + name = "Clown Magboots" + desc = "A pair of modified clown shoes fitted with an advanced magnetic traction system. Look and sound exactly like regular clown shoes unless closely inspected." + reference = "CM" + item = /obj/item/clothing/shoes/magboots/clown + cost = 3 + job = list("Clown") + //mime /datum/uplink_item/jobspecific/caneshotgun name = "Cane Shotgun + Assassination Darts" @@ -394,6 +403,13 @@ var/list/uplink_items = list() gamemodes = list(/datum/game_mode/nuclear) surplus = 0 +/datum/uplink_item/dangerous/rapid + name = "Gloves of the North Star" + desc = "These gloves let the user punch people very fast. Does not improve weapon attack speed." + reference = "RPGD" + item = /obj/item/clothing/gloves/fingerless/rapid + cost = 8 + /datum/uplink_item/dangerous/sniper name = "Sniper Rifle" desc = "Ranged fury, Syndicate style. guaranteed to cause shock and awe or your TC back!" @@ -1013,9 +1029,8 @@ var/list/uplink_items = list() /datum/uplink_item/suits/hardsuit name = "Syndicate Hardsuit" - desc = "The feared suit of a syndicate nuclear agent. Features slightly better armoring and a built in jetpack \ - that runs off standard atmospheric tanks. When the built in helmet is deployed your identity will be \ - protected, even in death, as the suit cannot be removed by outside forces. Toggling the suit in and out of \ + desc = "The feared suit of a syndicate nuclear agent. Features armor and a combat mode \ + for faster movement on station. Toggling the suit in and out of \ combat mode will allow you all the mobility of a loose fitting uniform without sacrificing armoring. \ Additionally the suit is collapsible, making it small enough to fit within a backpack. \ Nanotrasen crew who spot these suits are known to panic." @@ -1418,6 +1433,7 @@ var/list/uplink_items = list() for(var/category in temp_uplink_list) buyable_items += temp_uplink_list[category] var/list/bought_items = list() + var/list/itemlog = list() U.uses -= cost U.used_TC = 20 var/remaining_TC = 50 @@ -1433,8 +1449,10 @@ var/list/uplink_items = list() continue bought_items += I.item remaining_TC -= I.cost + itemlog += I.name // To make the name more readable for the log compared to just i.item U.purchase_log += "[bicon(C)]" for(var/item in bought_items) new item(C) U.purchase_log += "[bicon(item)]" + log_game("[key_name(usr)] purchased a surplus crate with [jointext(itemlog, ", ")]") diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index 320cc137806..7ee152648c2 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -1,10 +1,5 @@ //The effects of weather occur across an entire z-level. For instance, lavaland has periodic ash storms that scorch most unprotected creatures. -#define STARTUP_STAGE 1 -#define MAIN_STAGE 2 -#define WIND_DOWN_STAGE 3 -#define END_STAGE 4 - /datum/weather var/name = "space wind" var/desc = "Heavy gusts of wind blanket the area, periodically knocking down anyone caught in the open." @@ -29,24 +24,25 @@ var/area_type = /area/space //Types of area to affect var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins - var/target_z = MAIN_STATION //The z-level to affect var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas. + var/impacted_z_levels // The list of z-levels that this weather is actively affecting - var/overlay_layer = 10 //Since it's above everything else, this is the layer used by default. 2 is below mobs and walls if you need to use that. + var/overlay_layer = AREA_LAYER //Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that. var/aesthetic = FALSE //If the weather has no purpose other than looks var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather var/stage = END_STAGE //The stage of the weather, from 1-4 - var/probability = FALSE //Percent chance to happen if there are other possible weathers on the z-level + // These are read by the weather subsystem and used to determine when and where to run the weather. + var/probability = 0 // Weight amongst other eligible weather. If zero, will never happen randomly. + var/target_trait = STATION_LEVEL // The z-level trait to affect when run randomly or when not overridden. -/datum/weather/New() + var/barometer_predictable = FALSE + var/next_hit_time = 0 //For barometers to know when the next storm will hit + +/datum/weather/New(z_levels) ..() - weather_master.existing_weather |= src - -/datum/weather/Destroy() - weather_master.existing_weather -= src - return ..() + impacted_z_levels = z_levels /datum/weather/proc/telegraph() if(stage == STARTUP_STAGE) @@ -59,17 +55,18 @@ affectareas -= get_areas(V) for(var/V in affectareas) var/area/A = V - if(is_on_level_name(A,target_z)) + if(A.z in impacted_z_levels) impacted_areas |= A weather_duration = rand(weather_duration_lower, weather_duration_upper) + START_PROCESSING(SSweather, src) update_areas() - for(var/V in player_list) - var/mob/M = V - if(is_on_level_name(M,target_z)) + for(var/M in player_list) + var/turf/mob_turf = get_turf(M) + if(mob_turf && (mob_turf.z in impacted_z_levels)) if(telegraph_message) to_chat(M, telegraph_message) if(telegraph_sound) - M << sound(telegraph_sound) + SEND_SOUND(M, sound(telegraph_sound)) addtimer(CALLBACK(src, .proc/start), telegraph_duration) /datum/weather/proc/start() @@ -77,14 +74,13 @@ return stage = MAIN_STAGE update_areas() - for(var/V in player_list) - var/mob/M = V - if(is_on_level_name(M,target_z)) + for(var/M in player_list) + var/turf/mob_turf = get_turf(M) + if(mob_turf && (mob_turf.z in impacted_z_levels)) if(weather_message) to_chat(M, weather_message) if(weather_sound) - M << sound(weather_sound) - weather_master.processing_weather |= src + SEND_SOUND(M, sound(weather_sound)) addtimer(CALLBACK(src, .proc/wind_down), weather_duration) /datum/weather/proc/wind_down() @@ -92,24 +88,25 @@ return stage = WIND_DOWN_STAGE update_areas() - for(var/V in player_list) - var/mob/M = V - if(is_on_level_name(M,target_z)) + for(var/M in player_list) + var/turf/mob_turf = get_turf(M) + if(mob_turf && (mob_turf.z in impacted_z_levels)) if(end_message) to_chat(M, end_message) if(end_sound) - M << sound(end_sound) - weather_master.processing_weather -= src + SEND_SOUND(M, sound(end_sound)) addtimer(CALLBACK(src, .proc/end), end_duration) /datum/weather/proc/end() if(stage == END_STAGE) - return + return 1 stage = END_STAGE + STOP_PROCESSING(SSweather, src) update_areas() -/datum/weather/proc/can_impact(mob/living/L) //Can this weather impact a mob? - if(!is_on_level_name(L,target_z)) +/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob? + var/turf/mob_turf = get_turf(L) + if(mob_turf && !(mob_turf.z in impacted_z_levels)) return if(immunity_type in L.weather_immunities) return @@ -117,7 +114,7 @@ return return 1 -/datum/weather/proc/impact(mob/living/L) //What effect does this weather have on the hapless mob? +/datum/weather/proc/weather_act(mob/living/L) //What effect does this weather have on the hapless mob? return /datum/weather/proc/update_areas() @@ -136,8 +133,8 @@ N.icon_state = end_overlay if(END_STAGE) N.color = null - N.icon_state = initial(N.icon_state) + N.icon_state = "" N.icon = 'icons/turf/areas.dmi' - N.layer = 10 //Just default back to normal area stuff since I assume setting a var is faster than initial + N.layer = AREA_LAYER //Just default back to normal area stuff since I assume setting a var is faster than initial N.invisibility = INVISIBILITY_MAXIMUM - N.opacity = 0 + N.set_opacity(FALSE) diff --git a/code/datums/weather/weather_types.dm b/code/datums/weather/weather_types.dm deleted file mode 100644 index 1581938bd96..00000000000 --- a/code/datums/weather/weather_types.dm +++ /dev/null @@ -1,118 +0,0 @@ -//Different types of weather. - -/datum/weather/floor_is_lava //The Floor is Lava: Makes all turfs damage anyone on them unless they're standing on a solid object. - name = "the floor is lava" - desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor." - - telegraph_message = "Waves of heat emanate from the ground..." - telegraph_duration = 150 - - weather_message = "The floor is lava! Get on top of something!" - weather_duration_lower = 300 - weather_duration_upper = 600 - weather_overlay = "lava" - - end_message = "The ground cools and returns to its usual form." - end_duration = 0 - - area_type = /area - target_z = MAIN_STATION - - overlay_layer = 2 //Covers floors only - immunity_type = "lava" - -/datum/weather/floor_is_lava/impact(mob/living/L) - for(var/obj/structure/O in L.loc) - if(O.density) - return - if(L.loc.density) - return - if(!L.client) //Only sentient people are going along with it! - return - L.adjustFireLoss(3) - -/datum/weather/floor_is_lava/fake - name = "fake lava" - aesthetic = TRUE - -/datum/weather/advanced_darkness //Advanced Darkness: Restricts the vision of all affected mobs to a single tile in the cardinal directions. - name = "advanced darkness" - desc = "Everything in the area is effectively blinded, unable to see more than a foot or so around itself." - - telegraph_message = "The lights begin to dim... is the power going out?" - telegraph_duration = 150 - - weather_message = "This isn't your everyday darkness... this is advanced darkness!" - weather_duration_lower = 300 - weather_duration_upper = 300 - - end_message = "At last, the darkness recedes." - end_duration = 0 - - area_type = /area - target_z = MAIN_STATION - -/datum/weather/advanced_darkness/update_areas() - for(var/V in impacted_areas) - var/area/A = V - if(stage == MAIN_STAGE) - A.invisibility = 0 - A.opacity = 1 - A.layer = overlay_layer - A.icon = 'icons/effects/weather_effects.dmi' - A.icon_state = "darkness" - else - A.invisibility = INVISIBILITY_MAXIMUM - A.opacity = 0 - - -/datum/weather/ash_storm //Ash Storms: Common happenings on lavaland. Heavily obscures vision and deals heavy fire damage to anyone caught outside. - name = "ash storm" - desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected." - - telegraph_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter." - telegraph_duration = 300 - telegraph_sound = 'sound/lavaland/ash_storm_windup.ogg' - telegraph_overlay = "light_ash" - - weather_message = "Smoldering clouds of scorching ash billow down around you! Get inside!" - weather_duration_lower = 600 - weather_duration_upper = 1500 - weather_sound = 'sound/lavaland/ash_storm_start.ogg' - weather_overlay = "ash_storm" - - end_message = "The shrieking wind whips away the last of the ash falls to its usual murmur. It should be safe to go outside now." - end_duration = 300 - end_sound = 'sound/lavaland/ash_storm_end.ogg' - end_overlay = "light_ash" - - area_type = /area/mine/dangerous - target_z = MINING - - immunity_type = "ash" - - probability = 90 - -/datum/weather/ash_storm/impact(mob/living/L) - if(istype(L.loc, /obj/mecha)) - return - if(ishuman(L)) - var/mob/living/carbon/human/H = L - var/thermal_protection = H.get_thermal_protection() - if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) - return - L.adjustFireLoss(4) - -/datum/weather/ash_storm/emberfall //Emberfall: An ash storm passes by, resulting in harmless embers falling like snow. 10% to happen in place of an ash storm. - name = "emberfall" - desc = "A passing ash storm blankets the area in harmless embers." - - weather_message = "Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by..." - weather_sound = 'sound/lavaland/ash_storm_windup.ogg' - weather_overlay = "light_ash" - - end_message = "The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet." - - aesthetic = TRUE - - probability = 10 diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm new file mode 100644 index 00000000000..3f4c57c4196 --- /dev/null +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -0,0 +1,108 @@ +//Ash storms happen frequently on lavaland. They heavily obscure vision, and cause high fire damage to anyone caught outside. +/datum/weather/ash_storm + name = "ash storm" + desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected." + + telegraph_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter." + telegraph_duration = 300 + telegraph_overlay = "light_ash" + + weather_message = "Smoldering clouds of scorching ash billow down around you! Get inside!" + weather_duration_lower = 600 + weather_duration_upper = 1200 + weather_overlay = "ash_storm" + + end_message = "The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now." + end_duration = 300 + end_overlay = "light_ash" + + area_type = /area/mine/dangerous // /area/lavaland/surface/outdoors + target_trait = ORE_LEVEL + + immunity_type = "ash" + +// probability = 90 + + barometer_predictable = TRUE + + var/datum/looping_sound/active_outside_ashstorm/sound_ao = new(list(), FALSE, TRUE) + var/datum/looping_sound/active_inside_ashstorm/sound_ai = new(list(), FALSE, TRUE) + var/datum/looping_sound/weak_outside_ashstorm/sound_wo = new(list(), FALSE, TRUE) + var/datum/looping_sound/weak_inside_ashstorm/sound_wi = new(list(), FALSE, TRUE) + +/datum/weather/ash_storm/telegraph() + . = ..() + var/list/inside_areas = list() + var/list/outside_areas = list() + var/list/eligible_areas = list() + for(var/z in impacted_z_levels) + eligible_areas += space_manager.areas_in_z["[z]"] + for(var/i in 1 to eligible_areas.len) + var/area/place = eligible_areas[i] + if(place.outdoors) + outside_areas += place + else + inside_areas += place + CHECK_TICK + + sound_ao.output_atoms = outside_areas + sound_ai.output_atoms = inside_areas + sound_wo.output_atoms = outside_areas + sound_wi.output_atoms = inside_areas + + sound_wo.start() + sound_wi.start() + +/datum/weather/ash_storm/start() + . = ..() + sound_wo.stop() + sound_wi.stop() + + sound_ao.start() + sound_ai.start() + +/datum/weather/ash_storm/wind_down() + . = ..() + sound_ao.stop() + sound_ai.stop() + + sound_wo.start() + sound_wi.start() + +/datum/weather/ash_storm/end() + . = ..() + sound_wo.stop() + sound_wi.stop() + +/datum/weather/ash_storm/proc/is_ash_immune(atom/L) + while(L && !isturf(L)) + if(ismecha(L)) //Mechs are immune + return TRUE + if(ishuman(L)) //Are you immune? + var/mob/living/carbon/human/H = L + var/thermal_protection = H.get_thermal_protection() + if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) + return TRUE + L = L.loc //Matryoshka check + return FALSE //RIP you + +/datum/weather/ash_storm/weather_act(mob/living/L) + if(is_ash_immune(L)) + return + L.adjustFireLoss(4) + + +//Emberfalls are the result of an ash storm passing by close to the playable area of lavaland. They have a 10% chance to trigger in place of an ash storm. +/datum/weather/ash_storm/emberfall + name = "emberfall" + desc = "A passing ash storm blankets the area in harmless embers." + + weather_message = "Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by..." + weather_overlay = "light_ash" + + end_message = "The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet." + end_sound = null + + aesthetic = TRUE + +// probability = 10 \ No newline at end of file diff --git a/code/datums/weather/weather_types/floor_is_lava.dm b/code/datums/weather/weather_types/floor_is_lava.dm new file mode 100644 index 00000000000..fe7391ec9f0 --- /dev/null +++ b/code/datums/weather/weather_types/floor_is_lava.dm @@ -0,0 +1,39 @@ +//Causes fire damage to anyone not standing on a dense object. +/datum/weather/floor_is_lava + name = "the floor is lava" + desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor." + + telegraph_message = "You feel the ground beneath you getting hot. Waves of heat distort the air." + telegraph_duration = 150 + + weather_message = "The floor is lava! Get on top of something!" + weather_duration_lower = 300 + weather_duration_upper = 600 + weather_overlay = "lava" + + end_message = "The ground cools and returns to its usual form." + end_duration = 0 + + area_type = /area + protected_areas = list(/area/space) + target_trait = STATION_LEVEL + + overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only + immunity_type = "lava" + + +/datum/weather/floor_is_lava/weather_act(mob/living/L) + if(issilicon(L)) + return + for(var/obj/structure/O in L.loc) + if(O.density || O.buckled_mob && istype(O, /obj/structure/stool/bed)) + return + if(L.loc.density) + return + if(!L.client) //Only sentient people are going along with it! + return + L.adjustFireLoss(3) + +/datum/weather/floor_is_lava/fake + name = "the floor is lava (fake)" + aesthetic = TRUE \ No newline at end of file diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm new file mode 100644 index 00000000000..a1c6a83da61 --- /dev/null +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -0,0 +1,61 @@ +//Radiation storms occur when the station passes through an irradiated area, and irradiate anyone not standing in protected areas (maintenance, emergency storage, etc.) +/datum/weather/rad_storm + name = "radiation storm" + desc = "A cloud of intense radiation passes through the area dealing rad damage to those who are unprotected." + + telegraph_duration = 400 + telegraph_message = "The air begins to grow warm." + + weather_message = "You feel waves of heat wash over you! Find shelter!" + weather_overlay = "ash_storm" + weather_duration_lower = 600 + weather_duration_upper = 1500 + weather_color = "green" + weather_sound = 'sound/misc/bloblarm.ogg' + + end_duration = 100 + end_message = "The air seems to be cooling off again." + + area_type = /area + protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer, + /area/turret_protected/ai, /area/storage/emergency, /area/storage/emergency2, /area/crew_quarters/sleep, /area/security/brig, /area/shuttle) + target_trait = STATION_LEVEL + + immunity_type = "rad" + +/datum/weather/rad_storm/telegraph() + ..() + status_alarm(TRUE) + make_maint_all_access() + + +/datum/weather/rad_storm/weather_act(mob/living/L) + var/resist = L.getarmor(null, "rad") + if(prob(40)) + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(!(RADIMMUNE in H.dna.species.species_traits)) + if(prob(max(0, 100 - resist))) + randmuti(H) // Applies bad mutation + if(prob(50)) + if(prob(90)) + randmutb(H) + else + randmutg(H) + domutcheck(H, null, 1) + + L.apply_effect(20, IRRADIATE, resist) + +/datum/weather/rad_storm/end() + if(..()) + return + priority_announcement.Announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert") + status_alarm(FALSE) + revoke_maint_all_access() + +/datum/weather/rad_storm/proc/status_alarm(active) //Makes the status displays show the radiation warning for those who missed the announcement. + if(active) + post_status("alert", "radiation") + else + post_status("blank") + post_status("shuttle") \ No newline at end of file diff --git a/code/datums/weather/weather_types/snow_storm.dm b/code/datums/weather/weather_types/snow_storm.dm new file mode 100644 index 00000000000..4e4d5aab59d --- /dev/null +++ b/code/datums/weather/weather_types/snow_storm.dm @@ -0,0 +1,28 @@ +/datum/weather/snow_storm + name = "snow storm" + desc = "Harsh snowstorms roam the topside of this arctic planet, burying any area unfortunate enough to be in its path." +// probability = 90 + + telegraph_message = "Drifting particles of snow begin to dust the surrounding area.." + telegraph_duration = 300 + telegraph_overlay = "light_snow" + + weather_message = "Harsh winds pick up as dense snow begins to fall from the sky! Seek shelter!" + weather_overlay = "snow_storm" + weather_duration_lower = 600 + weather_duration_upper = 1500 + + end_duration = 100 + end_message = "The snowfall dies down, it should be safe to go outside again." + +// area_type = /area/awaymission/snowdin/outside + target_trait = AWAY_LEVEL + + immunity_type = "snow" + + barometer_predictable = TRUE + + +/datum/weather/snow_storm/weather_act(mob/living/L) + L.adjust_bodytemperature(-rand(5, 15)) + diff --git a/code/datums/wires/camera.dm b/code/datums/wires/camera.dm index ee25f8c3898..609dce59e84 100644 --- a/code/datums/wires/camera.dm +++ b/code/datums/wires/camera.dm @@ -3,52 +3,33 @@ /datum/wires/camera random = 0 holder_type = /obj/machinery/camera - wire_count = 6 + wire_count = 2 /datum/wires/camera/get_status() . = ..() var/obj/machinery/camera/C = holder . += "The focus light is [(C.view_range == initial(C.view_range)) ? "on" : "off"]." . += "The power link light is [C.can_use() ? "on" : "off"]." - . += "The camera light is [C.light_disabled ? "off" : "on"]." - . += "The alarm light is [C.alarm_on ? "on" : "off"]." /datum/wires/camera/CanUse(mob/living/L) var/obj/machinery/camera/C = holder if(!C.panel_open) - return 0 - return 1 + return FALSE + return TRUE var/const/CAMERA_WIRE_FOCUS = 1 var/const/CAMERA_WIRE_POWER = 2 -var/const/CAMERA_WIRE_LIGHT = 4 -var/const/CAMERA_WIRE_ALARM = 8 -var/const/CAMERA_WIRE_NOTHING1 = 16 -var/const/CAMERA_WIRE_NOTHING2 = 32 /datum/wires/camera/GetWireName(index) switch(index) if(CAMERA_WIRE_FOCUS) return "Focus" - + if(CAMERA_WIRE_POWER) return "Power" - - if(CAMERA_WIRE_LIGHT) - return "Light" - - if(CAMERA_WIRE_ALARM) - return "Alarm" - - if(CAMERA_WIRE_NOTHING1) - return "Nothing" - - if(CAMERA_WIRE_NOTHING2) - return "Nothing" /datum/wires/camera/UpdateCut(index, mended) var/obj/machinery/camera/C = holder - switch(index) if(CAMERA_WIRE_FOCUS) var/range = (mended ? initial(C.view_range) : C.short_range) @@ -56,16 +37,8 @@ var/const/CAMERA_WIRE_NOTHING2 = 32 if(CAMERA_WIRE_POWER) if(C.status && !mended || !C.status && mended) - C.toggle_cam(usr, 1) - - if(CAMERA_WIRE_LIGHT) - C.light_disabled = !mended - - if(CAMERA_WIRE_ALARM) - if(!mended) - C.triggerCameraAlarm() - else - C.cancelCameraAlarm() + C.toggle_cam(usr, TRUE) + C.obj_integrity = C.max_integrity //this is a pretty simplistic way to heal the camera, but there's no reason for this to be complex. ..() /datum/wires/camera/UpdatePulsed(index) @@ -79,16 +52,10 @@ var/const/CAMERA_WIRE_NOTHING2 = 32 if(CAMERA_WIRE_POWER) C.toggle_cam(null) // Deactivate the camera - - if(CAMERA_WIRE_LIGHT) - C.light_disabled = !C.light_disabled - - if(CAMERA_WIRE_ALARM) - C.visible_message("[bicon(C)] *beep*", "[bicon(C)] *beep*") ..() /datum/wires/camera/proc/CanDeconstruct() - if(IsIndexCut(CAMERA_WIRE_POWER) && IsIndexCut(CAMERA_WIRE_FOCUS) && IsIndexCut(CAMERA_WIRE_LIGHT) && IsIndexCut(CAMERA_WIRE_NOTHING1) && IsIndexCut(CAMERA_WIRE_NOTHING2)) - return 1 + if(IsIndexCut(CAMERA_WIRE_POWER) && IsIndexCut(CAMERA_WIRE_FOCUS)) + return TRUE else - return 0 \ No newline at end of file + return FALSE \ No newline at end of file diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 286ac454efc..054a7e4f669 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -1,5 +1,3 @@ -#define CAT_HIDDEN 2 // Also in code/game/machinery/vending.dm - /datum/wires/vending holder_type = /obj/machinery/vending wire_count = 4 diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index 0f2a2bd4393..cdf25ce9651 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -76,6 +76,10 @@ var/message = "[key_name(whom, 1)] [isLivingSSD(whom) ? "(SSD!)" : ""] ([admin_jump_link(whom)])" return message +/proc/key_name_log(whom) + // Key_name_admin, but does not include (?) or jump link - For logging purpose to reduce clutter while figuring out who is SSD and/or antag when being attacked. Also remove formatting since it is not displayed + var/message = "[key_name(whom, 0)][isAntag(whom) ? "(ANTAG)" : ""][isLivingSSD(whom) ? "(SSD!)": ""]" + return message /proc/log_and_message_admins(var/message as text) log_admin("[key_name(usr)] " + message) diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm index b6e3ecde8bd..1664a7051da 100644 --- a/code/defines/procs/announce.dm +++ b/code/defines/procs/announce.dm @@ -48,8 +48,8 @@ if(!message) return - var/tmp/message_title = new_title ? new_title : title - var/tmp/message_sound = new_sound ? sound(new_sound) : sound + var/message_title = new_title ? new_title : title + var/message_sound = new_sound ? sound(new_sound) : sound if(!msg_sanitized) message = trim_strip_html_properly(message, allow_lines = 1) diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 90b45a19170..e331376a0dc 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -20,13 +20,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/atmosalm = ATMOS_ALARM_NONE var/poweralm = 1 var/party = null - var/radalert = 0 var/report_alerts = 1 // Should atmos alerts notify the AI/computers level = null name = "Space" icon = 'icons/turf/areas.dmi' icon_state = "unknown" - layer = 10 + layer = AREA_LAYER luminosity = 0 mouse_opacity = 0 invisibility = INVISIBILITY_LIGHTING @@ -141,9 +140,6 @@ var/list/ghostteleportlocs = list() /area/space/readyalert() return -/area/space/radiation_alert() - return - /area/space/partyalert() return diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 8a9a108c7b3..44a9ae7e522 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -22,7 +22,7 @@ ..() icon_state = "" - layer = 10 + layer = AREA_LAYER uid = ++global_uid all_areas += src map_name = name // Save the initial (the name set in the map) name of the area. @@ -45,7 +45,24 @@ blend_mode = BLEND_MULTIPLY // Putting this in the constructor so that it stops the icons being screwed up in the map editor. /area/Initialize() - ..() + . = ..() + + if(contents.len) + var/list/areas_in_z = space_manager.areas_in_z + var/z + for(var/i in 1 to contents.len) + var/atom/thing = contents[i] + if(!thing) + continue + z = thing.z + break + if(!z) + WARNING("No z found for [src]") + return + if(!areas_in_z["[z]"]) + areas_in_z["[z]"] = list() + areas_in_z["[z]"] += src + return INITIALIZE_HINT_LATELOAD /area/LateInitialize() @@ -160,16 +177,6 @@ eject = 0 updateicon() -/area/proc/radiation_alert() - if(!radalert) - radalert = 1 - updateicon() - -/area/proc/reset_radiation_alert() - if(radalert) - radalert = 0 - updateicon() - /area/proc/partyalert() if(!party) party = 1 @@ -183,11 +190,8 @@ updateicon() /area/proc/updateicon() - if(radalert) // always show the radiation alert, regardless of power - icon_state = "radiation" - invisibility = INVISIBILITY_LIGHTING - else if((fire || eject || party) && (!requires_power||power_environ))//If it doesn't require power, can still activate this proc. - if(fire && !radalert && !eject && !party) + if((fire || eject || party) && (!requires_power||power_environ))//If it doesn't require power, can still activate this proc. + if(fire && !eject && !party) icon_state = "red" else if(!fire && eject && !party) icon_state = "red" @@ -197,9 +201,15 @@ icon_state = "blue-red" invisibility = INVISIBILITY_LIGHTING else - // new lighting behaviour with obj lights - icon_state = null - invisibility = INVISIBILITY_MAXIMUM + var/weather_icon + for(var/V in SSweather.processing) + var/datum/weather/W = V + if(W.stage != END_STAGE && (src in W.impacted_areas)) + W.update_areas() + weather_icon = TRUE + if(!weather_icon) + icon_state = null + invisibility = INVISIBILITY_MAXIMUM /area/space/updateicon() icon_state = null @@ -384,4 +394,4 @@ for(var/obj/machinery/door/airlock/temp_airlock in src) temp_airlock.prison_open() for(var/obj/machinery/door/window/temp_windoor in src) - temp_windoor.open() + temp_windoor.open() \ No newline at end of file diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 19af319aa20..ea3b9df4f54 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -143,6 +143,12 @@ /atom/proc/setDir(newdir) dir = newdir +/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(does_attack_animation) + user.changeNext_move(CLICK_CD_MELEE) + add_attack_logs(user, src, "Punched with hulk powers") + user.do_attack_animation(src, ATTACK_EFFECT_SMASH) + /atom/proc/CheckParts(list/parts_list) for(var/A in parts_list) if(istype(A, /datum/reagent)) @@ -296,6 +302,9 @@ /atom/proc/emag_act() return +/atom/proc/rpd_act() + return + /atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked) if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). addtimer(CALLBACK(src, .proc/hitby_react, AM), 2) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index c7e6401e204..a847350cb3d 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -29,11 +29,10 @@ areaMaster = get_area_master(src) /atom/movable/attempt_init() - if(ticker && ticker.current_state >= GAME_STATE_SETTING_UP) - var/turf/T = get_turf(src) - if(T && space_manager.is_zlevel_dirty(T.z)) - space_manager.postpone_init(T.z, src) - return + var/turf/T = get_turf(src) + if(T && SSatoms.initialized != INITIALIZATION_INSSATOMS && space_manager.is_zlevel_dirty(T.z)) + space_manager.postpone_init(T.z, src) + return . = ..() @@ -363,3 +362,70 @@ target.fingerprints += fingerprints target.fingerprintshidden += fingerprintshidden target.fingerprintslast = fingerprintslast + +/atom/movable/proc/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y) + if(!no_effect && (visual_effect_icon || used_item)) + do_item_attack_animation(A, visual_effect_icon, used_item) + + if(A == src) + return //don't do an animation if attacking self + var/pixel_x_diff = 0 + var/pixel_y_diff = 0 + var/final_pixel_y = initial(pixel_y) + if(end_pixel_y) + final_pixel_y = end_pixel_y + + var/direction = get_dir(src, A) + if(direction & NORTH) + pixel_y_diff = 8 + else if(direction & SOUTH) + pixel_y_diff = -8 + + if(direction & EAST) + pixel_x_diff = 8 + else if(direction & WEST) + pixel_x_diff = -8 + + animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2) + animate(pixel_x = initial(pixel_x), pixel_y = final_pixel_y, time = 2) + +/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item) + var/image/I + if(visual_effect_icon) + I = image('icons/effects/effects.dmi', A, visual_effect_icon, A.layer + 0.1) + else if(used_item) + I = image(used_item.icon, A, used_item.icon_state, A.layer + 0.1) + + // Scale the icon. + I.transform *= 0.75 + // The icon should not rotate. + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + + // Set the direction of the icon animation. + var/direction = get_dir(src, A) + if(direction & NORTH) + I.pixel_y = -16 + else if(direction & SOUTH) + I.pixel_y = 16 + + if(direction & EAST) + I.pixel_x = -16 + else if(direction & WEST) + I.pixel_x = 16 + + if(!direction) // Attacked self?! + I.pixel_z = 16 + + if(!I) + return + + // Who can see the attack? + var/list/viewing = list() + for(var/mob/M in viewers(A)) + if(M.client && M.client.prefs.show_ghostitem_attack) + viewing |= M.client + + flick_overlay(I, viewing, 5) // 5 ticks/half a second + + // And animate the attack! + animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index a4faafcf91f..db2fb3c64df 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -52,6 +52,9 @@ /datum/atom_hud/data/bot_path hud_icons = list(DIAG_PATH_HUD) +/datum/atom_hud/abductor + hud_icons = list(GLAND_HUD) + /datum/atom_hud/data/hydroponic hud_icons = list (PLANT_NUTRIENT_HUD, PLANT_WATER_HUD, PLANT_STATUS_HUD, PLANT_HEALTH_HUD, PLANT_TOXIN_HUD, PLANT_PEST_HUD, PLANT_WEED_HUD) diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index f21c2948b01..cba96ded0db 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -99,8 +99,7 @@ var/global/list/bad_blocks[0] var/b_type = "A+" // Should probably change to an integer => string map but I'm lazy. var/real_name // Stores the real name of the person who originally got this dna datum. Used primarily for changelings, - // New stuff - var/species = "Human" + var/datum/species/species = new /datum/species/human //The type of mutant race the player is if applicable (i.e. potato-man) // Make a copy of this strand. // USE THIS WHEN COPYING STUFF OR YOU'LL GET CORRUPTION! @@ -110,7 +109,7 @@ var/global/list/bad_blocks[0] new_dna.struc_enzymes_original=struc_enzymes_original // will make clone's SE the same as the original, do we want this? new_dna.b_type=b_type new_dna.real_name=real_name - new_dna.species=species + new_dna.species = new species.type for(var/b=1;b<=DNA_SE_LENGTH;b++) new_dna.SE[b]=SE[b] if(b<=DNA_UI_LENGTH) @@ -141,7 +140,7 @@ var/global/list/bad_blocks[0] // FIXME: Species-specific defaults pls var/obj/item/organ/external/head/H = character.get_organ("head") var/obj/item/organ/internal/eyes/eyes_organ = character.get_int_organ(/obj/item/organ/internal/eyes) - var/datum/species/S = character.species + var/datum/species/S = character.dna.species /*// Body Accessory if(!character.body_accessory) @@ -421,7 +420,7 @@ var/global/list/bad_blocks[0] data["UE"] = unique_enzymes data["SE"] = SE.Copy() // This is probably too lazy for my own good data["UI"] = UI.Copy() - data["species"] = species // This works because `species` is a string, not a datum + data["species"] = species.type // Because old DNA coders were insane or something data["b_type"] = b_type data["real_name"] = real_name @@ -434,10 +433,7 @@ var/global/list/bad_blocks[0] UI = data["UI"] UpdateUI() UpdateSE() - species = data["species"] + var/datum/species/S = data["species"] + species = new S b_type = data["b_type"] - real_name = data["real_name"] - -// a nice hook for if/when we refactor species on dna -/datum/dna/proc/get_species_name() - return species + real_name = data["real_name"] \ No newline at end of file diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm index f2ad2b2fe03..07979f40b7c 100644 --- a/code/game/dna/dna2_domutcheck.dm +++ b/code/game/dna/dna2_domutcheck.dm @@ -16,7 +16,7 @@ /proc/genemutcheck(var/mob/living/M, var/block, var/connected=null, var/flags=0) if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure. var/mob/living/carbon/human/H = M - if(NO_DNA in H.species.species_traits) + if(NO_DNA in H.dna.species.species_traits) return if(!M) return @@ -42,7 +42,7 @@ var/defaultgenes // Do not mutate inherent species abilities if(ishuman(M)) var/mob/living/carbon/human/H = M - defaultgenes = H.species.default_genes + defaultgenes = H.dna.species.default_genes if((gene in defaultgenes) && gene_active) return diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 6c05dfd6f2b..d392ab303ca 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -133,7 +133,7 @@ var/mob/living/carbon/human/H = src var/obj/item/organ/external/head/head_organ = H.get_organ("head") var/obj/item/organ/internal/eyes/eye_organ = H.get_int_organ(/obj/item/organ/internal/eyes) - var/datum/species/S = H.species + var/datum/species/S = H.dna.species if(istype(head_organ)) dna.write_head_attributes(head_organ) if(istype(eye_organ)) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 99355320491..354536561c1 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -192,7 +192,7 @@ return for(var/mob/living/carbon/slime/M in range(1,L)) if(M.Victim == L) - to_chat(usr, "[L.name] will not fit into the [src] because they have a slime latched onto their head.") + to_chat(usr, "[L.name] will not fit into the [src] because [L.p_they()] [L.p_have()] a slime latched onto [L.p_their()] head.") return if(L == user) visible_message("[user] climbs into the [src].") @@ -327,7 +327,7 @@ if(ishuman(occupant)) var/mob/living/carbon/human/H = occupant - if(NO_DNA in H.species.species_traits) + if(NO_DNA in H.dna.species.species_traits) return 1 var/radiation_protection = occupant.run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm.") diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm index e59dd3fc558..b39b31a1c5a 100644 --- a/code/game/dna/genes/goon_disabilities.dm +++ b/code/game/dna/genes/goon_disabilities.dm @@ -44,7 +44,7 @@ return 0 if(ishuman(M)) var/mob/living/carbon/human/H = M - if((RADIMMUNE in H.species.species_traits) && !(flags & MUTCHK_FORCED)) + if((RADIMMUNE in H.dna.species.species_traits) && !(flags & MUTCHK_FORCED)) return 0 return 1 diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index 6fbc30883ca..37292beb8fe 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -179,8 +179,7 @@ C.ExtinguishMob() C.visible_message("[user] sprays a cloud of fine ice crystals, engulfing [C]!") - log_attack(user, C, "Used cryokinesis on a victim without internals or a suit") - msg_admin_attack("[key_name_admin(user)] has cast cryokinesis on [key_name_admin(C)] (NO SUIT)") + add_attack_logs(user, C, "Cryokinesis- NO SUIT/INTERNALS") //playsound(user.loc, 'bamf.ogg', 50, 0) @@ -318,14 +317,6 @@ var/atom/movable/the_item = targets[1] if(ishuman(the_item)) - //My gender - var/m_his = "his" - if(user.gender == FEMALE) - m_his = "her" - // Their gender - var/t_his = "his" - if(the_item.gender == FEMALE) - t_his = "her" var/mob/living/carbon/human/H = the_item var/obj/item/organ/external/limb = H.get_organ(user.zone_sel.selecting) if(!istype(limb)) @@ -334,15 +325,15 @@ return 0 if(istype(limb,/obj/item/organ/external/head)) // Bullshit, but prevents being unable to clone someone. - to_chat(user, "You try to put \the [limb] in your mouth, but [t_his] ears tickle your throat!") + to_chat(user, "You try to put \the [limb] in your mouth, but [the_item.p_their()] ears tickle your throat!") revert_cast() return 0 if(istype(limb,/obj/item/organ/external/chest)) // Bullshit, but prevents being able to instagib someone. - to_chat(user, "You try to put their [limb] in your mouth, but it's too big to fit!") + to_chat(user, "You try to put [the_item.p_their()] [limb] in your mouth, but it's too big to fit!") revert_cast() return 0 - user.visible_message("[user] begins stuffing [the_item]'s [limb.name] into [m_his] gaping maw!") + user.visible_message("[user] begins stuffing [the_item]'s [limb.name] into [user.p_their()] gaping maw!") var/oldloc = H.loc if(!do_mob(user,H,EAT_MOB_DELAY)) to_chat(user, "You were interrupted before you could eat [the_item]!") @@ -434,7 +425,7 @@ user.flying = prevFlying if(FAT in user.mutations && prob(66)) - user.visible_message("[user.name] crashes due to their heavy weight!") + user.visible_message("[user.name] crashes due to [user.p_their()] heavy weight!") //playsound(user.loc, 'zhit.wav', 50, 1) user.AdjustWeakened(10) user.AdjustStunned(5) @@ -559,10 +550,10 @@ return if(M.stat == 2) - to_chat(user, "[M.name] is dead and cannot have their mind read.") + to_chat(user, "[M.name] is dead and cannot have [M.p_their()] mind read.") return if(M.health < 0) - to_chat(user, "[M.name] is dying, and their thoughts are too scrambled to read.") + to_chat(user, "[M.name] is dying, and [M.p_their()] thoughts are too scrambled to read.") return to_chat(user, "Mind Reading of [M.name]:") @@ -570,8 +561,8 @@ var/pain_condition = M.health / M.maxHealth // lower health means more pain var/list/randomthoughts = list("what to have for lunch","the future","the past","money", - "their hair","what to do next","their job","space","amusing things","sad things", - "annoying things","happy things","something incoherent","something they did wrong") + "[M.p_their()] hair","what to do next","[M.p_their()] job","space","amusing things","sad things", + "annoying things","happy things","something incoherent","something [M.p_they()] did wrong") var/thoughts = "thinking about [pick(randomthoughts)]" if(M.fire_stacks) @@ -592,7 +583,7 @@ to_chat(user, "Condition: [M.name] is suffering severe pain.") else to_chat(user, "Condition: [M.name] is suffering excruciating pain.") - thoughts = "haunted by their own mortality" + thoughts = "haunted by [M.p_their()] own mortality" switch(M.a_intent) if(INTENT_HELP) @@ -655,7 +646,7 @@ action_icon_state = "superfart" /obj/effect/proc_holder/spell/aoe_turf/superfart/invocation(mob/user = usr) - invocation = "[user] hunches down and grits their teeth!" + invocation = "[user] hunches down and grits [user.p_their()] teeth!" invocation_emote_self = "You hunch down and grit your teeth!" ..(user) diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index 666cb057635..d0c32b19620 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -7,8 +7,8 @@ /datum/dna/gene/monkey/can_activate(var/mob/M,var/flags) return ishuman(M) -/datum/dna/gene/monkey/activate(var/mob/living/carbon/human/H, var/connected, var/flags) - if(!istype(H,/mob/living/carbon/human)) +/datum/dna/gene/monkey/activate(mob/living/carbon/human/H, connected, flags) + if(!istype(H)) return if(issmall(H)) return @@ -24,6 +24,9 @@ H.canmove = 0 H.icon = null H.invisibility = 101 + var/has_primitive_form = H.dna.species.primitive_form // cache this + if(has_primitive_form) + H.set_species(has_primitive_form) new /obj/effect/temp_visual/monkeyify(H.loc) sleep(22) @@ -31,23 +34,24 @@ H.SetStunned(0) H.invisibility = initial(H.invisibility) - if(!H.species.primitive_form) //If the creature in question has no primitive set, this is going to be messy. + if(!has_primitive_form) //If the pre-change mob in question has no primitive set, this is going to be messy. H.gib() return - H.set_species(H.species.primitive_form) - QDEL_NULL(H.hud_used) if(H.client) H.hud_used = new /datum/hud/monkey(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha) + H.hud_used.show_hud(H.hud_used.hud_version) - to_chat(H, "You are now a [H.species.name].") + to_chat(H, "You are now a [H.dna.species.name].") return H -/datum/dna/gene/monkey/deactivate(var/mob/living/carbon/human/H, var/connected, var/flags) - if(!istype(H,/mob/living/carbon/human)) +/datum/dna/gene/monkey/deactivate(mob/living/carbon/human/H, connected, flags) + if(!istype(H)) + return + if(!issmall(H)) return for(var/obj/item/W in H) if(W == H.w_uniform) // will be torn @@ -62,6 +66,9 @@ H.canmove = 0 H.icon = null H.invisibility = 101 + var/has_greater_form = H.dna.species.greater_form //cache this + if(has_greater_form) + H.set_species(has_greater_form) new /obj/effect/temp_visual/monkeyify/humanify(H.loc) sleep(22) @@ -69,11 +76,10 @@ H.SetStunned(0) H.invisibility = initial(H.invisibility) - if(!H.species.greater_form) //If the creature in question has no primitive set, this is going to be messy. + if(!has_greater_form) //If the pre-change mob in question has no primitive set, this is going to be messy. H.gib() return - H.set_species(H.species.greater_form) H.real_name = H.dna.real_name H.name = H.real_name @@ -81,7 +87,8 @@ if(H.client) H.hud_used = new /datum/hud/human(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha) + H.hud_used.show_hud(H.hud_used.hud_version) - to_chat(H, "You are now a [H.species.name].") + to_chat(H, "You are now a [H.dna.species.name].") return H diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index e9d69c2b904..1e5e6b66842 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -39,7 +39,7 @@ return 0 if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.species && H.species.slowdown && !(flags & MUTCHK_FORCED)) + if(H.dna.species && H.dna.species.slowdown && !(flags & MUTCHK_FORCED)) return 0 return 1 diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index bfd75f486e0..f9e8620bef1 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -50,7 +50,7 @@ M.change_eye_color(new_eyes) //Alt heads. - if(head_organ.species.bodyflags & HAS_ALT_HEADS) + if(head_organ.dna.species.bodyflags & HAS_ALT_HEADS) var/list/valid_alt_heads = M.generate_valid_alt_heads() var/new_alt_head = input("Please select alternate head", "Character Generation", head_organ.alt_head) as null|anything in valid_alt_heads if(new_alt_head) @@ -92,7 +92,7 @@ M.change_facial_hair_color(new_facial, 1) //Head accessory. - if(head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + if(head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) var/list/valid_head_accessories = M.generate_valid_head_accessories() var/new_head_accessory = input("Please select head accessory style", "Character Generation", head_organ.ha_style) as null|anything in valid_head_accessories if(new_head_accessory) @@ -103,7 +103,7 @@ M.change_head_accessory_color(new_head_accessory_colour) //Body accessory. - if(M.species.tail && M.species.bodyflags & HAS_TAIL) + if(M.dna.species.tail && M.dna.species.bodyflags & HAS_TAIL) var/list/valid_body_accessories = M.generate_valid_body_accessories() if(valid_body_accessories.len > 1) //By default valid_body_accessories will always have at the very least a 'none' entry populating the list, even if the user's species is not present in any of the list items. var/new_body_accessory = input("Please select body accessory style", "Character Generation", M.body_accessory) as null|anything in valid_body_accessories @@ -111,7 +111,7 @@ M.change_body_accessory(new_body_accessory) //Head markings. - if(M.species.bodyflags & HAS_HEAD_MARKINGS) + if(M.dna.species.bodyflags & HAS_HEAD_MARKINGS) var/list/valid_head_markings = M.generate_valid_markings("head") var/new_marking = input("Please select head marking style", "Character Generation", M.m_styles["head"]) as null|anything in valid_head_markings if(new_marking) @@ -121,7 +121,7 @@ if(new_marking_colour) M.change_marking_color(new_marking_colour, "head") //Body markings. - if(M.species.bodyflags & HAS_BODY_MARKINGS) + if(M.dna.species.bodyflags & HAS_BODY_MARKINGS) var/list/valid_body_markings = M.generate_valid_markings("body") var/new_marking = input("Please select body marking style", "Character Generation", M.m_styles["body"]) as null|anything in valid_body_markings if(new_marking) @@ -131,7 +131,7 @@ if(new_marking_colour) M.change_marking_color(new_marking_colour, "body") //Tail markings. - if(M.species.bodyflags & HAS_TAIL_MARKINGS) + if(M.dna.species.bodyflags & HAS_TAIL_MARKINGS) var/list/valid_tail_markings = M.generate_valid_markings("tail") var/new_marking = input("Please select tail marking style", "Character Generation", M.m_styles["tail"]) as null|anything in valid_tail_markings if(new_marking) @@ -142,7 +142,7 @@ M.change_marking_color(new_marking_colour, "tail") //Skin tone. - if(M.species.bodyflags & HAS_SKIN_TONE) + if(M.dna.species.bodyflags & HAS_SKIN_TONE) var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", M.s_tone) as null|text if(!new_tone) new_tone = 35 @@ -150,11 +150,11 @@ new_tone = 35 - max(min(round(text2num(new_tone)), 220), 1) M.change_skin_tone(new_tone) - if(M.species.bodyflags & HAS_ICON_SKIN_TONE) - var/prompt = "Please select skin tone: 1-[M.species.icon_skin_tones.len] (" - for(var/i = 1 to M.species.icon_skin_tones.len) - prompt += "[i] = [M.species.icon_skin_tones[i]]" - if(i != M.species.icon_skin_tones.len) + if(M.dna.species.bodyflags & HAS_ICON_SKIN_TONE) + var/prompt = "Please select skin tone: 1-[M.dna.species.icon_skin_tones.len] (" + for(var/i = 1 to M.dna.species.icon_skin_tones.len) + prompt += "[i] = [M.dna.species.icon_skin_tones[i]]" + if(i != M.dna.species.icon_skin_tones.len) prompt += ", " prompt += ")" @@ -162,18 +162,18 @@ if(!new_tone) new_tone = 0 else - new_tone = max(min(round(text2num(new_tone)), M.species.icon_skin_tones.len), 1) + new_tone = max(min(round(text2num(new_tone)), M.dna.species.icon_skin_tones.len), 1) M.change_skin_tone(new_tone) //Skin colour. - if(M.species.bodyflags & HAS_SKIN_COLOR) + if(M.dna.species.bodyflags & HAS_SKIN_COLOR) var/new_body_colour = input("Please select body colour.", "Character Generation", M.skin_colour) as null|color if(new_body_colour) M.change_skin_color(new_body_colour) M.update_dna() - M.visible_message("[src] morphs and changes [M.get_visible_gender() == MALE ? "his" : M.get_visible_gender() == FEMALE ? "her" : "their"] appearance!", "You change your appearance!", "Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") + M.visible_message("[src] morphs and changes [p_their()] appearance!", "You change your appearance!", "Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") /datum/dna/gene/basic/grant_spell/remotetalk name="Telepathy" diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm index 93fe05ffa10..eb32bed006d 100644 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ b/code/game/gamemodes/autotraitor/autotraitor.dm @@ -191,7 +191,7 @@ //message_admins("The probability of a new traitor is [traitor_prob]%") if(prob(traitor_prob)) message_admins("New traitor roll passed. Making a new Traitor.") - character.mind.make_Tratior() //TEMP: Add proper checks for loyalty here. uc_guy + character.mind.make_Traitor() //TEMP: Add proper checks for loyalty here. uc_guy //else //message_admins("New traitor roll failed. No new traitor.") //else diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 0bcd942b7a0..80bba117a20 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -119,7 +119,7 @@ var/list/blob_nodes = list() if(!is_station_level(location.z) || istype(location, /turf/space)) if(!warned) to_chat(C, "You feel ready to burst, but this isn't an appropriate place! You must return to the station!") - message_admins("[key_name_admin(C)] was in space when the blobs burst, and will die if he doesn't return to the station.") + message_admins("[key_name_admin(C)] was in space when the blobs burst, and will die if [C.p_they()] [C.p_do()] not return to the station.") spawn(300) burst_blob(blob, 1) else diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index e53a74c8daa..15a3b2e222f 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -147,6 +147,9 @@ ..() take_damage(power/400, BURN) +/obj/structure/blob/hulk_damage() + return 15 + /obj/structure/blob/attackby(var/obj/item/W, var/mob/living/user, params) user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index a9c5882094d..477a0de2573 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -112,8 +112,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" if(identity_theft.target && identity_theft.target.current) identity_theft.target_real_name = kill_objective.target.current.real_name //Whoops, forgot this. var/mob/living/carbon/human/H = identity_theft.target.current - if(can_absorb_species(H.species)) // For species that can't be absorbed - should default to an escape objective - identity_theft.explanation_text = "Escape on the shuttle or an escape pod with the identity of [identity_theft.target_real_name], the [identity_theft.target.assigned_role] while wearing their identification card." + if(can_absorb_species(H.dna.species)) // For species that can't be absorbed - should default to an escape objective + identity_theft.explanation_text = "Escape on the shuttle or an escape pod with the identity of [identity_theft.target_real_name], the [identity_theft.target.assigned_role] while wearing [identity_theft.target.p_their()] identification card." changeling.objectives += identity_theft else qdel(identity_theft) @@ -273,7 +273,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" /datum/changeling/proc/find_dna(datum/dna/tDNA) for(var/datum/dna/D in (absorbed_dna + protected_dna)) - if(tDNA.unique_enzymes == D.unique_enzymes && tDNA.uni_identity == D.uni_identity && tDNA.species == D.species) + if(tDNA.unique_enzymes == D.unique_enzymes && tDNA.uni_identity == D.uni_identity && tDNA.species.type == D.species.type) return D return null @@ -316,7 +316,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" to_chat(user, "DNA of [target] is ruined beyond usability!") return - if(NO_DNA in T.species.species_traits) + if(NO_DNA in T.dna.species.species_traits) to_chat(user, "This creature does not have DNA!") return diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index d690f095236..befdf899253 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -20,7 +20,7 @@ var/list/sting_paths /obj/effect/proc_holder/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling) var/dat - dat +="Changling Evolution Menu" + dat +="Changeling Evolution Menu" //javascript, the part that does most of the work~ dat += {" @@ -375,7 +375,7 @@ var/list/sting_paths path.on_purchase(src) var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste - mind.changeling.absorbed_dna |= C.dna + mind.changeling.absorbed_dna |= C.dna.Clone() mind.changeling.trim_dna() return 1 diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index e9ae34d2cfa..b60cfee4718 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -73,8 +73,8 @@ recent_speech = target.say_log.Copy() if(recent_speech.len) - user.mind.store_memory("Some of [target]'s speech patterns, we should study these to better impersonate them!") - to_chat(user, "Some of [target]'s speech patterns, we should study these to better impersonate them!") + user.mind.store_memory("Some of [target]'s speech patterns. We should study these to better impersonate [target.p_them()]!") + to_chat(user, "Some of [target]'s speech patterns. We should study these to better impersonate [target.p_them()]!") for(var/spoken_memory in recent_speech) user.mind.store_memory("\"[spoken_memory]\"") to_chat(user, "\"[spoken_memory]\"") diff --git a/code/game/gamemodes/changeling/powers/biodegrade.dm b/code/game/gamemodes/changeling/powers/biodegrade.dm index 3103416b9e4..5142734183b 100644 --- a/code/game/gamemodes/changeling/powers/biodegrade.dm +++ b/code/game/gamemodes/changeling/powers/biodegrade.dm @@ -16,7 +16,7 @@ var/obj/O = user.get_item_by_slot(slot_handcuffed) if(!istype(O)) return FALSE - user.visible_message("[user] vomits a glob of acid on \his [O]!", \ + user.visible_message("[user] vomits a glob of acid on [user.p_their()] [O.name]!", \ "We vomit acidic ooze onto our restraints!") addtimer(CALLBACK(src, .proc/dissolve_handcuffs, user, O), 30) used = TRUE @@ -25,7 +25,7 @@ var/obj/item/clothing/suit/S = user.get_item_by_slot(slot_wear_suit) if(!istype(S)) return FALSE - user.visible_message("[user] vomits a glob of acid across the front of \his [S]!", \ + user.visible_message("[user] vomits a glob of acid across the front of [user.p_their()] [S.name]!", \ "We vomit acidic ooze onto our straight jacket!") addtimer(CALLBACK(src, .proc/dissolve_straightjacket, user, S), 30) used = TRUE diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index fb3012cd274..72b0e821e66 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -26,10 +26,10 @@ to_chat(user, "We transform our appearance.") user.dna.SetSEState(MONKEYBLOCK,0,1) genemutcheck(user,MONKEYBLOCK,null,MUTCHK_FORCED) + if(istype(user)) + user.set_species(chosen_dna.species.type) user.dna = chosen_dna.Clone() user.real_name = chosen_dna.real_name - if(istype(user)) - user.set_species(chosen_dna.species) domutcheck(user,null,MUTCHK_FORCED) user.flavor_text = "" user.dna.UpdateSE() diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index 3d3b7f2bc07..2197163cbd5 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -17,17 +17,13 @@ var/mob/living/carbon/human/H = user - if(!istype(H) || !H.species.primitive_form) + if(!istype(H) || !H.dna.species.primitive_form) to_chat(H, "We cannot perform this ability in this form!") return - user.dna = user.dna.Clone() H.visible_message("[H] transforms!") changeling.geneticdamage = 30 to_chat(H, "Our genes cry out!") - var/list/implants = list() //Try to preserve implants. - for(var/obj/item/implant/W in H) - implants += W H.monkeyize() changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) feedback_add_details("changeling_powers","LF") diff --git a/code/game/gamemodes/changeling/powers/linglink.dm b/code/game/gamemodes/changeling/powers/linglink.dm index 4b59c255128..52de921d7ec 100644 --- a/code/game/gamemodes/changeling/powers/linglink.dm +++ b/code/game/gamemodes/changeling/powers/linglink.dm @@ -47,7 +47,7 @@ to_chat(user, "We stealthily stab [target] with a minor proboscis...") to_chat(target, "You experience a stabbing sensation and your ears begin to ring...") if(3) - to_chat(user, "You mold the [target]'s mind like clay, they can now speak in the hivemind!") + to_chat(user, "You mold the [target]'s mind like clay, [target.p_they()] can now speak in the hivemind!") to_chat(target, "A migraine throbs behind your eyes, you hear yourself screaming - but your mouth has not opened!") for(var/mob/M in mob_list) if(all_languages["Changeling"] in M.languages) diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index 4e084e8b720..4cf998cf043 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -25,13 +25,13 @@ if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh qdel(user.l_hand) if(!silent) - user.visible_message("With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]", "You hear the organic matter ripping and tearing!") + H.visible_message("[H] casts off [H.p_their()] [suit_name_simple]!", "We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]", "You hear the organic matter ripping and tearing!") qdel(H.wear_suit) qdel(H.head) H.update_inv_wear_suit() @@ -138,7 +138,7 @@ loc.visible_message("A grotesque blade forms around [loc.name]\'s arm!", "Our arm twists and mutates, transforming it into a deadly blade.", "You hear organic matter ripping and tearing!") /obj/item/melee/arm_blade/dropped(mob/user) - user.visible_message("With a sickening crunch, [user] reforms his blade into an arm!", "We assimilate the blade back into our body.", "With a sickening crunch, [user] reforms [user.p_their()] blade into an arm!", "We assimilate the blade back into our body.", "[user] forces the airlock to open with \his [src]!", "We force the airlock to open.", "You hear a metal screeching sound.") + user.visible_message("[user] forces the airlock to open with [user.p_their()] [name]!", "We force the airlock to open.", "You hear a metal screeching sound.") A.open(2) /***************************************\ @@ -219,7 +219,7 @@ to_chat(user, "The [name] is not ready yet.") /obj/item/gun/magic/tentacle/suicide_act(mob/user) - user.visible_message("[user] coils [src] tightly around \his neck! It looks like \he's trying to commit suicide.") + user.visible_message("[user] coils [src] tightly around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide.") return (OXYLOSS) /obj/item/ammo_casing/magic/tentacle @@ -278,7 +278,7 @@ C.visible_message("[src] impales [C] with [I]!", "[src] impales you with [I]!") C.apply_damage(I.force, BRUTE, "chest") - do_attack_animation(C) + do_item_attack_animation(C, used_item = I) add_blood(C) playsound(get_turf(src), I.hitsound, 75, 1) @@ -386,7 +386,7 @@ if(remaining_uses < 1) if(ishuman(loc)) var/mob/living/carbon/human/H = loc - H.visible_message("With a sickening crunch, [H] reforms his shield into an arm!", "We assimilate our shield into our body", "With a sickening crunch, [H] reforms [H.p_their()] shield into an arm!", "We assimilate our shield into our body", "[loc.name]\'s flesh rapidly inflates, forming a bloated mass around their body!", "We inflate our flesh, creating a spaceproof suit!", "You hear organic matter ripping and tearing!") + loc.visible_message("[loc.name]\'s flesh rapidly inflates, forming a bloated mass around [loc.p_their()] body!", "We inflate our flesh, creating a spaceproof suit!", "You hear organic matter ripping and tearing!") processing_objects += src /obj/item/clothing/suit/space/changeling/process() @@ -485,4 +485,4 @@ icon_state = "lingarmorhelmet" flags = BLOCKHAIR | NODROP | DROPDEL armor = list(melee = 30, bullet = 30, laser = 40, energy = 20, bomb = 10, bio = 4, rad = 0) - flags_inv = HIDEEARS \ No newline at end of file + flags_inv = HIDEEARS diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 23efc38b403..3e03d49dc49 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -24,14 +24,14 @@ user.CureNearsighted() user.reagents.clear_reagents() user.germ_level = 0 - user.next_pain_time = 0 user.timeofdeath = 0 if(ishuman(user)) var/mob/living/carbon/human/H = user H.restore_blood() H.traumatic_shock = 0 H.shock_stage = 0 - H.species.create_organs(H) + H.next_pain_time = 0 + H.dna.species.create_organs(H) // Now that recreating all organs is necessary, the rest of this organ stuff probably // isn't, but I don't want to remove it, just in case. for(var/organ_name in H.bodyparts_by_name) diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm index 99eb634a2ff..c40a33284a1 100644 --- a/code/game/gamemodes/changeling/powers/swap_form.dm +++ b/code/game/gamemodes/changeling/powers/swap_form.dm @@ -17,7 +17,7 @@ if((NOCLONE || SKELETON || HUSK) in target.mutations) to_chat(user, "DNA of [target] is ruined beyond usability!") return - if(!istype(target) || issmall(target) || NO_DNA in target.species.species_traits) + if(!istype(target) || issmall(target) || NO_DNA in target.dna.species.species_traits) to_chat(user, "[target] is not compatible with this ability.") return return 1 @@ -36,7 +36,7 @@ to_chat(user, "The body swap has been interrupted!") return - to_chat(target, "[user] tightens their grip as a painful sensation invades your body.") + to_chat(target, "[user] tightens [user.p_their()] grip as a painful sensation invades your body.") changeling.absorbed_dna -= changeling.find_dna(user.dna) changeling.protected_dna -= changeling.find_dna(user.dna) diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index c344897c624..bb216ddad35 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -80,8 +80,7 @@ selected_dna = changeling.select_dna("Select the target DNA: ", "Target DNA") if(!selected_dna) return - var/datum/species/newspecies = all_species[selected_dna.species] - if((NOTRANSSTING in newspecies.species_traits) || newspecies.is_small) + if((NOTRANSSTING in selected_dna.species.species_traits) || selected_dna.species.is_small) to_chat(user, "The selected DNA is incompatible with our sting.") return ..() @@ -94,7 +93,7 @@ return FALSE if(ishuman(target)) var/mob/living/carbon/human/H = target - if(NO_DNA in H.species.species_traits) + if(NO_DNA in H.dna.species.species_traits) to_chat(user, "This won't work on a creature without DNA.") return FALSE return TRUE @@ -112,11 +111,11 @@ target.visible_message("[target] begins to violenty convulse!","You feel a tiny prick and a begin to uncontrollably convulse!") spawn(10) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + H.set_species(NewDNA.species.type) target.dna = NewDNA.Clone() target.real_name = NewDNA.real_name - var/mob/living/carbon/human/H = target - if(istype(H)) - H.set_species() target.UpdateAppearance() domutcheck(target, null) feedback_add_details("changeling_powers","TS") diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index b7c8abefd1d..bacdc8b0d8b 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -14,10 +14,10 @@ if(!chosen_dna) return + if(ishuman(user)) + user.set_species(chosen_dna.species.type) user.dna = chosen_dna.Clone() user.real_name = chosen_dna.real_name - if(ishuman(user)) - user.set_species(chosen_dna.species) domutcheck(user, null, MUTCHK_FORCED) //Ensures species that get powers by the species proc handle_dna keep them user.flavor_text = "" user.dna.UpdateSE() diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index b12a50bce13..f2e8db26b40 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -203,7 +203,7 @@ var/global/list/all_cults = list() update_cult_icons_removed(cult_mind) if(show_message) for(var/mob/M in viewers(cult_mind.current)) - to_chat(M, "[cult_mind.current] looks like they just reverted to their old faith!") + to_chat(M, "[cult_mind.current] looks like [cult_mind.current.p_they()] just reverted to [cult_mind.current.p_their()] old faith!") /datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 2edbfca609f..b8e5365cb5d 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -50,7 +50,7 @@ ..() if(ishuman(target)) var/mob/living/carbon/human/H = target - if((H.stat != DEAD) && !(NO_BLOOD in H.species.species_traits)) + if((H.stat != DEAD) && !(NO_BLOOD in H.dna.species.species_traits)) H.bleed(50) /obj/item/restraints/legcuffs/bola/cult @@ -201,6 +201,7 @@ increment = 5 max = 40 prefix = "darkened" + claw_damage_increase = 2 /obj/item/whetstone/cult/update_icon() icon_state = "cult_sharpener[used ? "_used" : ""]" diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm index 5ddc8ccdf98..34955ed42d4 100644 --- a/code/game/gamemodes/cult/cult_objectives.dm +++ b/code/game/gamemodes/cult/cult_objectives.dm @@ -24,7 +24,7 @@ spilltarget = 100 + rand(0,player_list.len * 3) explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles." if("sacrifice") - explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for their blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual." + explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for [sacrifice_target.p_their()] blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual." for(var/datum/mind/cult_mind in cult) to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]") @@ -81,7 +81,7 @@ spilltarget = 100 + rand(0,player_list.len * 3) explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles." if("sacrifice") - explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for their blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual." + explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for [sacrifice_target.p_their()] blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual." for(var/datum/mind/cult_mind in cult) if(cult_mind) diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index d8d7d03b6c4..84941f4d7a7 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -161,7 +161,7 @@ var/obj/item/organ/external/head/head = C.get_organ("head") if(head) C.apply_damage(30, BURN, "head") //30 fire damage because it's FUCKING LAVA - head.disfigure("burn") //Your face is unrecognizable because it's FUCKING LAVA + head.disfigure() //Your face is unrecognizable because it's FUCKING LAVA return 1 else ..() diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 19f9f57e9e7..a16cf76d9f1 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -294,7 +294,7 @@ var/mob/living/carbon/human/H = user var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot") var/obj/item/organ/external/affecting = H.get_organ(ran_zone(dam_zone)) - user.visible_message("[user] cuts open their [affecting] and begins writing in their own blood!", "You slice open your [affecting] and begin drawing a sigil of [ticker.cultdat.entity_title3].") + user.visible_message("[user] cuts open [user.p_their()] [affecting] and begins writing in [user.p_their()] own blood!", "You slice open your [affecting] and begin drawing a sigil of [ticker.cultdat.entity_title3].") user.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE , affecting) if(!do_after(user, initial(rune_to_scribe.scribe_delay)-scribereduct, target = get_turf(user))) for(var/V in shields) @@ -305,7 +305,7 @@ if(locate(/obj/effect/rune) in runeturf) to_chat(user, "There is already a rune here.") return - user.visible_message("[user] creates a strange circle in their own blood.", \ + user.visible_message("[user] creates a strange circle in [user.p_their()] own blood.", \ "You finish drawing the arcane markings of [ticker.cultdat.entity_title3].") for(var/V in shields) var/obj/machinery/shield/S = V diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 2bf4933e108..087bfbb4008 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -1,4 +1,4 @@ -/var/list/sacrificed = list() +var/list/sacrificed = list() var/list/non_revealed_runes = (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed) /* @@ -153,7 +153,10 @@ structure_check() searches for nearby cultist structures required for the invoca for(var/M in invokers) var/mob/living/L = M if(invocation) - L.say(invocation) + if(!L.IsVocal()) + L.emote("gestures ominously.") + else + L.say(invocation) L.changeNext_move(CLICK_CD_MELEE)//THIS IS WHY WE CAN'T HAVE NICE THINGS if(invoke_damage) L.apply_damage(invoke_damage, BRUTE) @@ -473,7 +476,6 @@ var/list/teleport_runes = list() rune_in_use = 0 - //Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station. /obj/effect/rune/narsie cultist_name = "Tear Reality (God)" @@ -700,7 +702,7 @@ var/list/teleport_runes = list() return mob_to_revive.revive() //This does remove disabilities and such, but the rune might actually see some use because of it! to_chat(mob_to_revive, "\"PASNAR SAVRAE YAM'TOTH. Arise.\"") - mob_to_revive.visible_message("[mob_to_revive] draws in a huge breath, red light shining from their eyes.", \ + mob_to_revive.visible_message("[mob_to_revive] draws in a huge breath, red light shining from [mob_to_revive.p_their()] eyes.", \ "You awaken suddenly from the void. You're alive!") rune_in_use = 0 @@ -740,7 +742,7 @@ var/list/teleport_runes = list() to_chat(L, "You chant in unison and a colossal burst of energy knocks you backward!") L.Weaken(2) qdel(src) //delete before pulsing because it's a delay reee - empulse(E, 9*invokers.len, 12*invokers.len) // Scales now, from a single room to most of the station depending on # of chanters + empulse(E, 9*invokers.len, 12*invokers.len, 1) // Scales now, from a single room to most of the station depending on # of chanters //Rite of Astral Communion: Separates one's spirit from their body. They will take damage while it is active. /obj/effect/rune/astral @@ -787,11 +789,11 @@ var/list/teleport_runes = list() return affecting.apply_damage(1, BRUTE) if(!(user in T.contents)) - user.visible_message("A spectral tendril wraps around [user] and pulls them back to the rune!") + user.visible_message("A spectral tendril wraps around [user] and pulls [user.p_them()] back to the rune!") Beam(user,icon_state="drainbeam",time=2) user.forceMove(get_turf(src)) //NO ESCAPE :^) if(user.key) - user.visible_message("[user] slowly relaxes, the glow around them dimming.", \ + user.visible_message("[user] slowly relaxes, the glow around [user.p_them()] dimming.", \ "You are re-united with your physical form. [src] releases its hold over you.") user.color = initial(user.color) user.Weaken(3) @@ -833,7 +835,7 @@ var/list/teleport_runes = list() var/mob/living/user = invokers[1] ..() density = !density - user.visible_message("[user] places their hands on [src], and [density ? "the air above it begins to shimmer" : "the shimmer above it fades"].", \ + user.visible_message("[user] places [user.p_their()] hands on [src], and [density ? "the air above it begins to shimmer" : "the shimmer above it fades"].", \ "You channel your life energy into [src], [density ? "preventing" : "allowing"] passage above it.") if(iscarbon(user)) var/mob/living/carbon/C = user @@ -875,7 +877,7 @@ var/list/teleport_runes = list() fail_invoke() log_game("Summon Cultist rune failed - target in away mission") return - if((cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained()) && invokers < 3) + if((cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained()) && invokers.len < 3) to_chat(user, "The summoning of [cultist_to_summon] is being blocked somehow! You need 3 chanters to counter it!") fail_invoke() new /obj/effect/temp_visual/cult/sparks(get_turf(cultist_to_summon)) //observer warning diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index e909a33410f..70e78176463 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -151,7 +151,7 @@ if(!src || QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune) return ..(user, 0) - user.visible_message("Dust flows from [user]'s hand, and they disappear in a flash of red light!", \ + user.visible_message("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] in a flash of red light!", \ "You speak the words of the talisman and find yourself somewhere else!") user.forceMove(get_turf(actual_selected_rune)) return ..() @@ -220,7 +220,7 @@ . = ..() user.visible_message("[user]'s hand flashes a bright blue!", \ "You speak the words of the talisman, emitting an EMP blast.") - empulse(src, 4, 8) + empulse(src, 4, 8, 1) //Rite of Disorientation: Stuns and inhibit speech on a single target for quite some time @@ -279,7 +279,7 @@ var/mob/living/carbon/human/H = user user.visible_message("Otherworldly armor suddenly appears on [user]!", \ "You speak the words of the talisman, arming yourself!") - if(H.get_species() == "Plasmaman") + if(isplasmaman(H)) H.equip_to_slot(new /obj/item/clothing/suit/space/eva/plasmaman/cultist(H), slot_wear_suit) H.equip_to_slot(new /obj/item/clothing/head/helmet/space/eva/plasmaman/cultist(H), slot_head) else @@ -419,4 +419,4 @@ /obj/item/restraints/handcuffs/energy/cult/used/dropped(mob/user) user.visible_message("[user]'s shackles shatter in a discharge of dark magic!", \ "Your [src] shatters in a discharge of dark magic!") - . = ..() \ No newline at end of file + . = ..() diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 4a2622c536d..760868e8435 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -107,7 +107,7 @@ tries_left = 5 //reset our tries since we found a new chump //make sure we have chumps before we try misinforming them. if we don't make a note of it. if(!chumps.len) - log_debug("Game mode failed to find ANY chumps. This is likely due to the server being in extreme low-pop with no one set to opposed or skeptical.") + log_debug("Game mode failed to find ANY chumps. This is likely due to the server being in extreme low-pop with no one set to opposed or skeptical.") return 0 //we've got chumps! misinform them! for(var/mob/living/carbon/human/chump in chumps) @@ -490,34 +490,39 @@ proc/display_roundstart_logout_report() M.ghostize() M.key = theghost.key else - message_admins("[M] ([M.key] has been converted into [role_type] with an active antagonist jobban for said role since no ghost has volunteered to take their place.") + message_admins("[M] ([M.key] has been converted into [role_type] with an active antagonist jobban for said role since no ghost has volunteered to take [M.p_their()] place.") to_chat(M, "You have been converted into [role_type] with an active jobban. Any further violations of the rules on your part are likely to result in a permanent ban.") -/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck) - var/text = "
[ply.key] was [ply.name] the [ply.assigned_role] and" +/proc/printplayer(datum/mind/ply, fleecheck) + var/jobtext = "" + if(ply.assigned_role) + jobtext = " the [ply.assigned_role]" + var/text = "[ply.key] was [ply.name][jobtext] and" if(ply.current) if(ply.current.stat == DEAD) - text += " died" + text += " died" else - text += " survived" - if(fleecheck && !is_station_level(ply.current.z)) - text += " while fleeing the station" + text += " survived" + if(fleecheck) + var/turf/T = get_turf(ply.current) + if(!T || !is_station_level(T.z)) + text += " while fleeing the station" if(ply.current.real_name != ply.name) text += " as [ply.current.real_name]" else - text += " had their body destroyed" + text += " had [ply.p_their()] body destroyed" return text -/datum/game_mode/proc/printobjectives(datum/mind/ply) - var/text = "" +/proc/printobjectives(datum/mind/ply) + var/list/objective_parts = list() var/count = 1 for(var/datum/objective/objective in ply.objectives) if(objective.check_completion()) - text += "
Objective #[count]: [objective.explanation_text] Success!" + objective_parts += "Objective #[count]: [objective.explanation_text] Success!" else - text += "
Objective #[count]: [objective.explanation_text] Fail." + objective_parts += "Objective #[count]: [objective.explanation_text] Fail." count++ - return text + return objective_parts.Join("
") /datum/game_mode/proc/generate_station_goals() var/list/possible = list() diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 8058ff6e5c9..0c609c818b4 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -368,7 +368,7 @@ var/round_start_time = 0 if(player && player.mind && player.mind.assigned_role) if(player.mind.assigned_role == "Captain") captainless=0 - if(player.mind.assigned_role != "MODE") + if(player.mind.assigned_role != player.mind.special_role) job_master.EquipRank(player, player.mind.assigned_role, 0) EquipCustomItems(player) if(captainless) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 0693ca9b279..4cbe909ef84 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -51,7 +51,7 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' raider_num-- for(var/datum/mind/raider in raiders) - raider.assigned_role = "MODE" + raider.assigned_role = SPECIAL_ROLE_RAIDER raider.special_role = SPECIAL_ROLE_RAIDER ..() return 1 @@ -101,7 +101,7 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' vox.name = vox.real_name newraider.name = vox.name vox.age = rand(12,20) - vox.set_species("Vox") + vox.set_species(/datum/species/vox) vox.s_tone = rand(1, 6) vox.languages = list() // Removing language from chargen. vox.flavor_text = "" diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index 6cb2956d3ee..ca868f4874e 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -91,7 +91,7 @@ var/list/dudes = list() for(var/mob/living/carbon/human/man in player_list) if(!man.mind) continue - if(man.mind.assigned_role=="MODE") continue + if(man.mind.assigned_role == man.mind.special_role) continue dudes += man if(dudes.len==0) return null @@ -116,7 +116,7 @@ if((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs)) return //don't include suspects who can't possibly be the antag based on their species (no suspecting the machines of being sneaky changelings) - if(man.get_species() in ticker.mode.protected_species) + if(man.dna.species.name in ticker.mode.protected_species) return dudes += man for(var/i = 0, i < max(player_list.len/10,2), i++) @@ -210,14 +210,14 @@ var/prob_right_job = rand(prob_correct_job_lower, prob_correct_job_higher) if(prob(prob_right_job)) if(correct_person) - if(correct_person:assigned_role=="MODE") + if(correct_person:assigned_role == correct_person:special_role) changeling_job = pick(joblist) else changeling_job = correct_person:assigned_role else changeling_job = pick(joblist) if(prob(prob_right_dude) && ticker.mode == "changeling") - if(correct_person:assigned_role=="MODE") + if(correct_person:assigned_role == correct_person:special_role) changeling_name = correct_person:current else changeling_name = src.pick_mob() diff --git a/code/game/gamemodes/miniantags/abduction/abductee_objectives.dm b/code/game/gamemodes/miniantags/abduction/abductee_objectives.dm new file mode 100644 index 00000000000..af2920c4626 --- /dev/null +++ b/code/game/gamemodes/miniantags/abduction/abductee_objectives.dm @@ -0,0 +1,147 @@ +/datum/objective/abductee + completed = 1 + +/datum/objective/abductee/steal + explanation_text = "Steal all" + +/datum/objective/abductee/steal/New() + var/target = pick(list("pets","lights","monkeys","fruits","shoes","bars of soap", "weapons", "computers", "organs")) + explanation_text+=" [target]." + +/datum/objective/abductee/paint + explanation_text = "The station is hideous. You must color it all" + +/datum/objective/abductee/paint/New() + var/color = pick(list("red", "blue", "green", "yellow", "orange", "purple", "black", "in rainbows", "in blood")) + explanation_text+= " [color]!" + +/datum/objective/abductee/speech + explanation_text = "Your brain is broken... you can only communicate in" + +/datum/objective/abductee/speech/New() + var/style = pick(list("pantomime", "rhyme", "haiku", "extended metaphors", "riddles", "extremely literal terms", "sound effects", "military jargon")) + explanation_text+= " [style]." + +/datum/objective/abductee/capture + explanation_text = "Capture" + +/datum/objective/abductee/capture/New() + var/list/jobs = job_master.occupations.Copy() + for(var/datum/job/J in jobs) + if(J.current_positions < 1) + jobs -= J + if(jobs.len > 0) + var/datum/job/target = pick(jobs) + explanation_text += " a [target.title]." + else + explanation_text += " someone." + +/datum/objective/abductee/shuttle + explanation_text = "You must escape the station! Get the shuttle called!" + +/datum/objective/abductee/noclone + explanation_text = "Don't allow anyone to be cloned." + +/datum/objective/abductee/oxygen + explanation_text = "The oxygen is killing them all and they don't even know it. Make sure no oxygen is on the station." + +/datum/objective/abductee/blazeit + explanation_text = "Your body must be improved. Ingest as many drugs as you can." + +/datum/objective/abductee/yumyum + explanation_text = "You are hungry. Eat as much food as you can find." + +/datum/objective/abductee/insane + explanation_text = "You see you see what they cannot you see the open door you seeE you SEeEe you SEe yOU seEee SHOW THEM ALL" + +/datum/objective/abductee/cannotmove + explanation_text = "Convince the crew that you are a paraplegic." + +/datum/objective/abductee/deadbodies + explanation_text = "Start a collection of corpses. Don't kill people to get these corpses." + +/datum/objective/abductee/floors + explanation_text = "Replace all the floor tiles with wood, carpeting, grass or bling." + +/datum/objective/abductee/POWERUNLIMITED + explanation_text = "Flood the station's powernet with as much electricity as you can." + +/datum/objective/abductee/pristine + explanation_text = "The CEO of Nanotrasen is coming! Ensure the station is in absolutely pristine condition." + +/datum/objective/abductee/nowalls + explanation_text = "The crew must get to know one another better. Break down the walls inside the station!" + +/datum/objective/abductee/nations + explanation_text = "Ensure your department prospers over all else." + +/datum/objective/abductee/abductception + explanation_text = "You have been changed forever. Find the ones that did this to you and give them a taste of their own medicine." + +/datum/objective/abductee/summon + explanation_text = "The elder gods hunger. Gather a cult and conduct a ritual to summon one." + +/datum/objective/abductee/machine + explanation_text = "You are secretly an android. Interface with as many machines as you can to boost your own power so the AI may acknowledge you at last." + +/datum/objective/abductee/calling + explanation_text = "Call forth a spirit from the other side." + +/datum/objective/abductee/calling/New() + var/mob/dead/D = pick(dead_mob_list) + if(D) + explanation_text = "You know that [D] has perished. Hold a seance to call them from the spirit realm." + +/datum/objective/abductee/social_experiment + explanation_text = "This is a secret social experiment conducted by Nanotrasen. Convince the crew that this is the truth." + +/datum/objective/abductee/vr + explanation_text = "It's all an entirely virtual simulation within an underground vault. Convince the crew to escape the shackles of VR." + +/datum/objective/abductee/pets + explanation_text = "Nanotrasen is abusing the animals! Save as many as you can!" + +/datum/objective/abductee/defect + explanation_text = "Fuck the system! Defect from the station and start an independent colony in space, Mining Outpost or the derelict. Recruit crewmates if you can." + +/datum/objective/abductee/promote + explanation_text = "Climb the corporate ladder all the way to the top!" + +/datum/objective/abductee/science + explanation_text = "So much lies undiscovered. Look deeper into the machinations of the universe." + +/datum/objective/abductee/build + explanation_text = "Expand the station." + +/datum/objective/abductee/pragnant + explanation_text = "You are pregnant and soon due. Find a safe place to deliver your baby." + +/datum/objective/abductee/engine + explanation_text = "Go have a good conversation with the singularity/tesla/supermatter crystal. Bonus points if it responds." + +/datum/objective/abductee/music + explanation_text = "You burn with passion for music. Share your vision. If anyone hates it, beat them on the head with your instrument!" + +/datum/objective/abductee/clown + explanation_text = "The clown is not funny. You can do better! Steal his audience and make the crew laugh!" + +/datum/objective/abductee/party + explanation_text = "You're throwing a huge rager. Make it as awesome as possible so the whole crew comes... OR ELSE!" + +/datum/objective/abductee/pets + explanation_text = "All the pets around here suck. You need to make them cooler. Replace them with exotic beasts!" + +/datum/objective/abductee/conspiracy + explanation_text = "The leaders of this station are hiding a grand, evil conspiracy. Only you can learn what it is, and expose it to the people!" + +/datum/objective/abductee/stalker + explanation_text = "The Syndicate has hired you to compile dossiers on all important members of the crew. Be sure they don't know you're doing it." + +/datum/objective/abductee/narrator + explanation_text = "You're the narrator of this tale. Follow around the protagonists to tell their story." + +/datum/objective/abductee/lurve + explanation_text = "You are doomed to feel woefully incomplete forever... until you find your true love on this station. They're waiting for you!" + +/datum/objective/abductee/sixthsense + explanation_text = "You died back there and went to heaven... or is it hell? No one here seems to know they're dead. Convince them, and maybe you can escape this limbo." \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index b54b18335ef..5d5c3342010 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -74,11 +74,11 @@ agent = preset_agent - scientist.assigned_role = "MODE" + scientist.assigned_role = SPECIAL_ROLE_ABDUCTOR_SCIENTIST scientist.special_role = SPECIAL_ROLE_ABDUCTOR_SCIENTIST log_game("[key_name(scientist)] has been selected as an abductor team [team_number] scientist.") - agent.assigned_role = "MODE" + agent.assigned_role = SPECIAL_ROLE_ABDUCTOR_AGENT agent.special_role = SPECIAL_ROLE_ABDUCTOR_AGENT log_game("[key_name(agent)] has been selected as an abductor team [team_number] agent.") @@ -89,62 +89,14 @@ return 1 /datum/game_mode/abduction/post_setup() - //Spawn Team - var/list/obj/effect/landmark/abductor/agent_landmarks = new - var/list/obj/effect/landmark/abductor/scientist_landmarks = new - agent_landmarks.len = max_teams - scientist_landmarks.len = max_teams - for(var/obj/effect/landmark/abductor/A in landmarks_list) - if(istype(A,/obj/effect/landmark/abductor/agent)) - agent_landmarks[text2num(A.team)] = A - else if(istype(A,/obj/effect/landmark/abductor/scientist)) - scientist_landmarks[text2num(A.team)] = A - - var/datum/mind/agent - var/obj/effect/landmark/L - var/datum/mind/scientist - var/team_name - var/mob/living/carbon/human/H for(var/team_number=1,team_number<=abductor_teams,team_number++) - team_name = team_names[team_number] - agent = agents[team_number] - H = agent.current - L = agent_landmarks[team_number] - H.forceMove(get_turf(L)) - H.body_accessory = null - H.set_species("Abductor") - H.mind.abductor.agent = 1 - H.mind.abductor.team = team_number - H.real_name = team_name + " Agent" - H.reagents.add_reagent("mutadone", 1) //No fat/blind/colourblind/epileptic/whatever ayys. - H.overeatduration = 0 - equip_common(H,team_number) - equip_agent(H,team_number) - greet_agent(agent,team_number) - update_abductor_icons_added(agent) - - scientist = scientists[team_number] - H = scientist.current - L = scientist_landmarks[team_number] - H.forceMove(get_turf(L)) - H.body_accessory = null - H.set_species("Abductor") - H.mind.abductor.scientist = 1 - H.mind.abductor.team = team_number - H.real_name = team_name + " Scientist" - H.reagents.add_reagent("mutadone", 1) //No fat/blind/colourblind/epileptic/whatever ayys. - H.overeatduration = 0 - equip_common(H,team_number) - equip_scientist(H,team_number) - greet_scientist(scientist,team_number) - update_abductor_icons_added(scientist) - + post_setup_team(team_number) return ..() //Used for create antag buttons /datum/game_mode/abduction/proc/post_setup_team(team_number) - var/list/obj/effect/landmark/abductor/agent_landmarks = new - var/list/obj/effect/landmark/abductor/scientist_landmarks = new + var/list/obj/effect/landmark/abductor/agent_landmarks = list() + var/list/obj/effect/landmark/abductor/scientist_landmarks = list() agent_landmarks.len = max_teams scientist_landmarks.len = max_teams for(var/obj/effect/landmark/abductor/A in landmarks_list) @@ -153,11 +105,13 @@ else if(istype(A,/obj/effect/landmark/abductor/scientist)) scientist_landmarks[text2num(A.team)] = A + var/team_name = team_names[team_number] + var/datum/mind/agent var/obj/effect/landmark/L var/datum/mind/scientist - var/team_name var/mob/living/carbon/human/H + var/datum/species/abductor/S team_name = team_names[team_number] agent = agents[team_number] @@ -165,12 +119,13 @@ L = agent_landmarks[team_number] H.forceMove(get_turf(L)) H.body_accessory = null - H.set_species("Abductor") - H.mind.abductor.agent = 1 - H.mind.abductor.team = team_number + H.set_species(/datum/species/abductor) + S = H.dna.species + S.team = team_number H.real_name = team_name + " Agent" - equip_common(H,team_number) - equip_agent(H,team_number) + H.reagents.add_reagent("mutadone", 1) //No fat/blind/colourblind/epileptic/whatever ayys. + H.overeatduration = 0 + H.equipOutfit(/datum/outfit/abductor/agent) greet_agent(agent,team_number) update_abductor_icons_added(agent) @@ -179,21 +134,17 @@ L = scientist_landmarks[team_number] H.forceMove(get_turf(L)) H.body_accessory = null - H.set_species("Abductor") - H.mind.abductor.scientist = 1 - H.mind.abductor.team = team_number + H.set_species(/datum/species/abductor) + S = H.dna.species + S.scientist = TRUE + S.team = team_number H.real_name = team_name + " Scientist" - equip_common(H,team_number) - equip_scientist(H,team_number) + H.reagents.add_reagent("mutadone", 1) //No fat/blind/colourblind/epileptic/whatever ayys. + H.overeatduration = 0 + H.equipOutfit(/datum/outfit/abductor/scientist) greet_scientist(scientist,team_number) update_abductor_icons_added(scientist) - -/datum/abductor //stores abductor's team and whether they're a scientist or agent; since species datums are global, we have to use this, instead. - var/scientist = 0 - var/agent = 0 - var/team = 1 - /datum/game_mode/abduction/proc/greet_agent(datum/mind/abductor,team_number) abductor.objectives += team_objectives[team_number] var/team_name = team_names[team_number] @@ -202,11 +153,7 @@ to_chat(abductor.current, "With the help of your teammate, kidnap and experiment on station crew members!") to_chat(abductor.current, "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve.") - var/obj_count = 1 - for(var/datum/objective/objective in abductor.objectives) - to_chat(abductor.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - return + abductor.announce_objectives() /datum/game_mode/abduction/proc/greet_scientist(datum/mind/abductor,team_number) abductor.objectives += team_objectives[team_number] @@ -216,64 +163,12 @@ to_chat(abductor.current, "With the help of your teammate, kidnap and experiment on station crew members!") to_chat(abductor.current, "Use your tool and ship consoles to support the agent and retrieve human specimens.") - var/obj_count = 1 - for(var/datum/objective/objective in abductor.objectives) - to_chat(abductor.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - return - -/datum/game_mode/abduction/proc/equip_common(mob/living/carbon/human/agent,team_number) - var/radio_freq = SYND_FREQ - - var/obj/item/radio/R = new /obj/item/radio/headset/syndicate/alt(agent) - R.set_frequency(radio_freq) - R.name = "alien headset" - agent.equip_to_slot_or_del(R, slot_l_ear) - agent.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(agent), slot_shoes) - agent.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(agent), slot_w_uniform) //they're greys gettit - agent.equip_to_slot_or_del(new /obj/item/storage/backpack(agent), slot_back) - -/datum/game_mode/abduction/proc/get_team_console(team) - var/obj/machinery/abductor/console/console - for(var/obj/machinery/abductor/console/c in abductor_equipment) - if(c.team == team) - console = c - break - return console - -/datum/game_mode/abduction/proc/equip_agent(mob/living/carbon/human/agent,team_number) - if(!team_number) - team_number = agent.mind.abductor.team - - var/obj/machinery/abductor/console/console = get_team_console(team_number) - var/obj/item/clothing/suit/armor/abductor/vest/V = new /obj/item/clothing/suit/armor/abductor/vest(agent) - if(console!=null) - console.vest = V - V.flags |= NODROP - agent.equip_to_slot_or_del(V, slot_wear_suit) - agent.equip_to_slot_or_del(new /obj/item/abductor_baton(agent), slot_in_backpack) - agent.equip_to_slot_or_del(new /obj/item/gun/energy/alien(agent), slot_in_backpack) - agent.equip_to_slot_or_del(new /obj/item/abductor/silencer(agent), slot_in_backpack) - agent.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/abductor(agent), slot_head) - agent.equip_to_slot_or_del(new /obj/item/storage/belt/military/abductor/full(agent), slot_belt) - agent.update_icons() - - -/datum/game_mode/abduction/proc/equip_scientist(var/mob/living/carbon/human/scientist,var/team_number) - if(!team_number) - team_number = scientist.mind.abductor.team - - var/obj/machinery/abductor/console/console = get_team_console(team_number) - var/obj/item/abductor/gizmo/G = new /obj/item/abductor/gizmo(scientist) - if(console!=null) - console.gizmo = G - G.console = console - scientist.equip_to_slot_or_del(G, slot_in_backpack) - - var/obj/item/implant/abductor/beamplant = new /obj/item/implant/abductor(scientist) - beamplant.implant(scientist) - scientist.update_icons() + abductor.announce_objectives() +/datum/game_mode/abduction/proc/get_team_console(team_number) + for(var/obj/machinery/abductor/console/C in machines) + if(C.team == team_number) + return C /datum/game_mode/abduction/check_finished() if(!finished) @@ -336,18 +231,19 @@ var/ab_team = team if(owner) if(!owner.current || !ishuman(owner.current)) - return 0 + return FALSE var/mob/living/carbon/human/H = owner.current - if(H.get_species() != "Abductor") - return 0 - ab_team = H.mind.abductor.team - for(var/obj/machinery/abductor/experiment/E in abductor_equipment) + if(!isabductor(H)) + return FALSE + var/datum/species/abductor/S = H.dna.species + ab_team = S.team + for(var/obj/machinery/abductor/experiment/E in machines) if(E.team == ab_team) if(E.points >= target_amount) - return 1 + return TRUE else - return 0 - return 0 + return FALSE + return FALSE /datum/game_mode/proc/remove_abductor(datum/mind/abductor_mind) if(abductor_mind in abductors) @@ -358,7 +254,7 @@ to_chat(abductor_mind.current, "You have been turned into a robot! You are no longer an abductor.") else to_chat(abductor_mind.current, "You have been brainwashed! You are no longer an abductor.") - ticker.mode.update_abductor_icons_added(abductor_mind) + ticker.mode.update_abductor_icons_removed(abductor_mind) /datum/game_mode/proc/update_abductor_icons_added(datum/mind/alien_mind) var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_ABDUCTOR] @@ -368,152 +264,4 @@ /datum/game_mode/proc/update_abductor_icons_removed(datum/mind/alien_mind) var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_ABDUCTOR] hud.leave_hud(alien_mind.current) - set_antag_hud(alien_mind.current, null) - -/datum/objective/abductee - completed = 1 - -/datum/objective/abductee/steal - explanation_text = "Steal all" - -/datum/objective/abductee/steal/New() - var/target = pick(list("pets","lights","monkeys","fruits","shoes","bars of soap", "weapons", "computers", "organs")) - explanation_text+=" [target]." - -/datum/objective/abductee/paint - explanation_text = "The station is hideous. You must color it all" - -/datum/objective/abductee/paint/New() - var/color = pick(list("red", "blue", "green", "yellow", "orange", "purple", "black", "in rainbows", "in blood")) - explanation_text+= " [color]!" - -/datum/objective/abductee/speech - explanation_text = "Your brain is broken... you can only communicate in" - -/datum/objective/abductee/speech/New() - var/style = pick(list("pantomime", "rhyme", "haiku", "extended metaphors", "riddles", "extremely literal terms", "sound effects", "military jargon")) - explanation_text+= " [style]." - -/datum/objective/abductee/capture - explanation_text = "Capture" - -/datum/objective/abductee/capture/New() - var/list/jobs = job_master.occupations.Copy() - for(var/datum/job/J in jobs) - if(J.current_positions < 1) - jobs -= J - if(jobs.len > 0) - var/datum/job/target = pick(jobs) - explanation_text += " a [target.title]." - else - explanation_text += " someone." - -/datum/objective/abductee/shuttle - explanation_text = "You must escape the station! Get the shuttle called!" - -/datum/objective/abductee/noclone - explanation_text = "Don't allow anyone to be cloned." - -/datum/objective/abductee/oxygen - explanation_text = "The oxygen is killing them all and they don't even know it. Make sure no oxygen is on the station." - -/datum/objective/abductee/blazeit - explanation_text = "Your body must be improved. Ingest as many drugs as you can." - -/datum/objective/abductee/yumyum - explanation_text = "You are hungry. Eat as much food as you can find." - -/datum/objective/abductee/insane - explanation_text = "You see you see what they cannot you see the open door you seeE you SEeEe you SEe yOU seEee SHOW THEM ALL" - -/datum/objective/abductee/cannotmove - explanation_text = "Convince the crew that you are a paraplegic." - -/datum/objective/abductee/deadbodies - explanation_text = "Start a collection of corpses. Don't kill people to get these corpses." - -/datum/objective/abductee/floors - explanation_text = "Replace all the floor tiles with wood, carpeting, grass or bling." - -/datum/objective/abductee/POWERUNLIMITED - explanation_text = "Flood the station's powernet with as much electricity as you can." - -/datum/objective/abductee/pristine - explanation_text = "The CEO of Nanotrasen is coming! Ensure the station is in absolutely pristine condition." - -/datum/objective/abductee/nowalls - explanation_text = "The crew must get to know one another better. Break down the walls inside the station!" - -/datum/objective/abductee/nations - explanation_text = "Ensure your department prospers over all else." - -/datum/objective/abductee/abductception - explanation_text = "You have been changed forever. Find the ones that did this to you and give them a taste of their own medicine." - -/datum/objective/abductee/summon - explanation_text = "The elder gods hunger. Gather a cult and conduct a ritual to summon one." - -/datum/objective/abductee/machine - explanation_text = "You are secretly an android. Interface with as many machines as you can to boost your own power so the AI may acknowledge you at last." - -/datum/objective/abductee/calling - explanation_text = "Call forth a spirit from the other side." - -/datum/objective/abductee/calling/New() - var/mob/dead/D = pick(dead_mob_list) - if(D) - explanation_text = "You know that [D] has perished. Hold a seance to call them from the spirit realm." - -/datum/objective/abductee/social_experiment - explanation_text = "This is a secret social experiment conducted by Nanotrasen. Convince the crew that this is the truth." - -/datum/objective/abductee/vr - explanation_text = "It's all an entirely virtual simulation within an underground vault. Convince the crew to escape the shackles of VR." - -/datum/objective/abductee/pets - explanation_text = "Nanotrasen is abusing the animals! Save as many as you can!" - -/datum/objective/abductee/defect - explanation_text = "Fuck the system! Defect from the station and start an independent colony in space, Mining Outpost or the derelict. Recruit crewmates if you can." - -/datum/objective/abductee/promote - explanation_text = "Climb the corporate ladder all the way to the top!" - -/datum/objective/abductee/science - explanation_text = "So much lies undiscovered. Look deeper into the machinations of the universe." - -/datum/objective/abductee/build - explanation_text = "Expand the station." - -/datum/objective/abductee/pragnant - explanation_text = "You are pregnant and soon due. Find a safe place to deliver your baby." - -/datum/objective/abductee/engine - explanation_text = "Go have a good conversation with the singularity/tesla/supermatter crystal. Bonus points if it responds." - -/datum/objective/abductee/music - explanation_text = "You burn with passion for music. Share your vision. If anyone hates it, beat them on the head with your instrument!" - -/datum/objective/abductee/clown - explanation_text = "The clown is not funny. You can do better! Steal his audience and make the crew laugh!" - -/datum/objective/abductee/party - explanation_text = "You're throwing a huge rager. Make it as awesome as possible so the whole crew comes... OR ELSE!" - -/datum/objective/abductee/pets - explanation_text = "All the pets around here suck. You need to make them cooler. Replace them with exotic beasts!" - -/datum/objective/abductee/conspiracy - explanation_text = "The leaders of this station are hiding a grand, evil conspiracy. Only you can learn what it is, and expose it to the people!" - -/datum/objective/abductee/stalker - explanation_text = "The Syndicate has hired you to compile dossiers on all important members of the crew. Be sure they don't know you're doing it." - -/datum/objective/abductee/narrator - explanation_text = "You're the narrator of this tale. Follow around the protagonists to tell their story." - -/datum/objective/abductee/lurve - explanation_text = "You are doomed to feel woefully incomplete forever... until you find your true love on this station. They're waiting for you!" - -/datum/objective/abductee/sixthsense - explanation_text = "You died back there and went to heaven... or is it hell? No one here seems to know they're dead. Convince them, and maybe you can escape this limbo." \ No newline at end of file + set_antag_hud(alien_mind.current, null) \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index 0b1962b1717..c8539b568db 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -2,6 +2,8 @@ #define VEST_COMBAT 2 #define GIZMO_SCAN 1 #define GIZMO_MARK 2 +#define MIND_DEVICE_MESSAGE 1 +#define MIND_DEVICE_CONTROL 2 //AGENT VEST /obj/item/clothing/suit/armor/abductor/vest @@ -14,6 +16,7 @@ origin_tech = "magnets=7;biotech=4;powerstorage=4;abductor=4" armor = list(melee = 15, bullet = 15, laser = 15, energy = 15, bomb = 15, bio = 15, rad = 15) actions_types = list(/datum/action/item_action/hands_free/activate) + allowed = list(/obj/item/abductor, /obj/item/abductor_baton, /obj/item/melee/baton, /obj/item/gun/energy, /obj/item/restraints/handcuffs) var/mode = VEST_STEALTH var/stealth_active = 0 var/combat_cooldown = 10 @@ -23,6 +26,11 @@ species_fit = null sprite_sheets = null +/obj/item/clothing/suit/armor/abductor/vest/proc/toggle_nodrop() + flags ^= NODROP + if(ismob(loc)) + to_chat(loc, "Your vest is now [flags & NODROP ? "locked" : "unlocked"].") + /obj/item/clothing/suit/armor/abductor/vest/proc/flip_mode() switch(mode) if(VEST_STEALTH) @@ -53,7 +61,7 @@ return stealth_active = 1 if(ishuman(loc)) - var/mob/living/carbon/human/M = src.loc + var/mob/living/carbon/human/M = loc new /obj/effect/temp_visual/dir_setting/ninja/cloak(get_turf(M), M.dir) M.name_override = disguise.name M.icon = disguise.icon @@ -67,7 +75,7 @@ return stealth_active = 0 if(ishuman(loc)) - var/mob/living/carbon/human/M = src.loc + var/mob/living/carbon/human/M = loc new /obj/effect/temp_visual/dir_setting/ninja(get_turf(M), M.dir) M.name_override = null M.overlays.Cut() @@ -94,9 +102,9 @@ /obj/item/clothing/suit/armor/abductor/vest/proc/Adrenaline() if(ishuman(loc)) if(combat_cooldown != initial(combat_cooldown)) - to_chat(src.loc, "Combat injection is still recharging.") + to_chat(loc, "Combat injection is still recharging.") return - var/mob/living/carbon/human/M = src.loc + var/mob/living/carbon/human/M = loc M.adjustStaminaLoss(-75) M.SetParalysis(0) M.SetStunned(0) @@ -109,6 +117,17 @@ if(combat_cooldown==initial(combat_cooldown)) processing_objects.Remove(src) +/obj/item/clothing/suit/armor/abductor/Destroy() + processing_objects.Remove(src) + for(var/obj/machinery/abductor/console/C in machines) + if(C.vest == src) + C.vest = null + break + return ..() + +/obj/item/abductor + icon = 'icons/obj/abductor.dmi' + /obj/item/abductor/proc/AbductorCheck(user) if(isabductor(user)) return TRUE @@ -116,14 +135,19 @@ return FALSE /obj/item/abductor/proc/ScientistCheck(user) + if(!AbductorCheck(user)) + return FALSE + var/mob/living/carbon/human/H = user - if(H.mind && H.mind.abductor) - return H.mind.abductor.scientist + var/datum/species/abductor/S = H.dna.species + if(S.scientist) + return TRUE + to_chat(user, "You're not trained to use this!") + return FALSE /obj/item/abductor/gizmo name = "science tool" desc = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras." - icon = 'icons/obj/abductor.dmi' icon_state = "gizmo_scan" item_state = "gizmo" origin_tech = "engineering=7;magnets=4;bluespace=4;abductor=3" @@ -132,11 +156,12 @@ var/obj/machinery/abductor/console/console /obj/item/abductor/gizmo/attack_self(mob/user) - if(!AbductorCheck(user)) - return if(!ScientistCheck(user)) - to_chat(user, "You're not trained to use this!") return + if(!console) + to_chat(user, "The device is not linked to a console!") + return + if(mode == GIZMO_SCAN) mode = GIZMO_MARK icon_state = "gizmo_mark" @@ -146,11 +171,12 @@ to_chat(user, "You switch the device to [mode==GIZMO_SCAN? "SCAN": "MARK"] MODE") /obj/item/abductor/gizmo/attack(mob/living/M, mob/user) - if(!AbductorCheck(user)) - return if(!ScientistCheck(user)) - to_chat(user, "You're not trained to use this") return + if(!console) + to_chat(user, "The device is not linked to console!") + return + switch(mode) if(GIZMO_SCAN) scan(M, user) @@ -161,11 +187,12 @@ /obj/item/abductor/gizmo/afterattack(atom/target, mob/living/user, flag, params) if(flag) return - if(!AbductorCheck(user)) - return if(!ScientistCheck(user)) - to_chat(user, "You're not trained to use this") return + if(!console) + to_chat(user, "The device is not linked to console!") + return + switch(mode) if(GIZMO_SCAN) scan(target, user) @@ -174,9 +201,8 @@ /obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user) if(ishuman(target)) - if(console!=null) - console.AddSnapshot(target) - to_chat(user, "You scan [target] and add them to the database.") + console.AddSnapshot(target) + to_chat(user, "You scan [target] and add [target.p_them()] to the database.") /obj/item/abductor/gizmo/proc/mark(atom/target, mob/living/user) if(marked == target) @@ -200,11 +226,15 @@ marked = target to_chat(user, "You finish preparing [target] for transport.") +/obj/item/abductor/gizmo/Destroy() + if(console) + console.gizmo = null + return ..() + /obj/item/abductor/silencer name = "abductor silencer" desc = "A compact device used to shut down communications equipment." - icon = 'icons/obj/abductor.dmi' icon_state = "silencer" item_state = "silencer" origin_tech = "materials=4;programming=7;abductor=3" @@ -222,7 +252,7 @@ radio_off(target, user) /obj/item/abductor/silencer/proc/radio_off(atom/target, mob/living/user) - if(!(user in (viewers(7,target)))) + if(!(user in (viewers(7, target)))) return var/turf/targloc = get_turf(target) @@ -238,17 +268,90 @@ var/list/all_items = M.GetAllContents() for(var/obj/I in all_items) - if(istype(I,/obj/item/radio/)) + if(istype(I, /obj/item/radio)) var/obj/item/radio/r = I r.listening = 0 - if(!istype(I,/obj/item/radio/headset)) + if(!istype(I, /obj/item/radio/headset)) r.broadcasting = 0 //goddamned headset hacks +/obj/item/abductor/mind_device + name = "mental interface device" + desc = "A dual-mode tool for directly communicating with sentient brains. It can be used to send a direct message to a target, or to send a command to a test subject with a charged gland." + icon_state = "mind_device_message" + item_state = "silencer" + var/mode = MIND_DEVICE_MESSAGE + +/obj/item/abductor/mind_device/attack_self(mob/user) + if(!ScientistCheck(user)) + return + + if(mode == MIND_DEVICE_MESSAGE) + mode = MIND_DEVICE_CONTROL + icon_state = "mind_device_control" + else + mode = MIND_DEVICE_MESSAGE + icon_state = "mind_device_message" + to_chat(user, "You switch the device to [mode == MIND_DEVICE_MESSAGE ? "TRANSMISSION" : "COMMAND"] MODE") + +/obj/item/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params) + if(!ScientistCheck(user)) + return + + switch(mode) + if(MIND_DEVICE_CONTROL) + mind_control(target, user) + if(MIND_DEVICE_MESSAGE) + mind_message(target, user) + +/obj/item/abductor/mind_device/proc/mind_control(atom/target, mob/living/user) + if(iscarbon(target)) + var/mob/living/carbon/C = target + var/obj/item/organ/internal/heart/gland/G = C.get_organ_slot("heart") + if(!istype(G)) + to_chat(user, "Your target does not have an experimental gland!") + return + if(!G.mind_control_uses) + to_chat(user, "Your target's gland is spent!") + return + if(G.active_mind_control) + to_chat(user, "Your target is already under a mind-controlling influence!") + return + + var/command = stripped_input(user, "Enter the command for your target to follow. Uses Left: [G.mind_control_uses], Duration: [DisplayTimeText(G.mind_control_duration)]", "Enter command") + + if(!command) + return + + if(QDELETED(user) || user.get_active_hand() != src || loc != user) + return + + if(QDELETED(G)) + return + + G.mind_control(command, user) + to_chat(user, "You send the command to your target.") + +/obj/item/abductor/mind_device/proc/mind_message(atom/target, mob/living/user) + if(isliving(target)) + var/mob/living/L = target + if(L.stat == DEAD) + to_chat(user, "Your target is dead!") + return + var/message = stripped_input(user, "Write a message to send to your target's brain.", "Enter message") + if(!message) + return + if(QDELETED(L) || L.stat == DEAD) + return + + to_chat(L, "You hear a voice in your head saying: [message]") + to_chat(user, "You send the message to your target.") + log_say("[key_name(user)] sent an abductor mind message to [key_name(L)]: '[message]'", user) + /obj/item/gun/energy/alien name = "alien pistol" desc = "A complicated gun that fires bursts of high-intensity radiation." ammo_type = list(/obj/item/ammo_casing/energy/declone) - restricted_species = list("Abductor") + restricted_species = list(/datum/species/abductor) icon_state = "alienpistol" item_state = "alienpistol" origin_tech = "combat=4;magnets=7;powerstorage=3;abductor=3" @@ -258,7 +361,6 @@ name = "Dissection Guide" icon_state = "alienpaper_words" info = {"Dissection for Dummies
-
1.Acquire fresh specimen.
2.Put the specimen on operating table.
@@ -303,7 +405,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} w_class = WEIGHT_CLASS_NORMAL actions_types = list(/datum/action/item_action/toggle_mode) -/obj/item/abductor_baton/proc/toggle(mob/living/user=usr) +/obj/item/abductor_baton/proc/toggle(mob/living/user = usr) mode = (mode+1)%BATON_MODES var/txt switch(mode) @@ -432,7 +534,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} if(ishuman(L)) var/mob/living/carbon/human/H = L - species = "[H.species.name]" + species = "[H.dna.species.name]" if(L.mind && L.mind.changeling) species = "Changeling lifeform" var/obj/item/organ/internal/heart/gland/temp = locate() in H.internal_organs @@ -476,6 +578,24 @@ Congratulations! You are now trained for invasive xenobiology research!"} if(BATON_PROBE) to_chat(user, "The baton is in probing mode.") +/obj/item/radio/headset/abductor + name = "alien headset" + desc = "An advanced alien headset designed to monitor communications of human space stations. Why does it have a microphone? No one knows." + flags = EARBANGPROTECT + origin_tech = "magnets=2;abductor=3" + icon = 'icons/obj/abductor.dmi' + icon_state = "abductor_headset" + item_state = "abductor_headset" + ks2type = /obj/item/encryptionkey/heads/captain + +/obj/item/radio/headset/abductor/New() + ..() + make_syndie() + +/obj/item/radio/headset/abductor/attackby(obj/item/I, mob/user, params) + if(isscrewdriver(I)) + return // Stops humans from disassembling abductor headsets. + return ..() /obj/item/scalpel/alien name = "alien scalpel" @@ -519,6 +639,27 @@ Congratulations! You are now trained for invasive xenobiology research!"} origin_tech = "materials=2;biotech=2;abductor=2" toolspeed = 0.25 +/obj/item/bonegel/alien + name = "alien bone gel" + desc = "It smells like duct tape." + icon = 'icons/obj/abductor.dmi' + origin_tech = "materials=2;biotech=2;abductor=2" + toolspeed = 0.25 + +/obj/item/FixOVein/alien + name = "alien FixOVein" + desc = "Bloodless aliens would totally know how to stop internal bleeding...right?" + icon = 'icons/obj/abductor.dmi' + origin_tech = "materials=2;biotech=2;abductor=2" + toolspeed = 0.25 + +/obj/item/bonesetter/alien + name = "alien bone setter" + desc = "You're not sure you want to know whether or not aliens have bones." + icon = 'icons/obj/abductor.dmi' + origin_tech = "materials=2;biotech=2;abductor=2" + toolspeed = 0.25 + /obj/item/clothing/head/helmet/abductor name = "agent headgear" desc = "Abduct with style - spiky style. Prevents digital tracking." @@ -535,6 +676,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} name = "resting contraption" desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" icon = 'icons/obj/abductor.dmi' + buildstacktype = /obj/item/stack/sheet/mineral/abductor icon_state = "bed" /obj/structure/table_frame/abductor @@ -593,7 +735,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} icon = 'icons/obj/abductor.dmi' icon_state = "bed" no_icon_updates = 1 //no icon updates for this; it's static. - injected_reagents = list("corazone") + injected_reagents = list("corazone","spaceacillin") /obj/structure/closet/abductor name = "alien locker" diff --git a/code/game/gamemodes/miniantags/abduction/abduction_outfits.dm b/code/game/gamemodes/miniantags/abduction/abduction_outfits.dm new file mode 100644 index 00000000000..bb39e90cd01 --- /dev/null +++ b/code/game/gamemodes/miniantags/abduction/abduction_outfits.dm @@ -0,0 +1,62 @@ +/datum/outfit/abductor + name = "Abductor Basic" + uniform = /obj/item/clothing/under/color/grey //they're greys gettit + shoes = /obj/item/clothing/shoes/combat + back = /obj/item/storage/backpack + l_ear = /obj/item/radio/headset/abductor + +/datum/outfit/abductor/proc/get_team_console(team_number) + for(var/obj/machinery/abductor/console/C in machines) + if(C.team == team_number) + return C + +/datum/outfit/abductor/proc/link_to_console(mob/living/carbon/human/H, team_number) + if(!team_number && isabductor(H)) + var/datum/species/abductor/S = H.dna.species + team_number = S.team + + if(!team_number) + team_number = 1 + + var/obj/machinery/abductor/console/console = get_team_console(team_number) + if(console) + var/obj/item/clothing/suit/armor/abductor/vest/V = locate() in H + if(V) + console.vest = V + V.flags |= NODROP + + var/obj/item/abductor/gizmo/G = locate() in H.get_item_by_slot(slot_back) + if(G) + console.gizmo = G + G.console = console + +/datum/outfit/abductor/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + ..() + if(!visualsOnly) + link_to_console(H) + + +/datum/outfit/abductor/agent + name = "Abductor Agent" + head = /obj/item/clothing/head/helmet/abductor + suit = /obj/item/clothing/suit/armor/abductor/vest + belt = /obj/item/storage/belt/military/abductor/full + + backpack_contents = list( + /obj/item/abductor_baton = 1, + /obj/item/gun/energy/alien = 1, + /obj/item/abductor/silencer = 1 + ) + +/datum/outfit/abductor/scientist + name = "Abductor Scientist" + + backpack_contents = list( + /obj/item/abductor/gizmo = 1 + ) + +/datum/outfit/abductor/scientist/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + ..() + if(!visualsOnly) + var/obj/item/implant/abductor/beamplant = new /obj/item/implant/abductor(H) + beamplant.implant(H) \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm b/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm index 2d3bed1e0cf..d4d791c5b19 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm @@ -11,11 +11,11 @@ var/obj/item/organ/external/affected = H.get_organ(target_zone) if(!affected) return FALSE - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return FALSE var/mob/living/carbon/human/H = user // You must either: Be of the abductor species, or contain an abductor implant - if((H.get_species() == "Abductor" || (locate(/obj/item/implant/abductor) in H))) + if((isabductor(H) || (locate(/obj/item/implant/abductor) in H))) return TRUE return FALSE @@ -37,7 +37,7 @@ /datum/surgery_step/internal/extract_organ/end_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) var/mob/living/carbon/human/AB = target - if(NO_INTORGANS in AB.species.species_traits) + if(NO_INTORGANS in AB.dna.species.species_traits) user.visible_message("[user] prepares [target]'s [target_zone] for further dissection!", "You prepare [target]'s [target_zone] for further dissection.") return TRUE if(IC) @@ -89,11 +89,11 @@ var/obj/item/organ/external/affected = H.get_organ(target_zone) if(!affected) return FALSE - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) return FALSE var/mob/living/carbon/human/H = user // You must either: Be of the abductor species, or contain an abductor implant - if((H.get_species() == "Abductor" || (locate(/obj/item/implant/abductor) in H))) + if((isabductor(H) || (locate(/obj/item/implant/abductor) in H))) return TRUE return FALSE diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm index a5660f86883..8f058a872e6 100644 --- a/code/game/gamemodes/miniantags/abduction/gland.dm +++ b/code/game/gamemodes/miniantags/abduction/gland.dm @@ -13,30 +13,70 @@ var/human_only = 0 var/active = 0 tough = TRUE //not easily broken by combat damage - sterile = TRUE //not very germy + + var/mind_control_uses = 1 + var/mind_control_duration = 1800 + var/active_mind_control = FALSE /obj/item/organ/internal/heart/gland/proc/ownerCheck() if(ishuman(owner)) - return 1 + return TRUE if(!human_only && iscarbon(owner)) - return 1 - return 0 + return TRUE + return FALSE /obj/item/organ/internal/heart/gland/proc/Start() active = 1 next_activation = world.time + rand(cooldown_low,cooldown_high) +/obj/item/organ/internal/heart/gland/proc/update_gland_hud() + if(!owner) + return + var/image/holder = owner.hud_list[GLAND_HUD] + var/icon/I = icon(owner.icon, owner.icon_state, owner.dir) + holder.pixel_y = I.Height() - world.icon_size + if(active_mind_control) + holder.icon_state = "hudgland_active" + else if(mind_control_uses) + holder.icon_state = "hudgland_ready" + else + holder.icon_state = "hudgland_spent" + +/obj/item/organ/internal/heart/gland/proc/mind_control(command, mob/living/user) + if(!ownerCheck() || !mind_control_uses || active_mind_control) + return + mind_control_uses-- + to_chat(owner, "You suddenly feel an irresistible compulsion to follow an order...") + to_chat(owner, "[command]") + active_mind_control = TRUE + log_admin("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]") + update_gland_hud() + + addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration) + +/obj/item/organ/internal/heart/gland/proc/clear_mind_control() + if(!ownerCheck() || !active_mind_control) + return + to_chat(owner, "You feel the compulsion fade, and you completely forget about your previous orders.") + active_mind_control = FALSE + update_gland_hud() /obj/item/organ/internal/heart/gland/remove(var/mob/living/carbon/M, special = 0) active = 0 if(initial(uses) == 1) uses = initial(uses) + var/datum/atom_hud/abductor/hud = huds[DATA_HUD_ABDUCTOR] + hud.remove_from_hud(owner) + clear_mind_control() . = ..() /obj/item/organ/internal/heart/gland/insert(var/mob/living/carbon/M, special = 0) ..() if(special != 2 && uses) // Special 2 means abductor surgery Start() + var/datum/atom_hud/abductor/hud = huds[DATA_HUD_ABDUCTOR] + hud.add_to_hud(owner) + update_gland_hud() /obj/item/organ/internal/heart/gland/on_life() if(!beating) @@ -62,9 +102,12 @@ cooldown_high = 400 uses = -1 icon_state = "health" + mind_control_uses = 3 + mind_control_duration = 3000 /obj/item/organ/internal/heart/gland/heals/activate() to_chat(owner, "You feel curiously revitalized.") + owner.adjustToxLoss(-20) owner.adjustBruteLoss(-20) owner.adjustOxyLoss(-20) owner.adjustFireLoss(-20) @@ -74,6 +117,13 @@ cooldown_high = 1200 uses = -1 icon_state = "slime" + mind_control_uses = 1 + mind_control_duration = 2400 + +/obj/item/organ/internal/heart/gland/slime/insert(mob/living/carbon/M, special = 0) + ..() + owner.faction |= "slime" + owner.add_language("Bubblish") /obj/item/organ/internal/heart/gland/slime/activate() to_chat(owner, "You feel nauseous!") @@ -85,10 +135,12 @@ /obj/item/organ/internal/heart/gland/mindshock origin_tech = "materials=4;biotech=4;magnets=6;abductor=3" - cooldown_low = 300 - cooldown_high = 300 + cooldown_low = 400 + cooldown_high = 700 uses = -1 icon_state = "mindshock" + mind_control_uses = 1 + mind_control_duration = 6000 /obj/item/organ/internal/heart/gland/mindshock/activate() to_chat(owner, "You get a headache.") @@ -97,19 +149,29 @@ for(var/mob/living/carbon/H in orange(4,T)) if(H == owner) continue - to_chat(H, "You hear a buzz in your head.") - H.AdjustConfused(20) + switch(pick(1,3)) + if(1) + to_chat(H, "You hear a loud buzz in your head, silencing your thoughts!") + H.Stun(3) + if(2) + to_chat(H, "You hear an annoying buzz in your head.") + H.AdjustConfused(15) + H.adjustBrainLoss(5, 15) + if(3) + H.hallucination += 60 /obj/item/organ/internal/heart/gland/pop cooldown_low = 900 cooldown_high = 1800 uses = -1 - human_only = 1 + human_only = TRUE icon_state = "species" + mind_control_uses = 5 + mind_control_duration = 3000 /obj/item/organ/internal/heart/gland/pop/activate() to_chat(owner, "You feel unlike yourself.") - var/species = pick("Unathi","Skrell","Diona","Tajaran","Vulpkanin","Kidan","Grey","Diona") + var/species = pick(/datum/species/unathi, /datum/species/skrell, /datum/species/diona, /datum/species/tajaran, /datum/species/vulpkanin, /datum/species/kidan, /datum/species/grey) owner.set_species(species) /obj/item/organ/internal/heart/gland/ventcrawling @@ -118,6 +180,8 @@ cooldown_high = 2400 uses = 1 icon_state = "vent" + mind_control_uses = 4 + mind_control_duration = 1800 /obj/item/organ/internal/heart/gland/ventcrawling/activate() to_chat(owner, "You feel very stretchy.") @@ -129,23 +193,44 @@ cooldown_high = 2400 uses = 1 icon_state = "viral" + mind_control_uses = 1 + mind_control_duration = 1800 /obj/item/organ/internal/heart/gland/viral/activate() to_chat(owner, "You feel sick.") - var/virus_type = pick(/datum/disease/beesease, /datum/disease/brainrot, /datum/disease/magnitis) - var/datum/disease/D = new virus_type() - D.carrier = TRUE - owner.viruses += D - D.affected_mob = owner - owner.med_hud_set_status() + var/datum/disease/advance/A = random_virus(pick(2, 6), 6) + A.carrier = TRUE + owner.ForceContractDisease(A) + +/obj/item/organ/internal/heart/gland/viral/proc/random_virus(max_symptoms, max_level) + if(max_symptoms > VIRUS_SYMPTOM_LIMIT) + max_symptoms = VIRUS_SYMPTOM_LIMIT + var/datum/disease/advance/A = new /datum/disease/advance() + var/list/datum/symptom/possible_symptoms = list() + for(var/symptom in subtypesof(/datum/symptom)) + var/datum/symptom/S = symptom + if(initial(S.level) > max_level) + continue + if(initial(S.level) <= 0) //unobtainable symptoms + continue + possible_symptoms += S + for(var/i in 1 to max_symptoms) + var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms) + if(chosen_symptom) + var/datum/symptom/S = new chosen_symptom + A.symptoms += S + A.Refresh() //just in case someone already made and named the same disease + return A /obj/item/organ/internal/heart/gland/emp //TODO : Replace with something more interesting origin_tech = "materials=4;biotech=4;magnets=6;abductor=3" - cooldown_low = 900 - cooldown_high = 1600 + cooldown_low = 800 + cooldown_high = 1200 uses = 10 icon_state = "emp" + mind_control_uses = 3 + mind_control_duration = 1800 /obj/item/organ/internal/heart/gland/emp/activate() to_chat(owner, "You feel a spike of pain in your head.") @@ -154,25 +239,71 @@ /obj/item/organ/internal/heart/gland/spiderman cooldown_low = 450 cooldown_high = 900 - uses = 10 + uses = -1 icon_state = "spider" + mind_control_uses = 2 + mind_control_duration = 2400 /obj/item/organ/internal/heart/gland/spiderman/activate() to_chat(owner, "You feel something crawling in your skin.") owner.faction |= "spiders" - new /obj/structure/spider/spiderling(owner.loc) + var/obj/structure/spider/spiderling/S = new(owner.loc) + S.master_commander = owner /obj/item/organ/internal/heart/gland/egg cooldown_low = 300 cooldown_high = 400 uses = -1 icon_state = "egg" + mind_control_uses = 2 + mind_control_duration = 1800 /obj/item/organ/internal/heart/gland/egg/activate() - to_chat(owner, "You lay an egg!") - var/obj/item/reagent_containers/food/snacks/egg/egg = new(owner.loc) - egg.reagents.add_reagent("sacid",20) - egg.desc += " It smells bad." + owner.visible_message("[owner] [pick(EGG_LAYING_MESSAGES)]") + new /obj/item/reagent_containers/food/snacks/egg/gland(get_turf(owner)) + +/obj/item/organ/internal/heart/gland/electric + cooldown_low = 800 + cooldown_high = 1200 + uses = -1 + mind_control_uses = 2 + mind_control_duration = 900 + +/obj/item/organ/internal/heart/gland/electric/insert(mob/living/carbon/M, special = 0) + ..() + if(ishuman(owner)) + owner.gene_stability += GENE_INSTABILITY_MODERATE // give them this gene for free + owner.dna.SetSEState(SHOCKIMMUNITYBLOCK, TRUE) + genemutcheck(owner, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED) + +/obj/item/organ/internal/heart/gland/electric/remove(mob/living/carbon/M, special = 0) + if(ishuman(owner)) + owner.gene_stability -= GENE_INSTABILITY_MODERATE // but return it to normal once it's removed + owner.dna.SetSEState(SHOCKIMMUNITYBLOCK, FALSE) + genemutcheck(owner, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED) + return ..() + +/obj/item/organ/internal/heart/gland/electric/activate() + owner.visible_message("[owner]'s skin starts emitting electric arcs!",\ + "You feel electric energy building up inside you!") + playsound(get_turf(owner), "sparks", 100, 1, -1) + addtimer(CALLBACK(src, .proc/zap), rand(30, 100)) + +/obj/item/organ/internal/heart/gland/electric/proc/zap() + tesla_zap(owner, 4, 8000) + playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1) + +/obj/item/organ/internal/heart/gland/chem + cooldown_low = 50 + cooldown_high = 50 + uses = -1 + mind_control_uses = 3 + mind_control_duration = 1200 + +/obj/item/organ/internal/heart/gland/chem/activate() + owner.reagents.add_reagent(get_random_reagent_id(), 2) + owner.adjustToxLoss(-2) + ..() /obj/item/organ/internal/heart/gland/bloody cooldown_low = 200 @@ -218,8 +349,8 @@ var/mob/living/carbon/human/interactive/greytide/clone = new(src) var/datum/dna/owner_dna = H.dna clone.rename_character(clone.name, owner_dna.real_name) + clone.set_species(owner_dna.species.type) clone.dna = owner_dna.Clone() - clone.set_species(H.species.name) clone.body_accessory = H.body_accessory domutcheck(clone) @@ -258,6 +389,8 @@ cooldown_high = 1800 origin_tech = "materials=4;biotech=4;plasmatech=6;abductor=3" uses = -1 + mind_control_uses = 1 + mind_control_duration = 800 /obj/item/organ/internal/heart/gland/plasma/activate() spawn(0) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/camera.dm b/code/game/gamemodes/miniantags/abduction/machinery/camera.dm index 219ae4b6e54..cd4f80f2527 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/camera.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/camera.dm @@ -2,7 +2,6 @@ name = "Human Observation Console" var/team = 0 networks = list("SS13","Abductor") - off_action = new /datum/action/innate/camera_off/abductor //specific datum var/datum/action/innate/teleport_in/tele_in_action = new var/datum/action/innate/teleport_out/tele_out_action = new var/datum/action/innate/teleport_self/tele_self_action = new @@ -25,65 +24,43 @@ eyeobj.icon_state = "camera_target" /obj/machinery/computer/camera_advanced/abductor/GrantActions(mob/living/carbon/user) - off_action.target = user - off_action.Grant(user) + ..() - jump_action.target = user - jump_action.Grant(user) - //TODO : add null checks - tele_in_action.target = console.pad - tele_in_action.Grant(user) + if(tele_in_action) + tele_in_action.target = console.pad + tele_in_action.Grant(user) + actions += tele_in_action - tele_out_action.target = console - tele_out_action.Grant(user) + if(tele_out_action) + tele_out_action.target = console + tele_out_action.Grant(user) + actions += tele_out_action - tele_self_action.target = console.pad - tele_self_action.Grant(user) + if(tele_self_action) + tele_self_action.target = console.pad + tele_self_action.Grant(user) + actions += tele_self_action - vest_mode_action.target = console - vest_mode_action.Grant(user) + if(vest_mode_action) + vest_mode_action.target = console + vest_mode_action.Grant(user) + actions += vest_mode_action - vest_disguise_action.target = console - vest_disguise_action.Grant(user) + if(vest_disguise_action) + vest_disguise_action.target = console + vest_disguise_action.Grant(user) + actions += vest_disguise_action - set_droppoint_action.target = console - set_droppoint_action.Grant(user) - -/obj/machinery/computer/camera_advanced/abductor/proc/IsScientist(mob/living/carbon/human/H) - if(H.mind && H.mind.abductor) - return H.mind.abductor.scientist + if(set_droppoint_action) + set_droppoint_action.target = console + set_droppoint_action.Grant(user) + actions += set_droppoint_action /obj/machinery/computer/camera_advanced/abductor/attack_hand(mob/user) if(!isabductor(user)) return return ..() -/datum/action/innate/camera_off/abductor/Activate() - if(!target || !iscarbon(target)) - return - var/mob/living/carbon/C = target - var/mob/camera/aiEye/remote/remote_eye = C.remote_control - var/obj/machinery/computer/camera_advanced/abductor/origin = remote_eye.origin - C.remote_view = 0 - origin.current_user = null - origin.jump_action.Remove(C) - origin.tele_in_action.Remove(C) - origin.tele_out_action.Remove(C) - origin.tele_self_action.Remove(C) - origin.vest_mode_action.Remove(C) - origin.vest_disguise_action.Remove(C) - origin.set_droppoint_action.Remove(C) - remote_eye.eye_user = null - C.reset_perspective(null) - if(C.client) - C.client.images -= remote_eye.user_image - for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks) - C.client.images -= chunk.obscured - C.remote_control = null - C.unset_machine() - src.Remove(C) - - /datum/action/innate/teleport_in name = "Send To" button_icon_state = "beam_down" diff --git a/code/game/gamemodes/miniantags/abduction/machinery/console.dm b/code/game/gamemodes/miniantags/abduction/machinery/console.dm index 10cd5473279..0e8c4d3c409 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/console.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/console.dm @@ -54,21 +54,22 @@ dat += "Agent Vest
" dat += "Radio Silencer
" dat += "Science Tool
" + dat += "Mental Interface Device
" else dat += "NO EXPERIMENT MACHINE DETECTED
" - if(pad!=null) + if(pad) dat += "Emergency Teleporter System." dat += "Consider using primary observation console first." dat += "Activate Teleporter
" - if(gizmo!=null && gizmo.marked!=null) + if(gizmo && gizmo.marked) dat += "Retrieve Mark
" else dat += "Retrieve Mark
" else dat += "NO TELEPAD DETECTED
" - if(vest!=null) + if(vest) dat += "

Agent Vest Mode


" var/mode = vest.mode if(mode == VEST_STEALTH) @@ -100,13 +101,14 @@ else if(href_list["flip_vest"]) FlipVest() else if(href_list["toggle_vest"]) - toggle_vest() + if(vest) + vest.toggle_nodrop() else if(href_list["select_disguise"]) SelectDisguise() else if(href_list["dispense"]) switch(href_list["dispense"]) if("baton") - Dispense(/obj/item/abductor_baton,cost=2) + Dispense(/obj/item/abductor_baton, cost = 2) if("helmet") Dispense(/obj/item/clothing/head/helmet/abductor) if("silencer") @@ -115,19 +117,21 @@ Dispense(/obj/item/abductor/gizmo) if("vest") Dispense(/obj/item/clothing/suit/armor/abductor/vest) + if("mind_device") + Dispense(/obj/item/abductor/mind_device, cost = 2) updateUsrDialog() /obj/machinery/abductor/console/proc/TeleporterRetrieve() - if(gizmo!=null && pad!=null && gizmo.marked) + if(pad && gizmo && gizmo.marked) pad.Retrieve(gizmo.marked) /obj/machinery/abductor/console/proc/TeleporterSend() - if(pad!=null) + if(pad) pad.Send() /obj/machinery/abductor/console/proc/FlipVest() - if(vest!=null) + if(vest) vest.flip_mode() /obj/machinery/abductor/console/proc/SelectDisguise(remote = 0) @@ -175,21 +179,36 @@ return disguises[entry.name] = entry +/obj/machinery/abductor/console/proc/AddGizmo(obj/item/abductor/gizmo/G) + if(G == gizmo && G.console == src) + return FALSE + + if(G.console) + G.console.gizmo = null + + gizmo = G + G.console = src + return TRUE + +/obj/machinery/abductor/console/proc/AddVest(obj/item/clothing/suit/armor/abductor/vest/V) + if(vest == V) + return FALSE + + for(var/obj/machinery/abductor/console/C in machines) + if(C.vest == V) + C.vest = null + break + + vest = V + return TRUE + /obj/machinery/abductor/console/attackby(obj/O, mob/user, params) - if(istype(O, /obj/item/abductor/gizmo)) - var/obj/item/abductor/gizmo/G = O + if(istype(O, /obj/item/abductor/gizmo) && AddGizmo(O)) to_chat(user, "You link the tool to the console.") - gizmo = G - G.console = src - else if(istype(O, /obj/item/clothing/suit/armor/abductor/vest)) - var/obj/item/clothing/suit/armor/abductor/vest/V = O + else if(istype(O, /obj/item/clothing/suit/armor/abductor/vest) && AddVest(O)) to_chat(user, "You link the vest to the console.") - if(istype(vest)) - if(vest.flags & NODROP) - toggle_vest() - vest = V else - ..() + return ..() /obj/machinery/abductor/console/proc/Dispense(item,cost=1) if(experiment && experiment.credits >= cost) @@ -201,10 +220,4 @@ else new item(src.loc) else - atom_say("Insufficent data!") - -/obj/machinery/abductor/console/proc/toggle_vest() - vest.flags ^= NODROP - var/mob/M = vest.loc - if(istype(M)) - to_chat(M, "[src] is now [vest.flags & NODROP ? "locked" : "unlocked"].") \ No newline at end of file + atom_say("Insufficent data!") \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/abduction/machinery/dispenser.dm b/code/game/gamemodes/miniantags/abduction/machinery/dispenser.dm index 9e07c9c04a9..1a377667650 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/dispenser.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/dispenser.dm @@ -3,8 +3,8 @@ desc = "A tank filled with replacement organs" icon = 'icons/obj/abductor.dmi' icon_state = "dispenser" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE var/list/gland_types var/list/gland_colors var/list/amounts @@ -49,7 +49,7 @@ var/g_color = gland_colors[i] var/amount = amounts[i] dat += "[amount]" - if(item_count == 3) // Three boxes per line + if(item_count == 4) // Three boxes per line dat +="

" item_count = 0 var/datum/browser/popup = new(user, "glands", "Gland Dispenser", 200, 200) @@ -68,7 +68,7 @@ if(gland_types[i] == W.type) amounts[i]++ else - ..() + return ..() /obj/machinery/abductor/gland_dispenser/Topic(href, href_list) if(..()) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 588900bb3e8..53969aaf7d1 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -3,8 +3,8 @@ desc = "A large man-sized tube sporting a complex array of surgical apparatus." icon = 'icons/obj/abductor.dmi' icon_state = "experiment-open" - anchored = 1 - density = 1 + anchored = TRUE + density = TRUE var/points = 0 var/credits = 0 var/list/history = list() @@ -29,7 +29,7 @@ return for(var/mob/living/carbon/slime/M in range(1, target)) if(M.Victim == target) - to_chat(user, "[target] has a slime attached to them, deal with that first.") + to_chat(user, "[target] has a slime attached to [target.p_them()], deal with that first.") return visible_message("[user] puts [target] into the [src].") @@ -47,9 +47,9 @@ /obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H) var/icon/I = icon(H.stand_icon) - var/icon/splat = icon(H.species.damage_overlays, "30") - splat.Blend(icon(H.species.damage_mask, "torso"), ICON_MULTIPLY) - splat.Blend(H.species.blood_color, ICON_MULTIPLY) + var/icon/splat = icon(H.dna.species.damage_overlays, "30") + splat.Blend(icon(H.dna.species.damage_mask, "torso"), ICON_MULTIPLY) + splat.Blend(H.dna.species.blood_color, ICON_MULTIPLY) I.Blend(splat, ICON_OVERLAY) return I @@ -137,6 +137,7 @@ to_chat(H, "You feel intensely watched.") sleep(5) to_chat(H, "Your mind snaps!") + to_chat(H, "You can't remember how you got here...") var/objtype = pick(subtypesof(/datum/objective/abductee/)) var/datum/objective/abductee/O = new objtype() ticker.mode.abductees += H.mind diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 00bf335c576..9593ee6b792 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -308,7 +308,7 @@ var/list/choices = list() for(var/mob/living/carbon/human/H in view(1,src)) var/obj/item/organ/external/head/head = H.get_organ("head") - if(head.status & ORGAN_ROBOT) + if(head.is_robotic()) continue if(H.stat != DEAD && Adjacent(H) && !H.has_brain_worms()) choices += H @@ -325,7 +325,7 @@ to_chat(src, "You cannot infest someone who is already infested!") return - to_chat(src, "You slither up [M] and begin probing at their ear canal...") + to_chat(src, "You slither up [M] and begin probing at [M.p_their()] ear canal...") if(!do_after(src, 50, target = M)) to_chat(src, "As [M] moves away, you are dislodged and fall to the ground.") @@ -500,7 +500,7 @@ to_chat(src, "You cannot dominate someone who is already infested!") return - to_chat(src, "You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread.") + to_chat(src, "You focus your psychic lance on [M] and freeze [M.p_their()] limbs with a wave of terrible dread.") to_chat(M, "You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.") M.Weaken(3) @@ -531,7 +531,7 @@ to_chat(src, "You decide against leaving your host.") return - to_chat(src, "You begin disconnecting from [host]'s synapses and prodding at their internal ear canal.") + to_chat(src, "You begin disconnecting from [host]'s synapses and prodding at [host.p_their()] internal ear canal.") leaving = TRUE @@ -623,7 +623,7 @@ to_chat(src,"You are feeling far too docile to do that.") return else - to_chat(src, "You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.") + to_chat(src, "You plunge your probosci deep into the cortex of the host brain, interfacing directly with [host.p_their()] nervous system.") to_chat(host, "You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.") var/borer_key = src.key add_attack_logs(src, host, "Assumed control of (borer)") diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index 03b7d2e1b56..6b976ad7f05 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -123,7 +123,7 @@ to_chat(src, "Prime Directives:") to_chat(src, "1. Consume resources and replicate until there are no more resources left.") to_chat(src, "2. Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable.") - to_chat(src, "3. Biological and Sentient resources will be harvested at a later date, do not harm them.") + to_chat(src, "3. Biological and sentient resources will be harvested at a later date, do not harm them.") /mob/living/simple_animal/hostile/swarmer/New() ..() @@ -306,6 +306,12 @@ /obj/spacepod/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) to_chat(S, "Destroying this vehicle would destroy us. Aborting.") +/obj/machinery/clonepod/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + if(occupant) + to_chat(S, "Destroying this machine while it is occupied would result in biological and sentient resources to be harmed. Aborting.") + return + ..() + /mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) S.DisperseTarget(src) diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index f76830910b1..68e8c16c5da 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -448,6 +448,14 @@ Support:Has two modes. Combat: Medium power attacks and damage resist. Healer: Attacks heal damage, but low damage resist and slow movemen. Can deploy a bluespace beacon and warp targets to it (including you) in either mode.

Explosive: High damage resist and medium power attack. Can turn any object into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered.
+
+ Assassin: Medium damage with no damage resistance, can enter stealth which massively increases the damage of the next attack causing it to ignore armour. +
+ Charger: Medium damage and defense, very fast and has a special charge attack which damages a target and knocks items out of their hands. +
+ Lightning: Applies lightning chains to any targets on attack with a link to your summoner, lightning chains will shock anyone nearby. +
+ Protector: You will become leashed to your holoparasite instead of them to you. Has two modes, a medium attack/defense mode and a protection mode which greatly reduces incoming damage to the holoparasite. "} /obj/item/paper/guardian/update_icon() diff --git a/code/game/gamemodes/miniantags/guardian/types/charger.dm b/code/game/gamemodes/miniantags/guardian/types/charger.dm index abdc349f175..17ed569f256 100644 --- a/code/game/gamemodes/miniantags/guardian/types/charger.dm +++ b/code/game/gamemodes/miniantags/guardian/types/charger.dm @@ -6,7 +6,7 @@ ranged_cooldown_time = 40 speed = -1 damage_transfer = 0.6 - playstyle_string = "As a Charger type you do medium damage, have medium damage resistance, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding." + playstyle_string = "As a Charger type you do medium damage, have medium damage resistance, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding. (Click a tile to use your charge ability)" magic_fluff_string = "..And draw the Hunter, an alien master of rapid assault." tech_fluff_string = "Boot sequence complete. Charge modules loaded. Holoparasite swarm online." bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to deal damage." diff --git a/code/game/gamemodes/miniantags/guardian/types/protector.dm b/code/game/gamemodes/miniantags/guardian/types/protector.dm index fe8b4897c42..9206b0d1b0b 100644 --- a/code/game/gamemodes/miniantags/guardian/types/protector.dm +++ b/code/game/gamemodes/miniantags/guardian/types/protector.dm @@ -51,7 +51,7 @@ Recall(TRUE) else to_chat(summoner, "You moved out of range, and were pulled back! You can only move [range] meters from [src]!") - summoner.visible_message("[summoner] jumps back to their protector.") + summoner.visible_message("[summoner] jumps back to [summoner.p_their()] protector.") new /obj/effect/temp_visual/guardian/phase/out(get_turf(summoner)) summoner.forceMove(get_turf(src)) new /obj/effect/temp_visual/guardian/phase(get_turf(summoner))//Protector \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/morph/morph_event.dm b/code/game/gamemodes/miniantags/morph/morph_event.dm index d9e26597a2b..ab875832451 100644 --- a/code/game/gamemodes/miniantags/morph/morph_event.dm +++ b/code/game/gamemodes/miniantags/morph/morph_event.dm @@ -19,7 +19,7 @@ return kill() var/mob/living/simple_animal/hostile/morph/S = new /mob/living/simple_animal/hostile/morph(pick(xeno_spawn)) player_mind.transfer_to(S) - player_mind.assigned_role = "Morph" + player_mind.assigned_role = SPECIAL_ROLE_MORPH player_mind.special_role = SPECIAL_ROLE_MORPH ticker.mode.traitors |= player_mind to_chat(S, S.playstyle_string) diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index fa659b50c43..953e6e91762 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -392,7 +392,7 @@ var/datum/mind/player_mind = new /datum/mind(key_of_revenant) player_mind.active = 1 player_mind.transfer_to(R) - player_mind.assigned_role = "revenant" + player_mind.assigned_role = SPECIAL_ROLE_REVENANT player_mind.special_role = SPECIAL_ROLE_REVENANT ticker.mode.traitors |= player_mind message_admins("[key_of_revenant] has been [client_to_revive ? "re":""]made into a revenant by reforming ectoplasm.") diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm index 32d51b579c4..5a7825c0cfe 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm @@ -73,7 +73,7 @@ icon_state = "revenant_draining" reveal(27) stun(27) - target.visible_message("[target] suddenly rises slightly into the air, their skin turning an ashy gray.") + target.visible_message("[target] suddenly rises slightly into the air, [target.p_their()] skin turning an ashy gray.") target.Beam(src,icon_state="drain_life",icon='icons/effects/effects.dmi',time=26) if(do_after(src, 30, 0, target)) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining. change_essence_amount(essence_drained, 0, target) @@ -263,8 +263,8 @@ new/obj/effect/temp_visual/revenant(T) T.ChangeTurf(/turf/simulated/wall/r_wall/rust) for(var/obj/structure/window/window in T.contents) - window.hit(rand(30,80)) - if(window && window.is_fulltile()) + window.take_damage(rand(30,80)) + if(window && window.fulltile) new/obj/effect/temp_visual/revenant/cracks(window.loc) for(var/obj/structure/closet/closet in T.contents) closet.open() diff --git a/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm b/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm index 859f863b03c..a70114d8f5e 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm @@ -43,7 +43,7 @@ return kill() var/mob/living/simple_animal/revenant/revvie = new /mob/living/simple_animal/revenant/(pick(spawn_locs)) player_mind.transfer_to(revvie) - player_mind.assigned_role = "revenant" + player_mind.assigned_role = SPECIAL_ROLE_REVENANT player_mind.special_role = SPECIAL_ROLE_REVENANT ticker.mode.traitors |= player_mind message_admins("[key_of_revenant] has been made into a revenant by an event.") diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm index aeb26f58822..6b5705cfa7f 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm @@ -149,7 +149,7 @@ if(!A) to_chat(usr, "You could not locate any sapient heretics for the Slaughter.") return 0 - to_chat(usr, "You sense a terrified soul at [A]. Show them the error of their ways.") + to_chat(usr, "You sense a terrified soul at [A]. Show [A.p_them()] the error of [A.p_their()] ways.") /mob/living/simple_animal/slaughter/cult/New() ..() @@ -241,7 +241,7 @@ return // Just so people don't accidentally waste it /obj/item/organ/internal/heart/demon/attack_self(mob/living/user) - user.visible_message("[user] raises [src] to their mouth and tears into it with their teeth!", \ + user.visible_message("[user] raises [src] to [user.p_their()] mouth and tears into it with [user.p_their()] teeth!", \ "An unnatural hunger consumes you. You raise [src] to your mouth and devour it!") playsound(user, 'sound/misc/Demon_consume.ogg', 50, 1) for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index b2f06a7913a..17afd375952 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -49,7 +49,7 @@ proc/issyndicate(mob/living/M as mob) agent_number-- for(var/datum/mind/synd_mind in syndicates) - synd_mind.assigned_role = "MODE" //So they aren't chosen for other jobs. + synd_mind.assigned_role = SPECIAL_ROLE_NUKEOPS //So they aren't chosen for other jobs. synd_mind.special_role = SPECIAL_ROLE_NUKEOPS return 1 @@ -141,15 +141,15 @@ proc/issyndicate(mob/living/M as mob) return ..() -/datum/game_mode/proc/create_syndicate(var/datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human +/datum/game_mode/proc/create_syndicate(datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human var/mob/living/carbon/human/M = synd_mind.current - var/obj/item/organ/external/head/head_organ = M.get_organ("head") - M.set_species("Human",1) + M.set_species(/datum/species/human, TRUE) M.dna.ready_dna(M) // Quadriplegic Nuke Ops won't be participating in the paralympics M.reagents.add_reagent("mutadone", 1) //No fat/blind/colourblind/epileptic/whatever ops. M.overeatduration = 0 + var/obj/item/organ/external/head/head_organ = M.get_organ("head") var/hair_c = pick("#8B4513","#000000","#FF4500","#FFD700") // Brown, black, red, blonde var/eye_c = pick("#000000","#8B4513","1E90FF") // Black, brown, blue var/skin_tone = pick(-50, -30, -10, 0, 0, 0, 10) // Caucasian/black @@ -159,8 +159,8 @@ proc/issyndicate(mob/living/M as mob) head_organ.sec_hair_colour = hair_c M.change_eye_color(eye_c) M.s_tone = skin_tone - head_organ.h_style = random_hair_style(M.gender, head_organ.species.name) - head_organ.f_style = random_facial_hair_style(M.gender, head_organ.species.name) + head_organ.h_style = random_hair_style(M.gender, head_organ.dna.species.name) + head_organ.f_style = random_facial_hair_style(M.gender, head_organ.dna.species.name) M.body_accessory = null M.regenerate_icons() M.update_body() @@ -253,7 +253,7 @@ proc/issyndicate(mob/living/M as mob) U.hidden_uplink.uses = 20 synd_mob.equip_to_slot_or_del(U, slot_in_backpack) - if(synd_mob.species) + if(synd_mob.dna.species) /* Incase anyone ever gets the burning desire to have nukeops with randomized apperances. -- Dave @@ -262,7 +262,7 @@ proc/issyndicate(mob/living/M as mob) A.randomize_appearance_for(synd_mob) */ - var/race = synd_mob.species.name + var/race = synd_mob.dna.species.name switch(race) if("Vox" || "Vox Armalis") diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm index 6bb181b4136..7e75f579bf5 100644 --- a/code/game/gamemodes/nuclear/nuclear_challenge.dm +++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm @@ -3,7 +3,7 @@ #define CHALLENGE_SCALE_PLAYER 1 // How many player per scaling bonus #define CHALLENGE_SCALE_BONUS 2 // How many TC per scaling bonus #define CHALLENGE_MIN_PLAYERS 50 -#define CHALLENGE_SHUTTLE_DELAY 15000 //25 minutes, so the ops have at least 5 minutes before the shuttle is callable. +#define CHALLENGE_SHUTTLE_DELAY 18000 //30 minutes, so the ops have at least 10 minutes before the shuttle is callable. Gives the nuke ops at least 15 minutes before shuttle arrive. /obj/item/nuclear_challenge name = "Declaration of War (Challenge Mode)" @@ -20,7 +20,7 @@ return declaring_war = TRUE - var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]]. Are you sure you want to alert the enemy crew? You have [-round((world.time-round_start_time - CHALLENGE_TIME_LIMIT)/10)] seconds to decide.", "Declare war?", "Yes", "No") + var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]. Are you sure you want to alert the enemy crew? You have [-round((world.time-round_start_time - CHALLENGE_TIME_LIMIT)/10)] seconds to decide.", "Declare war?", "Yes", "No") declaring_war = FALSE if(!check_allowed(user)) @@ -30,7 +30,7 @@ to_chat(user, "On second thought, the element of surprise isn't so bad after all.") return - var/war_declaration = "[user.real_name] has declared his intent to utterly destroy [station_name()] with a nuclear device, and dares the crew to try and stop them." + var/war_declaration = "[user.real_name] has declared [user.p_their()] intent to utterly destroy [station_name()] with a nuclear device, and dares the crew to try and stop them." declaring_war = TRUE var/custom_threat = alert(user, "Do you want to customize your declaration?", "Customize?", "Yes", "No") @@ -71,7 +71,7 @@ if(!is_admin_level(user.z)) to_chat(user, "You have to be at your base to use this.") return FALSE - if(world.time > CHALLENGE_TIME_LIMIT) + if((world.time - round_start_time) > CHALLENGE_TIME_LIMIT) // Only count after the round started to_chat(user, "It's too late to declare hostilities. Your benefactors are already busy with other schemes. You'll have to make do with what you have on hand.") return FALSE for(var/obj/machinery/computer/shuttle/syndicate/S in machines) diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 37a2979ae74..e9bea1d8b1d 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -53,7 +53,7 @@ var/turf/T = get_turf(target) var/turf/L = get_turf(src) - if(T.z != L.z) + if(!(T && L) || (T.z != L.z)) icon_state = icon_null else dir = get_dir(L, T) @@ -341,7 +341,7 @@ if(active) active = FALSE icon_state = icon_off - user.visible_message("[user] deactivates their pinpointer.", "You deactivate your pinpointer.") + user.visible_message("[user] deactivates [user.p_their()] pinpointer.", "You deactivate your pinpointer.") return var/list/name_counts = list() @@ -354,7 +354,8 @@ var/name = "Unknown" if(H.wear_id) var/obj/item/card/id/I = H.wear_id.GetID() - name = I.registered_name + if(I) + name = I.registered_name while(name in name_counts) name_counts[name]++ @@ -372,7 +373,7 @@ var/target = names[A] active = TRUE - user.visible_message("[user] activates their pinpointer.", "You activate your pinpointer.") + user.visible_message("[user] activates [user.p_their()] pinpointer.", "You activate your pinpointer.") point_at(target) /obj/item/pinpointer/crew/point_at(atom/target, spawnself = 1) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index c9ad5ce69e4..b7364970351 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -281,13 +281,13 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu for(var/datum/mind/possible_target in ticker.minds) if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && possible_target.current.client) var/mob/living/carbon/human/H = possible_target.current - if(!(NO_DNA in H.species.species_traits)) + if(!(NO_DNA in H.dna.species.species_traits)) possible_targets += possible_target if(possible_targets.len > 0) target = pick(possible_targets) if(target && target.current) target_real_name = target.current.real_name - explanation_text = "Escape on the shuttle or an escape pod with the identity of [target_real_name], the [target.assigned_role] while wearing their identification card." + explanation_text = "Escape on the shuttle or an escape pod with the identity of [target_real_name], the [target.assigned_role] while wearing [target.p_their()] identification card." else explanation_text = "Free Objective" @@ -445,7 +445,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu n_p++ else if(ticker.current_state == GAME_STATE_PLAYING) for(var/mob/living/carbon/human/P in player_list) - if(NO_DNA in P.species.species_traits) + if(NO_DNA in P.dna.species.species_traits) continue if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner) n_p++ @@ -515,7 +515,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu var/list/priority_targets = list() for(var/datum/mind/possible_target in ticker.minds) - if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && (possible_target.assigned_role != "MODE")) + if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && (possible_target.assigned_role != possible_target.special_role)) possible_targets += possible_target for(var/role in roles) if(possible_target.assigned_role == role) @@ -528,7 +528,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu target = pick(possible_targets) if(target && target.current) - explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take them alive." + explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take [target.current.p_them()] alive." else explanation_text = "Free Objective" return target diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 4f500825065..089cad71a3a 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -279,7 +279,7 @@ to_chat(M, "The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.") else - to_chat(M, "[rev_mind.current] looks like they just remembered their real allegiance!") + to_chat(M, "[rev_mind.current] looks like [rev_mind.current.p_they()] just remembered [rev_mind.current.p_their()] real allegiance!") ///////////////////////////////////// //Adds the rev hud to a new convert// diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index ed8603360fe..6a1c242efb4 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -188,7 +188,7 @@ Made by Xhuis M.audible_message("[M] lets out a short blip.", \ "You have been turned into a robot! You are no longer a thrall! Though you try, you cannot remember anything about your servitude...") else - M.visible_message("[M] looks like their mind is their own again!", \ + M.visible_message("[M] looks like [M.p_their()] mind is [M.p_their()] own again!", \ "A piercing white light floods your eyes. Your mind is your own again! Though you try, you cannot remember anything about the shadowlings or your time \ under their command...") return 1 @@ -209,7 +209,7 @@ Made by Xhuis if(shadow.special_role == SPECIAL_ROLE_SHADOWLING && config.shadowling_max_age) if(ishuman(shadow.current)) var/mob/living/carbon/human/H = shadow.current - if(H.get_species() != "Shadow") + if(!isshadowling(H)) for(var/obj/effect/proc_holder/spell/targeted/shadowling_hatch/hatch_ability in shadow.spell_list) hatch_ability.cycles_unused++ if(!H.stunned && prob(20) && hatch_ability.cycles_unused > config.shadowling_max_age) @@ -306,93 +306,6 @@ Made by Xhuis MISCELLANEOUS */ - -/datum/species/shadow/ling - //Normal shadowpeople but with enhanced effects - name = "Shadowling" - - icobase = 'icons/mob/human_races/r_shadowling.dmi' - deform = 'icons/mob/human_races/r_shadowling.dmi' - - blood_color = "#555555" - flesh_color = "#222222" - - species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE, NOGUNS) //Can't use guns due to muzzle flash - burn_mod = 1.5 //1.5x burn damage, 2x is excessive - oxy_mod = 0 - heatmod = 1.5 - - silent_steps = 1 - grant_vision_toggle = 0 - - has_organ = list( - "brain" = /obj/item/organ/internal/brain, - "eyes" = /obj/item/organ/internal/eyes) - -/datum/species/shadow/ling/handle_life(var/mob/living/carbon/human/H) - if(!H.weakeyes) - H.weakeyes = 1 //Makes them more vulnerable to flashes and flashbangs - var/light_amount = 0 - H.nutrition = NUTRITION_LEVEL_WELL_FED //i aint never get hongry - if(isturf(H.loc)) - var/turf/T = H.loc - light_amount = T.get_lumcount() * 10 - if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move) //Can survive in very small light levels. Also doesn't take damage while incorporeal, for shadow walk purposes - H.throw_alert("lightexposure", /obj/screen/alert/lightexposure) - H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN) - if(H.stat != DEAD) - to_chat(H, "The light burns you!")//Message spam to say "GET THE FUCK OUT" - H << 'sound/weapons/sear.ogg' - else if(light_amount < LIGHT_HEAL_THRESHOLD) - H.clear_alert("lightexposure") - var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes) - if(istype(E)) - E.receive_damage(-1) - H.heal_overall_damage(5, 5) - H.adjustToxLoss(-5) - H.adjustBrainLoss(-25) //Shad O. Ling gibbers, "CAN U BE MY THRALL?!!" - H.AdjustEyeBlurry(-1) - H.CureNearsighted() - H.CureBlind() - H.adjustCloneLoss(-1) - H.SetWeakened(0) - H.SetStunned(0) - ..() - - -/datum/species/shadow/ling/lesser //Empowered thralls. Obvious, but powerful - name = "Lesser Shadowling" - - icobase = 'icons/mob/human_races/r_lshadowling.dmi' - deform = 'icons/mob/human_races/r_lshadowling.dmi' - - blood_color = "#CCCCCC" - flesh_color = "#AAAAAA" - - species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE) - burn_mod = 1.1 - oxy_mod = 0 - heatmod = 1.1 - -/datum/species/shadow/ling/lesser/handle_life(var/mob/living/carbon/human/H) - if(!H.weakeyes) - H.weakeyes = 1 //Makes them more vulnerable to flashes and flashbangs - var/light_amount = 0 - H.nutrition = NUTRITION_LEVEL_WELL_FED //i aint never get hongry - if(isturf(H.loc)) - var/turf/T = H.loc - light_amount = T.get_lumcount() * 10 - if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move) - H.throw_alert("lightexposure", /obj/screen/alert/lightexposure) - H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN/2) - else if(light_amount < LIGHT_HEAL_THRESHOLD) - H.clear_alert("lightexposure") - H.heal_overall_damage(2,2) - H.adjustToxLoss(-5) - H.adjustBrainLoss(-25) - H.adjustCloneLoss(-1) - ..() - /datum/game_mode/proc/update_shadow_icons_added(datum/mind/shadow_mind) var/datum/atom_hud/antag/shadow_hud = huds[ANTAG_HUD_SHADOW] shadow_hud.join_hud(shadow_mind.current) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index 06f7bc9440c..ea846e394a5 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -2,8 +2,10 @@ /obj/effect/proc_holder/spell/proc/shadowling_check(var/mob/living/carbon/human/H) if(!H || !istype(H)) return - if(H.get_species() == "Shadowling" && is_shadow(H)) return 1 - if(H.get_species() == "Lesser Shadowling" && is_thrall(H)) return 1 + if(isshadowling(H) && is_shadow(H)) + return 1 + if(isshadowlinglesser(H) && is_thrall(H)) + return 1 if(!is_shadow_or_thrall(usr)) to_chat(usr, "You can't wrap your head around how to do this.") else if(is_thrall(usr)) @@ -40,9 +42,9 @@ return var/mob/living/carbon/human/M = target user.visible_message("[user]'s eyes flash a blinding red!") - target.visible_message("[target] freezes in place, their eyes glazing over...") + target.visible_message("[target] freezes in place, [target.p_their()] eyes glazing over...") if(in_range(target, user)) - to_chat(target, "Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by their heavenly beauty...") + to_chat(target, "Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by [user.p_their()] heavenly beauty...") else //Only alludes to the shadowling if the target is close by to_chat(target, "Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...") target.Stun(10) @@ -267,7 +269,7 @@ listclearnulls(ticker.mode.shadowling_thralls) if(!(ling.mind in ticker.mode.shadows)) return - if(ling.get_species() != "Shadowling") + if(!isshadowling(ling)) if(ticker.mode.shadowling_thralls.len >= 5) charge_counter = charge_max return @@ -306,7 +308,7 @@ switch(progress) if(1) to_chat(user, "You place your hands to [target]'s head...") - user.visible_message("[user] places their hands onto the sides of [target]'s head!") + user.visible_message("[user] places [user.p_their()] hands onto the sides of [target]'s head!") if(2) to_chat(user, "You begin preparing [target]'s mind as a blank slate...") user.visible_message("[user]'s palms flare a bright red against [target]'s temples!") @@ -315,7 +317,7 @@ sleep(20) if(ismindshielded(target)) to_chat(user, "They have a mindshield implant. You begin to deactivate it - this will take some time.") - user.visible_message("[user] pauses, then dips their head in concentration!") + user.visible_message("[user] pauses, then dips [user.p_their()] head in concentration!") to_chat(target, "Your mindshield implant becomes hot as it comes under attack!") sleep(100) //10 seconds - not spawn() so the enthralling takes longer to_chat(user, "The nanobots composing the mindshield implant have been rendered inert. Now to continue.") @@ -361,8 +363,9 @@ if(!istype(target) || !ishuman(target)) return var/mob/living/carbon/human/H = target - H.visible_message("[H]'s skin suddenly bubbles and shifts around their body!", \ + H.visible_message("[H]'s skin suddenly bubbles and shifts around [H.p_their()] body!", \ "You regenerate your protective armor and cleanse your form of defects.") + H.set_species(/datum/species/shadow/ling) H.adjustCloneLoss(-target.getCloneLoss()) H.equip_to_slot_or_del(new /obj/item/clothing/under/shadowling(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/shadowling(H), slot_shoes) @@ -371,7 +374,6 @@ H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(H), slot_gloves) H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(H), slot_wear_mask) H.equip_to_slot_or_del(new /obj/item/clothing/glasses/shadowling(H), slot_glasses) - H.set_species("Shadowling") /obj/effect/proc_holder/spell/targeted/collective_mind //Lets a shadowling bring together their thralls' strength, granting new abilities and a headcount name = "Collective Hivemind" @@ -493,7 +495,7 @@ to_chat(M, "You breathe in the black smoke, and your eyes burn horribly!") M.EyeBlind(5) if(prob(25)) - M.visible_message("[M] claws at their eyes!") + M.visible_message("[M] claws at [M.p_their()] eyes!") M.Stun(3) else to_chat(M, "You breathe in the black smoke, and you feel revitalized!") @@ -540,9 +542,7 @@ sp.start() S.Weaken(6) for(var/obj/structure/window/W in T.contents) - W.hit(rand(80, 100)) - - + W.take_damage(rand(80, 100)) /obj/effect/proc_holder/spell/aoe_turf/drainLife name = "Drain Life" @@ -612,7 +612,7 @@ to_chat(user, "[thrallToRevive] must be conscious to become empowered.") charge_counter = charge_max return - if(thrallToRevive.get_species() == "Lesser Shadowling") + if(isshadowlinglesser(thrallToRevive)) to_chat(user, "[thrallToRevive] is already empowered.") charge_counter = charge_max return @@ -621,15 +621,15 @@ if(!ishuman(M.current)) return var/mob/living/carbon/human/H = M.current - if(H.get_species() == "Lesser Shadowling") + if(isshadowlinglesser(H)) empowered_thralls++ if(empowered_thralls >= EMPOWERED_THRALL_LIMIT) to_chat(user, "You cannot spare this much energy. There are too many empowered thralls.") charge_counter = charge_max return - user.visible_message("[user] places their hands over [thrallToRevive]'s face, red light shining from beneath.", \ + user.visible_message("[user] places [user.p_their()] hands over [thrallToRevive]'s face, red light shining from beneath.", \ "You place your hands on [thrallToRevive]'s face and begin gathering energy...") - to_chat(thrallToRevive, "[user] places their hands over your face. You feel energy gathering. Stand still...") + to_chat(thrallToRevive, "[user] places [user.p_their()] hands over your face. You feel energy gathering. Stand still...") if(!do_mob(user, thrallToRevive, 80)) to_chat(user, "Your concentration snaps. The flow of energy ebbs.") charge_counter = charge_max @@ -640,13 +640,13 @@ playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1) user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1) thrallToRevive.Weaken(5) - thrallToRevive.visible_message("[thrallToRevive] collapses, their skin and face distorting!", \ + thrallToRevive.visible_message("[thrallToRevive] collapses, [thrallToRevive.p_their()] skin and face distorting!", \ "AAAAAAAAAAAAAAAAAAAGH-") sleep(20) thrallToRevive.visible_message("[thrallToRevive] slowly rises, no longer recognizable as human.", \ "You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \ darkness but wither slowly in light. In addition, you now have glare and true shadow walk.") - thrallToRevive.set_species("Lesser Shadowling") + thrallToRevive.set_species(/datum/species/shadow/ling/lesser) thrallToRevive.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk) thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null)) thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null)) @@ -659,7 +659,7 @@ to_chat(user, "[thrallToRevive] is not dead.") charge_counter = charge_max return - user.visible_message("[user] kneels over [thrallToRevive], placing their hands on \his chest.", \ + user.visible_message("[user] kneels over [thrallToRevive], placing [user.p_their()] hands on [thrallToRevive.p_their()] chest.", \ "You crouch over the body of your thrall and begin gathering energy...") thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.", source = thrallToRevive) if(!do_mob(user, thrallToRevive, 30)) @@ -673,7 +673,7 @@ user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1) sleep(10) if(thrallToRevive.revive()) - thrallToRevive.visible_message("[thrallToRevive] heaves in breath, dim red light shining in their eyes.", \ + thrallToRevive.visible_message("[thrallToRevive] heaves in breath, dim red light shining in [thrallToRevive.p_their()] eyes.", \ "You have returned. One of your masters has brought you from the darkness beyond.") thrallToRevive.Weaken(4) thrallToRevive.emote("gasp") @@ -710,7 +710,7 @@ var/mob/living/carbon/human/M = target user.visible_message("[user]'s eyes flash a bright red!", \ "You begin to draw [M]'s life force.") - M.visible_message("[M]'s face falls slack, their jaw slightly distending.", \ + M.visible_message("[M]'s face falls slack, [M.p_their()] jaw slightly distending.", \ "You are suddenly transported... far, far away...") if(!do_after(user, 50, target = M)) to_chat(M, "You are snapped back to reality, your haze dissipating!") @@ -754,7 +754,7 @@ to_chat(user, "Making an ally explode seems unwise.") charge_counter = charge_max return - user.visible_message("[user]'s markings flare as they gesture at [boom]!", \ + user.visible_message("[user]'s markings flare as [user.p_they()] gesture[user.p_s()] at [boom]!", \ "You direct a lance of telekinetic energy at [boom].") sleep(4) if(iscarbon(boom)) @@ -798,7 +798,7 @@ charge_counter = charge_max return - to_chat(user, "You instantly rearrange [target]'s memories, hyptonitizing them into a thrall.") + to_chat(user, "You instantly rearrange [target]'s memories, hyptonitizing [target.p_them()] into a thrall.") to_chat(target, "An agonizing spike of pain drives into your mind, and--") ticker.mode.add_thrall(target.mind) target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm index 5c05a028df0..7aebaa0b044 100644 --- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm @@ -43,7 +43,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N var/temp_flags = H.status_flags H.status_flags |= GODMODE //Can't die while hatching - H.visible_message("A chrysalis forms around [H], sealing them inside.", \ + H.visible_message("A chrysalis forms around [H], sealing [H.p_them()] inside.", \ "You create your chrysalis and begin to contort within.") sleep(100) @@ -51,7 +51,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N "Spines pierce your back. Your claws break apart your fingers. You feel excruciating pain as your true form begins its exit.") sleep(90) - H.visible_message("[H], skin shifting, begins tearing at the walls around them.", \ + H.visible_message("[H], skin shifting, begins tearing at the walls around [H.p_them()].", \ "Your false skin slips away. You begin tearing at the fragile membrane protecting you.") sleep(80) @@ -84,6 +84,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N H.socks = "None" H.faction |= "faithless" + H.set_species(/datum/species/shadow/ling) //can't be a shadowling without being a shadowling H.equip_to_slot_or_del(new /obj/item/clothing/under/shadowling(user), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/shadowling(user), slot_shoes) H.equip_to_slot_or_del(new /obj/item/clothing/suit/space/shadowling(user), slot_wear_suit) @@ -91,7 +92,6 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(user), slot_gloves) H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(user), slot_wear_mask) H.equip_to_slot_or_del(new /obj/item/clothing/glasses/shadowling(user), slot_glasses) - H.set_species("Shadowling") //can't be a shadowling without being a shadowling H.mind.RemoveSpell(src) diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index 44e722abfca..d3f29734815 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -118,7 +118,7 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C) typepath = /obj/item/documents //Any set of secret documents. Doesn't have to be NT's /datum/theft_objective/hypospray - name = "a hypospray" + name = "the Chief Medical Officer's hypospray" typepath = /obj/item/reagent_containers/hypospray/CMO protected_jobs = list("Chief Medical Officer") diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index ec8a1643c27..9234043976c 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -346,7 +346,7 @@ // Tell them about people they might want to contact. var/mob/living/carbon/human/M = get_nt_opposed() if(M && M != traitor_mob) - to_chat(traitor_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.") + to_chat(traitor_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting [M.p_them()].") traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") //let's also inform their contact that they might be called upon, but leave it vague. inform_collab(M) diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index c2431f17318..14ba6fb9dd0 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -279,8 +279,8 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha to_chat(owner, "[owner.wear_mask] prevents you from biting [H]!") draining = null return - add_attack_logs(owner, H, "vampirebit & is draining their blood.", FALSE) - owner.visible_message("[owner] grabs [H]'s neck harshly and sinks in their fangs!", "You sink your fangs into [H] and begin to drain their blood.", "You hear a soft puncture and a wet sucking noise.") + add_attack_logs(owner, H, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL) + owner.visible_message("[owner] grabs [H]'s neck harshly and sinks in [owner.p_their()] fangs!", "You sink your fangs into [H] and begin to drain [owner.p_their()] blood.", "You hear a soft puncture and a wet sucking noise.") if(!iscarbon(owner)) H.LAssailant = null else diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index e9a249d8412..6d82f6c48e1 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -175,7 +175,7 @@ /obj/effect/proc_holder/spell/vampire/targetted/hypnotise/cast(list/targets, mob/user = usr) for(var/mob/living/target in targets) - user.visible_message("[user]'s eyes flash briefly as he stares into [target]'s eyes") + user.visible_message("[user]'s eyes flash briefly as [user.p_they()] stare[user.p_s()] into [target]'s eyes") if(do_mob(user, target, 50)) if(!affects(target)) to_chat(user, "Your piercing gaze fails to knock out [target].") @@ -239,7 +239,7 @@ if(ishuman(user)) var/mob/living/carbon/human/H = user scramble(1, H, 100) - H.real_name = random_name(H.gender, H.species.name) //Give them a name that makes sense for their species. + H.real_name = random_name(H.gender, H.dna.species.name) //Give them a name that makes sense for their species. H.sync_organ_dna(assimilate = 1) H.update_body(0) H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover. @@ -270,7 +270,7 @@ C.Stun(4) C.Jitter(150) for(var/obj/structure/window/W in view(4)) - W.destroy() + W.deconstruct(FALSE) playsound(user.loc, 'sound/effects/creepyshriek.ogg', 100, 1) @@ -345,8 +345,8 @@ ticker.mode.vampire_enthralled.Add(H.mind) ticker.mode.vampire_enthralled[H.mind] = user.mind H.mind.special_role = SPECIAL_ROLE_VAMPIRE_THRALL - to_chat(H, "You have been Enthralled by [user]. Follow their every command.") - to_chat(user, "You have successfully Enthralled [H]. If they refuse to do as you say just adminhelp.") + to_chat(H, "You have been Enthralled by [user]. Follow [user.p_their()] every command.") + to_chat(user, "You have successfully Enthralled [H]. If [H.p_they()] refuse[H.p_s()] to do as you say just adminhelp.") add_attack_logs(user, H, "Vampire-thralled") diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 2e99f0238c5..2ac4bc0b2f8 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -56,7 +56,7 @@ new /obj/effect/particle_effect/smoke(H.loc) var/mob/living/carbon/human/M = new/mob/living/carbon/human(H.loc) M.key = C.key - to_chat(M, "You are the [H.real_name]'s apprentice! You are bound by magic contract to follow their orders and help them in accomplishing their goals.") + to_chat(M, "You are the [H.real_name]'s apprentice! You are bound by magic contract to follow [H.p_their()] orders and help [H.p_them()] in accomplishing their goals.") switch(href_list["school"]) if("destruction") M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null)) @@ -213,7 +213,7 @@ /obj/item/scrying/attack_self(mob/user as mob) to_chat(user, " You can see...everything!") - visible_message("[user] stares into [src], their eyes glazing over.") + visible_message("[user] stares into [src], [user.p_their()] eyes glazing over.") user.ghostize(1) /////////////////////Multiverse Blade//////////////////// @@ -277,7 +277,7 @@ var/global/list/multiverse = list() var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone hijack_objective.owner = usr.mind usr.mind.objectives += hijack_objective - hijack_objective.explanation_text = "Ensure only [usr.real_name] and their copies are on the shuttle!" + hijack_objective.explanation_text = "Ensure only [usr.real_name] and [usr.p_their()] copies are on the shuttle!" to_chat(usr, "Objective #[1]: [hijack_objective.explanation_text]") ticker.mode.traitors += usr.mind usr.mind.special_role = "[usr.real_name] Prime" @@ -318,14 +318,14 @@ var/global/list/multiverse = list() C.prefs.copy_to(M) M.key = C.key M.mind.name = user.real_name - to_chat(M, "You are an alternate version of [user.real_name] from another universe! Help them accomplish their goals at all costs.") + to_chat(M, "You are an alternate version of [user.real_name] from another universe! Help [user.p_them()] accomplish [user.p_their()] goals at all costs.") M.faction = list("[user.real_name]") if(duplicate_self) - M.set_species(user.get_species()) //duplicate the sword user's species. + M.set_species(user.dna.species.type) //duplicate the sword user's species. else if(prob(50)) - var/list/all_species = list("Human","Unathi","Skrell","Tajaran","Kidan","Golem","Diona","Machine","Slime People","Grey","Vulpkanin") - M.set_species(pick(all_species)) + var/list/list_all_species = list(/datum/species/human, /datum/species/unathi, /datum/species/skrell, /datum/species/tajaran, /datum/species/kidan, /datum/species/golem, /datum/species/diona, /datum/species/machine, /datum/species/slime, /datum/species/grey, /datum/species/vulpkanin) + M.set_species(pick(list_all_species)) M.real_name = user.real_name //this is clear down here in case the user happens to become a golem; that way they have the proper name. M.name = user.real_name if(duplicate_self) @@ -342,7 +342,7 @@ var/global/list/multiverse = list() var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone hijack_objective.owner = M.mind M.mind.objectives += hijack_objective - hijack_objective.explanation_text = "Ensure only [usr.real_name] and their copies are on the shuttle!" + hijack_objective.explanation_text = "Ensure only [usr.real_name] and [usr.p_their()] copies are on the shuttle!" to_chat(M, "Objective #[1]: [hijack_objective.explanation_text]") M.mind.special_role = SPECIAL_ROLE_MULTIVERSE log_game("[M.key] was made a multiverse traveller with the objective to help [usr.real_name] hijack.") @@ -350,7 +350,7 @@ var/global/list/multiverse = list() var/datum/objective/protect/new_objective = new /datum/objective/protect new_objective.owner = M.mind new_objective.target = usr.mind - new_objective.explanation_text = "Protect [usr.real_name], your copy, and help them defend the innocent from the mobs of multiverse clones." + new_objective.explanation_text = "Protect [usr.real_name], your copy, and help [usr.p_them()] defend the innocent from the mobs of multiverse clones." M.mind.objectives += new_objective to_chat(M, "Objective #[1]: [new_objective.explanation_text]") M.mind.special_role = SPECIAL_ROLE_MULTIVERSE @@ -429,7 +429,7 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(sword, slot_r_hand) //Don't duplicate what's equipped to hands, or else duplicate swords could be generated...or weird cases of factionless swords. else - if(M.get_species() == "Tajaran" || M.get_species() == "Unathi") + if(istajaran(M) || isunathi(M)) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) //If they can't wear shoes, give them a pair of sandals. var/randomize = pick("mobster","roman","wizard","cyborg","syndicate","assistant", "animu", "cultist", "highlander", "clown", "killer", "pirate", "soviet", "officer", "gladiator") @@ -461,7 +461,7 @@ var/global/list/multiverse = list() M.equip_to_slot_or_del(sword, slot_r_hand) if("cyborg") - if(M.get_species() != "Machine") + if(!ismachine(M)) for(var/obj/item/organ/O in M.bodyparts) O.robotize(make_tough = 1) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses) @@ -584,10 +584,10 @@ var/global/list/multiverse = list() W.SetOwnerInfo(M) M.equip_to_slot_or_del(W, slot_wear_id) - if(M.get_species() == "Vox") - M.species.after_equip_job(null, M) //Voxygen(tm) - if(M.get_species() == "Plasmaman") - M.species.after_equip_job(null, M) //No fireballs from other dimensions. + if(isvox(M)) + M.dna.species.after_equip_job(null, M) //Nitrogen tanks + if(isplasmaman(M)) + M.dna.species.after_equip_job(null, M) //No fireballs from other dimensions. M.update_icons() @@ -646,13 +646,13 @@ var/global/list/multiverse = list() if(heresy) spawnheresy(M)//oh god why else - M.set_species("Skeleton") + M.set_species(/datum/species/skeleton) M.visible_message(" A massive amount of flesh sloughs off [M] and a skeleton rises up!") M.revive() equip_skeleton(M) spooky_scaries |= M to_chat(M, "You have been revived by [user.real_name]!") - to_chat(M, "They are your master now, assist them even if it costs you your new life!") + to_chat(M, "[user.p_theyre(TRUE)] your master now, assist them even if it costs you your new life!") desc = "A shard capable of resurrecting humans as skeleton thralls[unlimited ? "." : ", [spooky_scaries.len]/3 active thralls."]" /obj/item/necromantic_stone/proc/check_spooky() @@ -713,7 +713,7 @@ var/global/list/multiverse = list() H.equip_to_slot_or_del(new /obj/item/twohanded/spear(H), slot_back) /obj/item/necromantic_stone/proc/spawnheresy(mob/living/carbon/human/H as mob) - H.set_species("Human") + H.set_species(/datum/species/human) if(H.gender == MALE) H.change_gender(FEMALE) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index cb303a90932..4bd7f3004d8 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -167,9 +167,9 @@ icon_state = "soulstone" name = initial(name) if(iswizard(usr) || usability) - to_chat(A, "You have been released from your prison, but you are still bound to [usr.real_name]'s will. Help them succeed in their goals at all costs.") + to_chat(A, "You have been released from your prison, but you are still bound to [usr.real_name]'s will. Help [usr.p_them()] succeed in [usr.p_their()] goals at all costs.") else if(iscultist(usr)) - to_chat(A, "You have been released from your prison, but you are still bound to the cult's will. Help them succeed in their goals at all costs.") + to_chat(A, "You have been released from your prison, but you are still bound to the cult's will. Help [usr.p_them()] succeed in [usr.p_their()] goals at all costs.") was_used() attack_self(U) @@ -280,7 +280,7 @@ ticker.mode.update_cult_icons_added(Z.mind) qdel(T) to_chat(Z, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike.") - to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") + to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") Z.cancel_camera() qdel(C) @@ -296,7 +296,7 @@ ticker.mode.update_cult_icons_added(Z.mind) qdel(T) to_chat(Z, "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.") - to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") + to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") Z.cancel_camera() qdel(C) @@ -312,7 +312,7 @@ ticker.mode.update_cult_icons_added(Z.mind) qdel(T) to_chat(Z, "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone).") - to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") + to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") Z.cancel_camera() qdel(C) else @@ -332,11 +332,11 @@ ticker.mode.cult+=newstruct.mind ticker.mode.update_cult_icons_added(newstruct.mind) if(stoner && iswizard(stoner)) - to_chat(newstruct, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") + to_chat(newstruct, "You are still bound to serve your creator, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") else if(stoner && iscultist(stoner)) - to_chat(newstruct, "You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.") + to_chat(newstruct, "You are still bound to serve the cult, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") else - to_chat(newstruct, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") + to_chat(newstruct, "You are still bound to serve your creator, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") newstruct.cancel_camera() /obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/U, vic = 0) @@ -362,11 +362,11 @@ name = "soulstone: Shade of [T.real_name]" icon_state = "soulstone2" if(U && iswizard(U)) - to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help them succeed in their goals at all costs.") + to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help [U.p_them()] succeed in their goals at all costs.") else if(U && iscultist(U)) - to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.") + to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help [U.p_them()] succeed in their goals at all costs.") if(vic && U) - to_chat(U, "Capture successful!: [T.real_name]'s soul has been ripped from their body and stored within the soul stone.") + to_chat(U, "Capture successful!: [T.real_name]'s soul has been ripped from [U.p_their()] body and stored within the soul stone.") /obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/U) var/mob/dead/observer/chosen_ghost diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 3294f1f3a0b..18dda0fcbc4 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -27,7 +27,7 @@ wizards += wizard modePlayer += wizard - wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. + wizard.assigned_role = SPECIAL_ROLE_WIZARD //So they aren't chosen for other jobs. wizard.special_role = SPECIAL_ROLE_WIZARD wizard.original = wizard.current if(wizardstart.len == 0) @@ -141,15 +141,10 @@ wizard_mob.equip_to_slot_or_del(new /obj/item/radio/headset(wizard_mob), slot_l_ear) wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), slot_w_uniform) wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes) - if(!wizard_mob.get_species() == "Plasmaman")//handled in the species file for plasmen on the afterjob equip proc for now + if(!isplasmaman(wizard_mob)) //handled in the species file for plasmen on the afterjob equip proc for now wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit) wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head) - if(wizard_mob.backbag == 2) - wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack(wizard_mob), slot_back) - if(wizard_mob.backbag == 3) - wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel_norm(wizard_mob), slot_back) - if(wizard_mob.backbag == 4) - wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(wizard_mob), slot_back) + wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(wizard_mob), slot_back) wizard_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival(wizard_mob), slot_in_backpack) wizard_mob.equip_to_slot_or_del(new /obj/item/teleportation_scroll(wizard_mob), slot_r_store) var/obj/item/spellbook/spellbook = new /obj/item/spellbook(wizard_mob) @@ -158,7 +153,7 @@ wizard_mob.faction = list("wizard") - wizard_mob.species.after_equip_job(null, wizard_mob) + wizard_mob.dna.species.after_equip_job(null, wizard_mob) to_chat(wizard_mob, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.") to_chat(wizard_mob, "The spellbook is bound to you, and others cannot use it.") diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index ffcb288c1c5..418539b5bed 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -74,12 +74,12 @@ if(!H) return 0 - H.species.before_equip_job(src, H, visualsOnly) + H.dna.species.before_equip_job(src, H, visualsOnly) if(outfit) H.equipOutfit(outfit, visualsOnly) - H.species.after_equip_job(src, H, visualsOnly) + H.dna.species.after_equip_job(src, H, visualsOnly) if(!visualsOnly && announce) announce(H) @@ -183,7 +183,7 @@ else permitted = TRUE - if(G.whitelisted && (G.whitelisted != H.species.name || !is_alien_whitelisted(H, G.whitelisted))) + if(G.whitelisted && (G.whitelisted != H.dna.species.name || !is_alien_whitelisted(H, G.whitelisted))) permitted = FALSE if(!permitted) diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index 154a34750cd..972b5732a9b 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -244,7 +244,7 @@ if(visualsOnly) return - if(H.get_species() == "Machine") + if(ismachine(H)) var/obj/item/organ/internal/cyberimp/brain/clown_voice/implant = new implant.insert(H) @@ -381,7 +381,6 @@ shoes = /obj/item/clothing/shoes/black l_ear = /obj/item/radio/headset/headset_service backpack_contents = list( - /obj/item/clothing/shoes/black = 1, /obj/item/storage/box/lip_stick = 1, /obj/item/storage/box/barber = 1 ) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 61c14efc2e5..0e315e03b2c 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -1,10 +1,6 @@ var/global/datum/controller/occupations/job_master -#define GET_RANDOM_JOB 0 -#define BE_ASSISTANT 1 -#define RETURN_TO_LOBBY 2 - /datum/controller/occupations //List of all jobs var/list/occupations = list() diff --git a/code/game/jobs/job_objective.dm b/code/game/jobs/job_objective.dm index 8860cdf4931..90bac6d8383 100644 --- a/code/game/jobs/job_objective.dm +++ b/code/game/jobs/job_objective.dm @@ -49,7 +49,7 @@ if(!employee.job_objectives.len)//If the employee had no objectives, don't need to process this. continue - if(!employee.assigned_role=="MODE")//If the employee is a gamemode thing, skip. + if(employee.assigned_role == employee.special_role) //If the character is an offstation character, skip them. continue var/tasks_completed=0 @@ -68,7 +68,7 @@ count++ if(tasks_completed >= 1) - text += "
 [employee.name] did their fucking job!" + text += "
 [employee.name] did [employee.p_their()] fucking job!" feedback_add_details("employee_success","SUCCESS") else feedback_add_details("employee_success","FAIL") diff --git a/code/game/jobs/job_scaling.dm b/code/game/jobs/job_scaling.dm new file mode 100644 index 00000000000..7d8804783f1 --- /dev/null +++ b/code/game/jobs/job_scaling.dm @@ -0,0 +1,11 @@ +/hook/roundstart/proc/jobscaling() + sleep(10 SECONDS) // give everyone time to finish spawning, and the lag to die down + var/playercount = length(clients) + var/highpop_trigger = 80 + + if(playercount >= highpop_trigger) + log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - loading highpop job config"); + job_master.LoadJobs("config/jobs_highpop.txt") + else + log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config"); + return 1 \ No newline at end of file diff --git a/code/game/machinery/Freezer.dm b/code/game/machinery/Freezer.dm index b065c87b8ab..dc06a13e076 100644 --- a/code/game/machinery/Freezer.dm +++ b/code/game/machinery/Freezer.dm @@ -57,9 +57,10 @@ if(exchange_parts(user, I)) return - default_deconstruction_crowbar(I) + if(default_deconstruction_crowbar(I)) + return - if(istype(I, /obj/item/wrench)) + if(iswrench(I)) if(!panel_open) to_chat(user, "Open the maintenance panel first.") return @@ -75,6 +76,8 @@ break build_network() update_icon() + else + return ..() /obj/machinery/atmospherics/unary/cold_sink/freezer/update_icon() if(panel_open) @@ -137,7 +140,11 @@ if(href_list["toggleStatus"]) src.on = !src.on update_icon() - if(href_list["temp"]) + else if(href_list["minimum"]) + current_temperature = min_temperature + else if(href_list["maximum"]) + current_temperature = T20C + else if(href_list["temp"]) var/amount = text2num(href_list["temp"]) if(amount > 0) src.current_temperature = min(T20C, src.current_temperature+amount) @@ -216,9 +223,10 @@ if(exchange_parts(user, I)) return - default_deconstruction_crowbar(I) + if(default_deconstruction_crowbar(I)) + return - if(istype(I, /obj/item/wrench)) + if(iswrench(I)) if(!panel_open) to_chat(user, "Open the maintenance panel first.") return @@ -234,6 +242,8 @@ break build_network() update_icon() + else + return ..() /obj/machinery/atmospherics/unary/heat_reservoir/heater/update_icon() if(panel_open) @@ -293,7 +303,11 @@ if(href_list["toggleStatus"]) src.on = !src.on update_icon() - if(href_list["temp"]) + else if(href_list["minimum"]) + current_temperature = T20C + else if(href_list["maximum"]) + current_temperature = max_temperature + T20C + else if(href_list["temp"]) var/amount = text2num(href_list["temp"]) if(amount > 0) src.current_temperature = min((T20C+max_temperature), src.current_temperature+amount) diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 3c9c27f1590..360d5cc5aff 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -54,13 +54,12 @@ if(prob(75)) qdel(src) -/obj/machinery/optable/attack_hand(mob/user as mob) - if(HULK in usr.mutations) - to_chat(usr, text("You destroy the table.")) - visible_message("[usr] destroys the operating table!") - src.density = 0 +/obj/machinery/optable/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + ..(user, TRUE) + visible_message("[user] destroys the operating table!") qdel(src) - return + return TRUE /obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height=0) if(height==0) return 1 @@ -143,19 +142,20 @@ take_victim(usr,usr) -/obj/machinery/optable/attackby(obj/item/W as obj, mob/living/carbon/user as mob, params) - if(istype(W, /obj/item/grab)) - if(iscarbon(W:affecting)) - take_victim(W:affecting,usr) - qdel(W) - return - if(istype(W, /obj/item/wrench)) - playsound(src.loc, W.usesound, 50, 1) - if(do_after(user, 20 * W.toolspeed, target = src)) +/obj/machinery/optable/attackby(obj/item/I, mob/living/carbon/user, params) + if(istype(I, /obj/item/grab)) + var/obj/item/grab/G = I + if(iscarbon(G.affecting)) + take_victim(G.affecting, user) + qdel(G) + if(iswrench(I)) + playsound(loc, I.usesound, 50, 1) + if(do_after(user, 20 * I.toolspeed, target = src)) to_chat(user, "You deconstruct the table.") new /obj/item/stack/sheet/plasteel(loc, 5) qdel(src) - + else + return ..() /obj/machinery/optable/proc/check_table(mob/living/carbon/patient as mob) if(src.victim && get_turf(victim) == get_turf(src) && victim.lying) diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index a90bc66bce3..f3701945017 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -43,19 +43,21 @@ QDEL_NULL(storedpda) return ..() -/obj/machinery/pdapainter/attackby(var/obj/item/O as obj, var/mob/user as mob, params) - if(istype(O, /obj/item/pda)) +/obj/machinery/pdapainter/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/pda)) if(storedpda) to_chat(user, "There is already a PDA inside.") return else - var/obj/item/pda/P = usr.get_active_hand() + var/obj/item/pda/P = user.get_active_hand() if(istype(P)) - user.drop_item() - storedpda = P - P.loc = src - P.add_fingerprint(usr) - update_icon() + if(user.drop_item()) + storedpda = P + P.forceMove(src) + P.add_fingerprint(user) + update_icon() + else + return ..() /obj/machinery/pdapainter/attack_hand(mob/user as mob) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 7d386ddfb1a..44ef4ee26da 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -11,7 +11,7 @@ var/base_icon = "sleeper" density = 1 anchored = 1 - dir = 8 + dir = WEST var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" var/mob/living/carbon/human/occupant = null var/possible_chems = list(list("epinephrine", "ether", "salbutamol", "styptic_powder", "silver_sulfadiazine"), @@ -92,15 +92,15 @@ if(filtering > 0) if(beaker) // To prevent runtimes from drawing blood from runtime, and to prevent getting IPC blood. - if(!istype(occupant) || !occupant.dna || (NO_BLOOD in occupant.species.species_traits)) + if(!istype(occupant) || !occupant.dna || (NO_BLOOD in occupant.dna.species.species_traits)) filtering = 0 return if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - src.occupant.transfer_blood_to(beaker, 1) - for(var/datum/reagent/x in src.occupant.reagents.reagent_list) - src.occupant.reagents.trans_to(beaker, 3) - src.occupant.transfer_blood_to(beaker, 1) + occupant.transfer_blood_to(beaker, 1) + for(var/datum/reagent/x in occupant.reagents.reagent_list) + occupant.reagents.trans_to(beaker, 3) + occupant.transfer_blood_to(beaker, 1) if(occupant) for(var/A in occupant.reagents.addiction_list) @@ -117,7 +117,7 @@ if(M == occupant) continue else - M.forceMove(src.loc) + M.forceMove(loc) updateDialog() return @@ -167,10 +167,10 @@ occupantData["maxTemp"] = 1000 // If you get a burning vox armalis into the sleeper, congratulations // Because we can put simple_animals in here, we need to do something tricky to get things working nice occupantData["temperatureSuitability"] = 0 // 0 is the baseline - if(ishuman(occupant) && occupant.species) + if(ishuman(occupant) && occupant.dna.species) // I wanna do something where the bar gets bluer as the temperature gets lower // For now, I'll just use the standard format for the temperature status - var/datum/species/sp = occupant.species + var/datum/species/sp = occupant.dna.species if(occupant.bodytemperature < sp.cold_level_3) occupantData["temperatureSuitability"] = -3 else if(occupant.bodytemperature < sp.cold_level_2) @@ -197,7 +197,7 @@ crisis = (occupant.health < min_health) // I'm not sure WHY you'd want to put a simple_animal in a sleeper, but precedent is precedent // Runtime is aptly named, isn't she? - if(ishuman(occupant) && !(NO_BLOOD in occupant.species.species_traits)) + if(ishuman(occupant) && !(NO_BLOOD in occupant.dna.species.species_traits)) occupantData["pulse"] = occupant.get_pulse(GETPULSE_TOOL) occupantData["hasBlood"] = 1 occupantData["bloodLevel"] = round(occupant.blood_volume) @@ -253,11 +253,11 @@ to_chat(usr, "Close the maintenance panel first.") return 0 - if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) + if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) if(href_list["chemical"]) if(occupant) if(occupant.stat == DEAD) - to_chat(usr, "This person has no life for to preserve anymore. Take them to a department capable of reanimating them.") + to_chat(usr, "This person has no life for to preserve anymore. Take [occupant.p_them()] to a department capable of reanimating them.") else if(occupant.health > min_health || (href_list["chemical"] in emergency_chems)) inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"])) else @@ -268,7 +268,7 @@ toggle_filter() if(href_list["ejectify"]) eject() - src.add_fingerprint(usr) + add_fingerprint(usr) return 1 /obj/machinery/sleeper/blob_act() @@ -280,83 +280,84 @@ return -/obj/machinery/sleeper/attackby(var/obj/item/G as obj, var/mob/user as mob, params) - if(istype(G, /obj/item/reagent_containers/glass)) +/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/reagent_containers/glass)) if(!beaker) if(!user.drop_item()) - to_chat(user, "\The [G] is stuck to you!") + to_chat(user, "[I] is stuck to you!") return - beaker = G - G.forceMove(src) - user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") + beaker = I + I.forceMove(src) + user.visible_message("[user] adds \a [I] to [src]!", "You add \a [I] to [src]!") return else to_chat(user, "The sleeper has a beaker already.") return - if(istype(G, /obj/item/screwdriver)) - if(src.occupant) + if(isscrewdriver(I)) + if(occupant) to_chat(user, "The maintenance panel is locked.") return - default_deconstruction_screwdriver(user, "[base_icon]-o", "[base_icon]-open", G) + default_deconstruction_screwdriver(user, "[base_icon]-o", "[base_icon]-open", I) return - if(istype(G, /obj/item/wrench)) - if(src.occupant) + if(iswrench(I)) + if(occupant) to_chat(user, "The scanner is occupied.") return if(panel_open) to_chat(user, "Close the maintenance panel first.") return - if(dir == 4) + if(dir == EAST) orient = "LEFT" - dir = 8 + setDir(WEST) else orient = "RIGHT" - dir = 4 - playsound(src.loc, G.usesound, 50, 1) + setDir(EAST) + playsound(loc, I.usesound, 50, 1) return - if(exchange_parts(user, G)) + if(exchange_parts(user, I)) return - if(istype(G, /obj/item/crowbar)) - default_deconstruction_crowbar(G) + if(default_deconstruction_crowbar(I)) return - if(istype(G, /obj/item/grab)) + if(istype(I, /obj/item/grab)) + var/obj/item/grab/G = I if(panel_open) to_chat(user, "Close the maintenance panel first.") return - if(!ismob(G:affecting)) + if(!ismob(G.affecting)) return - if(src.occupant) + if(occupant) to_chat(user, "The sleeper is already occupied!") return - for(var/mob/living/carbon/slime/M in range(1,G:affecting)) - if(M.Victim == G:affecting) - to_chat(usr, "[G:affecting.name] will not fit into the sleeper because they have a slime latched onto their head.") + for(var/mob/living/carbon/slime/M in range(1, G.affecting)) + if(M.Victim == G.affecting) + to_chat(user, "[G.affecting.name] will not fit into the sleeper because [G.affecting.p_they()] [G.affecting.p_have()] a slime latched onto [G.affecting.p_their()] head.") return - visible_message("[user] starts putting [G:affecting:name] into the sleeper.") + visible_message("[user] starts putting [G.affecting.name] into the sleeper.") - if(do_after(user, 20, target = G:affecting)) - if(src.occupant) + if(do_after(user, 20, target = G.affecting)) + if(occupant) to_chat(user, "The sleeper is already occupied!") return - if(!G || !G:affecting) return - var/mob/M = G:affecting + if(!G || !G.affecting) + return + var/mob/M = G.affecting M.forceMove(src) - src.occupant = M - src.icon_state = "[base_icon]" + occupant = M + icon_state = "[base_icon]" to_chat(M, "You feel cool air surround you. You go numb as your senses turn inward.") - - src.add_fingerprint(user) + add_fingerprint(user) qdel(G) - return - return + return + + return ..() /obj/machinery/sleeper/ex_act(severity) @@ -365,21 +366,21 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) A.ex_act(severity) qdel(src) return if(2.0) if(prob(50)) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) A.ex_act(severity) qdel(src) return if(3.0) if(prob(25)) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) A.ex_act(severity) qdel(src) return @@ -422,10 +423,10 @@ to_chat(user, "The sleeper does not offer that chemical!") return - if(src.occupant) - if(src.occupant.reagents) - if(src.occupant.reagents.get_reagent_amount(chemical) + amount <= max_chem) - src.occupant.reagents.add_reagent(chemical, amount) + if(occupant) + if(occupant.reagents) + if(occupant.reagents.get_reagent_amount(chemical) + amount <= max_chem) + occupant.reagents.add_reagent(chemical, amount) return else to_chat(user, "You can not inject any more of this chemical.") @@ -445,8 +446,8 @@ if(usr.incapacitated()) //are you cuffed, dying, lying, stunned or other return - src.icon_state = "[base_icon]-open" - src.go_out() + icon_state = "[base_icon]-open" + go_out() add_fingerprint(usr) return @@ -496,7 +497,7 @@ return for(var/mob/living/carbon/slime/M in range(1,L)) if(M.Victim == L) - to_chat(usr, "[L.name] will not fit into the sleeper because they have a slime latched onto their head.") + to_chat(usr, "[L.name] will not fit into the sleeper because [L.p_they()] [L.p_have()] a slime latched onto their head.") return if(L == user) visible_message("[user] starts climbing into the sleeper.") @@ -504,15 +505,15 @@ visible_message("[user] starts putting [L.name] into the sleeper.") if(do_after(user, 20, target = L)) - if(src.occupant) + if(occupant) to_chat(user, "The sleeper is already occupied!") return if(!L) return L.forceMove(src) - src.occupant = L - src.icon_state = "[base_icon]" + occupant = L + icon_state = "[base_icon]" to_chat(L, "You feel cool air surround you. You go numb as your senses turn inward.") - src.add_fingerprint(user) + add_fingerprint(user) if(user.pulling == L) user.stop_pulling() return @@ -527,7 +528,7 @@ set src in oview(1) if(usr.stat != 0 || !(ishuman(usr))) return - if(src.occupant) + if(occupant) to_chat(usr, "The sleeper is already occupied!") return if(panel_open) @@ -541,17 +542,17 @@ return visible_message("[usr] starts climbing into the sleeper.") if(do_after(usr, 20, target = usr)) - if(src.occupant) + if(occupant) to_chat(usr, "The sleeper is already occupied!") return usr.stop_pulling() usr.forceMove(src) - src.occupant = usr - src.icon_state = "[base_icon]" + occupant = usr + icon_state = "[base_icon]" for(var/obj/O in src) qdel(O) - src.add_fingerprint(usr) + add_fingerprint(usr) return return diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index f2dc8c8bfa2..2566cc0f410 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -2,9 +2,9 @@ name = "body scanner" icon = 'icons/obj/Cryogenic2.dmi' icon_state = "bodyscanner-open" - density = 1 - dir = 8 - anchored = 1 + density = TRUE + dir = WEST + anchored = TRUE idle_power_usage = 1250 active_power_usage = 2500 @@ -32,7 +32,7 @@ if(M == occupant) continue else - M.forceMove(src.loc) + M.forceMove(loc) /obj/machinery/bodyscanner/New() ..() @@ -54,37 +54,36 @@ component_parts += new /obj/item/stack/cable_coil(null, 2) RefreshParts() -/obj/machinery/bodyscanner/attackby(var/obj/item/G as obj, var/mob/user as mob) - if(istype(G, /obj/item/screwdriver)) - if(src.occupant) +/obj/machinery/bodyscanner/attackby(obj/item/I, mob/user) + if(isscrewdriver(I)) + if(occupant) to_chat(user, "The maintenance panel is locked.") return - default_deconstruction_screwdriver(user, "bodyscanner-o", "bodyscanner-open", G) + default_deconstruction_screwdriver(user, "bodyscanner-o", "bodyscanner-open", I) return - if(istype(G, /obj/item/wrench)) - if(src.occupant) + if(iswrench(I)) + if(occupant) to_chat(user, "The scanner is occupied.") return if(panel_open) to_chat(user, "Close the maintenance panel first.") return - if(dir == 4) - dir = 8 + if(dir == EAST) + setDir(WEST) else - dir = 4 - playsound(src.loc, G.usesound, 50, 1) + setDir(EAST) + playsound(loc, I.usesound, 50, 1) return - if(exchange_parts(user, G)) + if(exchange_parts(user, I)) return - if(istype(G, /obj/item/crowbar)) - default_deconstruction_crowbar(G) + if(default_deconstruction_crowbar(I)) return - if(istype(G, /obj/item/grab)) - var/obj/item/grab/TYPECAST_YOUR_SHIT = G + if(istype(I, /obj/item/grab)) + var/obj/item/grab/TYPECAST_YOUR_SHIT = I if(panel_open) to_chat(user, "Close the maintenance panel first.") return @@ -95,7 +94,7 @@ return for(var/mob/living/carbon/slime/M in range(1, TYPECAST_YOUR_SHIT.affecting)) if(M.Victim == TYPECAST_YOUR_SHIT.affecting) - to_chat(user, "[TYPECAST_YOUR_SHIT.affecting.name] has a fucking slime attached to them, deal with that first.") + to_chat(user, "[TYPECAST_YOUR_SHIT.affecting.name] has a fucking slime attached to [TYPECAST_YOUR_SHIT.affecting.p_them()], deal with that first.") return var/mob/M = TYPECAST_YOUR_SHIT.affecting if(M.abiotic()) @@ -105,7 +104,10 @@ occupant = M icon_state = "body_scanner_1" add_fingerprint(user) - qdel(G) + qdel(TYPECAST_YOUR_SHIT) + return + + return ..() /obj/machinery/bodyscanner/MouseDrop_T(mob/living/carbon/human/O, mob/user as mob) @@ -123,7 +125,7 @@ to_chat(user, "Close the maintenance panel first.") return 0 //panel open if(occupant) - to_chat(user, "\The [src] is already occupied.") + to_chat(user, "[src] is already occupied.") return 0 //occupied if(O.buckled) @@ -133,11 +135,11 @@ return 0 for(var/mob/living/carbon/slime/M in range(1, O)) if(M.Victim == O) - to_chat(user, "[O] has a fucking slime attached to them, deal with that first.") + to_chat(user, "[O] has a fucking slime attached to [O.p_them()], deal with that first.") return 0 if(O == user) - visible_message("[user] climbs into \the [src].") + visible_message("[user] climbs into [src].") else visible_message("[user] puts [O] into the body scanner.") @@ -175,21 +177,21 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) A.ex_act(severity) qdel(src) return if(2.0) if(prob(50)) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) A.ex_act(severity) qdel(src) return if(3.0) if(prob(25)) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) A.ex_act(severity) qdel(src) return @@ -220,7 +222,7 @@ icon_state = "bodyscannerconsole" density = 1 anchored = 1 - dir = 8 + dir = WEST idle_power_usage = 250 active_power_usage = 500 var/obj/machinery/bodyscanner/connected = null @@ -238,7 +240,7 @@ stat &= ~NOPOWER else spawn(rand(0, 15)) - src.icon_state = "bodyscannerconsole-p" + icon_state = "bodyscannerconsole-p" stat |= NOPOWER /obj/machinery/body_scanconsole/New() @@ -292,33 +294,35 @@ break -/obj/machinery/body_scanconsole/attackby(var/obj/item/G as obj, var/mob/user as mob, params) - if(istype(G, /obj/item/screwdriver)) - default_deconstruction_screwdriver(user, "bodyscannerconsole-p", "bodyscannerconsole", G) +/obj/machinery/body_scanconsole/attackby(obj/item/I, mob/user, params) + if(default_deconstruction_screwdriver(user, "bodyscannerconsole-p", "bodyscannerconsole", I)) return - if(istype(G, /obj/item/wrench)) + if(iswrench(I)) if(panel_open) to_chat(user, "Close the maintenance panel first.") return - if(dir == 4) - dir = 8 + if(dir == EAST) + setDir(WEST) else - dir = 4 - playsound(loc, G.usesound, 50, 1) + setDir(EAST) + playsound(loc, I.usesound, 50, 1) - if(exchange_parts(user, G)) + if(exchange_parts(user, I)) return - default_deconstruction_crowbar(G) + if(default_deconstruction_crowbar(I)) + return + else + return ..() -/obj/machinery/body_scanconsole/attack_ai(user as mob) +/obj/machinery/body_scanconsole/attack_ai(user) return attack_hand(user) -/obj/machinery/body_scanconsole/attack_ghost(user as mob) +/obj/machinery/body_scanconsole/attack_ghost(user) return attack_hand(user) -/obj/machinery/body_scanconsole/attack_hand(user as mob) +/obj/machinery/body_scanconsole/attack_hand(user) if(stat & (NOPOWER|BROKEN)) return @@ -326,13 +330,13 @@ to_chat(user, "Close the maintenance panel first.") return - if(!src.connected) + if(!connected) findscanner() ui_interact(user) -/obj/machinery/body_scanconsole/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/body_scanconsole/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "adv_med.tmpl", "Body Scanner", 690, 600) @@ -383,7 +387,7 @@ var/bloodData[0] bloodData["hasBlood"] = 0 - if(ishuman(H) && !(NO_BLOOD in H.species.species_traits)) + if(ishuman(H) && !(NO_BLOOD in H.dna.species.species_traits)) bloodData["hasBlood"] = 1 bloodData["volume"] = H.blood_volume bloodData["percent"] = round(((H.blood_volume / BLOOD_VOLUME_NORMAL)*100)) @@ -427,7 +431,7 @@ var/organStatus[0] if(E.status & ORGAN_BROKEN) organStatus["broken"] = E.broken_description - if(E.status & ORGAN_ROBOT) + if(E.is_robotic()) organStatus["robotic"] = 1 if(E.status & ORGAN_SPLINTED) organStatus["splinted"] = 1 @@ -456,7 +460,7 @@ organData["maxHealth"] = I.max_damage organData["bruised"] = I.min_broken_damage organData["broken"] = I.min_bruised_damage - organData["robotic"] = I.robotic + organData["robotic"] = I.is_robotic() organData["dead"] = (I.status & ORGAN_DEAD) intOrganData.Add(list(organData)) @@ -475,14 +479,14 @@ return 1 if(href_list["ejectify"]) - src.connected.eject() + connected.eject() if(href_list["print_p"]) generate_printing_text() if(!(printing) && printing_text) printing = 1 - visible_message("\The [src] rattles and prints out a sheet of paper.") + visible_message("[src] rattles and prints out a sheet of paper.") var/obj/item/paper/P = new /obj/item/paper(loc) playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1) P.info = "
Body Scan - [href_list["name"]]

" @@ -596,8 +600,8 @@ splint = "Splinted:" if(e.status & ORGAN_BROKEN) AN = "[e.broken_description]:" - if(e.status & ORGAN_ROBOT) - robot = "Prosthetic:" + if(e.is_robotic()) + robot = "Robotic:" if(e.open) open = "Open:" switch(e.germ_level) @@ -654,7 +658,7 @@ if(occupant.disabilities & NEARSIGHTED) dat += "Retinal misalignment detected.
" else - dat += "\The [src] is empty." + dat += "[src] is empty." else dat = " Error: No Body Scanner connected." diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index f9d83ff43f6..de32918c068 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -118,6 +118,8 @@ var/report_danger_level = 1 + var/automatic_emergency = 1 //Does the alarm automaticly respond to an emergency condition + /obj/machinery/alarm/monitor report_danger_level = 0 @@ -236,9 +238,11 @@ elect_master() /obj/machinery/alarm/proc/master_is_operating() - if(! alarm_area) + if(!alarm_area) alarm_area = areaMaster - + if(!alarm_area) + log_runtime(EXCEPTION("Air alarm /obj/machinery/alarm lacks alarm_area and areaMaster vars during proc/master_is_operating()"), src) + return FALSE return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN)) @@ -304,7 +308,7 @@ if(old_danger_level!=danger_level) apply_danger_level() - if(mode == AALARM_MODE_SCRUBBING && danger_level == ATMOS_ALARM_DANGER) + if(automatic_emergency && mode == AALARM_MODE_SCRUBBING && danger_level == ATMOS_ALARM_DANGER) if(pressure_dangerlevel == ATMOS_ALARM_DANGER) mode = AALARM_MODE_OFF if(temperature_dangerlevel == ATMOS_ALARM_DANGER && cur_tlv.max2 <= environment.temperature) @@ -969,31 +973,30 @@ playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1) return -/obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob, params) - src.add_fingerprint(user) +/obj/machinery/alarm/attackby(obj/item/I, mob/user, params) + add_fingerprint(user) switch(buildstage) if(2) - if(istype(W, /obj/item/screwdriver)) // Opening that Air Alarm up. -// to_chat(user, "You pop the Air Alarm's maintence panel open.") + if(isscrewdriver(I)) // Opening that Air Alarm up. wiresexposed = !wiresexposed to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") update_icon() return - if(istype(W, /obj/item/wirecutters)) // cutting the wires out + if(iswirecutter(I)) // cutting the wires out if(wires.wires_status == 31) // all wires cut var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil() new_coil.amount = 5 - new_coil.loc = user.loc + new_coil.forceMove(user.loc) buildstage = 1 update_icon() - return + return - if(wiresexposed && ((istype(W, /obj/item/multitool) || istype(W, /obj/item/wirecutters)))) + if(wiresexposed && ((ismultitool(I) || iswirecutter(I)))) return attack_hand(user) - if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))// trying to unlock the interface with an ID card + if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))// trying to unlock the interface with an ID card if(stat & (NOPOWER|BROKEN)) to_chat(user, "It does nothing") return @@ -1004,13 +1007,11 @@ updateUsrDialog() else to_chat(user, "Access denied.") - - - return + return if(1) - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W + if(istype(I, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = I if(coil.amount < 5) to_chat(user, "You need more cable for this!") return @@ -1026,34 +1027,35 @@ first_run() return - else if(istype(W, /obj/item/crowbar)) + else if(iscrowbar(I)) to_chat(user, "You start prying out the circuit.") - playsound(get_turf(src), W.usesound, 50, 1) - if(do_after(user, 20 * W.toolspeed, target = src)) + playsound(get_turf(src), I.usesound, 50, 1) + if(do_after(user, 20 * I.toolspeed, target = src)) if(buildstage != 1) return to_chat(user, "You pry out the circuit!") var/obj/item/airalarm_electronics/circuit = new /obj/item/airalarm_electronics() - circuit.loc = user.loc + circuit.forceMove(user.loc) buildstage = 0 update_icon() return if(0) - if(istype(W, /obj/item/airalarm_electronics)) + if(istype(I, /obj/item/airalarm_electronics)) to_chat(user, "You insert the circuit!") - playsound(get_turf(src), W.usesound, 50, 1) - qdel(W) + playsound(get_turf(src), I.usesound, 50, 1) + qdel(I) buildstage = 1 update_icon() return - else if(istype(W, /obj/item/wrench)) + else if(iswrench(I)) to_chat(user, "You remove the fire alarm assembly from the wall!") new /obj/item/mounted/frame/alarm_frame(get_turf(user)) - playsound(get_turf(src), W.usesound, 50, 1) + playsound(get_turf(src), I.usesound, 50, 1) qdel(src) + return - return 0 + return ..() /obj/machinery/alarm/power_change() if(powered(power_channel)) diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index b61d5513561..9ad575f74d7 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -338,6 +338,7 @@ update_flag ..() /obj/machinery/portable_atmospherics/canister/attackby(var/obj/item/W as obj, var/mob/user as mob, params) + user.changeNext_move(CLICK_CD_MELEE) if(iswelder(W) && src.destroyed) if(weld(W, user)) to_chat(user, "You salvage whats left of \the [src]") diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 0e9f261d73d..e555ee91ce8 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -6,15 +6,18 @@ use_power = 2 idle_power_usage = 5 active_power_usage = 10 - layer = 5 + layer = WALL_OBJ_LAYER + armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0) var/datum/wires/camera/wires = null // Wires datum + max_integrity = 100 + integrity_failure = 50 var/list/network = list("SS13") var/c_tag = null var/c_tag_order = 999 var/status = 1 - anchored = 1 - var/start_active = 0 //If it ignores the random chance to start broken on round start + anchored = TRUE + var/start_active = FALSE //If it ignores the random chance to start broken on round start var/invuln = null var/obj/item/camera_bug/bug = null var/obj/item/camera_assembly/assembly = null @@ -24,17 +27,14 @@ var/view_range = 7 var/short_range = 2 - var/light_disabled = 0 - var/alarm_on = 0 - var/busy = 0 - var/emped = 0 //Number of consecutive EMP's on this camera + var/busy = FALSE + var/emped = FALSE //Number of consecutive EMP's on this camera - var/toggle_message = 'sound/items/Wirecutter.ogg' + var/toggle_sound = 'sound/items/Wirecutter.ogg' /obj/machinery/camera/New() ..() wires = new(src) - assembly = new(src) assembly.state = 4 assembly.anchored = 1 @@ -46,14 +46,14 @@ /obj/machinery/camera/Initialize() ..() if(is_station_level(z) && prob(3) && !start_active) - toggle_cam() + toggle_cam(null, FALSE) wires.CutAll() /obj/machinery/camera/Destroy() - toggle_cam(null, 0) //kick anyone viewing out + toggle_cam(null, FALSE) //kick anyone viewing out QDEL_NULL(assembly) if(istype(bug)) - bug.bugged_cameras -= src.c_tag + bug.bugged_cameras -= c_tag if(bug.current == src) bug.current = null bug = null @@ -71,147 +71,124 @@ return if(!isEmpProof()) if(prob(150/severity)) - icon_state = "[initial(icon_state)]emp" + update_icon() var/list/previous_network = network network = list() cameranet.removeCamera(src) stat |= EMPED set_light(0) emped = emped+1 //Increase the number of consecutive EMP's + update_icon() var/thisemp = emped //Take note of which EMP this proc is for spawn(900) - if(loc) //qdel limbo + if(!QDELETED(src)) triggerCameraAlarm() //camera alarm triggers even if multiple EMPs are in effect. if(emped == thisemp) //Only fix it if the camera hasn't been EMP'd again network = previous_network - icon_state = initial(icon_state) stat &= ~EMPED - cancelCameraAlarm() + update_icon() if(can_use()) cameranet.addCamera(src) emped = 0 //Resets the consecutive EMP count spawn(100) if(!QDELETED(src)) cancelCameraAlarm() - for(var/mob/O in mob_list) - if(O.client && O.client.eye == src) - O.unset_machine() - O.reset_perspective(null) - to_chat(O, "The screen bursts into static.") + for(var/mob/M in player_list) + if(M.client && M.client.eye == src) + M.unset_machine() + M.reset_perspective(null) + to_chat(M, "The screen bursts into static.") ..() -/obj/machinery/camera/tesla_act(var/power)//EMP proof upgrade also makes it tesla immune +/obj/machinery/camera/tesla_act(power)//EMP proof upgrade also makes it tesla immune if(isEmpProof()) return ..() qdel(src)//to prevent bomb testing camera from exploding over and over forever -/obj/machinery/camera/ex_act(severity, target) - if(src.invuln) +/obj/machinery/camera/ex_act(severity) + if(invuln) return - else - ..() - return - -/obj/machinery/camera/blob_act() - qdel(src) - return - -/obj/machinery/camera/attack_ghost(mob/user) - if(panel_open) - wires.Interact(user) - -/obj/machinery/camera/attack_alien(mob/living/carbon/alien/humanoid/user) - if(!istype(user)) - return - user.do_attack_animation(src) - add_hiddenprint(user) - status = 0 - visible_message("\The [user] slashes at [src]!") - playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) - toggle_cam(user, 0) - + ..() /obj/machinery/camera/proc/setViewRange(num = 7) - src.view_range = num + view_range = num cameranet.updateVisibility(src, 0) -/obj/machinery/camera/attackby(obj/item/W, mob/living/user as mob, params) - var/msg = "You attach [W] into the assembly inner circuits." +/obj/machinery/camera/attackby(obj/item/I, mob/living/user, params) + var/msg = "You attach [I] into the assembly inner circuits." var/msg2 = "The camera already has that upgrade!" // DECONSTRUCTION - if(istype(W, /obj/item/screwdriver)) -// to_chat(user, "You start to [panel_open ? "close" : "open"] the camera's panel.") - //if(toggle_panel(user)) // No delay because no one likes screwdrivers trying to be hip and have a duration cooldown + if(isscrewdriver(I)) panel_open = !panel_open - user.visible_message("[user] screws the camera's panel [panel_open ? "open" : "closed"]!", - "You screw the camera's panel [panel_open ? "open" : "closed"].") - playsound(src.loc, W.usesound, 50, 1) + to_chat(user, "You screw the camera's panel [panel_open ? "open" : "closed"].") + playsound(loc, I.usesound, 50, 1) - else if((istype(W, /obj/item/wirecutters) || istype(W, /obj/item/multitool)) && panel_open) + else if((iswirecutter(I) || ismultitool(I)) && panel_open) wires.Interact(user) - else if(istype(W, /obj/item/weldingtool) && wires.CanDeconstruct()) - if(weld(W, user)) - to_chat(user, "You unweld the camera leaving it as just a frame screwed to the wall.") - if(!assembly) - assembly = new() - assembly.loc = src.loc - assembly.state = 1 - assembly.dir = src.dir - assembly.update_icon() - assembly = null - qdel(src) + else if(iswelder(I) && panel_open && wires.CanDeconstruct()) + var/obj/item/weldingtool/WT = I + if(!WT.remove_fuel(0, user)) return - else if(istype(W, /obj/item/analyzer) && panel_open) //XRay - if(!user.unEquip(W)) - to_chat(user, "[W] is stuck!") + to_chat(user, "You start to weld [src]...") + playsound(loc, WT.usesound, 50, 1) + if(do_after(user, 100 * WT.toolspeed, target = src)) + user.visible_message("[user] unwelds [src], leaving it as just a frame bolted to the wall.", + "You unweld [src], leaving it as just a frame bolted to the wall") + deconstruct(TRUE) + + else if(istype(I, /obj/item/analyzer) && panel_open) //XRay + if(!user.drop_item()) + to_chat(user, "[I] is stuck to your hand!") return if(!isXRay()) upgradeXRay() - qdel(W) + qdel(I) to_chat(user, "[msg]") else to_chat(user, "[msg2]") - else if(istype(W, /obj/item/stack/sheet/mineral/plasma) && panel_open) - if(!user.unEquip(W)) - to_chat(user, "[W] is stuck!") + else if(istype(I, /obj/item/stack/sheet/mineral/plasma) && panel_open) + if(!user.drop_item()) + to_chat(user, "[I] is stuck to your hand!") return if(!isEmpProof()) + var/obj/item/stack/sheet/mineral/plasma/P = I upgradeEmpProof() to_chat(user, "[msg]") - qdel(W) + P.use(1) else to_chat(user, "[msg2]") - else if(istype(W, /obj/item/assembly/prox_sensor) && panel_open) - if(!user.unEquip(W)) + else if(istype(I, /obj/item/assembly/prox_sensor) && panel_open) + if(!user.drop_item()) + to_chat(user, "[I] is stuck to your hand!") return if(!isMotion()) upgradeMotion() to_chat(user, "[msg]") - qdel(W) + qdel(I) else to_chat(user, "[msg2]") // OTHER - else if((istype(W, /obj/item/paper) || istype(W, /obj/item/pda)) && isliving(user)) + else if((istype(I, /obj/item/paper) || istype(I, /obj/item/pda)) && isliving(user)) var/mob/living/U = user var/obj/item/paper/X = null - var/obj/item/pda/P = null + var/obj/item/pda/PDA = null var/itemname = "" var/info = "" - if(istype(W, /obj/item/paper)) - X = W + if(istype(I, /obj/item/paper)) + X = I itemname = X.name info = X.info else - P = W - var/datum/data/pda/app/notekeeper/N = P.find_program(/datum/data/pda/app/notekeeper) + PDA = I + var/datum/data/pda/app/notekeeper/N = PDA.find_program(/datum/data/pda/app/notekeeper) if(N) - itemname = P.name + itemname = PDA.name info = N.notehtml to_chat(U, "You hold \the [itemname] up to the camera ...") U.changeNext_move(CLICK_CD_MELEE) @@ -229,37 +206,59 @@ to_chat(O, "[U] holds \a [itemname] up to one of the cameras ...") O << browse(text("[][]", itemname, info), text("window=[]", itemname)) - else if(istype(W, /obj/item/camera_bug)) - if(!src.can_use()) + else if(istype(I, /obj/item/camera_bug)) + if(!can_use()) to_chat(user, "Camera non-functional.") return - if(istype(src.bug)) + if(istype(bug)) to_chat(user, "Camera bug removed.") - src.bug.bugged_cameras -= src.c_tag - src.bug = null + bug.bugged_cameras -= c_tag + bug = null else to_chat(user, "Camera bugged.") - src.bug = W - src.bug.bugged_cameras[src.c_tag] = src + bug = I + bug.bugged_cameras[c_tag] = src - else if(istype(W, /obj/item/melee/energy/blade))//Putting it here last since it's a special case. I wonder if there is a better way to do these than type casting. - toggle_cam(user, 1) - var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() - spark_system.set_up(5, 0, loc) - spark_system.start() - playsound(loc, W.usesound, 50, 1) - playsound(loc, "sparks", 50, 1) - visible_message("[user] has sliced the camera apart with an energy blade!") - qdel(src) - - else if(istype(W, /obj/item/laser_pointer)) - var/obj/item/laser_pointer/L = W + else if(istype(I, /obj/item/laser_pointer)) + var/obj/item/laser_pointer/L = I L.laser_act(src, user) else - ..() - return + return ..() -/obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = 1) +/obj/machinery/camera/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) + if(damage_flag == "melee" && damage_amount < 12 && !(stat & BROKEN)) + return 0 + . = ..() + +/obj/machinery/camera/obj_break(damage_flag) + if(status) + triggerCameraAlarm() + toggle_cam(null, FALSE) + wires.CutAll() + +/obj/machinery/camera/deconstruct(disassembled = TRUE) + if(disassembled) + if(!assembly) + assembly = new() + assembly.forceMove(loc) + assembly.state = 1 + assembly.setDir(dir) + assembly.update_icon() + assembly = null + else + new /obj/item/camera_assembly(loc) + new /obj/item/stack/cable_coil(loc, 2) + qdel(src) + +/obj/machinery/camera/update_icon() + if(!status) + icon_state = "[initial(icon_state)]1" + else if(stat & EMPED) + icon_state = "[initial(icon_state)]emp" + else + icon_state = "[initial(icon_state)]" + +/obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = TRUE) status = !status if(can_use()) cameranet.addCamera(src) @@ -268,10 +267,7 @@ cameranet.removeCamera(src) cameranet.updateChunk(x, y, z) var/change_msg = "deactivates" - if(!status) - icon_state = "[initial(icon_state)]1" - else - icon_state = initial(icon_state) + if(status) change_msg = "reactivates" triggerCameraAlarm() spawn(100) @@ -284,7 +280,8 @@ else visible_message("\The [src] [change_msg]!") - playsound(src.loc, toggle_message, 100, 1) + playsound(loc, toggle_sound, 100, 1) + update_icon() // now disconnect anyone using the camera //Apparently, this will disconnect anyone even if the camera was re-activated. @@ -295,16 +292,11 @@ O.reset_perspective(null) to_chat(O, "The screen bursts into static.") -/obj/machinery/camera/proc/triggerCameraAlarm(var/duration = 0) - alarm_on = 1 - motion_alarm.triggerAlarm(loc, src) +/obj/machinery/camera/proc/triggerCameraAlarm() + camera_alarm.triggerAlarm(loc, src) /obj/machinery/camera/proc/cancelCameraAlarm() - if(wires.IsIndexCut(CAMERA_WIRE_ALARM)) - return - - alarm_on = 0 - motion_alarm.clearAlarm(loc, src) + camera_alarm.clearAlarm(loc, src) /obj/machinery/camera/proc/can_use() if(!status) @@ -331,25 +323,25 @@ //If someone knows a better way to do this, let me know. -Giacom switch(i) if(NORTH) - src.dir = SOUTH + setDir(SOUTH) if(SOUTH) - src.dir = NORTH + setDir(NORTH) if(WEST) - src.dir = EAST + setDir(EAST) if(EAST) - src.dir = WEST + setDir(WEST) break //Return a working camera that can see a given mob //or null if none -/proc/seen_by_camera(var/mob/M) +/proc/seen_by_camera(mob/M) for(var/obj/machinery/camera/C in oview(4, M)) if(C.can_use()) // check if camera disabled return C break return null -/proc/near_range_camera(var/mob/M) +/proc/near_range_camera(mob/M) for(var/obj/machinery/camera/C in range(4, M)) if(C.can_use()) // check if camera disabled return C @@ -357,32 +349,15 @@ return null -/obj/machinery/camera/proc/weld(var/obj/item/weldingtool/WT, var/mob/user) - if(busy) - return 0 - if(!WT.remove_fuel(0, user)) - return 0 - - to_chat(user, "You start to weld [src]...") - playsound(src.loc, WT.usesound, 50, 1) - busy = 1 - if(do_after(user, 100 * WT.toolspeed, target = src)) - busy = 0 - if(!WT.isOn()) - return 0 - return 1 - busy = 0 - return 0 - -/obj/machinery/camera/proc/Togglelight(on=0) +/obj/machinery/camera/proc/Togglelight(on = FALSE) for(var/mob/living/silicon/ai/A in ai_list) for(var/obj/machinery/camera/cam in A.lit_cameras) if(cam == src) return if(on) - src.set_light(AI_CAMERA_LUMINOSITY) + set_light(AI_CAMERA_LUMINOSITY) else - src.set_light(0) + set_light(0) /obj/machinery/camera/proc/nano_structure() var/cam[0] diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index dc5a0141b27..8baf02088bb 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -6,7 +6,8 @@ w_class = WEIGHT_CLASS_SMALL anchored = 0 materials = list(MAT_METAL=400, MAT_GLASS=250) - + max_integrity = 150 + can_be_hit = TRUE // Motion, EMP-Proof, X-Ray var/list/obj/item/possible_upgrades = list(/obj/item/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/analyzer) var/list/upgrades = list() @@ -24,13 +25,13 @@ QDEL_LIST(upgrades) return ..() -/obj/item/camera_assembly/attackby(obj/item/W, mob/living/user, params) +/obj/item/camera_assembly/attackby(obj/item/I, mob/living/user, params) switch(state) if(0) // State 0 - if(iswrench(W) && isturf(src.loc)) - playsound(src.loc, W.usesound, 50, 1) + if(iswrench(I) && isturf(loc)) + playsound(loc, I.usesound, 50, 1) to_chat(user, "You wrench the assembly into place.") anchored = 1 state = 1 @@ -40,15 +41,15 @@ if(1) // State 1 - if(iswelder(W)) - if(weld(W, user)) + if(iswelder(I)) + if(weld(I, user)) to_chat(user, "You weld the assembly securely into place.") anchored = 1 state = 2 return - else if(iswrench(W)) - playsound(src.loc, W.usesound, 50, 1) + else if(iswrench(I)) + playsound(loc, I.usesound, 50, 1) to_chat(user, "You unattach the assembly from it's place.") anchored = 0 update_icon() @@ -57,19 +58,18 @@ if(2) // State 2 - if(iscoil(W)) - var/obj/item/stack/cable_coil/C = W + if(iscoil(I)) + var/obj/item/stack/cable_coil/C = I if(C.use(2)) to_chat(user, "You add wires to the assembly.") - playsound(loc, W.usesound, 50, 1) + playsound(loc, I.usesound, 50, 1) state = 3 else to_chat(user, "You need 2 coils of wire to wire the assembly.") return - else if(iswelder(W)) - - if(weld(W, user)) + else if(iswelder(I)) + if(weld(I, user)) to_chat(user, "You unweld the assembly from it's place.") state = 1 anchored = 1 @@ -78,8 +78,8 @@ if(3) // State 3 - if(isscrewdriver(W)) - playsound(src.loc, W.usesound, 50, 1) + if(isscrewdriver(I)) + playsound(loc, I.usesound, 50, 1) var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? Seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")) if(!input) @@ -96,8 +96,8 @@ input = strip_html(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag)) state = 4 - var/obj/machinery/camera/C = new(src.loc) - src.loc = C + var/obj/machinery/camera/C = new(loc) + loc = C C.assembly = src C.auto_turn() @@ -119,35 +119,36 @@ break return - else if(iswirecutter(W)) + else if(iswirecutter(I)) new/obj/item/stack/cable_coil(get_turf(src), 2) - playsound(src.loc, W.usesound, 50, 1) + playsound(loc, I.usesound, 50, 1) to_chat(user, "You cut the wires from the circuits.") state = 2 return // Upgrades! - if(is_type_in_list(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. - if(!user.unEquip(W)) - to_chat(user, "[W] is stuck!") + if(is_type_in_list(I, possible_upgrades) && !is_type_in_list(I, upgrades)) // Is a possible upgrade and isn't in the camera already. + if(!user.unEquip(I)) + to_chat(user, "[I] is stuck!") return - to_chat(user, "You attach \the [W] into the assembly inner circuits.") - upgrades += W + to_chat(user, "You attach [I] into the assembly inner circuits.") + upgrades += I user.drop_item() - W.loc = src + I.loc = src return // Taking out upgrades - else if(iscrowbar(W) && upgrades.len) + else if(iscrowbar(I) && upgrades.len) var/obj/U = locate(/obj) in upgrades if(U) to_chat(user, "You unattach an upgrade from the assembly.") - playsound(src.loc, W.usesound, 50, 1) + playsound(loc, I.usesound, 50, 1) U.loc = get_turf(src) upgrades -= U return - ..() + else + return ..() /obj/item/camera_assembly/update_icon() if(anchored) @@ -159,7 +160,7 @@ if(!anchored) ..() -/obj/item/camera_assembly/proc/weld(var/obj/item/weldingtool/WT, var/mob/living/user) +/obj/item/camera_assembly/proc/weld(obj/item/weldingtool/WT, mob/living/user) if(busy) return 0 @@ -167,7 +168,7 @@ return 0 to_chat(user, "You start to weld the [src]..") - playsound(src.loc, WT.usesound, 50, 1) + playsound(loc, WT.usesound, 50, 1) busy = 1 if(do_after(user, 20 * WT.toolspeed, target = src)) busy = 0 @@ -176,3 +177,7 @@ return 1 busy = 0 return 0 + +/obj/item/camera_assembly/deconstruct(disassembled = TRUE) + new /obj/item/stack/sheet/metal(loc) + qdel(src) \ No newline at end of file diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index b7edd86b1af..6b728f2a20b 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -36,8 +36,8 @@ if(charging) to_chat(user, "Current charge: [round(charging.percent(), 1)]%") -/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/stock_parts/cell)) +/obj/machinery/cell_charger/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/stock_parts/cell)) if(stat & BROKEN) to_chat(user, "[src] is broken!") return @@ -57,25 +57,25 @@ if(!user.drop_item()) return - W.forceMove(src) - charging = W + I.forceMove(src) + charging = I user.visible_message("[user] inserts a cell into the charger.", "You insert a cell into the charger.") chargelevel = -1 updateicon() - else if(iswrench(W)) + else if(iswrench(I)) if(charging) to_chat(user, "Remove the cell first!") return anchored = !anchored to_chat(user, "You [anchored ? "attach" : "detach"] the cell charger [anchored ? "to" : "from"] the ground") - playsound(src.loc, W.usesound, 75, 1) + playsound(src.loc, I.usesound, 75, 1) else return ..() /obj/machinery/cell_charger/proc/removecell() - charging.updateicon() + charging.update_icon() charging = null chargelevel = -1 updateicon() diff --git a/code/game/machinery/chiller.dm b/code/game/machinery/chiller.dm index 4fae326fd6c..d2f76a7c42a 100644 --- a/code/game/machinery/chiller.dm +++ b/code/game/machinery/chiller.dm @@ -68,8 +68,8 @@ user << browse(null, "window=aircond") user.unset_machine() else - ..() - return + return ..() + /obj/machinery/space_heater/air_conditioner/attack_hand(mob/user as mob) src.add_fingerprint(user) interact(user) @@ -120,7 +120,7 @@ if("cellremove") if(open && cell && !usr.get_active_hand()) - cell.updateicon() + cell.update_icon() usr.put_in_hands(cell) cell.add_fingerprint(usr) cell = null diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index ee53fdbce8b..798a01f2bda 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -231,7 +231,7 @@ R.dna = new /datum/dna() var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) - H.set_species(R.dna.species) + H.set_species(R.dna.species.type) occupant = H if(!R.dna.real_name) //to prevent null names @@ -349,19 +349,19 @@ use_power(200) //Let's unlock this early I guess. Might be too early, needs tweaking. -/obj/machinery/clonepod/attackby(obj/item/W, mob/user, params) +/obj/machinery/clonepod/attackby(obj/item/I, mob/user, params) if(!(occupant || mess)) - if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", W)) + if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I)) return - if(exchange_parts(user, W)) + if(exchange_parts(user, I)) return - if(default_deconstruction_crowbar(W)) + if(default_deconstruction_crowbar(I)) return - if(W.GetID()) - if(!check_access(W)) + if(I.GetID()) + if(!check_access(I)) to_chat(user, "Access Denied.") return if(!(occupant || mess)) @@ -374,34 +374,33 @@ go_out() //Removing cloning pod biomass - else if(istype(W, /obj/item/reagent_containers/food/snacks/meat)) - to_chat(user, "\The [src] processes \the [W].") - biomass += BIOMASS_MEAT_AMOUNT - user.drop_item() - qdel(W) - return - else if(istype(W, /obj/item/wrench)) + else if(istype(I, /obj/item/reagent_containers/food/snacks/meat)) + if(user.drop_item()) + to_chat(user, "[src] processes [I].") + biomass += BIOMASS_MEAT_AMOUNT + qdel(I) + else if(iswrench(I)) if(occupant) to_chat(user, "Can not do that while [src] is in use.") else if(anchored) - anchored = 0 + anchored = FALSE connected.pods -= src connected = null else - anchored = 1 - playsound(loc, W.usesound, 100, 1) + anchored = TRUE + playsound(loc, I.usesound, 100, 1) if(anchored) user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.") else user.visible_message("[user] unsecures [src] from the floor.", "You unsecure [src] from the floor.") - else if(istype(W, /obj/item/multitool)) - var/obj/item/multitool/M = W + else if(ismultitool(I)) + var/obj/item/multitool/M = I M.buffer = src to_chat(user, "You load connection data from [src] to [M].") return else - ..() + return ..() /obj/machinery/clonepod/emag_act(user) if(isnull(occupant)) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 42061760d92..00bd309b21e 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -123,8 +123,8 @@ occupantData["maxTemp"] = 1000 // If you get a burning vox armalis into the sleeper, congratulations // Because we can put simple_animals in here, we need to do something tricky to get things working nice occupantData["temperatureSuitability"] = 0 // 0 is the baseline - if(ishuman(occupant) && occupant.species) - var/datum/species/sp = occupant.species + if(ishuman(occupant) && occupant.dna.species) + var/datum/species/sp = occupant.dna.species if(occupant.bodytemperature < sp.cold_level_3) occupantData["temperatureSuitability"] = -3 else if(occupant.bodytemperature < sp.cold_level_2) @@ -147,7 +147,7 @@ occupantData["btCelsius"] = occupant.bodytemperature - T0C occupantData["btFaren"] = ((occupant.bodytemperature - T0C) * (9.0/5.0))+ 32 - if(ishuman(occupant) && !(NO_BLOOD in occupant.species.species_traits)) + if(ishuman(occupant) && !(NO_BLOOD in occupant.dna.species.species_traits)) occupantData["pulse"] = occupant.get_pulse(GETPULSE_TOOL) occupantData["hasBlood"] = 1 occupantData["bloodLevel"] = round(occupant.blood_volume) diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 2b3c338fa3d..67f1dba85f0 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -117,7 +117,7 @@ return laws = M.laws - if(istype(P, /obj/item/mmi) || istype(P, /obj/item/mmi/posibrain)) + if(istype(P, /obj/item/mmi)) if(!P:brainmob) to_chat(user, "Sticking an empty [P] into the frame would sort of defeat the purpose.") return diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 1e207e3bdde..eebae34b9ea 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -814,7 +814,7 @@ if(ORION_TRAIL_SPACEPORT) if(spaceport_raided) - eventdat += "The Spaceport is on high alert! they wont let you dock since you tried to attack them!" + eventdat += "The Spaceport is on high alert! They wont let you dock since you tried to attack them!" if(last_spaceport_action) eventdat += "
Last Spaceport Action: [last_spaceport_action]" eventdat += "

Depart Spaceport

" diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index cf94e35f1cf..30ccb23b467 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -362,7 +362,7 @@ /obj/item/circuitboard/rdconsole/attackby(obj/item/I as obj, mob/user as mob, params) if(istype(I,/obj/item/card/id)||istype(I, /obj/item/pda)) if(allowed(user)) - user.visible_message("\the [user] waves their ID past the [src]'s access protocol scanner.", "You swipe your ID past the [src]'s access protocol scanner.") + user.visible_message("\the [user] waves [user.p_their()] ID past the [src]'s access protocol scanner.", "You swipe your ID past the [src]'s access protocol scanner.") var/console_choice = input(user, "What do you want to configure the access to?", "Access Modification", "R&D Core") as null|anything in access_types if(console_choice == null) return diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 2195ee25522..99eaeae3fe6 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -8,16 +8,40 @@ var/list/networks = list("SS13") var/datum/action/innate/camera_off/off_action = new var/datum/action/innate/camera_jump/jump_action = new + var/list/actions = list() /obj/machinery/computer/camera_advanced/proc/CreateEye() eyeobj = new() eyeobj.origin = src -/obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/carbon/user) - off_action.target = user - off_action.Grant(user) - jump_action.target = user - jump_action.Grant(user) +/obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/user) + if(off_action) + off_action.target = user + off_action.Grant(user) + actions += off_action + + if(jump_action) + jump_action.target = user + jump_action.Grant(user) + actions += jump_action + +/obj/machinery/computer/camera_advanced/proc/remove_eye_control(mob/living/user) + if(!user) + return + for(var/V in actions) + var/datum/action/A = V + A.Remove(user) + actions.Cut() + if(user.client) + user.reset_perspective(null) + eyeobj.RemoveImages() + eyeobj.eye_user = null + user.remote_control = null + user.remote_view = FALSE + + current_user = null + user.unset_machine() + playsound(src, 'sound/machines/terminal_off.ogg', 25, 0) /obj/machinery/computer/camera_advanced/check_eye(mob/user) if((stat & (NOPOWER|BROKEN)) || !Adjacent(user) || !user.has_vision() || user.incapacitated()) @@ -29,11 +53,12 @@ if(current_user) current_user.unset_machine() QDEL_NULL(eyeobj) + QDEL_LIST(actions) return ..() /obj/machinery/computer/camera_advanced/on_unset_machine(mob/M) if(M == current_user) - off_action.Activate() + remove_eye_control(M) /obj/machinery/computer/camera_advanced/attack_hand(mob/user) if(current_user) @@ -95,6 +120,13 @@ origin = null return ..() +/mob/camera/aiEye/remote/RemoveImages() + ..() + if(visible_icon) + var/client/C = GetViewerClient() + if(C) + C.images -= user_image + /mob/camera/aiEye/remote/GetViewerClient() if(eye_user) return eye_user.client @@ -140,20 +172,8 @@ return var/mob/living/carbon/C = target var/mob/camera/aiEye/remote/remote_eye = C.remote_control - C.remote_view = 0 - remote_eye.origin.current_user = null - remote_eye.origin.jump_action.Remove(C) - remote_eye.eye_user = null - if(C.client) - C.reset_perspective(null) - if(remote_eye.visible_icon) - C.client.images -= remote_eye.user_image - for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks) - C.client.images -= chunk.obscured - C.remote_control = null - C.unset_machine() - src.Remove(C) - playsound(remote_eye.origin, 'sound/machines/terminal_off.ogg', 25, 0) + var/obj/machinery/computer/camera_advanced/console = remote_eye.origin + console.remove_eye_control(target) /datum/action/innate/camera_jump name = "Jump To Camera" diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 95aee7cb9fe..c134747cd41 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -356,15 +356,14 @@ return if(scan_brain && !can_brainscan()) return - if((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna) || (NO_SCAN in subject.species.species_traits)) + if((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna) || (NO_SCAN in subject.dna.species.species_traits)) scantemp = "Error: Unable to locate valid genetic data." SSnanoui.update_uis(src) return if(subject.get_int_organ(/obj/item/organ/internal/brain)) var/obj/item/organ/internal/brain/Brn = subject.get_int_organ(/obj/item/organ/internal/brain) if(istype(Brn)) - var/datum/species/S = all_species[Brn.dna.species] // stepladder code wooooo - if(NO_SCAN in S.species_traits) + if(NO_SCAN in Brn.dna.species.species_traits) scantemp = "Error: Subject's brain is incompatible." SSnanoui.update_uis(src) return @@ -402,10 +401,9 @@ var/obj/item/organ/B = subject.get_int_organ(/obj/item/organ/internal/brain) B.dna.check_integrity() R.dna=B.dna.Clone() - var/datum/species/S = all_species[R.dna.species] - if(NO_SCAN in S.species_traits) + if(NO_SCAN in R.dna.species.species_traits) extra_info = "Proper genetic interface not found, defaulting to genetic data of the body." - R.dna.species = subject.species.name + R.dna.species = new subject.dna.species.type R.id= copytext(md5(B.dna.real_name), 2, 6) R.name=B.dna.real_name else diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index fa582362308..865f683946e 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -231,7 +231,7 @@ to_chat(usr, "Arrays recycling. Please stand by.") SSnanoui.update_uis(src) return - var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","") as text|null + var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) SSnanoui.update_uis(src) return @@ -250,7 +250,7 @@ to_chat(usr, "Arrays recycling. Please stand by.") SSnanoui.update_uis(src) return - var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") as text|null + var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) SSnanoui.update_uis(src) return @@ -270,7 +270,7 @@ to_chat(usr, "Arrays recycling. Please stand by.") SSnanoui.update_uis(src) return - var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") as text|null + var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) SSnanoui.update_uis(src) return @@ -528,7 +528,8 @@ if("alert") status_signal.data["picture_state"] = data1 - frequency.post_signal(src, status_signal) + spawn(0) + frequency.post_signal(src, status_signal) /obj/machinery/computer/communications/Destroy() diff --git a/code/game/machinery/computer/hologram.dm b/code/game/machinery/computer/hologram.dm deleted file mode 100644 index 2d2e5d37ae0..00000000000 --- a/code/game/machinery/computer/hologram.dm +++ /dev/null @@ -1,118 +0,0 @@ -/obj/machinery/computer/hologram_comp - name = "hologram computer" - desc = "Rumoured to control holograms." - icon = 'icons/obj/stationobjs.dmi' - icon_keyboard = "tech_key" - icon_screen = "holocontrol" - var/obj/machinery/hologram/projector/projector = null - var/temp = null - var/lumens = 0.0 - var/h_r = 245.0 - var/h_g = 245.0 - var/h_b = 245.0 - - -/obj/machinery/computer/hologram_comp/New() - ..() - spawn( 10 ) - src.projector = locate(/obj/machinery/hologram/projector, get_step(src.loc, NORTH)) - return - return - -/obj/machinery/computer/hologram_comp/attack_hand() - if(!in_range(src, usr)) - return 0 - src.show_console(usr) - return - -/obj/machinery/computer/hologram_comp/proc/render() - var/icon/I = new /icon('icons/mob/human.dmi', "body_m_s") - - if(src.lumens >= 0) - I.Blend(rgb(src.lumens, src.lumens, src.lumens), ICON_ADD) - else - I.Blend(rgb(- src.lumens, -src.lumens, -src.lumens), ICON_SUBTRACT) - - I.Blend(new /icon('icons/mob/human.dmi', "mouth_m_s"), ICON_OVERLAY) - I.Blend(new /icon('icons/mob/underwear.dmi', "Mens White"), ICON_OVERLAY) - - var/icon/U = new /icon('icons/mob/human_face.dmi', "hair_a_s") - U.Blend(rgb(src.h_r, src.h_g, src.h_b), ICON_ADD) - - I.Blend(U, ICON_OVERLAY) - - src.projector.hologram.icon = I - -/obj/machinery/computer/hologram_comp/proc/show_console(var/mob/user as mob) - var/dat - user.set_machine(src) - if(src.temp) - dat = text("[]

Clear", src.temp) - else - dat = text({"Hologram Status:
\n - Power: []
\n - Hologram Control:
\n - Color Luminosity: []/220 \[Reset\]
\n - Lighten: 1 10
\n - Darken: 1 10
\n -
\nHair Color: ([],[],[]) \[Reset\]
\n - Red (0-255): \[0\] -10 -1 [] 1 10 \[255\]
\n - Green (0-255): \[0\] -10 -1 [] 1 10 \[255\]
\n - Blue (0-255): \[0\] -10 -1 [] 1 10 \[255\]
- "}, (src.projector.hologram ? "On" : "Off"), -src.lumens + 35, src.h_r, src.h_g, src.h_b, src.h_r, src.h_g, src.h_b) - user << browse(dat, "window=hologram_console") - onclose(user, "hologram_console") - return - -/obj/machinery/computer/hologram_comp/Topic(href, href_list) - if(..()) - return 1 - if(in_range(src, usr)) - flick("holo_console1", src) - if(href_list["power"]) - if(src.projector.hologram) - src.projector.icon_state = "hologram0" - //src.projector.hologram = null - qdel(src.projector.hologram) - else - src.projector.hologram = new(src.projector.loc) - src.projector.hologram.icon = 'icons/mob/human.dmi' - src.projector.hologram.icon_state = "body_m_s" - src.projector.icon_state = "hologram1" - src.render() - else - if(href_list["h_r"]) - if(src.projector.hologram) - src.h_r += text2num(href_list["h_r"]) - src.h_r = min(max(src.h_r, 0), 255) - render() - else - if(href_list["h_g"]) - if(src.projector.hologram) - src.h_g += text2num(href_list["h_g"]) - src.h_g = min(max(src.h_g, 0), 255) - render() - else - if(href_list["h_b"]) - if(src.projector.hologram) - src.h_b += text2num(href_list["h_b"]) - src.h_b = min(max(src.h_b, 0), 255) - render() - else - if(href_list["light"]) - if(src.projector.hologram) - src.lumens += text2num(href_list["light"]) - src.lumens = min(max(src.lumens, -185.0), 35) - render() - else - if(href_list["reset"]) - if(src.projector.hologram) - src.lumens = 0 - render() - else - if(href_list["temp"]) - src.temp = null - for(var/mob/M in viewers(1, src)) - if((M.client && M.machine == src)) - src.show_console(M) - return diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 8bdc6b87243..bcbe7a07e5d 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -22,7 +22,7 @@ var/defaultmsg = "Welcome. Please select an option." var/rebootmsg = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" //Computer properties - var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message, 4 = chat room selection, 5 = chat room logs + var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message var/hacking = 0 // Is it being hacked into by the AI/Cyborg var/emag = 0 // When it is emagged. var/message = "System bootup complete. Please select an option." // The message that shows on the main menu. @@ -33,7 +33,6 @@ var/obj/item/pda/customrecepient = null var/customjob = "Admin" var/custommessage = "This is a test, please ignore." - var/datum/chatroom/current_chatroom = null light_color = LIGHT_COLOR_DARKGREEN @@ -129,7 +128,6 @@ dat += "
[++i]. Clear Request Console Logs
" dat += "
[++i]. Set Custom Key
" dat += "
[++i]. Send Admin Message
" - dat += "
[++i]. View Chatrooms
" else for(var/n = ++i; n <= optioncount; n++) dat += "
[n]. ---------------
" @@ -247,42 +245,6 @@ dat += {"
X
[rc.send_dpt] [rc.rec_dpt][rc.message][rc.stamp][rc.id_auth][rc.priority]"} dat += "" - //Chat room list - if(5) - dat += "
Back - Refresh

" - dat += {" - - - - - - "} - for(var/datum/chatroom/C in chatrooms) - var/list/invites = (C.invites - C.users) - dat += {" - - - - - "} - dat += "
Room NameUsersInvitesMessages
[C.name][C.users.len][invites.len][C.logs.len]
" - //View chat room logs - if(6) - dat += "
Back - Refresh

" - dat += {" - - - - "} - if(current_chatroom) - for(var/M in current_chatroom.logs) - var/list/message = M - dat += {" - - - "} - dat += "
NameMessage
[message["username"]][message["message"]]
" - dat += "" message = defaultmsg user << browse(dat, "window=message;size=700x700") @@ -520,19 +482,6 @@ if(href_list["back"]) src.screen = 0 - // View chat room list - if(href_list["chatroom"]) - if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else if(auth) - screen = 5 - if(href_list["viewroom"]) - if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else if(auth) - current_chatroom = locate(href_list["viewroom"]) - if(current_chatroom) - screen = 6 return src.attack_hand(usr) diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 98d14c8ac30..4cbf105c100 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -205,8 +205,8 @@ if(href_list["dstele"]) var/choices = list(0) var/list/reachable_levels = levels_by_trait(REACHABLE) - for(var/datum/space_level/S in reachable_levels) - choices += S.zpos + for(var/z in reachable_levels) + choices += z var/obj/machinery/computer/pod/deathsquad/D = src var/input = input("Enter the destination Z-Level. The mechs will arrive from the East. Leave 0 if you don't want to set a specific ZLevel", "Mass Driver Controls", 0) in choices D.teleporter_dest = input diff --git a/code/game/machinery/computer/store.dm b/code/game/machinery/computer/store.dm index dcdb4b1134e..bfa2820d9b3 100644 --- a/code/game/machinery/computer/store.dm +++ b/code/game/machinery/computer/store.dm @@ -13,7 +13,6 @@ /obj/machinery/computer/merch/New() ..() - /obj/machinery/computer/merch/attack_ai(mob/user as mob) src.add_hiddenprint(user) return attack_hand(user) @@ -43,43 +42,49 @@ html { color:#999; } +table {background:#303030;border:1px solid #262626;} + +caption {text-align:left;} + +.button { + color:#cfcfcf; + text-decoration:none; + font-weight:bold; + text-align:center; + width:75px; + padding:21px; + box-sizing:border-box; + background:none; + border:none; + display: inline-block; +} +.button:hover {color:#ffffff;} + a { color:#cfcfcf; text-decoration:none; font-weight:bold; } +a:hover {color:#ffffff;} -a:hover { - color:#ffffff; -} -tr { - background:#303030; - border-radius:6px; - margin-bottom:0.5em; - border-bottom:1px solid black; -} -tr:nth-child(even) { - background:#3f3f3f; -} +p {margin:0;} -td.cost { - font-size:20pt; - font-weight:bold; -} +tr.dark {background:#303030;} -td.cost.affordable { - background:green; -} +tr.light {background:#3f3f3f;} -td.cost.toomuch { - background:maroon; -} +td,th {padding:15px;border-bottom:1px solid #262626;} +th.cost {padding:0px;border-left:1px solid #262626;} + +th.cost.affordable {background:green;} + +th.cost.toomuch {background:maroon;} -

Refresh | Balance: $[balance]

+

Refresh | Balance: $[balance]

[command_name()] Merchandise

Doing your job and not getting any recognition at work? Well, welcome to the @@ -87,8 +92,9 @@ td.cost.toomuch { completed your Job Objectives.

Work hard. Get cash. Acquire bragging rights.

-

In Stock:

+
+ @@ -101,8 +107,11 @@ td.cost.toomuch { if(item.cost>balance) cost_class="toomuch" var/itemID=centcomm_store.items.Find(item) + var/row_color="light" + if(itemID%2 == 0) + row_color="dark" dat += {" - + @@ -110,9 +119,9 @@ td.cost.toomuch {

[item.name]

[item.desc]

- + "} dat += {" @@ -120,7 +129,7 @@ td.cost.toomuch {
In Stock:
# Name/Description
[itemID] - $[item.cost] - + $[item.cost] +
"} - user << browse(dat, "window=merch") + user << browse(dat, "window=merch;size=440x600;can_resize=0") onclose(user, "merch") return @@ -142,6 +151,6 @@ td.cost.toomuch { if(!centcomm_store.PlaceOrder(usr,itemID)) to_chat(usr, "Unable to charge your account.") else - to_chat(usr, "You've successfully purchased the item. It should be in your hands or on the floor.") + to_chat(usr, "You've successfully purchased the item. It should be in your hands or on the floor.") src.updateUsrDialog() return diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 63d5c9811b4..2cf9de49571 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -108,13 +108,14 @@ return for(var/mob/living/carbon/slime/M in range(1,L)) if(M.Victim == L) - to_chat(usr, "[L.name] will not fit into the cryo cell because they have a slime latched onto their head.") + to_chat(usr, "[L.name] will not fit into the cryo cell because [L.p_they()] [L.p_have()] a slime latched onto [L.p_their()] head.") return if(put_mob(L)) if(L == user) visible_message("[user] climbs into the cryo cell.") else visible_message("[user] puts [L.name] into the cryo cell.") + add_attack_logs(user, L, "put into a cryo cell at [COORD(src)].", ATKLOG_ALL) if(user.pulling == L) user.stop_pulling() @@ -262,6 +263,7 @@ if(href_list["ejectOccupant"]) if(!occupant || isslime(usr) || ispAI(usr)) return 0 // don't update UIs attached to this object + add_attack_logs(usr, occupant, "ejected from cryo cell at [COORD(src)]", ATKLOG_ALL) go_out() add_fingerprint(usr) @@ -269,16 +271,18 @@ /obj/machinery/atmospherics/unary/cryo_cell/attackby(var/obj/item/G as obj, var/mob/user as mob, params) if(istype(G, /obj/item/reagent_containers/glass)) + var/obj/item/reagent_containers/B = G if(beaker) to_chat(user, "A beaker is already loaded into the machine.") return if(!user.drop_item()) - to_chat(user, "The [G] is stuck to you!") + to_chat(user, "[B] is stuck to you!") return - G.forceMove(src) - beaker = G + B.forceMove(src) + beaker = B + add_attack_logs(user, null, "Added [B] containing [B.reagentlist()] to a cryo cell at [COORD(src)]") + user.visible_message("[user] adds \a [B] to [src]!", "You add \a [B] to [src]!") - user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") if(istype(G, /obj/item/screwdriver)) if(occupant || on) @@ -293,18 +297,19 @@ default_deconstruction_crowbar(G) if(istype(G, /obj/item/grab)) + var/obj/item/grab/GG = G if(panel_open) to_chat(user, "Close the maintenance panel first.") return - if(!ismob(G:affecting)) + if(!ismob(GG.affecting)) return - for(var/mob/living/carbon/slime/M in range(1,G:affecting)) - if(M.Victim == G:affecting) - to_chat(usr, "[G:affecting:name] will not fit into the cryo because they have a slime latched onto their head.") + for(var/mob/living/carbon/slime/M in range(1,GG.affecting)) + if(M.Victim == GG.affecting) + to_chat(usr, "[GG.affecting.name] will not fit into the cryo because [GG.affecting.p_they()] [GG.affecting.p_have()] a slime latched onto [GG.affecting.p_their()] head.") return - var/mob/M = G:affecting + var/mob/M = GG.affecting if(put_mob(M)) - qdel(G) + qdel(GG) return /obj/machinery/atmospherics/unary/cryo_cell/update_icon() @@ -452,6 +457,7 @@ else if(usr.incapacitated()) //are you cuffed, dying, lying, stunned or other return + add_attack_logs(usr, occupant, "Ejected from cryo cell at [COORD(src)]") go_out() add_fingerprint(usr) return diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 88827a6ab05..332dc2854e1 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -112,7 +112,7 @@ to_chat(user, "\The [I] is no longer in storage.") return - visible_message("The console beeps happily as it disgorges \the [I].") + visible_message("The console beeps happily as it disgorges [I].") dispense_item(I) @@ -120,7 +120,8 @@ if(!allowed(user)) to_chat(user, "Access Denied.") return - if(!allow_items) return + if(!allow_items) + return if(frozen_items.len == 0) to_chat(user, "There is nothing to recover from storage.") @@ -238,7 +239,7 @@ ) // These items will NOT be preserved var/list/do_not_preserve_items = list ( - /obj/item/mmi/posibrain + /obj/item/mmi/robotic_brain ) /obj/machinery/cryopod/right @@ -323,15 +324,15 @@ // Also make sure there is a valid control computer /obj/machinery/cryopod/proc/despawn_occupant() //Drop all items into the pod. - for(var/obj/item/W in occupant) - occupant.unEquip(W) - W.forceMove(src) + for(var/obj/item/I in occupant) + occupant.unEquip(I) + I.forceMove(src) - if(W.contents.len) //Make sure we catch anything not handled by qdel() on the items. - if(should_preserve_item(W) != CRYO_DESTROY) // Don't remove the contents of things that need preservation + if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items. + if(should_preserve_item(I) != CRYO_DESTROY) // Don't remove the contents of things that need preservation continue - for(var/obj/item/O in W.contents) - if(istype(O,/obj/item/tank)) //Stop eating pockets, you fuck! + for(var/obj/item/O in I.contents) + if(istype(O, /obj/item/tank)) //Stop eating pockets, you fuck! continue O.forceMove(src) @@ -345,23 +346,23 @@ items -= occupant // Don't delete the occupant items -= announce // or the autosay radio. - for(var/obj/item/W in items) - if(istype(W,/obj/item/pda)) - var/obj/item/pda/P = W + for(var/obj/item/I in items) + if(istype(I, /obj/item/pda)) + var/obj/item/pda/P = I QDEL_NULL(P.id) qdel(P) continue - var/preserve = should_preserve_item(W) + var/preserve = should_preserve_item(I) if(preserve == CRYO_DESTROY) - qdel(W) + qdel(I) else if(control_computer && control_computer.allow_items) - control_computer.frozen_items += W + control_computer.frozen_items += I if(preserve == CRYO_OBJECTIVE) - control_computer.objective_items += W - W.loc = null + control_computer.objective_items += I + I.loc = null else - W.forceMove(loc) + I.forceMove(loc) // Skip past any cult sacrifice objective using this person if(GAMEMODE_IS_CULT && is_sacrifice_target(occupant.mind)) @@ -461,22 +462,23 @@ #undef CRYO_PRESERVE #undef CRYO_OBJECTIVE -/obj/machinery/cryopod/attackby(var/obj/item/G as obj, var/mob/user as mob, params) +/obj/machinery/cryopod/attackby(obj/item/I, mob/user, params) - if(istype(G, /obj/item/grab)) + if(istype(I, /obj/item/grab)) + var/obj/item/grab/G = I if(occupant) - to_chat(user, "\The [src] is in use.") + to_chat(user, "[src] is in use.") return - if(!ismob(G:affecting)) + if(!ismob(G.affecting)) return - if(!check_occupant_allowed(G:affecting)) + if(!check_occupant_allowed(G.affecting)) return var/willing = null //We don't want to allow people to be forced into despawning. - var/mob/living/M = G:affecting + var/mob/living/M = G.affecting time_till_despawn = initial(time_till_despawn) if(!istype(M) || M.stat == DEAD) @@ -485,20 +487,21 @@ if(M.client) if(alert(M,"Would you like to enter long-term storage?",,"Yes","No") == "Yes") - if(!M || !G || !G:affecting) return + if(!M || !G || !G.affecting) return willing = willing_time_divisor else willing = 1 if(willing) - visible_message("[user] starts putting [G:affecting:name] into \the [src].") + visible_message("[user] starts putting [G.affecting.name] into [src].") - if(do_after(user, 20, target = G:affecting)) - if(!M || !G || !G:affecting) return + if(do_after(user, 20, target = G.affecting)) + if(!M || !G || !G.affecting) + return if(occupant) - to_chat(user, "\The [src] is in use.") + to_chat(user, "[src] is in use.") return take_occupant(M, willing) @@ -516,6 +519,8 @@ to_chat(M, "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.") take_occupant(M, willing) + else + return ..() /obj/machinery/cryopod/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) @@ -551,7 +556,7 @@ for(var/mob/living/carbon/slime/M in range(1,L)) if(M.Victim == L) - to_chat(usr, "[L.name] will not fit into the cryo pod because they have a slime latched onto their head.") + to_chat(usr, "[L.name] will not fit into the cryo pod because [L.p_they()] [L.p_have()] a slime latched onto [L.p_their()] head.") return @@ -567,7 +572,7 @@ if(willing) if(!Adjacent(L)) - to_chat(user, "You're not close enough to \the [src].") + to_chat(user, "You're not close enough to [src].") return if(L == user) visible_message("[user] starts climbing into the cryo pod.") @@ -633,14 +638,13 @@ if(occupant) items -= occupant if(announce) items -= announce - for(var/obj/item/W in items) - W.loc = get_turf(src) + for(var/obj/item/I in items) + I.forceMove(get_turf(src)) go_out() add_fingerprint(usr) name = initial(name) - return /obj/machinery/cryopod/verb/move_inside() set name = "Enter Pod" @@ -659,7 +663,7 @@ to_chat(usr, "You're too busy getting your life sucked out of you.") return - visible_message("[usr] starts climbing into \the [src].") + visible_message("[usr] starts climbing into [src].") if(do_after(usr, 20, target = usr)) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 501f510348b..4de934f1c96 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -647,7 +647,7 @@ About the new airlock wires panel: if(affecting.receive_damage(10, 0)) H.UpdateDamageIcon() else - visible_message("[user] headbutts the airlock. Good thing they're wearing a helmet.") + visible_message("[user] headbutts the airlock. Good thing [user.p_theyre()] wearing a helmet.") return if(panel_open) @@ -796,7 +796,7 @@ About the new airlock wires panel: if(do_after(user, 20, 1, target = src)) if(!panel_open || !S.use(2)) return - user.visible_message("[user] reinforce \the [src] with metal.", + user.visible_message("[user] reinforces \the [src] with metal.", "You reinforce \the [src] with metal.") security_level = AIRLOCK_SECURITY_METAL update_icon() @@ -810,7 +810,7 @@ About the new airlock wires panel: if(do_after(user, 20, 1, target = src)) if(!panel_open || !S.use(2)) return - user.visible_message("[user] reinforce \the [src] with plasteel.", + user.visible_message("[user] reinforces \the [src] with plasteel.", "You reinforce \the [src] with plasteel.") security_level = AIRLOCK_SECURITY_PLASTEEL modify_max_integrity(normal_integrity * AIRLOCK_INTEGRITY_MULTIPLIER) diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 678e29d3ae0..db508b9288f 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -10,8 +10,6 @@ usesound = 'sound/items/Deconstruct.ogg' var/list/conf_access = null var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access - var/last_configurator = null - var/locked = TRUE var/const/max_brain_damage = 60 // Maximum brain damage a mob can have until it can't use the electronics /obj/item/airlock_electronics/attack_self(mob/user) @@ -26,31 +24,23 @@ var/t1 = text("Access control
\n") - if(last_configurator) - t1 += "Operator: [last_configurator]
" + t1 += "Access requirement is set to " + t1 += one_access ? "ONE
" : "ALL
" - if(locked) - t1 += "Swipe ID
" - else - t1 += "Block
" + t1 += conf_access == null ? "All
" : "All
" - t1 += "Access requirement is set to " - t1 += one_access ? "ONE
" : "ALL
" + t1 += "
" - t1 += conf_access == null ? "All
" : "All
" + var/list/accesses = get_all_accesses() + for(var/acc in accesses) + var/aname = get_access_desc(acc) - t1 += "
" - - var/list/accesses = get_all_accesses() - for(var/acc in accesses) - var/aname = get_access_desc(acc) - - if(!conf_access || !conf_access.len || !(acc in conf_access)) - t1 += "[aname]
" - else if(one_access) - t1 += "[aname]
" - else - t1 += "[aname]
" + if(!conf_access || !conf_access.len || !(acc in conf_access)) + t1 += "[aname]
" + else if(one_access) + t1 += "[aname]
" + else + t1 += "[aname]
" t1 += "

Close

\n" @@ -66,20 +56,9 @@ return 1 if(href_list["close"]) - usr << browse(null, "window=airlock") + usr << browse(null, "window=airlock_electronics") return - if(href_list["login"]) - if(allowed(usr)) - locked = FALSE - last_configurator = usr.name - - if(locked) - return - - if(href_list["logout"]) - locked = TRUE - if(href_list["one_access"]) one_access = !one_access diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index db78e8c82ef..8f5c1144686 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -341,7 +341,7 @@ if(isElectrified()) if(shock(user, 75)) return - if(istype(C, /obj/item/detective_scanner) || istype(C, /obj/item/taperoll)) + if(istype(C, /obj/item/detective_scanner)) return if(istype(C, /obj/item/grenade/plastic/c4)) @@ -394,7 +394,7 @@ if(isElectrified()) if(shock(user, 75)) return - if(istype(C, /obj/item/detective_scanner) || istype(C, /obj/item/taperoll)) + if(istype(C, /obj/item/detective_scanner)) return add_fingerprint(user) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 78949fa0e45..563e4eb49f2 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -325,7 +325,7 @@ /obj/machinery/door/proc/crush() for(var/mob/living/L in get_turf(src)) - L.visible_message("[src] closes on [L], crushing them!", "[src] closes on you and crushes you!") + L.visible_message("[src] closes on [L], crushing [L.p_them()]!", "[src] closes on you and crushes you!") if(isalien(L)) //For xenos L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans. L.emote("roar") diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index b20d99b2613..3f9e4f55a08 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -53,11 +53,38 @@ if(!hasPower()) open() -/obj/machinery/door/poddoor/multi_tile // Whoever wrote the old code for multi-tile spesspod doors needs to burn in hell. + // Whoever wrote the old code for multi-tile spesspod doors needs to burn in hell. - Unknown + // Wise words. - Bxil +/obj/machinery/door/poddoor/multi_tile name = "large pod door" layer = CLOSED_DOOR_LAYER closingLayer = CLOSED_DOOR_LAYER +/obj/machinery/door/poddoor/multi_tile/New() + . = ..() + apply_opacity_to_my_turfs(opacity) + +/obj/machinery/door/poddoor/multi_tile/open() + if(..()) + apply_opacity_to_my_turfs(opacity) + + +/obj/machinery/door/poddoor/multi_tile/close() + if(..()) + apply_opacity_to_my_turfs(opacity) + +/obj/machinery/door/poddoor/multi_tile/Destroy() + apply_opacity_to_my_turfs(0) + return ..() + +//Multi-tile poddoors don't turn invisible automatically, so we change the opacity of the turfs below instead one by one. +/obj/machinery/door/poddoor/multi_tile/proc/apply_opacity_to_my_turfs(var/new_opacity) + for(var/turf/T in locs) + T.opacity = new_opacity + T.has_opaque_atom = new_opacity + T.reconsider_lights() + update_freelook_sight() + /obj/machinery/door/poddoor/multi_tile/four_tile_ver/ icon = 'icons/obj/doors/1x4blast_vert.dmi' width = 4 diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 181e273dd43..1ab22f341b6 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -16,17 +16,20 @@ var/obj/item/airlock_electronics/electronics var/base_state = "left" var/reinf = 0 + var/cancolor = TRUE var/shards = 2 var/rods = 2 var/cable = 1 var/list/debris = list() -/obj/machinery/door/window/New() +/obj/machinery/door/window/New(loc, set_dir) ..() + if(set_dir) + setDir(set_dir) if(req_access && req_access.len) icon_state = "[icon_state]" base_state = icon_state - if(!color) + if(!color && cancolor) color = color_windows(src) for(var/i in 1 to shards) debris += new /obj/item/shard(src) @@ -97,6 +100,16 @@ return 1 if(get_dir(loc, target) == dir) //Make sure looking at appropriate border return !density + if(istype(mover, /obj/structure/window)) + var/obj/structure/window/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/structure/windoor_assembly)) + var/obj/structure/windoor_assembly/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir)) + return FALSE else return 1 @@ -128,7 +141,7 @@ if(emagged) return 0 if(!operating) //in case of emag - operating = 1 + operating = TRUE do_animate("opening") playsound(loc, 'sound/machines/windowdoor.ogg', 100, 1) icon_state ="[base_state]open" @@ -152,7 +165,7 @@ if(forced < 2) if(emagged) return 0 - operating = 1 + operating = TRUE do_animate("closing") playsound(loc, 'sound/machines/windowdoor.ogg', 100, 1) icon_state = base_state @@ -186,6 +199,11 @@ /obj/machinery/door/window/narsie_act() color = NARSIE_WINDOW_COLOUR +/obj/machinery/door/window/ratvar_act() + var/obj/machinery/door/window/clockwork/C = new(loc, dir) + C.name = name + qdel(src) + /obj/machinery/door/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature > T0C + (reinf ? 1600 : 800)) take_damage(round(exposed_volume / 200), BURN, 0, 0) @@ -204,7 +222,7 @@ /obj/machinery/door/window/emag_act(mob/user, obj/weapon) if(!operating && density && !emagged) emagged = TRUE - operating = 1 + operating = TRUE flick("[base_state]spark", src) playsound(src, "sparks", 75, 1) sleep(6) @@ -314,6 +332,45 @@ desc = "For keeping in criminal scum." req_access = list(access_brig) +/obj/machinery/door/window/clockwork + name = "brass windoor" + desc = "A thin door with translucent brass paneling." + icon_state = "clockwork" + base_state = "clockwork" + shards = 0 + rods = 0 + burn_state = FIRE_PROOF + cancolor = FALSE + var/made_glow = FALSE + +/obj/machinery/door/window/clockwork/New(loc, set_dir) + ..() + debris += new/obj/item/stack/tile/brass(src, 2) + +/obj/machinery/door/window/clockwork/setDir(direct) + if(!made_glow) + var/obj/effect/E = new /obj/effect/temp_visual/ratvar/door/window(get_turf(src)) + E.setDir(direct) + made_glow = TRUE + ..() + +/obj/machinery/door/window/clockwork/emp_act(severity) + if(prob(80/severity)) + open() + +/obj/machinery/door/window/clockwork/ratvar_act() + obj_integrity = max_integrity + +/obj/machinery/door/window/clockwork/hasPower() + return TRUE //yup that's power all right + +/obj/machinery/door/window/clockwork/narsie_act() + take_damage(rand(30, 60), BRUTE) + if(src) + var/previouscolor = color + color = "#960000" + animate(src, color = previouscolor, time = 8) + /obj/machinery/door/window/northleft dir = NORTH diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index f8d7432c540..f06f7ac1b37 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -8,6 +8,20 @@ var/list/doppler_arrays = list() density = 1 anchored = 1 atom_say_verb = "states coldly" + var/list/logged_explosions = list() + +/datum/explosion_log + var/logged_time + var/epicenter + var/actual_size_message + var/theoretical_size_message + +/datum/explosion_log/New(var/log_time, var/log_epicenter, var/log_actual_size_message, var/log_theoretical_size_message) + ..() + logged_time = log_time + epicenter = log_epicenter + actual_size_message = log_actual_size_message + theoretical_size_message = log_theoretical_size_message /obj/machinery/doppler_array/New() ..() @@ -15,70 +29,122 @@ var/list/doppler_arrays = list() /obj/machinery/doppler_array/Destroy() doppler_arrays -= src + logged_explosions.Cut() return ..() /obj/machinery/doppler_array/process() return PROCESS_KILL -/obj/machinery/doppler_array/attackby(var/obj/item/O, var/mob/user, params) - if(istype(O, /obj/item/wrench)) +/obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params) + if(iswrench(I)) if(!anchored && !isinspace()) - anchored = 1 + anchored = TRUE power_change() to_chat(user, "You fasten [src].") else if(anchored) - anchored = 0 + anchored = FALSE power_change() to_chat(user, "You unfasten [src].") - playsound(loc, O.usesound, 50, 1) + playsound(loc, I.usesound, 50, 1) + else + return ..() -/obj/machinery/doppler_array/verb/rotate() +/obj/machinery/doppler_array/attack_hand(mob/user) + if(..()) + return + add_fingerprint(user) + ui_interact(user) + +/obj/machinery/doppler_array/attack_ghost(mob/user) + ui_interact(user) + +/obj/machinery/doppler_array/AltClick(mob/user) + rotate(user) + +/obj/machinery/doppler_array/verb/rotate(mob/user) set name = "Rotate Tachyon-doppler Dish" set category = "Object" set src in oview(1) - if(!usr || !isturf(usr.loc)) + if(user.incapacitated()) return - if(usr.stat || usr.restrained() || !usr.canmove) + if(!Adjacent(user)) return - src.dir = turn(src.dir, 90) - return + if(!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do that!") + return + dir = turn(dir, 90) + to_chat(user, "You rotate [src].") + +/obj/machinery/doppler_array/proc/print_explosive_logs(mob/user) + if(!logged_explosions.len) + atom_say("No logs currently stored in internal database.") + return + if(active_timers) + to_chat(user, "[src] is already printing something, please wait.") + return + atom_say("Printing explosive log. Standby...") + addtimer(CALLBACK(src, .print), 50) + +/obj/machinery/doppler_array/proc/print() + visible_message("[src] prints a piece of paper!") + playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1) + var/obj/item/paper/explosive_log/P = new(get_turf(src)) + for(var/D in logged_explosions) + var/datum/explosion_log/E = D + P.info += "\ + [E.logged_time]\ + [E.epicenter]\ + [E.actual_size_message]\ + [E.theoretical_size_message]\ + " + P.info += "
\ + Printed at [station_time_timestamp()]." /obj/machinery/doppler_array/proc/sense_explosion(var/x0,var/y0,var/z0,var/devastation_range,var/heavy_impact_range,var/light_impact_range, var/took,var/orig_dev_range,var/orig_heavy_range,var/orig_light_range) - if(stat & NOPOWER) return - if(z != z0) return + if(stat & NOPOWER) + return + if(z != z0) + return var/dx = abs(x0-x) var/dy = abs(y0-y) var/distance var/direct + var/capped = FALSE if(dx > dy) distance = dx - if(x0 > x) direct = EAST - else direct = WEST + if(x0 > x) + direct = EAST + else + direct = WEST else distance = dy - if(y0 > y) direct = NORTH - else direct = SOUTH - - if(distance > 100) return - if(!(direct & dir)) return + if(y0 > y) + direct = NORTH + else + direct = SOUTH + if(distance > 100) + return + if(!(direct & dir)) + return var/list/messages = list("Explosive disturbance detected.", \ "Epicenter at: grid ([x0],[y0]). Temporal displacement of tachyons: [took] seconds.", \ "Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].") - // If the bomb was capped, say it's theoretical size. + // If the bomb was capped, say its theoretical size. if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range) + capped = TRUE messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]." - + logged_explosions.Insert(1, new /datum/explosion_log(station_time_timestamp(), "[x0],[y0]", "[devastation_range], [heavy_impact_range], [light_impact_range]", capped ? "[orig_dev_range], [orig_heavy_range], [orig_light_range]" : "n/a")) //Newer logs appear first + messages += "Event successfully logged in internal database." for(var/message in messages) atom_say(message) - /obj/machinery/doppler_array/power_change() if(stat & BROKEN) icon_state = "[initial(icon_state)]-broken" @@ -88,4 +154,55 @@ var/list/doppler_arrays = list() stat &= ~NOPOWER else icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER \ No newline at end of file + stat |= NOPOWER + +/obj/machinery/doppler_array/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "doppler_array.tmpl", "Tachyon-doppler array", 500, 650) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/doppler_array/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) + var/data[0] + var/list/explosion_data = list() + for(var/D in logged_explosions) + var/datum/explosion_log/E = D + explosion_data += list(list( + "logged_time" = E.logged_time, + "epicenter" = E.epicenter, + "actual_size_message" = E.actual_size_message, + "theoretical_size_message" = E.theoretical_size_message, + "unique_datum_id" = E.UID())) + data["explosion_data"] = explosion_data + data["printing"] = active_timers + return data + +/obj/machinery/doppler_array/Topic(href, href_list) + if(..()) + return + if(href_list["log_to_delete"]) + var/log_to_delete = sanitize(href_list["log_to_delete"]) + for(var/D in logged_explosions) + var/datum/explosion_log/E = D + if(E.UID() == log_to_delete) + logged_explosions -= E + qdel(E) + to_chat(usr, "Log deletion successful.") + break + else if(href_list["print_logs"]) + print_explosive_logs(usr) + else + return + SSnanoui.update_uis(src) + +/obj/item/paper/explosive_log + name = "explosive log" + info = "

Explosive Log Report

\ + \ + \ + \ + \ + \ + \ + " //NB: the
Time loggedEpicenterActualTheoretical
tag is left open, it is closed later on, when the doppler array adds its data diff --git a/code/game/machinery/dye_generator.dm b/code/game/machinery/dye_generator.dm index bb47a4939ec..52b11da599b 100644 --- a/code/game/machinery/dye_generator.dm +++ b/code/game/machinery/dye_generator.dm @@ -41,7 +41,7 @@ stat |= BROKEN icon_state = "[initial(icon_state)]-broken" -/obj/machinery/dye_generator/attack_hand(mob/user as mob) +/obj/machinery/dye_generator/attack_hand(mob/user) ..() src.add_fingerprint(user) if(stat & (BROKEN|NOPOWER)) @@ -50,18 +50,18 @@ dye_color = temp set_light(2, l_color = temp) -/obj/machinery/dye_generator/attackby(obj/item/W, mob/user, params) +/obj/machinery/dye_generator/attackby(obj/item/I, mob/user, params) - if(default_unfasten_wrench(user, W, time = 60)) + if(default_unfasten_wrench(user, I, time = 60)) return - if(istype(W, /obj/item/hair_dye_bottle)) - user.visible_message("[user] fills the [W] up with some dye.","You fill the [W] up with some hair dye.") - var/obj/item/hair_dye_bottle/HD = W + if(istype(I, /obj/item/hair_dye_bottle)) + var/obj/item/hair_dye_bottle/HD = I + user.visible_message("[user] fills the [HD] up with some dye.","You fill the [HD] up with some hair dye.") HD.dye_color = dye_color HD.update_dye_overlay() else - ..() + return ..() //Hair Dye Bottle @@ -87,7 +87,7 @@ I.color = dye_color overlays += I -/obj/item/hair_dye_bottle/attack(mob/living/carbon/M as mob, mob/user as mob) +/obj/item/hair_dye_bottle/attack(mob/living/carbon/M, mob/user) if(user.a_intent != INTENT_HELP) ..() return @@ -98,11 +98,11 @@ var/mob/living/carbon/human/H = M var/dye_list = list("hair", "alt. hair theme") - if(H.gender == MALE || H.get_species() == "Vulpkanin") + if(H.gender == MALE || isvulpkanin(H)) dye_list += "facial hair" dye_list += "alt. facial hair theme" - if(H && (H.species.bodyflags & HAS_SKIN_COLOR)) + if(H && (H.dna.species.bodyflags & HAS_SKIN_COLOR)) dye_list += "body" var/what_to_dye = input(user, "Choose an area to apply the dye", "Dye Application") in dye_list diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 8cb98021576..b3664c58cd6 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -45,7 +45,7 @@ FIRE ALARM /obj/machinery/firealarm/emag_act(mob/user) if(!emagged) - emagged = 1 + emagged = TRUE if(user) user.visible_message("Sparks fly out of the [src]!", "You emag [src], disabling its thermal sensors.") @@ -62,19 +62,15 @@ FIRE ALARM /obj/machinery/firealarm/attack_ghost(mob/user) ui_interact(user) -/obj/machinery/firealarm/bullet_act(BLAH) - return alarm() - - /obj/machinery/firealarm/emp_act(severity) if(prob(50/severity)) alarm(rand(30/severity, 60/severity)) ..() -/obj/machinery/firealarm/attackby(obj/item/W, mob/user, params) +/obj/machinery/firealarm/attackby(obj/item/I, mob/user, params) add_fingerprint(user) - if(istype(W, /obj/item/screwdriver) && buildstage == 2) + if(iswirecutter(I) && buildstage == 2) wiresexposed = !wiresexposed update_icon() return @@ -82,37 +78,37 @@ FIRE ALARM if(wiresexposed) switch(buildstage) if(2) - if(istype(W, /obj/item/multitool)) + if(ismultitool(I)) detecting = !detecting if(detecting) user.visible_message("[user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") else user.visible_message("[user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") - else if(istype(W, /obj/item/wirecutters)) // cutting the wires out + else if(iswirecutter(I)) // cutting the wires out to_chat(user, "You cut the wires!") - playsound(loc, W.usesound, 50, 1) + playsound(loc, I.usesound, 50, 1) var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil() new_coil.amount = 5 - new_coil.loc = user.loc + new_coil.forceMove(user.loc) buildstage = 1 update_icon() if(1) - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W + if(istype(I, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = I if(!coil.use(5)) to_chat(user, "You cut the wires!") return buildstage = 2 - playsound(get_turf(src), W.usesound, 50, 1) - to_chat(user, "You wire \the [src]!") + playsound(get_turf(src), I.usesound, 50, 1) + to_chat(user, "You wire [src]!") update_icon() - else if(istype(W, /obj/item/crowbar)) + else if(iscrowbar(I)) to_chat(user, "You pry out the circuit!") - playsound(get_turf(src), W.usesound, 50, 1) - if(do_after(user, 20 * W.toolspeed, target = src)) + playsound(get_turf(src), I.usesound, 50, 1) + if(do_after(user, 20 * I.toolspeed, target = src)) if(buildstage != 1) return var/obj/item/firealarm_electronics/circuit = new /obj/item/firealarm_electronics() @@ -120,20 +116,20 @@ FIRE ALARM buildstage = 0 update_icon() if(0) - if(istype(W, /obj/item/firealarm_electronics)) + if(istype(I, /obj/item/firealarm_electronics)) to_chat(user, "You insert the circuit!") - qdel(W) + qdel(I) buildstage = 1 update_icon() - else if(istype(W, /obj/item/wrench)) + else if(iswrench(I)) to_chat(user, "You remove the fire alarm assembly from the wall!") new /obj/item/mounted/frame/firealarm(get_turf(user)) - playsound(get_turf(src), W.usesound, 50, 1) + playsound(get_turf(src), I.usesound, 50, 1) qdel(src) - return - alarm() + else + return ..() /obj/machinery/firealarm/process()//Note: this processing was mostly phased out due to other code, and only runs when needed if(stat & (NOPOWER|BROKEN)) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index da64430b941..7a13b0bf796 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -38,14 +38,16 @@ // sd_set_light(0) //Don't want to render prison breaks impossible -/obj/machinery/flasher/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/wirecutters)) +/obj/machinery/flasher/attackby(obj/item/I, mob/user, params) + if(iswirecutter(I)) add_fingerprint(user) disable = !disable if(disable) - user.visible_message("[user] has disconnected the [src]'s flashbulb!", "You disconnect the [src]'s flashbulb!") + user.visible_message("[user] has disconnected [src]'s flashbulb!", "You disconnect [src]'s flashbulb!") if(!disable) - user.visible_message("[user] has connected the [src]'s flashbulb!", "You connect the [src]'s flashbulb!") + user.visible_message("[user] has connected [src]'s flashbulb!", "You connect [src]'s flashbulb!") + else + return ..() //Let the AI trigger them directly. /obj/machinery/flasher/attack_ai(mob/user) @@ -76,7 +78,7 @@ L.Weaken(strength) if(L.weakeyes) L.Weaken(strength * 1.5) - L.visible_message("[L] gasps and shields their eyes!") + L.visible_message("[L] gasps and shields [L.p_their()] eyes!") /obj/machinery/flasher/emp_act(severity) if(stat & (BROKEN|NOPOWER)) @@ -95,8 +97,8 @@ if((M.m_intent != MOVE_INTENT_WALK) && (anchored)) flash() -/obj/machinery/flasher/portable/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/wrench)) +/obj/machinery/flasher/portable/attackby(obj/item/I, mob/user, params) + if(iswrench(I)) add_fingerprint(user) anchored = !anchored @@ -107,6 +109,8 @@ else if(anchored) user.show_message(text("[src] is now secured.")) overlays += "[base_state]-s" + else + return ..() // Flasher button /obj/machinery/flasher_button diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm index 5428e03d4a8..8ac57a5cec6 100644 --- a/code/game/machinery/floodlight.dm +++ b/code/game/machinery/floodlight.dm @@ -48,7 +48,7 @@ cell.loc = loc cell.add_fingerprint(user) - cell.updateicon() + cell.update_icon() src.cell = null to_chat(user, "You remove the power cell") diff --git a/code/game/machinery/gameboard.dm b/code/game/machinery/gameboard.dm index f1bd8b65a10..526a935cf90 100644 --- a/code/game/machinery/gameboard.dm +++ b/code/game/machinery/gameboard.dm @@ -93,8 +93,11 @@ if(href_list["close"]) close_game() -/obj/machinery/gameboard/attackby(var/obj/item/G as obj, var/mob/user as mob, params) - if(istype(G, /obj/item/wrench)) - default_unfasten_wrench(user, G) - else if(istype(G, /obj/item/crowbar)) - default_deconstruction_crowbar(G, ignore_panel = 1) +/obj/machinery/gameboard/attackby(obj/item/I, mob/user, params) + if(default_unfasten_wrench(user, I)) + return + + if(default_deconstruction_crowbar(I, ignore_panel = TRUE)) + return + else + return ..() \ No newline at end of file diff --git a/code/game/machinery/guestpass.dm b/code/game/machinery/guestpass.dm index 6d90de7bf4d..450260f5f79 100644 --- a/code/game/machinery/guestpass.dm +++ b/code/game/machinery/guestpass.dm @@ -48,20 +48,22 @@ var/list/internal_log = list() var/mode = 0 // 0 - making pass, 1 - viewing logs -/obj/machinery/computer/guestpass/attackby(obj/O, mob/user, params) - if(istype(O, /obj/item/card/id)) +/obj/machinery/computer/guestpass/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/card/id)) if(!giver) - user.drop_item() - O.loc = src - giver = O - updateUsrDialog() + if(user.drop_item()) + I.forceMove(src) + giver = I + updateUsrDialog() else to_chat(user, "There is already ID card inside.") + else + return ..() /obj/machinery/computer/guestpass/proc/get_changeable_accesses() return giver.access -/obj/machinery/computer/guestpass/attack_ai(var/mob/user as mob) +/obj/machinery/computer/guestpass/attack_ai(mob/user) return attack_hand(user) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 58404b133bd..bda66a55622 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -1,7 +1,7 @@ -/* Holograms! +/* holograms! * Contains: * Holopad - * Hologram + * hologram * Other stuff */ @@ -9,11 +9,10 @@ Revised. Original based on space ninja hologram code. Which is also mine. /N How it works: AI clicks on holopad in camera view. View centers on holopad. -AI clicks again on the holopad to display a hologram. Hologram stays as long as AI is looking at the pad and it (the hologram) is in range of the pad. +AI clicks again on the holopad to display a hologram. hologram stays as long as AI is looking at the pad and it (the hologram) is in range of the pad. AI can use the directional keys to move the hologram around, provided the above conditions are met and the AI in question is the holopad's master. Only one AI may project from a holopad at any given time. AI may cancel the hologram at any time by clicking on the holopad once more. - Possible to do for anyone motivated enough: Give an AI variable for different hologram icons. Itegrate EMP effect to disable the unit. @@ -27,19 +26,35 @@ Possible to do for anyone motivated enough: // HOLOPAD MODE // 0 = RANGE BASED // 1 = AREA BASED -var/const/HOLOPAD_MODE = 0 +#define HOLOPAD_PASSIVE_POWER_USAGE 1 +#define HOLOGRAM_POWER_USAGE 2 +#define RANGE_BASED 0 +#define AREA_BASED 1 + +var/const/HOLOPAD_MODE = RANGE_BASED + var/list/holopads = list() /obj/machinery/hologram/holopad - name = "\improper AI holopad" - desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely." + name = "holopad" + desc = "It's a floor-mounted device for projecting holographic images." icon_state = "holopad0" - + anchored = 1 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 100 layer = TURF_LAYER+0.1 //Preventing mice and drones from sneaking under them. armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0) - var/mob/living/silicon/ai/master//Which AI, if any, is controlling the object? Only one AI may control a hologram at any time. + var/list/masters = list()//List of living mobs that use the holopad + var/list/holorays = list()//Holoray-mob link. var/last_request = 0 //to prevent request spam. ~Carn var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating. + var/temp = "" + var/list/holo_calls //array of /datum/holocalls + var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs + var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging + var/obj/effect/overlay/holoray/ray + var/ringing = FALSE /obj/machinery/hologram/holopad/New() ..() @@ -49,216 +64,426 @@ var/list/holopads = list() component_parts += new /obj/item/stock_parts/capacitor(null) RefreshParts() +/obj/machinery/hologram/holopad/Destroy() + if(outgoing_call) + outgoing_call.ConnectionFailure(src) + + for(var/I in holo_calls) + var/datum/holocall/HC = I + HC.ConnectionFailure(src) + + for(var/I in masters) + clear_holo(I) + holopads -= src + return ..() + +/obj/machinery/hologram/holopad/power_change() + if(powered()) + stat &= ~NOPOWER + else + stat |= NOPOWER + if(outgoing_call) + outgoing_call.ConnectionFailure(src) + /obj/machinery/hologram/holopad/RefreshParts() var/holograph_range = 4 for(var/obj/item/stock_parts/capacitor/B in component_parts) holograph_range += 1 * B.rating holo_range = holograph_range -/obj/machinery/hologram/holopad/attackby(obj/item/P as obj, mob/user as mob, params) - if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", P)) +/obj/machinery/hologram/holopad/attackby(obj/item/I, mob/user, params) + if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", I)) return - if(exchange_parts(user, P)) + if(exchange_parts(user, I)) return - if(default_unfasten_wrench(user, P)) + if(default_unfasten_wrench(user, I)) return - default_deconstruction_crowbar(P) + if(default_deconstruction_crowbar(I)) + return + else + return ..() -/obj/machinery/hologram/holopad/attack_hand(var/mob/living/carbon/human/user) //Carn: Hologram requests. +/obj/machinery/hologram/holopad/attack_hand(mob/living/carbon/human/user) + if(..()) + return + + if(outgoing_call) + return + + user.set_machine(src) + interact(user) + +/obj/machinery/hologram/holopad/AltClick(mob/living/carbon/human/user) + if(..()) + return + if(isAI(user)) + hangup_all_calls() + return + +//Stop ringing the AI!! +/obj/machinery/hologram/holopad/proc/hangup_all_calls() + for(var/I in holo_calls) + var/datum/holocall/HC = I + HC.Disconnect(src) + +/obj/machinery/hologram/holopad/interact(mob/living/carbon/human/user) //Carn: hologram requests. if(!istype(user)) return - if(alert(user,"Would you like to request an AI's presence?",,"Yes","No") == "Yes") - if(last_request + 200 < world.time) //don't spam the AI with requests you jerk! - last_request = world.time - to_chat(user, "You request an AI's presence.") - var/area/area = get_area(src) - for(var/mob/living/silicon/ai/AI in living_mob_list) - if(!AI.client) continue - to_chat(AI, "Your presence is requested at \the [area].") - else - to_chat(user, "A request for AI presence was already sent recently.") + var/dat + if(temp) + dat = temp + else + dat = "Request an AI's presence.
" + dat += "Call another holopad.
" + + if(LAZYLEN(holo_calls)) + dat += "=====================================================
" + + var/one_answered_call = FALSE + var/one_unanswered_call = FALSE + for(var/I in holo_calls) + var/datum/holocall/HC = I + if(HC.connected_holopad != src) + dat += "Answer call from [get_area(HC.calling_holopad)].
" + one_unanswered_call = TRUE + else + one_answered_call = TRUE + + if(one_answered_call && one_unanswered_call) + dat += "=====================================================
" + //we loop twice for formatting + for(var/I in holo_calls) + var/datum/holocall/HC = I + if(HC.connected_holopad == src) + dat += "Disconnect call from [HC.user].
" + + var/area/area = get_area(src) + var/datum/browser/popup = new(user, "holopad", "[area] holopad", 400, 300) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.open() + +/obj/machinery/hologram/holopad/Topic(href, href_list) + if(..() || isAI(usr)) + return + add_fingerprint(usr) + if(stat & NOPOWER) + return + if(href_list["AIrequest"]) + if(last_request + 200 < world.time) + last_request = world.time + temp = "You requested an AI's presence.
" + temp += "Main Menu" + var/area/area = get_area(src) + for(var/mob/living/silicon/ai/AI in ai_list) + if(!AI.client) + continue + to_chat(AI, "Your presence is requested at \the [area].") + else + temp = "A request for AI presence was already sent recently.
" + temp += "Main Menu" + + else if(href_list["Holocall"]) + if(outgoing_call) + return + + temp = "You must stand on the holopad to make a call!
" + temp += "Main Menu" + if(usr.loc == loc) + var/list/callnames = list() + for(var/I in holopads) + var/area/A = get_area(I) + if(A) + LAZYADD(callnames[A], I) + callnames -= get_area(src) + + var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames + + if(QDELETED(usr) || !result || outgoing_call) + return + + if(usr.loc == loc) + temp = "Dialing...
" + temp += "Main Menu" + new /datum/holocall(usr, src, callnames[result]) + + else if(href_list["connectcall"]) + var/datum/holocall/call_to_connect = locateUID(href_list["connectcall"]) + if(!QDELETED(call_to_connect) && (call_to_connect in holo_calls)) + call_to_connect.Answer(src) + temp = "" + + else if(href_list["disconnectcall"]) + var/datum/holocall/call_to_disconnect = locateUID(href_list["disconnectcall"]) + if(!QDELETED(call_to_disconnect)) + call_to_disconnect.Disconnect(src) + temp = "" + + else if(href_list["mainmenu"]) + temp = "" + if(outgoing_call) + outgoing_call.Disconnect() + + updateDialog() + +//do not allow AIs to answer calls or people will use it to meta the AI satellite /obj/machinery/hologram/holopad/attack_ai(mob/living/silicon/ai/user) if(!istype(user)) return + if(outgoing_call) + return /*There are pretty much only three ways to interact here. I don't need to check for client since they're clicking on an object. This may change in the future but for now will suffice.*/ - if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already. + if(user.eyeobj.loc != loc)//Set client eye on the object if it's not already. user.eyeobj.setLoc(get_turf(src)) - else if(!hologram)//If there is no hologram, possibly make one. - activate_holo(user, 0) - else if(master == user)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing. - clear_holo() - return + else if(!LAZYLEN(masters) || !masters[user])//If there is no hologram, possibly make one. + activate_holo(user, 1) + else//If there is a hologram, remove it. + clear_holo(user) -/obj/machinery/hologram/holopad/proc/activate_holo(mob/living/silicon/ai/user, var/force = 0) - if(!force && user.eyeobj.loc != src.loc) // allows holopads to pass off holograms to the next holopad in the chain +/obj/machinery/hologram/holopad/process() + for(var/I in masters) + var/mob/living/master = I + if((stat & NOPOWER) || !validate_user(master)) + clear_holo(master) + + if(outgoing_call) + outgoing_call.Check() + + ringing = FALSE + + for(var/I in holo_calls) + var/datum/holocall/HC = I + //Sanity check and skip if no longer valid call + if(!HC.Check()) + atom_say("Call was terminated at remote terminal.") + continue + + if(HC.connected_holopad != src) + if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2))) + HC.Answer(src) + break + if(outgoing_call) + HC.Disconnect(src)//can't answer calls while calling + else + playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring! + ringing = TRUE + + update_icon() + + +//Try to transfer hologram to another pad that can project on T +/obj/machinery/hologram/holopad/proc/transfer_to_nearby_pad(turf/T, mob/holo_owner) + if(!isAI(holo_owner)) + return + for(var/pad in holopads) + var/obj/machinery/hologram/holopad/another = pad + if(another == src) + continue + if(another.validate_location(T)) + var/obj/effect/overlay/holo_pad_hologram/h = masters[holo_owner] + unset_holo(holo_owner) + another.set_holo(holo_owner, h) + return TRUE + return FALSE + +/obj/machinery/hologram/holopad/proc/validate_user(mob/living/user) + if(QDELETED(user) || user.incapacitated() || !user.client) + return FALSE + + if(istype(user, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = user + if(!AI.current) + return FALSE + return TRUE + +//Can we display holos there +//Area check instead of line of sight check because this is a called a lot if AI wants to move around. +/obj/machinery/hologram/holopad/proc/validate_location(turf/T,check_los = FALSE) + if(T.z == z && get_dist(T, src) <= holo_range && T.loc == get_area(src)) + return TRUE + return FALSE + + +/obj/machinery/hologram/holopad/proc/move_hologram(mob/living/user, turf/new_turf) + if(masters[user]) + var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] + var/transfered = FALSE + if(!validate_location(new_turf)) + if(!transfer_to_nearby_pad(new_turf,user)) + clear_holo(user) + return FALSE + else + transfered = TRUE + //All is good. + holo.setDir(get_dir(holo.loc, new_turf)) + holo.forceMove(new_turf) + if(!transfered) + update_holoray(user,new_turf) + return TRUE + +/obj/machinery/hologram/holopad/proc/activate_holo(mob/living/user, var/force = 0) + var/mob/living/silicon/ai/AI = user + if(!istype(AI)) + AI = null + if(AI && !force && AI.eyeobj.loc != loc) // allows holopads to pass off holograms to the next holopad in the chain to_chat(user, "ERROR: Unable to project hologram.") - else if(!(stat & NOPOWER))//If the projector has power - if(user.holo) - var/obj/machinery/hologram/holopad/current = user.holo - current.clear_holo() - if(!hologram)//If there is not already a hologram. - create_holo(user)//Create one. - src.visible_message("A holographic image of [user] flicks to life right before your eyes!") - else - to_chat(user, "ERROR: Image feed in progress.") - else - to_chat(user, "ERROR: Unable to project hologram.") - return + if(!(stat & NOPOWER) && (!AI || force)) + if(AI && (istype(AI.current, /obj/machinery/hologram/holopad))) + to_chat(user, "ERROR: Image feed in progress.") + return + + var/obj/effect/overlay/holo_pad_hologram/hologram = new(loc)//Spawn a blank effect at the location. + if(isAI(user)) + hologram.icon = AI.holo_icon + else //make it like real life + hologram.icon = getHologramIcon(get_id_photo(user)) + hologram.icon_state = user.icon_state + hologram.alpha = 100 + hologram.Impersonation = user + + hologram.mouse_opacity = 0//So you can't click on it. + hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. + hologram.anchored = 1//So space wind cannot drag it. + hologram.name = "[user.name] (hologram)"//If someone decides to right click. + hologram.set_light(2) //hologram lighting + move_hologram() + + set_holo(user, hologram) + + if(!masters[user])//If there is not already a hologram. + visible_message("A holographic image of [user] flicks to life right before your eyes!") + + return hologram + + + to_chat(user, "ERROR: Hologram Projection Malfunction.") + clear_holo(user)//safety check /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ -/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb, datum/language/speaking) - if(M && hologram && master)//Master is mostly a safety in case lag hits or something. - master.relay_speech(M, text, verb, speaking) +/obj/machinery/hologram/holopad/hear_talk(atom/movable/speaker, message, verb, datum/language/message_language) + if(speaker && masters.len)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. + for(var/mob/living/silicon/ai/master in masters) + if(masters[master] && speaker != master) + master.relay_speech(speaker, message, verb, message_language) -/obj/machinery/hologram/holopad/hear_message(mob/living/M, text) - if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something. - var/name_used = M.GetVoice() - var/rendered = "Holopad received, [name_used] [text]" - master.show_message(rendered, 2) - return + for(var/I in holo_calls) + var/datum/holocall/HC = I + if(HC.connected_holopad == src && speaker != HC.hologram) + HC.user.hear_say(message, verb, message_language, speaker = speaker) -/obj/machinery/hologram/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc) - hologram = new(T)//Spawn a blank effect at the location. - hologram.icon = A.holo_icon - hologram.mouse_opacity = 0//So you can't click on it. - hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. - hologram.anchored = 1//So space wind cannot drag it. - hologram.name = "[A.name] (Hologram)"//If someone decides to right click. - hologram.set_light(2) //hologram lighting - set_light(2) //pad lighting - icon_state = "holopad1" - A.holo = src - master = A//AI is the master. - use_power = 2//Active power usage. - return 1 + if(outgoing_call && speaker == outgoing_call.user) + outgoing_call.hologram.atom_say(message) -/obj/machinery/hologram/holopad/proc/clear_holo() -// hologram.set_light(0)//Clear lighting. //handled by the lighting controller when its ower is deleted - QDEL_NULL(hologram)//Get rid of hologram. - if(master.holo == src) - master.holo = null - master = null//Null the master, since no-one is using it now. - set_light(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted) - icon_state = "holopad0" - use_power = 1//Passive power usage. - return 1 -/obj/machinery/hologram/holopad/process() - if(hologram)//If there is a hologram. - if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector. - if(!(stat & NOPOWER))//If the machine has power. - if((HOLOPAD_MODE == 0 && (get_dist(master.eyeobj, src) <= holo_range))) - return 1 - else if(HOLOPAD_MODE == 1) - - var/area/holo_area = get_area(src) - var/area/eye_area = get_area(master.eyeobj) - - if(eye_area != holo_area) - return 1 - - var/mob/living/silicon/ai/theai = master - var/turf/target_turf = get_turf(master.eyeobj) - var/newdir = hologram.dir - clear_holo()//If not, we want to get rid of the hologram. - var/obj/machinery/hologram/holopad/pad_close = get_closest_atom(/obj/machinery/hologram/holopad, holopads, theai.eyeobj) - if(get_dist(pad_close, theai.eyeobj) <= pad_close.holo_range) - if(!(pad_close.stat & NOPOWER) && !pad_close.hologram && (theai && !theai.stat && theai.client)) - pad_close.activate_holo(theai, 1) - if(pad_close.hologram) - pad_close.hologram.forceMove(target_turf) - pad_close.hologram.dir = newdir - return 1 - -/obj/machinery/hologram/holopad/proc/move_hologram() - if(hologram) - step_to(hologram, master.eyeobj) // So it turns. - hologram.loc = get_turf(master.eyeobj) - - return 1 - -// Simple helper to face what you clicked on, in case it should be needed in more than one place -/obj/machinery/hologram/holopad/proc/face_atom(var/atom/A) - if( !hologram || !A || !hologram.x || !hologram.y || !A.x || !A.y ) return - var/dx = A.x - hologram.x - var/dy = A.y - hologram.y - if(!dx && !dy) // Wall items are graphically shifted but on the floor - if(A.pixel_y > 16) hologram.dir = NORTH - else if(A.pixel_y < -16)hologram.dir = SOUTH - else if(A.pixel_x > 16) hologram.dir = EAST - else if(A.pixel_x < -16)hologram.dir = WEST - return - - if(abs(dx) < abs(dy)) - if(dy > 0) hologram.dir = NORTH - else hologram.dir = SOUTH +/obj/machinery/hologram/holopad/proc/SetLightsAndPower() + var/total_users = masters.len + LAZYLEN(holo_calls) + use_power = HOLOPAD_PASSIVE_POWER_USAGE + HOLOGRAM_POWER_USAGE * total_users + if(total_users) + set_light(2) + icon_state = "holopad1" else - if(dx > 0) hologram.dir = EAST - else hologram.dir = WEST + set_light(0) + icon_state = "holopad0" + update_icon() -/* - * Hologram - */ +/obj/machinery/hologram/holopad/update_icon() + var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls) + if(ringing) + icon_state = "holopad_ringing" + else if(total_users) + icon_state = "holopad1" + else + icon_state = "holopad0" -/obj/machinery/hologram - anchored = 1 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 100 - var/obj/effect/overlay/hologram//The projection itself. If there is one, the instrument is on, off otherwise. -//Destruction procs. -/obj/machinery/hologram/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - if(prob(50)) - qdel(src) - if(3.0) - if(prob(5)) - qdel(src) - return +/obj/machinery/hologram/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h) + masters[user] = h + holorays[user] = new /obj/effect/overlay/holoray(loc) + var/mob/living/silicon/ai/AI = user + if(istype(AI)) + AI.current = src + SetLightsAndPower() + update_holoray(user, get_turf(loc)) + return TRUE -/obj/machinery/hologram/blob_act() - qdel(src) - return +/obj/machinery/hologram/holopad/proc/clear_holo(mob/living/user) + qdel(masters[user]) // Get rid of user's hologram + unset_holo(user) + return TRUE -/obj/machinery/hologram/holopad/Destroy() - holopads -= src - if(hologram) - clear_holo() +/obj/machinery/hologram/holopad/proc/unset_holo(mob/living/user) + var/mob/living/silicon/ai/AI = user + if(istype(AI) && AI.current == src) + AI.current = null + masters -= user // Discard AI from the list of those who use holopad + qdel(holorays[user]) + holorays -= user + SetLightsAndPower() + return TRUE + +/obj/machinery/hologram/holopad/proc/update_holoray(mob/living/user, turf/new_turf) + var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] + var/obj/effect/overlay/holoray/ray = holorays[user] + var/disty = holo.y - ray.y + var/distx = holo.x - ray.x + var/newangle + if(!disty) + if(distx >= 0) + newangle = 90 + else + newangle = 270 + else + newangle = arctan(distx/disty) + if(disty < 0) + newangle += 180 + else if(distx < 0) + newangle += 360 + var/matrix/M = matrix() + if(get_dist(get_turf(holo), new_turf) <= 1) + animate(ray, transform = turn(M.Scale(1, sqrt(distx*distx+disty*disty)), newangle), time = 1) + else + ray.transform = turn(M.Scale(1, sqrt(distx*distx+disty*disty)), newangle) + + +/obj/effect/overlay/holo_pad_hologram + var/mob/living/Impersonation + var/datum/holocall/HC + +/obj/effect/overlay/holo_pad_hologram/Destroy() + Impersonation = null + if(!QDELETED(HC)) + HC.Disconnect(HC.calling_holopad) return ..() -/* -Holographic project of everything else. +/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0) + return 1 -/mob/verb/hologram_test() - set name = "Hologram Debug New" - set category = "CURRENT DEBUG" +/obj/effect/overlay/holo_pad_hologram/examine(mob/user) + if(Impersonation) + return Impersonation.examine(user) + return ..() - var/obj/effect/overlay/hologram = new(loc)//Spawn a blank effect at the location. - var/icon/flat_icon = icon(getFlatIcon(src,0))//Need to make sure it's a new icon so the old one is not reused. - flat_icon.ColorTone(rgb(125,180,225))//Let's make it bluish. - flat_icon.ChangeOpacity(0.5)//Make it half transparent. - var/input = input("Select what icon state to use in effect.",,"") - if(input) - var/icon/alpha_mask = new('icons/effects/effects.dmi', "[input]") - flat_icon.AddAlphaMask(alpha_mask)//Finally, let's mix in a distortion effect. - hologram.icon = flat_icon - to_chat(world, "Your icon should appear now.") - return -*/ +/obj/effect/overlay/holoray + name = "holoray" + icon = 'icons/effects/96x96.dmi' + icon_state = "holoray" + layer = FLY_LAYER + density = FALSE + anchored = TRUE + mouse_opacity = 1 + pixel_x = -32 + pixel_y = -32 + alpha = 100 /* * Other Stuff: Is this even used? @@ -268,3 +493,6 @@ Holographic project of everything else. desc = "It makes a hologram appear...with magnets or something..." icon = 'icons/obj/stationobjs.dmi' icon_state = "hologram0" + +#undef HOLOPAD_PASSIVE_POWER_USAGE +#undef HOLOGRAM_POWER_USAGE diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 411543b662f..22d1177c437 100755 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -68,21 +68,23 @@ icon_state = "[base_state]-p" // src.sd_set_light(0) -/obj/machinery/sparker/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/detective_scanner)) +/obj/machinery/sparker/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/detective_scanner)) return - if(istype(W, /obj/item/screwdriver)) + if(isscrewdriver(I)) add_fingerprint(user) - src.disable = !src.disable - if(src.disable) - user.visible_message("[user] has disabled the [src]!", "You disable the connection to the [src].") + disable = !disable + if(disable) + user.visible_message("[user] has disabled [src]!", "You disable the connection to [src].") icon_state = "[base_state]-d" - if(!src.disable) - user.visible_message("[user] has reconnected the [src]!", "You fix the connection to the [src].") - if(src.powered()) + if(!disable) + user.visible_message("[user] has reconnected [src]!", "You fix the connection to [src].") + if(powered()) icon_state = "[base_state]" else icon_state = "[base_state]-p" + else + return ..() /obj/machinery/sparker/attack_ai() if(src.anchored) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index d7a4a3e2b04..4ccaa246578 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -88,17 +88,17 @@ to_chat(usr, "There's nothing attached to the IV drip!") -/obj/machinery/iv_drip/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/reagent_containers)) +/obj/machinery/iv_drip/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/reagent_containers)) if(beaker) to_chat(user, "There is already a reagent container loaded!") return if(!user.drop_item()) return - W.forceMove(src) - beaker = W - to_chat(user, "You attach [W] to [src].") + I.forceMove(src) + beaker = I + to_chat(user, "You attach [I] to [src].") update_icon() else return ..() diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 18fc505a49b..aef8de7c306 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -117,7 +117,7 @@ Class Procs: var/use_log = list() var/list/settagwhitelist = list()//WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST. atom_say_verb = "beeps" - var/speed_process = 0 // Process as fast as possible? + var/defer_process = 0 /obj/machinery/Initialize() addAtProcessing() @@ -128,13 +128,16 @@ Class Procs: if(use_power) myArea = get_area_master(src) if(!speed_process) - START_PROCESSING(SSmachines, src) + if(!defer_process) + START_PROCESSING(SSmachines, src) + else + START_DEFERRED_PROCESSING(SSmachines, src) else fast_processing += src isprocessing = TRUE // all of these isprocessing = TRUE can be removed when the PS is dead // gotta go fast -/obj/machinery/proc/makeSpeedProcess() +/obj/machinery/makeSpeedProcess() if(speed_process) return speed_process = 1 @@ -143,7 +146,7 @@ Class Procs: isprocessing = TRUE // gotta go slow -/obj/machinery/proc/makeNormalProcess() +/obj/machinery/makeNormalProcess() if(!speed_process) return speed_process = 0 @@ -558,7 +561,7 @@ Class Procs: if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee)) threatcount += 2 - if(perp.species.name != "Human") //beepsky so racist. + if(!ishumanbasic(perp)) //beepsky so racist. threatcount += 2 if(check_records || check_arrest) diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index ee4f2e6eb62..116a0f8dbe1 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -97,17 +97,18 @@ updateicon() - else if(istype(I, /obj/item/card/id)||istype(I, /obj/item/pda)) + else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda)) if(open) - if(src.allowed(user)) - src.locked = !src.locked - to_chat(user, "Controls are now [src.locked ? "locked" : "unlocked"].") + if(allowed(user)) + locked = !locked + to_chat(user, "Controls are now [locked ? "locked" : "unlocked"].") else to_chat(user, "Access denied.") updateDialog() else to_chat(user, "You must open the cover first!") - return + else + return ..() /obj/machinery/navbeacon/attack_ai(mob/user) interact(user, 1) diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 422e697e7b0..491cb93018e 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -306,21 +306,21 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(FC.channel_name == channel_name) check = 1 break - if(channel_name == "" || channel_name == REDACTED || scanned_user == "Unknown" || check || (scanned_user in existing_authors)) - temp = "ERROR: Could not submit feed channel to Network.
    " - if(scanned_user in existing_authors) - temp += "
  • There already exists a feed channel under your name.
  • " - if(channel_name == "" || channel_name == REDACTED) - temp += "
  • Invalid channel name.
  • " - if(check) - temp += "
  • Channel name already in use.
  • " - if(scanned_user == "Unknown") - temp += "
  • Channel author unverified.
  • " - temp += "
" - temp_back_screen = NEWSCASTER_CREATE_FC - else - var/choice = alert("Please confirm feed channel creation", "Network Channel Handler", "Confirm", "Cancel") - if(choice == "Confirm") + var/choice = alert("Please confirm feed channel creation", "Network Channel Handler", "Confirm", "Cancel") + if(choice == "Confirm") + if(channel_name == "" || channel_name == REDACTED || scanned_user == "Unknown" || check || (scanned_user in existing_authors)) + temp = "ERROR: Could not submit feed channel to Network.
    " + if(scanned_user in existing_authors) + temp += "
  • There already exists a feed channel under your name.
  • " + if(channel_name == "" || channel_name == REDACTED) + temp += "
  • Invalid channel name.
  • " + if(check) + temp += "
  • Channel name already in use.
  • " + if(scanned_user == "Unknown") + temp += "
  • Channel author unverified.
  • " + temp += "
" + temp_back_screen = NEWSCASTER_CREATE_FC + else var/datum/feed_channel/newChannel = new /datum/feed_channel newChannel.channel_name = channel_name newChannel.author = scanned_user @@ -422,19 +422,19 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co else if(href_list["submit_wanted"]) var/input_param = text2num(href_list["submit_wanted"]) - if(msg == "" || channel_name == "" || scanned_user == "Unknown") - temp = "ERROR: Wanted issue rejected by Network.
    " - if(channel_name == "" || channel_name == REDACTED) - temp += "
  • Invalid name for person wanted.
  • " - if(scanned_user == "Unknown") - temp += "
  • Channel author unverified.
  • " - if(msg == "" || msg == REDACTED) - temp += "
  • Invalid description.
  • " - temp += "
" - temp_back_screen = NEWSCASTER_MAIN - else - var/choice = alert("Please confirm wanted issue [input_param == 1 ? "creation." : "edit."]", "Network Security Handler", "Confirm", "Cancel") - if(choice == "Confirm") + var/choice = alert("Please confirm wanted issue [input_param == 1 ? "creation." : "edit."]", "Network Security Handler", "Confirm", "Cancel") + if(choice == "Confirm") + if(msg == "" || channel_name == "" || scanned_user == "Unknown") + temp = "ERROR: Wanted issue rejected by Network.
    " + if(channel_name == "" || channel_name == REDACTED) + temp += "
  • Invalid name for person wanted.
  • " + if(scanned_user == "Unknown") + temp += "
  • Channel author unverified.
  • " + if(msg == "" || msg == REDACTED) + temp += "
  • Invalid description.
  • " + temp += "
" + temp_back_screen = NEWSCASTER_MAIN + else if(input_param == 1) //input_param == 1: new wanted issue, input_param == 2: editing an existing one var/datum/feed_message/W = new /datum/feed_message W.author = channel_name diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 2d5a885aba1..270b2a99411 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -1,44 +1,3 @@ -#define PIPE_SIMPLE_STRAIGHT 0 -#define PIPE_SIMPLE_BENT 1 -#define PIPE_HE_STRAIGHT 2 -#define PIPE_HE_BENT 3 -#define PIPE_CONNECTOR 4 -#define PIPE_MANIFOLD 5 -#define PIPE_JUNCTION 6 -#define PIPE_UVENT 7 -#define PIPE_MVALVE 8 -#define PIPE_PUMP 9 -#define PIPE_SCRUBBER 10 -#define PIPE_INSULATED_STRAIGHT 11 -#define PIPE_INSULATED_BENT 12 -#define PIPE_GAS_FILTER 13 -#define PIPE_GAS_MIXER 14 -#define PIPE_PASSIVE_GATE 15 -#define PIPE_VOLUME_PUMP 16 -#define PIPE_HEAT_EXCHANGE 17 -#define PIPE_TVALVE 18 -#define PIPE_MANIFOLD4W 19 -#define PIPE_CAP 20 -#define PIPE_OMNI_MIXER 21 -#define PIPE_OMNI_FILTER 22 -#define PIPE_UNIVERSAL 23 -#define PIPE_SUPPLY_STRAIGHT 24 -#define PIPE_SUPPLY_BENT 25 -#define PIPE_SCRUBBERS_STRAIGHT 26 -#define PIPE_SCRUBBERS_BENT 27 -#define PIPE_SUPPLY_MANIFOLD 28 -#define PIPE_SCRUBBERS_MANIFOLD 29 -#define PIPE_SUPPLY_MANIFOLD4W 30 -#define PIPE_SCRUBBERS_MANIFOLD4W 31 -#define PIPE_SUPPLY_CAP 32 -#define PIPE_SCRUBBERS_CAP 33 -#define PIPE_INJECTOR 34 -#define PIPE_DVALVE 35 -#define PIPE_DP_VENT 36 -#define PIPE_PASV_VENT 37 -#define PIPE_DTVALVE 38 -#define PIPE_CIRCULATOR 39 - /obj/item/pipe name = "pipe" desc = "A pipe" @@ -180,93 +139,19 @@ //update the name and icon of the pipe item depending on the type +/obj/item/pipe/rpd_act(mob/user, obj/item/rpd/our_rpd) + if(our_rpd.mode == RPD_ROTATE_MODE) + rotate() + else if(our_rpd.mode == RPD_FLIP_MODE) + flip() + else if(our_rpd.mode == RPD_DELETE_MODE) + our_rpd.delete_single_pipe(user, src) + else + ..() + /obj/item/pipe/proc/update(var/obj/machinery/atmospherics/make_from) - var/list/nlist = list( \ - "pipe", \ - "bent pipe", \ - "h/e pipe", \ - "bent h/e pipe", \ - "connector", \ - "manifold", \ - "junction", \ - "uvent", \ - "mvalve", \ - "pump", \ - "scrubber", \ - "insulated pipe", \ - "bent insulated pipe", \ - "gas filter", \ - "gas mixer", \ - "passive gate", \ - "volume pump", \ - "heat exchanger", \ - "t-valve", \ - "4-way manifold", \ - "pipe cap", \ - "omni mixer", \ - "omni filter", \ - "universal pipe adapter", \ - "supply pipe", \ - "bent supply pipe", \ - "scrubbers pipe", \ - "bent scrubbers pipe", \ - "supply manifold", \ - "scrubbers manifold", \ - "supply 4-way manifold", \ - "scrubbers 4-way manifold", \ - "supply pipe cap", \ - "scrubbers pipe cap", \ - "air injector", \ - "digital valve", \ - "dual-port vent", \ - "passive vent", \ - "digital t-valve", \ - "circulator/heat exchanger", \ - ) - name = nlist[pipe_type+1] + " fitting" - var/list/islist = list( \ - "simple", \ - "simple", \ - "he", \ - "he", \ - "connector", \ - "manifold", \ - "junction", \ - "uvent", \ - "mvalve", \ - "pump", \ - "scrubber", \ - "insulated", \ - "insulated", \ - "filter", \ - "mixer", \ - "passivegate", \ - "volumepump", \ - "heunary", \ - "tvalve", \ - "manifold4w", \ - "cap", \ - "omni_mixer", \ - "omni_filter", \ - "universal", \ - "simple", \ - "simple", \ - "simple", \ - "simple", \ - "manifold", \ - "manifold", \ - "manifold4w", \ - "manifold4w", \ - "cap", \ - "cap", \ - "injector", \ - "dvalve", \ - "dual-port vent", \ - "passive vent", \ - "dtvalve", \ - "circ", \ - ) - icon_state = islist[pipe_type + 1] + name = "[get_pipe_name(pipe_type, PIPETYPE_ATMOS)] fitting" + icon_state = get_pipe_icon(pipe_type) var/obj/machinery/atmospherics/trinary/triP = make_from if(istype(triP) && triP.flipped) icon_state = "m_[icon_state]" @@ -650,6 +535,12 @@ to_chat(user, "You have fastened the meter to the pipe.") qdel(src) +/obj/item/pipe_meter/rpd_act(mob/user, obj/item/rpd/our_rpd) + if(our_rpd.mode == RPD_DELETE_MODE) + our_rpd.delete_single_pipe(user, src) + else + ..() + /obj/item/pipe_gsensor name = "gas sensor" desc = "A sensor that can be hooked to a computer" @@ -667,43 +558,8 @@ to_chat(user, "You have fastened the gas sensor.") qdel(src) -#undef PIPE_SIMPLE_STRAIGHT -#undef PIPE_SIMPLE_BENT -#undef PIPE_HE_STRAIGHT -#undef PIPE_HE_BENT -#undef PIPE_CONNECTOR -#undef PIPE_MANIFOLD -#undef PIPE_JUNCTION -#undef PIPE_UVENT -#undef PIPE_MVALVE -#undef PIPE_PUMP -#undef PIPE_SCRUBBER -#undef PIPE_INSULATED_STRAIGHT -#undef PIPE_INSULATED_BENT -#undef PIPE_GAS_FILTER -#undef PIPE_GAS_MIXER -#undef PIPE_PASSIVE_GATE -#undef PIPE_VOLUME_PUMP -#undef PIPE_HEAT_EXCHANGE -#undef PIPE_TVALVE -#undef PIPE_MANIFOLD4W -#undef PIPE_CAP -#undef PIPE_OMNI_MIXER -#undef PIPE_OMNI_FILTER -#undef PIPE_UNIVERSAL -#undef PIPE_SUPPLY_STRAIGHT -#undef PIPE_SUPPLY_BENT -#undef PIPE_SCRUBBERS_STRAIGHT -#undef PIPE_SCRUBBERS_BENT -#undef PIPE_SUPPLY_MANIFOLD -#undef PIPE_SCRUBBERS_MANIFOLD -#undef PIPE_SUPPLY_MANIFOLD4W -#undef PIPE_SCRUBBERS_MANIFOLD4W -#undef PIPE_SUPPLY_CAP -#undef PIPE_SCRUBBERS_CAP -#undef PIPE_INJECTOR -#undef PIPE_DVALVE -#undef PIPE_DP_VENT -#undef PIPE_PASV_VENT -#undef PIPE_DTVALVE -#undef PIPE_CIRCULATOR +/obj/item/pipe_gsensor/rpd_act(mob/user, obj/item/rpd/our_rpd) + if(our_rpd.mode == RPD_DELETE_MODE) + our_rpd.delete_single_pipe(user, src) + else + ..() diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index cb2892722aa..43613ef4990 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -10,12 +10,12 @@ /obj/machinery/pipedispenser/attack_hand(mob/user) if(..()) return 1 - + interact(user) - + /obj/machinery/pipedispenser/attack_ghost(mob/user) interact(user) - + /obj/machinery/pipedispenser/interact(mob/user) var/dat = {" Regular pipes:
@@ -163,22 +163,22 @@ /obj/machinery/pipedispenser/disposal/attack_hand(mob/user) if(..()) return - + interact(user) - + /obj/machinery/pipedispenser/disposal/attack_ghost(mob/user) interact(user) - + /obj/machinery/pipedispenser/disposal/interact(mob/user) var/dat = {"Disposal Pipes

-Pipe
-Bent Pipe
-Junction
-Y-Junction
-Trunk
-Bin
-Outlet
-Chute
+Pipe
+Bent Pipe
+Junction
+Y-Junction
+Trunk
+Bin
+Outlet
+Chute
"} var/datum/browser/popup = new(user, "pipedispenser", name, 400, 400) @@ -194,29 +194,10 @@ if(!wait) var/p_type = text2num(href_list["dmake"]) - var/obj/structure/disposalconstruct/C = new (loc) - switch(p_type) - if(0) - C.ptype = 0 - if(1) - C.ptype = 1 - if(2) - C.ptype = 2 - if(3) - C.ptype = 4 - if(4) - C.ptype = 5 - if(5) - C.ptype = 6 - C.density = 1 - if(6) - C.ptype = 7 - C.density = 1 - if(7) - C.ptype = 8 - C.density = 1 + var/obj/structure/disposalconstruct/C = new(loc, p_type) + if(p_type in list(PIPE_DISPOSALS_BIN, PIPE_DISPOSALS_OUTLET, PIPE_DISPOSALS_CHUTE)) + C.density = TRUE C.add_fingerprint(usr) - C.update() wait = 1 spawn(15) - wait = 0 \ No newline at end of file + wait = 0 diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm index f6ecd511b2b..3d7f6a52e70 100644 --- a/code/game/machinery/poolcontroller.dm +++ b/code/game/machinery/poolcontroller.dm @@ -31,18 +31,18 @@ emagged = 1 //Set the emag var to true. -/obj/machinery/poolcontroller/attackby(obj/item/P as obj, mob/user as mob, params) //Proc is called when a user hits the pool controller with something. - if(istype(P,/obj/item/multitool)) //If the mob hits the pool controller with a multitool, reset the emagged status +/obj/machinery/poolcontroller/attackby(obj/item/I, mob/user, params) //Proc is called when a user hits the pool controller with something. + if(ismultitool(I)) //If the mob hits the pool controller with a multitool, reset the emagged status if(emagged) //Check the emag status - to_chat(user, "You re-enable \the [src]'s temperature safeguards.")//Inform the user that they have just fixed the safeguards. + to_chat(user, "You re-enable [src]'s temperature safeguards.")//Inform the user that they have just fixed the safeguards. - emagged = 0 //Set the emagged var to false. + emagged = FALSE //Set the emagged var to false. else to_chat(user, "Nothing happens.")//If not emagged, don't do anything, and don't tell the user that it can be emagged. else //If it's not a multitool, defer to /obj/machinery/attackby - ..() + return ..() /obj/machinery/poolcontroller/attack_hand(mob/user as mob) ui_interact(user) @@ -90,9 +90,9 @@ if(drownee && (drownee.lying || deep_water)) //Mob lying down or water is deep (determined by controller) if(drownee.internal) return //Has internals, no drowning - if((NO_BREATHE in drownee.species.species_traits) || (BREATHLESS in drownee.mutations)) + if((NO_BREATHE in drownee.dna.species.species_traits) || (BREATHLESS in drownee.mutations)) return //doesn't breathe, no drowning - if(drownee.get_species() == "Skrell" || drownee.get_species() == "Neara") + if(isskrell(drownee) || isneara(drownee)) return //fish things don't drown if(drownee.stat == DEAD) //Dead spacemen don't drown more @@ -100,14 +100,14 @@ if(drownee.losebreath > 20) //You've probably got bigger problems than drowning at this point, so we won't add to it until you get that under control. return - add_attack_logs(src, drownee, "Drowned", isLivingSSD(drownee)) + add_attack_logs(src, drownee, "Drowned", isLivingSSD(drownee) ? null : ATKLOG_ALL) if(drownee.stat) //Mob is in critical. drownee.AdjustLoseBreath(3, bound_lower = 0, bound_upper = 20) drownee.visible_message("\The [drownee] appears to be drowning!","You're quickly drowning!") //inform them that they are fucked. else drownee.AdjustLoseBreath(2, bound_lower = 0, bound_upper = 20) //For every time you drown, you miss 2 breath attempts. Hope you catch on quick! if(prob(35)) //35% chance to tell them what is going on. They should probably figure it out before then. - drownee.visible_message("\The [drownee] flails, almost like they are drowning!","You're lacking air!") //*gasp* *gasp* *gasp* *gasp* *gasp* + drownee.visible_message("\The [drownee] flails, almost like [drownee.p_they()] [drownee.p_are()] drowning!","You're lacking air!") //*gasp* *gasp* *gasp* *gasp* *gasp* diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 68e6eaf2ad2..abc8d137679 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -54,7 +54,7 @@ to_chat(user, "[src] isn't connected to anything!") return 1 else - ..() + return ..() /obj/machinery/recharger/attack_hand(mob/user) if(issilicon(user)) diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index fd973290244..f987b698772 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -136,18 +136,21 @@ else icon_state = "borgcharger0" -/obj/machinery/recharge_station/attackby(obj/item/P as obj, mob/user as mob, params) - if(istype(P, /obj/item/screwdriver)) - if(src.occupant) +/obj/machinery/recharge_station/attackby(obj/item/I, mob/user, params) + if(isscrewdriver(I)) + if(occupant) to_chat(user, "The maintenance panel is locked.") return - default_deconstruction_screwdriver(user, "borgdecon2", "borgcharger0", P) + default_deconstruction_screwdriver(user, "borgdecon2", "borgcharger0", I) return - if(exchange_parts(user, P)) + if(exchange_parts(user, I)) return - default_deconstruction_crowbar(P) + if(default_deconstruction_crowbar(I)) + return + else + return ..() /obj/machinery/recharge_station/proc/process_occupant() if(src.occupant) diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index d80a628927b..72c0cd91002 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -51,6 +51,7 @@ var/const/SAFETY_COOLDOWN = 100 /obj/machinery/recycler/attackby(obj/item/I, mob/user, params) + add_fingerprint(user) if(default_deconstruction_screwdriver(user, "grinder-oOpen", "grinder-o0", I)) return @@ -60,9 +61,10 @@ var/const/SAFETY_COOLDOWN = 100 if(default_unfasten_wrench(user, I)) return - default_deconstruction_crowbar(I) - ..() - add_fingerprint(user) + if(default_deconstruction_crowbar(I)) + return + else + return ..() /obj/machinery/recycler/emag_act(mob/user) if(!emagged) diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index e9c7c497d72..3aae4af4405 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -269,7 +269,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() return //err... hacking code, which has no reason for existing... but anyway... it was once supposed to unlock priority 3 messanging on that console (EXTREME priority...), but the code for that was removed. -/obj/machinery/requests_console/attackby(var/obj/item/O as obj, var/mob/user as mob) +/obj/machinery/requests_console/attackby(obj/item/I, mob/user) /* if(istype(O, /obj/item/crowbar)) if(open) @@ -292,14 +292,15 @@ var/list/obj/machinery/requests_console/allConsoles = list() else to_chat(user, "You can't do much with that.")*/ - if(istype(O, /obj/item/card/id)) - if(inoperable(MAINT)) return + if(istype(I, /obj/item/card/id)) + if(inoperable(MAINT)) + return if(screen == RCS_MESSAUTH) - var/obj/item/card/id/T = O + var/obj/item/card/id/T = I msgVerified = text("Verified by [T.registered_name] ([T.assignment])") updateUsrDialog() if(screen == RCS_ANNOUNCE) - var/obj/item/card/id/ID = O + var/obj/item/card/id/ID = I if(access_RC_announce in ID.GetAccess()) announceAuth = 1 announcement.announcer = ID.assignment ? "[ID.assignment] [ID.registered_name]" : ID.registered_name @@ -308,16 +309,18 @@ var/list/obj/machinery/requests_console/allConsoles = list() to_chat(user, "You are not authorized to send announcements.") updateUsrDialog() if(screen == RCS_SHIPPING) - var/obj/item/card/id/T = O + var/obj/item/card/id/T = I msgVerified = text("Sender verified as [T.registered_name] ([T.assignment])") updateUsrDialog() - if(istype(O, /obj/item/stamp)) - if(inoperable(MAINT)) return + if(istype(I, /obj/item/stamp)) + if(inoperable(MAINT)) + return if(screen == RCS_MESSAUTH) - var/obj/item/stamp/T = O + var/obj/item/stamp/T = I msgStamped = text("Stamped with the [T.name]") updateUsrDialog() - return + else + return ..() /obj/machinery/requests_console/proc/reset_message(var/mainmenu = 0) message = "" diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index a4a4091df7b..3777dfc866d 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -56,27 +56,26 @@ return else // insert cell - var/obj/item/stock_parts/cell/C = usr.get_active_hand() + var/obj/item/stock_parts/cell/C = user.get_active_hand() if(istype(C)) - user.drop_item() - cell = C - C.loc = src - C.add_fingerprint(usr) + if(user.drop_item()) + cell = C + C.forceMove(src) + C.add_fingerprint(user) - user.visible_message("[user] inserts a power cell into [src].", "You insert the power cell into [src].") + user.visible_message("[user] inserts a power cell into [src].", "You insert the power cell into [src].") else to_chat(user, "The hatch must be open to insert a power cell.") return - else if(istype(I, /obj/item/screwdriver)) + else if(isscrewdriver(I)) open = !open - user.visible_message("[user] [open ? "opens" : "closes"] the hatch on the [src].", "You [open ? "open" : "close"] the hatch on the [src].") + user.visible_message("[user] [open ? "opens" : "closes"] the hatch on [src].", "You [open ? "open" : "close"] the hatch on [src].") update_icon() if(!open && user.machine == src) user << browse(null, "window=spaceheater") user.unset_machine() else - ..() - return + return ..() /obj/machinery/space_heater/attack_hand(mob/user as mob) src.add_fingerprint(user) @@ -106,7 +105,7 @@ else on = !on - user.visible_message("[user] switches [on ? "on" : "off"] the [src].","You switch [on ? "on" : "off"] the [src].") + user.visible_message("[user] switches [on ? "on" : "off"] [src].","You switch [on ? "on" : "off"] [src].") update_icon() return @@ -127,11 +126,11 @@ if("cellremove") if(open && cell && !usr.get_active_hand()) - cell.updateicon() + cell.update_icon() usr.put_in_hands(cell) cell.add_fingerprint(usr) cell = null - usr.visible_message("[usr] removes the power cell from \the [src].", "You remove the power cell from \the [src].") + usr.visible_message("[usr] removes the power cell from [src].", "You remove the power cell from [src].") if("cellinstall") @@ -143,7 +142,7 @@ C.loc = src C.add_fingerprint(usr) - usr.visible_message("[usr] inserts a power cell into \the [src].", "You insert the power cell into \the [src].") + usr.visible_message("[usr] inserts a power cell into [src].", "You insert the power cell into [src].") updateDialog() else diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index a77bd744f92..ebf3cfeadf9 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -276,7 +276,6 @@ overlays.Cut() overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) -#undef CHARS_PER_LINE #undef FONT_SIZE #undef FONT_COLOR #undef WARNING_FONT_COLOR diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index a7d68adbe62..370cef73559 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -413,13 +413,13 @@ var/i for(i=0,i<4,i++) //Gradually give the guy inside some damaged based on the intensity spawn(50) - if(src.OCCUPANT) - if(src.issuperUV) + if(OCCUPANT) + if(issuperUV) OCCUPANT.take_organ_damage(0,40) - to_chat(user, "Test. You gave him 40 damage") + to_chat(user, "Test. You gave [OCCUPANT.p_them()] 40 damage") else OCCUPANT.take_organ_damage(0,8) - to_chat(user, "Test. You gave him 8 damage") + to_chat(user, "Test. You gave [OCCUPANT.p_them()] 8 damage") return*/ diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index 7ec64373373..37d1c3ae93c 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -158,14 +158,14 @@ return -/obj/machinery/power/singularity_beacon/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W,/obj/item/screwdriver)) +/obj/machinery/power/singularity_beacon/attackby(obj/item/I, mob/user, params) + if(isscrewdriver(I)) if(active) to_chat(user, "You need to deactivate the beacon first!") return if(anchored) - anchored = 0 + anchored = FALSE to_chat(user, "You unscrew the beacon from the floor.") disconnect_from_network() return @@ -173,11 +173,10 @@ if(!connect_to_network()) to_chat(user, "This device must be placed over an exposed cable.") return - anchored = 1 + anchored = TRUE to_chat(user, "You screw the beacon to the floor and attach the cable.") - return - ..() - return + else + return ..() /obj/machinery/power/singularity_beacon/Destroy() diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index a4c73cc8fac..b5806d1472e 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -230,8 +230,9 @@ var/turf/bombturf = get_turf(src) var/area/A = get_area(bombturf) if(payload && !istype(payload, /obj/item/bombcore/training)) - msg_admin_attack("[key_name_admin(user)] has primed a [name] ([payload]) for detonation at [A.name] (JMP).") - log_game("[key_name(user)] has primed a [name] ([payload]) for detonation at [A.name] ([bombturf.x], [bombturf.y], [bombturf.z])") + msg_admin_attack("[key_name_admin(user)] has primed a [name] ([payload]) for detonation at [A.name] (JMP).", ATKLOG_FEW) + log_game("[key_name(user)] has primed a [name] ([payload]) for detonation at [A.name] [COORD(bombturf)]") + investigate_log("[key_name(user)] has has primed a [name] ([payload]) for detonation at [A.name] [COORD(bombturf)]", INVESTIGATE_BOMB) payload.adminlog = "\The [src] that [key_name(user)] had primed detonated!" /obj/machinery/syndicatebomb/proc/isWireCut(var/index) @@ -486,7 +487,8 @@ else to_chat(user, "The [I] wont fit! The [src] can only hold up to [max_beakers] containers.") return - ..() + else + return ..() /obj/item/bombcore/chemical/CheckParts(list/parts_list) ..() @@ -556,11 +558,11 @@ var/area/A = get_area(T) detonated-- message_admins("[key_name_admin(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] (JMP).") - bombers += "[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] ([T.x],[T.y],[T.z])" + investigate_log("[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] ([T.x],[T.y],[T.z])", INVESTIGATE_BOMB) log_game("[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] ([T.x],[T.y],[T.z])") detonated = 0 existant = 0 timer = world.time + BUTTON_COOLDOWN #undef BUTTON_COOLDOWN -#undef BUTTON_DELAY \ No newline at end of file +#undef BUTTON_DELAY diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 48384f78f1e..64e387fb731 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -156,8 +156,26 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency, signal.data["verb"], signal.data["language"]) - - +#define CREW_RADIO_TYPE 0 +#define CENTCOMM_RADIO_TYPE 1 +#define SYNDICATE_RADIO_TYPE 2 +/proc/Is_Bad_Connection(old_freq, new_freq) //Makes sure players cant read radios of a higher level than they are + var/old_type = CREW_RADIO_TYPE + var/new_type = CREW_RADIO_TYPE + for(var/antag_freq in ANTAG_FREQS) + if(old_freq == antag_freq) + old_type = SYNDICATE_RADIO_TYPE + if(new_freq == antag_freq) + new_type = SYNDICATE_RADIO_TYPE + + for(var/cent_freq in CENT_FREQS) + if(old_freq == cent_freq) + old_type = CENTCOMM_RADIO_TYPE + if(new_freq == cent_freq) + new_type = CENTCOMM_RADIO_TYPE + + return new_type > old_type + /** Here is the big, bad function that broadcasts a message given the appropriate @@ -226,21 +244,28 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept var/display_freq = freq + var/bad_connection = FALSE + var/datum/radio_frequency/new_connection = connection + + if(connection.frequency != display_freq) + bad_connection = Is_Bad_Connection(connection.frequency, display_freq) + new_connection = radio_controller.return_frequency(display_freq) + var/list/obj/item/radio/radios = list() // --- Broadcast only to intercom devices --- - if(data == 1) + if(data == 1 && !bad_connection) - for(var/obj/item/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) + for(var/obj/item/radio/intercom/R in new_connection.devices["[RADIO_CHAT]"]) if(R.receive_range(display_freq, level) > -1) radios += R // --- Broadcast only to intercoms and station-bounced radios --- - else if(data == 2) + else if(data == 2 && !bad_connection) - for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) if(istype(R, /obj/item/radio/headset)) continue @@ -259,9 +284,9 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept // --- Broadcast to ALL radio devices --- - else + else if(!bad_connection) - for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) if(R.receive_range(display_freq, level) > -1) radios += R diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 9dc30edf61e..0b9b1449137 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -436,7 +436,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) var/list/memory = list() // stored memory - var/rawcode = "" // the code to compile (raw text) + var/list/rawcode = list() // the code to compile (list of characters) var/datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code var/autoruncode = 0 // 1 if the code is set to run every time a signal is picked up @@ -516,10 +516,9 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() relay_information(signal, "/obj/machinery/telecomms/broadcaster") -/obj/machinery/telecomms/server/proc/setcode(var/t) - if(t) - if(istext(t)) - rawcode = t +/obj/machinery/telecomms/server/proc/setcode(var/list/code) + if(istype(code)) + rawcode = code /obj/machinery/telecomms/server/proc/compile(mob/user as mob) if(Compiler) @@ -548,8 +547,8 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/server/proc/admin_log(var/mob/mob) var/msg="[key_name(mob)] has compiled a script to server [src]:" log_game("NTSL: [msg]") - log_game("NTSL: [rawcode]") - src.investigate_log("[msg]
[rawcode]", "ntsl") + log_game("NTSL: [rawcode.Join("")]") + src.investigate_log("[msg]
[rawcode.Join("")]", "ntsl") if(length(rawcode)) // Let's not bother the admins for empty code. message_admins("[key_name_admin(mob)] has compiled and uploaded a NTSL script to [src.id] (JMP)") diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm index a2580285a38..45f0817ef55 100644 --- a/code/game/machinery/telecomms/traffic_control.dm +++ b/code/game/machinery/telecomms/traffic_control.dm @@ -117,6 +117,7 @@ function compileCode() { var codeText = cMirror_fSubmit.getValue(); document.getElementById("cMirrorPost").value = codeText; + document.getElementById("cMirrorPostList").value = JSON.stringify(codeText.split('')); document.getElementById("theform").submit(); } @@ -135,6 +136,7 @@ + "} else @@ -189,6 +191,10 @@ if(code) storedcode = code + var/list/codelist = href_list["cMirrorList"] + if(istext(codelist)) + codelist = json_decode(codelist) + add_fingerprint(user) user.set_machine(src) @@ -198,14 +204,14 @@ switch(href_list["choice"]) if("Compile") - if(!code) + if(!istype(codelist)) return 0 if(user != editingcode) return 0 //only one editor if(SelectedServer) var/obj/machinery/telecomms/server/Server = SelectedServer - Server.setcode(code) + Server.setcode(codelist) spawn(0) // Output all the compile-time errors @@ -234,7 +240,7 @@ updateUsrDialog() for(var/obj/machinery/telecomms/server/Server in servers) - Server.setcode(code) + Server.setcode(codelist) var/list/compileerrors = Server.compile(user) if(!telecomms_check(user)) return diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index a1248fc0b6d..46671a9f4fa 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -38,21 +38,20 @@ break return power_station -/obj/machinery/computer/teleporter/attackby(I as obj, mob/living/user as mob, params) +/obj/machinery/computer/teleporter/attackby(obj/item/I, mob/living/user, params) if(istype(I, /obj/item/gps)) var/obj/item/gps/L = I if(L.locked_location && !(stat & (NOPOWER|BROKEN))) if(!user.unEquip(L)) - to_chat(user, "\the [I] is stuck to your hand, you cannot put it in \the [src]") + to_chat(user, "[I] is stuck to your hand, you cannot put it in [src]") return - L.loc = src + L.forceMove(src) locked = L - to_chat(user, "You insert the GPS device into the [name]'s slot.") + to_chat(user, "You insert the GPS device into the [src]'s slot.") else - ..() - return + return ..() -/obj/machinery/computer/teleporter/emag_act(user as mob) +/obj/machinery/computer/teleporter/emag_act(mob/user) if(!emagged) emagged = 1 to_chat(user, "The teleporter can now lock on to Syndicate beacons!") @@ -341,14 +340,17 @@ //--FalseIncarnate return -/obj/machinery/teleport/hub/attackby(obj/item/W, mob/user, params) - if(default_deconstruction_screwdriver(user, "tele-o", "tele0", W)) +/obj/machinery/teleport/hub/attackby(obj/item/I, mob/user, params) + if(default_deconstruction_screwdriver(user, "tele-o", "tele0", I)) return - if(exchange_parts(user, W)) + if(exchange_parts(user, I)) return - default_deconstruction_crowbar(W) + if(default_deconstruction_crowbar(I)) + return + + return ..() /obj/machinery/teleport/hub/proc/teleport(atom/movable/M as mob|obj, turf/T) var/obj/machinery/computer/teleporter/com = power_station.teleporter_console @@ -438,14 +440,17 @@ else icon_state = "tele0" -/obj/machinery/teleport/perma/attackby(obj/item/W, mob/user, params) - if(default_deconstruction_screwdriver(user, "tele-o", "tele0", W)) +/obj/machinery/teleport/perma/attackby(obj/item/I, mob/user, params) + if(default_deconstruction_screwdriver(user, "tele-o", "tele0", I)) return - if(exchange_parts(user, W)) + if(exchange_parts(user, I)) return - default_deconstruction_crowbar(W) + if(default_deconstruction_crowbar(I)) + return + + return ..() /obj/machinery/teleport/station name = "station" @@ -506,41 +511,46 @@ teleporter_console = null return ..() -/obj/machinery/teleport/station/attackby(var/obj/item/W, mob/user, params) - if(istype(W, /obj/item/multitool) && !panel_open) - var/obj/item/multitool/M = W +/obj/machinery/teleport/station/attackby(obj/item/I, mob/user, params) + if(ismultitool(I) && !panel_open) + var/obj/item/multitool/M = I if(M.buffer && istype(M.buffer, /obj/machinery/teleport/station) && M.buffer != src) if(linked_stations.len < efficiency) linked_stations.Add(M.buffer) M.buffer = null - to_chat(user, "You upload the data from the [W.name]'s buffer.") + to_chat(user, "You upload the data from [M]'s buffer.") else to_chat(user, "This station can't hold more information, try to use better parts.") - if(default_deconstruction_screwdriver(user, "controller-o", "controller", W)) + return + + if(default_deconstruction_screwdriver(user, "controller-o", "controller", I)) update_icon() return - if(exchange_parts(user, W)) + if(exchange_parts(user, I)) return - default_deconstruction_crowbar(W) + if(default_deconstruction_crowbar(I)) + return if(panel_open) - if(istype(W, /obj/item/multitool)) - var/obj/item/multitool/M = W + if(ismultitool(I)) + var/obj/item/multitool/M = I M.buffer = src - to_chat(user, "You download the data to the [W.name]'s buffer.") + to_chat(user, "You download the data to the [M]'s buffer.") return - if(istype(W, /obj/item/wirecutters)) + if(iswirecutter(I)) link_console_and_hub() to_chat(user, "You reconnect the station to nearby machinery.") return - if(istype(W, /obj/item/circuitboard/teleporter_perma)) - var/obj/item/circuitboard/teleporter_perma/C = W + if(istype(I, /obj/item/circuitboard/teleporter_perma)) + var/obj/item/circuitboard/teleporter_perma/C = I C.target = teleporter_console.target - to_chat(user, "You copy the targeting information from \the [src] to \the [W]") + to_chat(user, "You copy the targeting information from [src] to [C]") return + return ..() + /obj/machinery/teleport/station/attack_ai() src.attack_hand() diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index 45294f01286..5e99a954650 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -289,18 +289,18 @@ qdel(I) H.equipOutfit(selected_outfit) - H.species.after_equip_job(null, H) + H.dna.species.after_equip_job(null, H) /obj/machinery/transformer/transmogrifier name = "species transmogrifier" desc = "As promoted in Calvin & Hobbes!" - var/target_species = "Human" + var/datum/species/target_species = /datum/species/human /obj/machinery/transformer/transmogrifier/do_transform(mob/living/carbon/human/H) if(!istype(H)) return - if(!(target_species in all_species)) + if(!ispath(target_species)) to_chat(H, "'[target_species]' is not a valid species!") return H.set_species(target_species) @@ -336,7 +336,7 @@ to_chat(H, "No genetic template configured!") return var/prev_ue = H.dna.unique_enzymes - H.set_species(template.species) + H.set_species(template.species.type) H.dna = template.Clone() H.real_name = template.real_name H.sync_organ_dna(assimilate = 0, old_ue = prev_ue) @@ -344,12 +344,12 @@ domutcheck(H, null, MUTCHK_FORCED) H.update_mutations() -/obj/machinery/transformer/gene_applier/attackby(obj/item/W, mob/living/user, params) - if(istype(W, /obj/item/disk/data)) +/obj/machinery/transformer/gene_applier/attackby(obj/item/I, mob/living/user, params) + if(istype(I, /obj/item/disk/data)) if(locked) to_chat(user, "Access Denied.") return FALSE - var/obj/item/disk/data/D = W + var/obj/item/disk/data/D = I if(!D.buf) to_chat(user, "Error: No data found.") return FALSE diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index db228aff04f..42eeafd338c 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1,7 +1,3 @@ -#define CAT_NORMAL 1 -#define CAT_HIDDEN 2 // also used in corresponding wires/vending.dm -#define CAT_COIN 4 - /** * Datum used to hold information about a product in a vending machine */ @@ -292,7 +288,7 @@ insert_item(user, I) return else - ..() + return ..() //Override this proc to do per-machine checks on the inserted item, but remember to call the parent to handle these generic checks before your logic! /obj/machinery/vending/proc/item_slot_check(mob/user, obj/item/I) @@ -840,6 +836,9 @@ /obj/item/reagent_containers/food/drinks/chicken_soup = 30,/obj/item/reagent_containers/food/drinks/weightloss = 50, /obj/item/reagent_containers/food/drinks/mug = 50) refill_canister = /obj/item/vending_refill/coffee +/obj/machinery/vending/coffee/free + prices = list() + /obj/machinery/vending/coffee/New() ..() component_parts = list() @@ -892,6 +891,9 @@ /obj/item/reagent_containers/food/snacks/pistachios = 35, /obj/item/reagent_containers/food/snacks/spacetwinkie = 30,/obj/item/reagent_containers/food/snacks/cheesiehonkers = 25,/obj/item/reagent_containers/food/snacks/tastybread = 30) refill_canister = /obj/item/vending_refill/snack +/obj/machinery/vending/snack/free + prices = list() + /obj/machinery/vending/snack/New() ..() component_parts = list() @@ -913,6 +915,9 @@ /obj/item/reagent_containers/food/snacks/chinese/rice = 50) refill_canister = /obj/item/vending_refill/chinese +/obj/machinery/vending/chinese/free + prices = list() + /obj/machinery/vending/chinese/New() ..() component_parts = list() @@ -938,6 +943,9 @@ /obj/item/reagent_containers/food/drinks/cans/space_up = 20,/obj/item/reagent_containers/food/drinks/cans/grape_juice = 20) refill_canister = /obj/item/vending_refill/cola +/obj/machinery/vending/cola/free + prices = list() + /obj/machinery/vending/cola/New() ..() component_parts = list() @@ -965,6 +973,9 @@ /obj/item/cartridge/signal = 75) armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0) +/obj/machinery/vending/cart/free + prices = list() + /obj/machinery/vending/liberationstation name = "\improper Liberation Station" desc = "An overwhelming amount of ancient patriotism washes over you just by looking at the machine." @@ -994,6 +1005,9 @@ prices = list(/obj/item/storage/fancy/cigarettes = 60,/obj/item/storage/fancy/cigarettes/cigpack_uplift = 60,/obj/item/storage/fancy/cigarettes/cigpack_robust = 60,/obj/item/storage/fancy/cigarettes/cigpack_carp = 60,/obj/item/storage/fancy/cigarettes/cigpack_midori = 60,/obj/item/storage/fancy/cigarettes/cigpack_random = 150, /obj/item/reagent_containers/food/pill/patch/nicotine = 15, /obj/item/storage/box/matches = 10,/obj/item/lighter/random = 60, /obj/item/storage/fancy/rollingpapers = 20) refill_canister = /obj/item/vending_refill/cigarette +/obj/machinery/vending/cigarette/free + prices = list() + /obj/machinery/vending/cigarette/New() ..() component_parts = list() @@ -1013,7 +1027,7 @@ req_access_txt = "5" products = list(/obj/item/reagent_containers/glass/bottle/charcoal = 4,/obj/item/reagent_containers/glass/bottle/morphine = 4,/obj/item/reagent_containers/glass/bottle/ether = 4,/obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/toxin = 4,/obj/item/reagent_containers/syringe/antiviral = 6,/obj/item/reagent_containers/syringe/insulin = 4, - /obj/item/reagent_containers/syringe = 12,/obj/item/healthanalyzer = 5,/obj/item/healthupgrade = 5,/obj/item/reagent_containers/glass/beaker = 4, + /obj/item/reagent_containers/syringe = 12,/obj/item/healthanalyzer = 5,/obj/item/healthupgrade = 5,/obj/item/reagent_containers/glass/beaker = 4, /obj/item/reagent_containers/hypospray/safety = 2, /obj/item/reagent_containers/dropper = 2,/obj/item/stack/medical/bruise_pack/advanced = 3, /obj/item/stack/medical/ointment/advanced = 3, /obj/item/stack/medical/bruise_pack = 3,/obj/item/stack/medical/splint = 4, /obj/item/sensor_device = 2, /obj/item/reagent_containers/hypospray/autoinjector = 4, /obj/item/pinpointer/crew = 2) @@ -1433,6 +1447,9 @@ premium = list(/obj/item/toy/pet_rock/fred = 1, /obj/item/toy/pet_rock/roxie = 1) refill_canister = /obj/item/vending_refill/crittercare +/obj/machinery/vending/crittercare/free + prices = list() + /obj/machinery/vending/crittercare/New() ..() component_parts = list() diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index 217b1e70165..248514179af 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -1,62 +1,42 @@ /obj/machinery/wish_granter - name = "Wish Granter" + name = "wish granter" desc = "You're not so sure about this, anymore..." icon = 'icons/obj/device.dmi' icon_state = "syndbeacon" - use_power = 0 - anchored = 1 - density = 1 - var/datum/mind/target - var/list/types = list() - var/inuse = 0 + use_power = NO_POWER_USE + anchored = TRUE + density = TRUE -/obj/machinery/wish_granter/New() - for(var/supname in all_superheroes) - types |= supname - ..() + var/charges = 1 + var/insisting = FALSE -/obj/machinery/wish_granter/attack_hand(var/mob/user as mob) - usr.set_machine(src) +/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user) + . = ..() + if(.) + return + if(charges <= 0) + to_chat(user, "The Wish Granter lies silent.") + return - if(!istype(user, /mob/living/carbon/human)) + else if(!ishuman(user)) to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.") return - if(is_special_character(user)) + else if(is_special_character(user)) to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.") - return - if(inuse) - to_chat(user, "Someone is already communing with the Wish Granter.") - return + else if(!insisting) + to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?") + insisting = TRUE - to_chat(user, "The power of the Wish Granter have turned you into the superhero the station deserves. You are a masked vigilante, and answer to no man. Will you use your newfound strength to protect the innocent, or will you hunt the guilty?") - - inuse = 1 - var/wish - if(types.len == 1) - wish = pick(types) else - wish = input("You want to become...","Wish") as null|anything in types - if(!wish) - inuse=0 - return - types -= wish - var/mob/living/carbon/human/M = user - var/datum/superheroes/S = all_superheroes[wish] - if(S) - S.create(M) - inuse=0 + to_chat(user, "You speak. [pick("I want the station to disappear", "Humanity is corrupt, mankind must be destroyed", "I want to be rich", "I want to rule the world", "I want immortality.")]. The Wish Granter answers.") + to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.") - //Remove the wishgranter or teleport it randomly on the station - if(!types.len) - to_chat(user, "The wishgranter slowly fades into mist...") - qdel(src) - return - else - var/impact_area = findEventArea() - var/turf/T = pick(get_area_turfs(impact_area)) - if(T) - src.loc = T - return \ No newline at end of file + charges-- + insisting = FALSE + + user.mind.add_antag_datum(/datum/antagonist/wishgranter) + + to_chat(user, "You have a very bad feeling about this.") \ No newline at end of file diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index b990029423c..62928c95be5 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -12,7 +12,6 @@ var/energy_drain = 0 var/obj/mecha/chassis = null var/range = MELEE //bitflags - reliability = 1000 var/salvageable = 1 var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 5f3483d2ce4..a9d4b4008b6 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -74,7 +74,7 @@ /obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/patient_insertion_check(mob/living/carbon/target) if(target.buckled) - occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled]!") + occupant_message("[target] will not fit into the sleeper because [target.p_they()] [target.p_are()] buckled to [target.buckled]!") return if(target.has_buckled_mobs()) occupant_message("[target] will not fit into the sleeper because of the creatures attached to it!") diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 2ff4f478e2d..d0af747dc64 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -158,15 +158,16 @@ overlays -= "fab-active" desc = initial(desc) - var/obj/item/I = new D.build_path + var/obj/item/I = new D.build_path(loc) if(D.locked) - var/obj/item/storage/lockbox/large/L = new /obj/item/storage/lockbox/large(get_step(src,SOUTH)) //(Don't use capitals in paths, or single letters. - I.loc = L + var/obj/item/storage/lockbox/large/L = new /obj/item/storage/lockbox/large(get_step(src, SOUTH)) //(Don't use capitals in paths, or single letters. + I.forceMove(L) L.name += " [initial(I.name)]" L.origin_tech = I.origin_tech else - I.loc = get_step(src,SOUTH) - I.materials = res_coef + I.forceMove(get_step(src, SOUTH)) + if(istype(I)) + I.materials = res_coef atom_say("[I] is complete.") being_built = null diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index bb666a63da1..a2fa4220c3c 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -469,18 +469,11 @@ /obj/mecha/attack_hand(mob/living/user) user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) log_message("Attack by hand/paw. Attacker - [user].",1) - - if((HULK in user.mutations) && !prob(deflect_chance)) - take_damage(15) - check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - user.visible_message("[user] hits [name], doing some damage.", - "You hit [name] with all your might. The metal creaks and bends.") - else - user.visible_message("[user] hits [name]. Nothing happens","You hit [name] with no visible effect.") - log_append_to_last("Armor saved.") - return + user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) + playsound(loc, 'sound/weapons/tap.ogg', 40, 1, -1) + user.visible_message("[user] hits [name]. Nothing happens", "You hit [name] with no visible effect.") + log_append_to_last("Armor saved.") /obj/mecha/attack_alien(mob/living/user) @@ -524,6 +517,16 @@ user.create_attack_log("attacked [name]") return +/obj/mecha/hulk_damage() + return 15 + +/obj/mecha/attack_hulk(mob/living/carbon/human/user) + . = ..() + if(.) + check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL, MECHA_INT_TANK_BREACH, MECHA_INT_CONTROL_LOST)) + log_message("Attack by hulk. Attacker - [user].", 1) + add_attack_logs(user, src, "Punched with hulk powers") + /obj/mecha/hitby(atom/movable/A) //wrapper ..() log_message("Hit by [A].",1) @@ -1203,6 +1206,10 @@ occupant = brainmob brainmob.forceMove(src) //should allow relaymove brainmob.canmove = 1 + if(istype(mmi_as_oc, /obj/item/mmi/robotic_brain)) + var/obj/item/mmi/robotic_brain/R = mmi_as_oc + if(R.imprinted_master) + to_chat(brainmob, "Your imprint to [R.imprinted_master] has been temporarily disabled. You should help the crew and not commit harm.") mmi_as_oc.loc = src mmi_as_oc.mecha = src verbs -= /obj/mecha/verb/eject @@ -1302,6 +1309,10 @@ mmi.mecha = null mmi.update_icon() L.canmove = 0 + if(istype(mmi, /obj/item/mmi/robotic_brain)) + var/obj/item/mmi/robotic_brain/R = mmi + if(R.imprinted_master) + to_chat(L, "Imprint re-enabled, you are once again bound to [R.imprinted_master]'s commands.") icon_state = initial(icon_state)+"-open" dir = dir_in @@ -1478,3 +1489,15 @@ if(occupant_sight_flags) if(user == occupant) user.sight |= occupant_sight_flags + +/obj/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y) + if(!no_effect) + if(selected) + used_item = selected + else if(!visual_effect_icon) + visual_effect_icon = ATTACK_EFFECT_SMASH + if(damtype == BURN) + visual_effect_icon = ATTACK_EFFECT_MECHFIRE + else if(damtype == TOX) + visual_effect_icon = ATTACK_EFFECT_MECHTOXIN + ..() \ No newline at end of file diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 6c455c673f3..2ce732f83ed 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -298,6 +298,7 @@ var/newname = strip_html_simple(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN) if(newname && trim(newname)) name = newname + log_game("[key_name(occupant)] has renamed an exosuit [newname]") else alert(occupant, "nope.avi") return diff --git a/code/game/objects/effects/barsign.dm b/code/game/objects/effects/barsign.dm deleted file mode 100644 index fd66f8028d1..00000000000 --- a/code/game/objects/effects/barsign.dm +++ /dev/null @@ -1,8 +0,0 @@ -/obj/effect/sign/double/barsign - icon = 'icons/obj/barsigns.dmi' - icon_state = "empty" - anchored = 1 - - New() - var/list/valid_states = list("pinkflamingo", "magmasea", "limbo", "rustyaxe", "armokbar", "brokendrum", "meadbay", "thedamnwall", "thecavern", "cindikate", "theorchard", "thesaucyclown", "theclownshead", "whiskeyimplant", "carpecarp", "robustroadhouse", "greytide", "theredshirt") - src.icon_state = "[pick(valid_states)]" diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm index 6bcfb253454..301fd71a98d 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/misc.dm @@ -1,12 +1,3 @@ -/obj/effect/decal/point - name = "arrow" - desc = "It's an arrow hanging in mid-air. There may be a wizard about." - icon = 'icons/mob/screen_gen.dmi' - icon_state = "arrow" - layer = 16.0 - anchored = 1 - mouse_opacity = 0 - // Used for spray that you spray at walls, tables, hydrovats etc /obj/effect/decal/spraystill density = 0 diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 17723adcde7..e765e59442d 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -163,13 +163,14 @@ // dense and opaque, but easy to break /obj/structure/foamedmetal - icon = 'icons/effects/effects.dmi' - icon_state = "metalfoam" - density = 1 - opacity = 1 // changed in New() - anchored = 1 name = "foamed metal" desc = "A lightweight foamed metal wall." + icon = 'icons/effects/effects.dmi' + icon_state = "metalfoam" + density = TRUE + opacity = TRUE // changed in New() + anchored = TRUE + max_integrity = 20 var/metal = MFOAM_ALUMINUM /obj/structure/foamedmetal/Initialize() @@ -177,7 +178,6 @@ air_update_turf(1) /obj/structure/foamedmetal/Destroy() - density = 0 air_update_turf(1) return ..() @@ -186,64 +186,31 @@ ..() move_update_air(T) +/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + playsound(loc, 'sound/weapons/tap.ogg', 100, 1) + /obj/structure/foamedmetal/proc/updateicon() if(metal == MFOAM_ALUMINUM) icon_state = "metalfoam" + max_integrity = 20 + obj_integrity = max_integrity else icon_state = "ironfoam" - -/obj/structure/foamedmetal/ex_act(severity) - qdel(src) - -/obj/structure/foamedmetal/blob_act() - qdel(src) - -/obj/structure/foamedmetal/bullet_act() - if(metal==MFOAM_ALUMINUM || prob(50)) - qdel(src) + max_integrity = 50 + obj_integrity = max_integrity /obj/structure/foamedmetal/attack_hand(mob/user) user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - if((HULK in user.mutations) || (prob(75 - metal*25))) - user.visible_message("[user] smashes through \the [src].", "You smash through \the [src].") + user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) + if(prob(75 - metal * 25)) + user.visible_message("[user] smashes through [src].", "You smash through [src].") qdel(src) else to_chat(user, "You hit the metal foam but bounce off it.") + playsound(loc, 'sound/weapons/tap.ogg', 100, 1) -/obj/structure/foamedmetal/attackby(obj/item/I, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - if(istype(I, /obj/item/grab)) - var/obj/item/grab/G = I - G.affecting.loc = src.loc - user.visible_message("[G.assailant] smashes [G.affecting] through the foamed metal wall.") - qdel(I) - qdel(src) - return - - if(prob(I.force*20 - metal*25)) - user.visible_message("[user] smashes through the foamed metal with \the [I].", "You smash through the foamed metal with \the [I].") - qdel(src) - else - to_chat(user, "You hit the metal foam to no effect.") - -/obj/structure/foamedmetal/attack_animal(mob/living/simple_animal/M) - M.do_attack_animation(src) - if(M.melee_damage_upper == 0) - M.visible_message("[M] nudges \the [src].") - else - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - M.visible_message("\The [M] [M.attacktext] [src]!") - qdel(src) - -/obj/structure/foamedmetal/attack_alien(mob/living/carbon/alien/humanoid/M) - M.visible_message("[M] tears apart \the [src]!"); - qdel(src) - -/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5) +/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target) return !density /obj/structure/foamedmetal/CanAtmosPass() - return !density + return !density \ No newline at end of file diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 385067e0611..1df0166260e 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -263,13 +263,13 @@ var/more = "" if(M) more = " " - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1) + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", ATKLOG_FEW) log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].") else - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1) + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", ATKLOG_FEW) log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") else - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", 0, 1) + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", ATKLOG_FEW) log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key. CODERS: carry.my_atom may be null.") /datum/effect_system/smoke_spread/chem/start(effect_range = 2) diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index 467858ad670..5836136401e 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -6,9 +6,13 @@ icon = 'icons/effects/effects.dmi' burn_state = LAVA_PROOF | FIRE_PROOF resistance_flags = INDESTRUCTIBLE + can_be_hit = FALSE /obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) return /obj/effect/fire_act() - return \ No newline at end of file + return + +/obj/effect/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + return FALSE \ No newline at end of file diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index a11236df0e5..18506a5c882 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -60,7 +60,7 @@ victim.apply_effect(radiation_amount, IRRADIATE, 0) if(ishuman(victim)) var/mob/living/carbon/human/V = victim - if(NO_DNA in V.species.species_traits) + if(NO_DNA in V.dna.species.species_traits) return randmutb(victim) domutcheck(victim ,null) diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index cf65c0b912f..9ffca668c28 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -130,7 +130,7 @@ ////////////////CONTRABAND STUFF////////////////// /obj/item/grenade/clown_grenade = 3, /obj/item/seeds/ambrosia/cruciatus = 3, - /obj/item/gun/projectile/automatic/pistol/empty = 1, + /obj/item/gun/projectile/automatic/pistol = 1, /obj/item/ammo_box/magazine/m10mm = 4, /obj/item/soap/syndie = 7, /obj/item/gun/syringe/syndicate = 2, diff --git a/code/game/objects/effects/spawners/random_barrier.dm b/code/game/objects/effects/spawners/random_barrier.dm index 3fd81bcf9b0..e337df8df27 100644 --- a/code/game/objects/effects/spawners/random_barrier.dm +++ b/code/game/objects/effects/spawners/random_barrier.dm @@ -11,7 +11,7 @@ // This needs to come before the initialization wave because // the thing it creates might need to be initialized too -/obj/effect/spawner/random_barrier/New() +/obj/effect/spawner/random_barrier/Initialize() . = ..() var/turf/T = get_turf(src) if(!T) diff --git a/code/game/objects/effects/spawners/random_spawners.dm b/code/game/objects/effects/spawners/random_spawners.dm index 621c8799cc2..4e381c96c3b 100644 --- a/code/game/objects/effects/spawners/random_spawners.dm +++ b/code/game/objects/effects/spawners/random_spawners.dm @@ -12,7 +12,7 @@ // This needs to come before the initialization wave because // the thing it creates might need to be initialized too -/obj/effect/spawner/random_spawners/New() +/obj/effect/spawner/random_spawners/Initialize() . = ..() var/turf/T = get_turf(src) if(!T) diff --git a/code/game/objects/effects/spawners/windowspawner.dm b/code/game/objects/effects/spawners/windowspawner.dm index 6d271039070..e6e2aaa1a21 100644 --- a/code/game/objects/effects/spawners/windowspawner.dm +++ b/code/game/objects/effects/spawners/windowspawner.dm @@ -8,33 +8,34 @@ anchored = 1 // No sliding out while you prime /obj/effect/spawner/window/Initialize() - ..() - spawn(0) - var/turf/T = get_turf(src) - for(var/obj/structure/grille/G in get_turf(src)) - // Complain noisily - log_runtime(EXCEPTION("Extra grille on turf: ([T.x],[T.y],[T.z])"), src) - qdel(G) //just in case mappers don't know what they are doing + . = ..() + var/turf/T = get_turf(src) + for(var/obj/structure/grille/G in get_turf(src)) + // Complain noisily + log_runtime(EXCEPTION("Extra grille on turf: ([T.x],[T.y],[T.z])"), src) + qdel(G) //just in case mappers don't know what they are doing - if(!useFull) - for(var/cdir in cardinal) - for(var/obj/effect/spawner/window/WS in get_step(src,cdir)) - cdir = null - break - if(!cdir) continue - var/obj/structure/window/WI = new windowtospawn(get_turf(src)) - WI.dir = cdir - else - var/obj/structure/window/W = new windowtospawn(get_turf(src)) - W.dir = SOUTHWEST + if(!useFull) + for(var/cdir in cardinal) + for(var/obj/effect/spawner/window/WS in get_step(src,cdir)) + cdir = null + break + if(!cdir) continue + var/obj/structure/window/WI = new windowtospawn(get_turf(src)) + WI.dir = cdir + else + var/obj/structure/window/W = new windowtospawn(get_turf(src)) + W.dir = SOUTHWEST - if(useGrille) - new /obj/structure/grille(get_turf(src)) + if(useGrille) + new /obj/structure/grille(get_turf(src)) - src.air_update_turf(1) //atmos can pass otherwise - - spawn(10) - qdel(src) + src.air_update_turf(1) //atmos can pass otherwise + // Give some time for nearby window spawners to initialize + spawn(10) + qdel(src) + // why is this line a no-op + // QDEL_IN(src, 10) /obj/effect/spawner/window/reinforced diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 02c04fbfbea..29abbef2d76 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -219,7 +219,7 @@ if(C) S.key = C.key if(S.master_commander) - to_chat(S, "You are a spider who is loyal to [S.master_commander], obey [S.master_commander]'s every order and assist them in completing their goals at any cost.") + to_chat(S, "You are a spider who is loyal to [S.master_commander], obey [S.master_commander]'s every order and assist [S.master_commander.p_them()] in completing [S.master_commander.p_their()] goals at any cost.") qdel(src) /obj/effect/decal/cleanable/spiderling_remains diff --git a/code/game/objects/effects/temporary_visuals/clockcult.dm b/code/game/objects/effects/temporary_visuals/clockcult.dm index 4a70c73c9c3..f6b654ccbbe 100644 --- a/code/game/objects/effects/temporary_visuals/clockcult.dm +++ b/code/game/objects/effects/temporary_visuals/clockcult.dm @@ -6,6 +6,10 @@ randomdir = 0 layer = ABOVE_NORMAL_TURF_LAYER +/obj/effect/temp_visual/ratvar/door/window + icon_state = "ratvarwindoorglow" + layer = ABOVE_WINDOW_LAYER + /obj/effect/temp_visual/ratvar/beam icon_state = "ratvarbeamglow" @@ -15,6 +19,13 @@ /obj/effect/temp_visual/ratvar/floor icon_state = "ratvarfloorglow" +/obj/effect/temp_visual/ratvar/window + icon_state = "ratvarwindowglow" + layer = ABOVE_OBJ_LAYER + +/obj/effect/temp_visual/ratvar/window/single + icon_state = "ratvarwindowglow_s" + /obj/effect/temp_visual/ratvar/grille icon_state = "ratvargrilleglow" layer = BELOW_OBJ_LAYER diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 001c482a922..03e8ea8fcd9 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -1,3 +1,12 @@ +/obj/effect/temp_visual/point + name = "arrow" + desc = "It's an arrow hanging in mid-air. There may be a wizard about." + icon = 'icons/mob/screen_gen.dmi' + icon_state = "arrow" + layer = POINT_LAYER + duration = 20 + randomdir = FALSE + /obj/effect/temp_visual/dir_setting/bloodsplatter icon = 'icons/effects/blood.dmi' duration = 5 diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm index ddf5b618bd5..2188337ba77 100644 --- a/code/game/objects/empulse.dm +++ b/code/game/objects/empulse.dm @@ -5,8 +5,8 @@ epicenter = get_turf(epicenter.loc) if(log) - message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") - log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") + message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [ADMIN_COORDJMP(epicenter)]") + log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [COORD(epicenter)]") if(heavy_range > 1) new/obj/effect/temp_visual/emp/pulse(epicenter) @@ -29,4 +29,4 @@ T.emp_act(2) else if(distance <= light_range) T.emp_act(2) - return 1 \ No newline at end of file + return 1 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index b2d0d6720c7..03b4f4adfaa 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -15,6 +15,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d var/inhand_x_dimension = 32 var/inhand_y_dimension = 32 + can_be_hit = FALSE + var/r_speed = 1.0 var/health = null var/hitsound = null @@ -277,25 +279,25 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d // Due to storage type consolidation this should get used more now. // I have cleaned it up a little, but it could probably use more. -Sayu -/obj/item/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W,/obj/item/storage)) - var/obj/item/storage/S = W +/obj/item/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/storage)) + var/obj/item/storage/S = I if(S.use_to_pickup) if(S.collection_mode) //Mode is set to collect all items on a tile and we clicked on a valid one. - if(isturf(src.loc)) + if(isturf(loc)) var/list/rejections = list() var/success = 0 var/failure = 0 - for(var/obj/item/I in src.loc) - if(I.type in rejections) // To limit bag spamming: any given type only complains once + for(var/obj/item/IT in loc) + if(IT.type in rejections) // To limit bag spamming: any given type only complains once continue - if(!S.can_be_inserted(I)) // Note can_be_inserted still makes noise when the answer is no - rejections += I.type // therefore full bags are still a little spammy + if(!S.can_be_inserted(IT)) // Note can_be_inserted still makes noise when the answer is no + rejections += IT.type // therefore full bags are still a little spammy failure = 1 continue success = 1 - S.handle_item_insertion(I, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed. + S.handle_item_insertion(IT, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed. if(success && !failure) to_chat(user, "You put everything in [S].") else if(success) @@ -305,8 +307,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d else if(S.can_be_inserted(src)) S.handle_item_insertion(src) - - return + else + return ..() /obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) if(prob(final_block_chance)) @@ -443,13 +445,14 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d playsound(loc, src.hitsound, 30, 1, -1) + user.do_attack_animation(M) + if(M != user) M.visible_message("[user] has stabbed [M] in the eye with [src]!", \ "[user] stabs you in the eye with [src]!") - user.do_attack_animation(M) else user.visible_message( \ - "[user] has stabbed themself in the eyes with [src]!", \ + "[user] has stabbed [user.p_them()]self in the eyes with [src]!", \ "You stab yourself in the eyes with [src]!" \ ) @@ -464,7 +467,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d eyes.receive_damage(rand(3,4), 1) if(eyes.damage >= eyes.min_bruised_damage) if(M.stat != 2) - if(!(eyes.status & ORGAN_ROBOT) || !(eyes.status & ORGAN_ASSISTED)) //robot eyes bleeding might be a bit silly + if(!eyes.is_robotic()) //robot eyes bleeding might be a bit silly to_chat(M, "Your eyes start to bleed profusely!") if(prob(50)) if(M.stat != DEAD) @@ -549,3 +552,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d /obj/item/proc/on_trip(mob/living/carbon/human/H) if(H.slip(src, trip_stun, trip_weaken, trip_tiles, trip_walksafe, trip_any, trip_verb)) return TRUE + +/obj/item/attack_hulk(mob/living/carbon/human/user) + return FALSE \ No newline at end of file diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 295b133d92e..b4dd66e3be5 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -22,7 +22,7 @@ var/list/validSurfaces = list(/turf/simulated/floor) /obj/item/toy/crayon/suicide_act(mob/user) - user.visible_message("[user] is jamming the [src.name] up \his nose and into \his brain. It looks like \he's trying to commit suicide.") + user.visible_message("[user] is jamming the [name] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide.") return (BRUTELOSS|OXYLOSS) /obj/item/toy/crayon/New() diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 154a2032825..737abd10bb1 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -83,8 +83,8 @@ if(href_list["wipe"]) var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE)) - msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].") - log_attack(user, AI, "Wiped with [src].") + msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].", ATKLOG_FEW) + add_attack_logs(user, AI, "Wiped with [src].") flush = 1 AI.suiciding = 1 to_chat(AI, "Your core files are being wiped!") diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 0e2e3cc3785..5056c90793f 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -95,7 +95,7 @@ to_chat(M, "[user] blinds you with the flash!") if(M.weakeyes) M.Stun(2) - M.visible_message("[M] gasps and shields their eyes!", "You gasp and shields your eyes!") + M.visible_message("[M] gasps and shields [M.p_their()] eyes!", "You gasp and shields your eyes!") else visible_message("[user] fails to blind [M] with the flash!") to_chat(user, "You fail to blind [M] with the flash!") @@ -123,7 +123,7 @@ for(var/obj/item/borg/combat/shield/S in R.module.modules) if(R.activated(S)) add_attack_logs(user, M, "Flashed with [src]") - user.visible_message("[user] tries to overloads [M]'s sensors with the [src.name], but is blocked by [M]'s shield!", "You try to overload [M]'s sensors with the [src.name], but are blocked by their shield!") + user.visible_message("[user] tries to overloads [M]'s sensors with the [src.name], but is blocked by [M]'s shield!", "You try to overload [M]'s sensors with the [src.name], but are blocked by [M.p_their()] shield!") return 1 add_attack_logs(user, M, "Flashed with [src]") if(M.flash_eyes(affect_silicon = 1)) @@ -168,9 +168,9 @@ resisted = 1 if(resisted) - to_chat(user, "This mind seems resistant to the [src.name]!") + to_chat(user, "This mind seems resistant to the [name]!") else - to_chat(user, "They must be conscious before you can convert them!") + to_chat(user, "They must be conscious before you can convert [M.p_them()]!") else to_chat(user, "This mind is so vacant that it is not susceptible to influence!") diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index e7156cb6888..fb1956a56e9 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -61,10 +61,10 @@ if(M == user) //they're using it on themselves if(M.flash_eyes(visual = 1)) - M.visible_message("[M] directs [src] to \his eyes.", \ + M.visible_message("[M] directs [src] to [M.p_their()] eyes.", \ "You wave the light in front of your eyes! Trippy!") else - M.visible_message("[M] directs [src] to \his eyes.", \ + M.visible_message("[M] directs [src] to [M.p_their()] eyes.", \ "You wave the light in front of your eyes.") else diff --git a/code/game/objects/items/devices/instruments.dm b/code/game/objects/items/devices/instruments.dm index 3a0f2b6941d..639382ed03e 100644 --- a/code/game/objects/items/devices/instruments.dm +++ b/code/game/objects/items/devices/instruments.dm @@ -18,7 +18,7 @@ return ..() /obj/item/instrument/suicide_act(mob/user) - user.visible_message("[user] begins to play 'Gloomy Sunday'! It looks like \he's trying to commit suicide!") + user.visible_message("[user] begins to play 'Gloomy Sunday'! It looks like [user.p_theyre()] trying to commit suicide!") return (BRUTELOSS) /obj/item/instrument/Initialize(mapload) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 678d6837a8e..32b548c38aa 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -81,7 +81,7 @@ return if(ishuman(user)) var/mob/living/carbon/human/H = user - if((HULK in H.mutations) || (NOGUNS in H.species.species_traits)) + if((HULK in H.mutations) || (NOGUNS in H.dna.species.species_traits)) user << "Your fingers can't press the button!" return @@ -109,11 +109,11 @@ //20% chance to actually hit the eyes if(prob(effectchance * diode.rating) && C.flash_eyes(severity)) - outmsg = "You blind [C] by shining [src] in their eyes." + outmsg = "You blind [C] by shining [src] in [C.p_their()] eyes." if(C.weakeyes) C.Stun(1) else - outmsg = "You fail to blind [C] by shining [src] at their eyes!" + outmsg = "You fail to blind [C] by shining [src] at [C.p_their()] eyes!" //robots and AI else if(issilicon(target)) @@ -123,11 +123,11 @@ S.flash_eyes(affect_silicon = 1) S.Weaken(rand(5,10)) to_chat(S, "Your sensors were overloaded by a laser!") - outmsg = "You overload [S] by shining [src] at their sensors." + outmsg = "You overload [S] by shining [src] at [S.p_their()] sensors." add_attack_logs(user, S, "shone [src] in their eyes") else - outmsg = "You fail to overload [S] by shining [src] at their sensors." + outmsg = "You fail to overload [S] by shining [src] at [S.p_their()] sensors." //cameras else if(istype(target, /obj/machinery/camera)) diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 4bbdaa2f723..5fa97f07d62 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -24,7 +24,7 @@ return if(ishuman(user)) var/mob/living/carbon/human/abductor/H = user - if(H && H.mind.abductor) + if(isabductor(H)) to_chat(user, "Megaphones can't project psionic communication!") return if(ishuman(user)) @@ -59,6 +59,7 @@ /obj/item/megaphone/proc/saymsg(mob/living/user as mob, message) audible_message("[user] broadcasts, \"[message]\"", hearing_distance = 14) + log_say(message, user) for(var/obj/O in oview(14, get_turf(src))) O.hear_talk(user, "[message]") diff --git a/code/game/objects/items/devices/pizza_bomb.dm b/code/game/objects/items/devices/pizza_bomb.dm index 12ffe91cef5..b69c1114bd6 100644 --- a/code/game/objects/items/devices/pizza_bomb.dm +++ b/code/game/objects/items/devices/pizza_bomb.dm @@ -1,7 +1,7 @@ /obj/item/pizza_bomb name = "pizza box" desc = "A box suited for pizzas." - icon = 'icons/obj/food/food.dmi' + icon = 'icons/obj/food/pizza.dmi' icon_state = "pizzabox1" var/timer = 10 //Adjustable timer var/timer_set = 0 diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 2a8e155dd06..62d8dc6c87d 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -245,7 +245,7 @@ REAGENT SCANNER user.show_message("Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.") var/implant_detect for(var/obj/item/organ/internal/cyberimp/CI in H.internal_organs) - if(CI.status == ORGAN_ROBOT) + if(CI.is_robotic()) implant_detect += "[H.name] is modified with a [CI.name].
" if(implant_detect) user.show_message("Detected cybernetic modifications:") @@ -313,6 +313,9 @@ REAGENT SCANNER throw_range = 7 materials = list(MAT_METAL=30, MAT_GLASS=20) origin_tech = "magnets=1;engineering=1" + var/cooldown = FALSE + var/cooldown_time = 250 + var/accuracy // 0 is the best accuracy. /obj/item/analyzer/attack_self(mob/user as mob) @@ -366,6 +369,69 @@ REAGENT SCANNER src.add_fingerprint(user) return +/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens + ..() + + if(!user.incapacitated() && Adjacent(user)) + + if(cooldown) + to_chat(user, "[src]'s barometer function is prepraring itself.") + return + + var/turf/T = get_turf(user) + if(!T) + return + + playsound(src, 'sound/effects/pop.ogg', 100) + var/area/user_area = T.loc + var/datum/weather/ongoing_weather = null + + if(!user_area.outdoors) + to_chat(user, "[src]'s barometer function won't work indoors!") + return + + for(var/V in SSweather.processing) + var/datum/weather/W = V + if(W.barometer_predictable && (T.z in W.impacted_z_levels) && W.area_type == user_area.type && !(W.stage == END_STAGE)) + ongoing_weather = W + break + + if(ongoing_weather) + if((ongoing_weather.stage == MAIN_STAGE) || (ongoing_weather.stage == WIND_DOWN_STAGE)) + to_chat(user, "[src]'s barometer function can't trace anything while the storm is [ongoing_weather.stage == MAIN_STAGE ? "already here!" : "winding down."]") + return + + to_chat(user, "The next [ongoing_weather] will hit in [butchertime(ongoing_weather.next_hit_time - world.time)].") + if(ongoing_weather.aesthetic) + to_chat(user, "[src]'s barometer function says that the next storm will breeze on by.") + else + var/next_hit = SSweather.next_hit_by_zlevel["[T.z]"] + var/fixed = next_hit ? next_hit - world.time : -1 + if(fixed < 0) + to_chat(user, "[src]'s barometer function was unable to trace any weather patterns.") + else + to_chat(user, "[src]'s barometer function says a storm will land in approximately [butchertime(fixed)].") + cooldown = TRUE + addtimer(CALLBACK(src,/obj/item/analyzer/proc/ping), cooldown_time) + +/obj/item/analyzer/proc/ping() + if(isliving(loc)) + var/mob/living/L = loc + to_chat(L, "[src]'s barometer function is ready!") + playsound(src, 'sound/machines/click.ogg', 100) + cooldown = FALSE + +/obj/item/analyzer/proc/butchertime(amount) + if(!amount) + return + if(accuracy) + var/inaccurate = round(accuracy * (1 / 3)) + if(prob(50)) + amount -= inaccurate + if(prob(50)) + amount += inaccurate + return DisplayTimeText(max(1, amount)) + /obj/item/mass_spectrometer desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample. Inject sample with syringe." name = "mass-spectrometer" diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index beed9fb75c3..dbd7701ce93 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -63,8 +63,8 @@ A.holder = src A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb). - bombers += "[key_name(user)] attached a [A] to a transfer valve." - msg_admin_attack("[key_name_admin(user)]attached [A] to a transfer valve.") + investigate_log("[key_name(user)] attached a [A] to a transfer valve.", INVESTIGATE_BOMB) + msg_admin_attack("[key_name_admin(user)]attached [A] to a transfer valve.", ATKLOG_FEW) log_game("[key_name_admin(user)] attached [A] to a transfer valve.") attacher = user SSnanoui.update_uis(src) // update all UIs attached to src @@ -204,7 +204,7 @@ var/mob/mob = get_mob_by_key(src.fingerprintslast) - bombers += "Bomb valve opened at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name(mob)]" + investigate_log("Bomb valve opened at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name(mob)]", INVESTIGATE_BOMB) message_admins("Bomb valve opened at [A.name] (JMP) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name_admin(mob)]") log_game("Bomb valve opened at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name(mob)]") merge_gases() diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index 2d40c1e683c..cc3320489f6 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -54,7 +54,7 @@ var/list/world_uplinks = list() dat += "Telecrystals left: [src.uses]
" dat += "
" dat += "Request item:
" - dat += "Each item costs a number of telecrystals as indicated by the number following their name.
" + dat += "Each item costs a number of telecrystals as indicated by the number following its name.
" var/category_items = 1 for(var/category in ItemsCategory) diff --git a/code/game/objects/items/policetape.dm b/code/game/objects/items/policetape.dm deleted file mode 100644 index f9769a64e23..00000000000 --- a/code/game/objects/items/policetape.dm +++ /dev/null @@ -1,203 +0,0 @@ -//Define all tape types in policetape.dm -/obj/item/taperoll - name = "tape roll" - icon = 'icons/policetape.dmi' - icon_state = "rollstart" - w_class = WEIGHT_CLASS_TINY - var/turf/start - var/turf/end - var/tape_type = /obj/item/tape - var/icon_base - -var/list/image/hazard_overlays -var/list/tape_roll_applications = list() - -/obj/item/tape - name = "tape" - icon = 'icons/policetape.dmi' - anchored = 1 - density = 1 - var/icon_base - -/obj/item/tape/New() - ..() - if(!hazard_overlays) - hazard_overlays = list() - hazard_overlays["[NORTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "N") - hazard_overlays["[EAST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "E") - hazard_overlays["[SOUTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "S") - hazard_overlays["[WEST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "W") - -/obj/item/taperoll/New() //just using tape is not enough to guarantee the overlays are genned - ..() - if(!hazard_overlays) - hazard_overlays = list() - hazard_overlays["[NORTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "N") - hazard_overlays["[EAST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "E") - hazard_overlays["[SOUTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "S") - hazard_overlays["[WEST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "W") - -/obj/item/taperoll/police - name = "police tape" - desc = "A roll of police tape used to block off crime scenes from the public." - icon_state = "police_start" - tape_type = /obj/item/tape/police - icon_base = "police" - -/obj/item/tape/police - name = "police tape" - desc = "A length of police tape. Do not cross." - req_one_access = list(access_security,access_forensics_lockers) - icon_base = "police" - -/obj/item/taperoll/engineering - name = "engineering tape" - desc = "A roll of engineering tape used to block off working areas from the public." - icon_state = "engineering_start" - tape_type = /obj/item/tape/engineering - icon_base = "engineering" - -/obj/item/tape/engineering - name = "engineering tape" - desc = "A length of engineering tape. Better not cross it." - req_one_access = list(access_engine,access_atmospherics) - icon_base = "engineering" - -/obj/item/taperoll/attack_self(mob/user as mob) - if(icon_state == "[icon_base]_start") - start = get_turf(src) - to_chat(usr, "You place the first end of the [src].") - icon_state = "[icon_base]_stop" - else - icon_state = "[icon_base]_start" - end = get_turf(src) - if(start.y != end.y && start.x != end.x || start.z != end.z) - to_chat(usr, "[src] can only be laid horizontally or vertically.") - return - - var/turf/cur = start - var/dir - if(start.x == end.x) - var/d = end.y-start.y - if(d) d = d/abs(d) - end = get_turf(locate(end.x,end.y+d,end.z)) - dir = "v" - else - var/d = end.x-start.x - if(d) d = d/abs(d) - end = get_turf(locate(end.x+d,end.y,end.z)) - dir = "h" - - var/can_place = 1 - while(cur!=end && can_place) - if(cur.density == 1) - can_place = 0 - else if(istype(cur, /turf/space)) - can_place = 0 - else - for(var/obj/O in cur) - if(!istype(O, /obj/item/tape) && O.density) - can_place = 0 - break - cur = get_step_towards(cur,end) - if(!can_place) - to_chat(usr, "You can't run \the [src] through that!") - return - - cur = start - var/tapetest = 0 - while(cur!=end) - for(var/obj/item/tape/Ptest in cur) - if(Ptest.icon_state == "[Ptest.icon_base]_[dir]") - tapetest = 1 - if(tapetest != 1) - var/obj/item/tape/P = new tape_type(cur) - P.icon_state = "[P.icon_base]_[dir]" - cur = get_step_towards(cur,end) - //is_blocked_turf(var/turf/T) - to_chat(usr, "You finish placing the [src].")//Git Test - - -/obj/item/taperoll/afterattack(var/atom/A, mob/user as mob, proximity) - if(!proximity) - return - - if(istype(A, /obj/machinery/door/airlock)) - var/turf/T = get_turf(A) - var/obj/item/tape/P = new tape_type(T.x,T.y,T.z) - P.loc = locate(T.x,T.y,T.z) - P.icon_state = "[src.icon_base]_door" - P.layer = 3.2 - to_chat(user, "You finish placing the [src].") - - if(istype(A, /turf/simulated/floor) ||istype(A, /turf/unsimulated/floor)) - var/turf/F = A - var/direction = user.loc == F ? user.dir : turn(user.dir, 180) - var/icon/hazard_overlay = hazard_overlays["[direction]"] - if(tape_roll_applications[F] == null) - tape_roll_applications[F] = 0 - - if(tape_roll_applications[F] & direction) // hazard_overlay in F.overlays wouldn't work. - user.visible_message("[user] uses the adhesive of \the [src] to remove area markings from \the [F].", "You use the adhesive of \the [src] to remove area markings from \the [F].") - F.overlays -= hazard_overlay - tape_roll_applications[F] &= ~direction - else - user.visible_message("[user] applied \the [src] on \the [F] to create area markings.", "You apply \the [src] on \the [F] to create area markings.") - F.overlays |= hazard_overlay - tape_roll_applications[F] |= direction - return - -/obj/item/tape/CanPass(atom/movable/mover, turf/target, height=0) - if(!density) return 1 - if(height==0) return 1 - - if((mover.pass_flags & PASSTABLE || istype(mover, /obj/effect/meteor) || mover.throwing)) - return 1 - else if(ismob(mover) && allowed(mover)) - return 1 - else - return 0 - -/obj/item/tape/attackby(obj/item/W as obj, mob/user as mob, params) - breaktape(W, user) - -/obj/item/tape/attack_hand(mob/user as mob) - if(user.a_intent == INTENT_HELP && src.allowed(user)) - user.visible_message("[user] lifts [src], allowing passage.", "You lift [src], allowing passage.") - src.density = 0 - spawn(200) - src.density = 1 - else - breaktape(/obj/item/soap, user)//cant be null, and can't be sharp. - -/obj/item/tape/attack_alien(mob/user as mob) - breaktape(/obj/item/wirecutters,user) - -/obj/item/tape/proc/breaktape(obj/item/W as obj, mob/user as mob) - if(user.a_intent == INTENT_HELP && ((!is_pointed(W) && src.allowed(user)))) - to_chat(user, "You can't break the [src] with that!") - return - user.visible_message("[user] breaks the [src]!", "You break the [src]!") - - var/dir[2] - var/icon_dir = src.icon_state - if(icon_dir == "[src.icon_base]_h") - dir[1] = EAST - dir[2] = WEST - if(icon_dir == "[src.icon_base]_v") - dir[1] = NORTH - dir[2] = SOUTH - - for(var/i=1;i<3;i++) - var/N = 0 - var/turf/cur = get_step(src,dir[i]) - while(N != 1) - N = 1 - for(var/obj/item/tape/P in cur) - if(P.icon_state == icon_dir) - N = 0 - qdel(P) - cur = get_step(cur,dir[i]) - - qdel(src) - return diff --git a/code/game/objects/items/random_items.dm b/code/game/objects/items/random_items.dm index 2625d2b865a..ded05d6f795 100644 --- a/code/game/objects/items/random_items.dm +++ b/code/game/objects/items/random_items.dm @@ -130,8 +130,7 @@ /obj/item/storage/pill_bottle/random_meds/New() ..() - var/i = 1 - while(i < storage_slots) + for(var/i in 1 to storage_slots) var/list/possible_medicines = standard_medicines.Copy() if(prob(50)) possible_medicines += rare_medicines.Copy() @@ -144,7 +143,6 @@ P.reagents.add_reagent(R, rand(2, 5)*10) P.name = "Unlabelled Pill" P.desc = "Something about this pill entices you to try it, against your better judgement." - i++ pixel_x = rand(-10, 10) pixel_y = rand(-10, 10) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 3ffdfaaf751..622b0b230c9 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -12,6 +12,7 @@ var/self_delay = 20 var/unique_handling = 0 //some things give a special prompt, do we want to bypass some checks in parent? var/stop_bleeding = 0 + var/healverb = "bandage" /obj/item/stack/medical/attack(mob/living/M, mob/user) if(!iscarbon(M) && !isanimal(M)) @@ -34,7 +35,7 @@ to_chat(user, "That limb is missing!") return 1 - if(affecting.status & ORGAN_ROBOT) + if(affecting.is_robotic()) to_chat(user, "This can't be used on a robotic limb.") return 1 @@ -77,6 +78,42 @@ "You apply [src] on [M].") use(1) +/obj/item/stack/medical/proc/heal(mob/living/M, mob/user) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + user.visible_message("[user] [healverb]s the wounds on [H]'s [affecting.name].", \ + "You [healverb] the wounds on [H]'s [affecting.name]." ) + + var/rembrute = max(0, heal_brute - affecting.brute_dam) // Maxed with 0 since heal_damage let you pass in a negative value + var/remburn = max(0, heal_burn - affecting.burn_dam) // And deduct it from their health (aka deal damage) + var/nrembrute = rembrute + var/nremburn = remburn + affecting.heal_damage(heal_brute, heal_burn) + var/list/achildlist + if(!isnull(affecting.children)) + achildlist = affecting.children.Copy() + var/parenthealed = FALSE + while(rembrute + remburn > 0) // Don't bother if there's not enough leftover heal + var/obj/item/organ/external/E + if(LAZYLEN(achildlist)) + E = pick_n_take(achildlist) // Pick a random children and then remove it from the list + else if(affecting.parent && !parenthealed) // If there's a parent and no healing attempt was made on it + E = affecting.parent + parenthealed = TRUE + else + break // If the organ have no child left and no parent / parent healed, break + if(E.status & ORGAN_ROBOT || E.open) // Ignore robotic or open limb + continue + else if(!E.brute_dam && !E.burn_dam) // Ignore undamaged limb + continue + nrembrute = max(0, rembrute - E.brute_dam) // Deduct the healed damage from the remain + nremburn = max(0, remburn - E.burn_dam) + E.heal_damage(rembrute, remburn) + rembrute = nrembrute + remburn = nremburn + user.visible_message("[user] [healverb]s the wounds on [H]'s [E.name] with the remaining medication.", \ + "You [healverb] the wounds on [H]'s [E.name] with the remaining medication." ) + //Bruise Packs// /obj/item/stack/medical/bruise_pack @@ -98,13 +135,12 @@ if(affecting.open == 0) affecting.germ_level = 0 - user.visible_message("[user] bandages the wounds on [H]'s [affecting.name].", \ - "You bandage the wounds on [H]'s [affecting.name]." ) - if(stop_bleeding) if(!H.bleedsuppress) //so you can't stack bleed suppression H.suppress_bloodloss(stop_bleeding) - affecting.heal_damage(heal_brute, heal_burn) + + heal(H, user) + H.UpdateDamageIcon() use(1) else @@ -131,6 +167,7 @@ singular_name = "ointment" icon_state = "ointment" origin_tech = "biotech=2" + healverb = "salve" /obj/item/stack/medical/ointment/attack(mob/living/M, mob/user) if(..()) @@ -143,9 +180,8 @@ if(affecting.open == 0) affecting.germ_level = 0 - user.visible_message("[user] salves the wounds on [H]'s [affecting.name].", \ - "You salve the wounds on [H]'s [affecting.name]." ) - affecting.heal_damage(heal_brute, heal_burn) + heal(H, user) + H.UpdateDamageIcon() use(1) else @@ -211,7 +247,7 @@ to_chat(user, "You remove the splint from [H]'s [limb].") return if(M == user) - user.visible_message("[user] starts to apply [src] to their [limb].", \ + user.visible_message("[user] starts to apply [src] to [user.p_their()] [limb].", \ "You start to apply [src] to your [limb].", \ "You hear something being wrapped.") if(!do_mob(user, H, self_delay)) diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 593ef9a820f..ec5ba4ef684 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -28,7 +28,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/S = H.get_organ(user.zone_sel.selecting) - if(S && (S.status & ORGAN_ROBOT)) + if(S && S.is_robotic()) if(S.get_damage()) S.heal_damage(15, 15, robo_repair = 1) H.updatehealth() diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index a30c3e1b716..ebc89cdca7a 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -13,6 +13,15 @@ /* * Glass sheets */ + +GLOBAL_LIST_INIT(glass_recipes, list ( \ + new/datum/stack_recipe/window("directional window", /obj/structure/window/basic, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe/window("fulltile window", /obj/structure/window/full/basic, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe("fishbowl", /obj/machinery/fishtank/bowl, 1, time = 0), \ + new/datum/stack_recipe("fish tank", /obj/machinery/fishtank/tank, 3, time = 0, on_floor = TRUE), \ + new/datum/stack_recipe("wall aquariam", /obj/machinery/fishtank/wall, 4, time = 0, on_floor = TRUE) \ +)) + /obj/item/stack/sheet/glass name = "glass" desc = "HOLY SHEET! That is a lot of glass." @@ -30,8 +39,9 @@ /obj/item/stack/sheet/glass/cyborg materials = list() -/obj/item/stack/sheet/glass/attack_self(mob/user as mob) - construct_window(user) +/obj/item/stack/sheet/glass/New(loc, amount) + recipes = GLOB.glass_recipes + ..() /obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user, params) ..() @@ -59,94 +69,18 @@ else return ..() -/obj/item/stack/sheet/glass/proc/construct_window(mob/user as mob) - if(!user || !src) return 0 - if(!istype(user.loc,/turf)) return 0 - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return 0 - var/title = "Sheet-Glass" - title += " ([src.amount] sheet\s left)" - switch(input(title, "What would you like to construct?") in list("One Direction Window", "Full Window", "Fishbowl", "Fish Tank", "Wall Aquarium", "Cancel")) - if("One Direction Window") - if(!src) return 1 - if(src.loc != user) return 1 - - var/list/directions = new/list(cardinal) - var/i = 0 - for(var/obj/structure/window/win in user.loc) - i++ - if(i >= 4) - to_chat(user, "There are too many windows in this location.") - return 1 - directions-=win.dir - if(win.is_fulltile()) - to_chat(user, "Can't let you do that.") - return 1 - - //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. - var/dir_to_set = 2 - for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) - var/found = 0 - for(var/obj/structure/window/WT in user.loc) - if(WT.dir == direction) - found = 1 - if(!found) - dir_to_set = direction - break - - var/obj/structure/window/W - W = new /obj/structure/window/basic( user.loc, 0 ) - W.dir = dir_to_set - W.ini_dir = W.dir - W.state = 0 - W.anchored = 0 - W.air_update_turf(1) - src.use(1) - if("Full Window") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 2) - to_chat(user, "You need more glass to do that.") - return 1 - if(locate(/obj/structure/window/full) in user.loc) - to_chat(user, "There is a full window in the way.") - return 1 - var/obj/structure/window/W = new full_window( user.loc, 0 ) - W.state = 0 - W.anchored = 0 - W.air_update_turf(1) - src.use(2) - if("Fishbowl") - if(!src) return 1 - if(src.loc != user) return 1 - var/obj/machinery/fishtank/F = new /obj/machinery/fishtank/bowl(user.loc, 0) - F.air_update_turf(1) - src.use(1) - if("Fish Tank") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 3) - to_chat(user, "You need more glass to do that.") - return 1 - var/obj/machinery/fishtank/F = new /obj/machinery/fishtank/tank(user.loc, 0) - F.air_update_turf(1) - src.use(3) - if("Wall Aquarium") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 4) - to_chat(user, "You need more glass to do that.") - return 1 - var/obj/machinery/fishtank/F = new /obj/machinery/fishtank/wall(user.loc, 0) - F.air_update_turf(1) - src.use(4) - return 0 - /* * Reinforced glass sheets */ + +GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \ + new/datum/stack_recipe/window("windoor frame", /obj/structure/windoor_assembly, 5, time = 0, on_floor = TRUE, window_checks = TRUE), \ + null, \ + new/datum/stack_recipe/window("directional reinforced window", /obj/structure/window/reinforced, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe/window("fulltile reinforced window", /obj/structure/window/full/reinforced, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \ +)) + /obj/item/stack/sheet/rglass name = "reinforced glass" desc = "Glass which seems to have rods or something stuck in them." @@ -161,105 +95,14 @@ /obj/item/stack/sheet/rglass/cyborg materials = list() -/obj/item/stack/sheet/rglass/attack_self(mob/user as mob) - construct_window(user) - -/obj/item/stack/sheet/rglass/proc/construct_window(mob/user as mob) - if(!user || !src) return 0 - if(!istype(user.loc,/turf)) return 0 - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return 0 - var/title = "Sheet Reinf. Glass" - title += " ([src.amount] sheet\s left)" - switch(input(title, "Would you like full tile glass a one direction glass pane or a windoor?") in list("One Direction", "Full Window", "Windoor", "Cancel")) - if("One Direction") - if(!src) return 1 - if(src.loc != user) return 1 - var/list/directions = new/list(cardinal) - var/i = 0 - for(var/obj/structure/window/win in user.loc) - i++ - if(i >= 4) - to_chat(user, "There are too many windows in this location.") - return 1 - directions-=win.dir - if(win.is_fulltile()) - to_chat(user, "Can't let you do that.") - return 1 - - //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. - var/dir_to_set = 2 - for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) - var/found = 0 - for(var/obj/structure/window/WT in user.loc) - if(WT.dir == direction) - found = 1 - if(!found) - dir_to_set = direction - break - - var/obj/structure/window/W - W = new /obj/structure/window/reinforced( user.loc, 1 ) - W.state = 0 - W.dir = dir_to_set - W.ini_dir = W.dir - W.anchored = 0 - src.use(1) - - if("Full Window") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 2) - to_chat(user, "You need more glass to do that.") - return 1 - if(locate(/obj/structure/window/full) in user.loc) - to_chat(user, "There is a window in the way.") - return 1 - var/obj/structure/window/W = new full_window( user.loc, 0 ) - W.state = 0 - W.anchored = 0 - src.use(2) - - if("Windoor") - if(!src || src.loc != user) return 1 - - if(isturf(user.loc) && locate(/obj/structure/windoor_assembly/, user.loc)) - to_chat(user, "There is already a windoor assembly in that location.") - return 1 - - if(isturf(user.loc) && locate(/obj/machinery/door/window/, user.loc)) - to_chat(user, "There is already a windoor in that location.") - return 1 - - if(src.amount < 5) - to_chat(user, "You need more glass to do that.") - return 1 - - var/obj/structure/windoor_assembly/WD - WD = new /obj/structure/windoor_assembly(user.loc) - WD.state = "01" - WD.anchored = 0 - src.use(5) - switch(user.dir) - if(SOUTH) - WD.dir = SOUTH - WD.ini_dir = SOUTH - if(EAST) - WD.dir = EAST - WD.ini_dir = EAST - if(WEST) - WD.dir = WEST - WD.ini_dir = WEST - else//If the user is facing northeast. northwest, southeast, southwest or north, default to north - WD.dir = NORTH - WD.ini_dir = NORTH - else - return 1 - - - return 0 +/obj/item/stack/sheet/rglass/New(loc, amount) + recipes = GLOB.reinforced_glass_recipes + ..() +GLOBAL_LIST_INIT(pglass_recipes, list ( \ + new/datum/stack_recipe/window("directional window", /obj/structure/window/plasmabasic, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe/window("fulltile window", /obj/structure/window/full/plasmabasic, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \ +)) /obj/item/stack/sheet/plasmaglass name = "plasma glass" @@ -271,8 +114,9 @@ created_window = /obj/structure/window/plasmabasic full_window = /obj/structure/window/full/plasmabasic -/obj/item/stack/sheet/plasmaglass/attack_self(mob/user as mob) - construct_window(user) +/obj/item/stack/sheet/plasmaglass/New(loc, amount) + recipes = GLOB.pglass_recipes + ..() /obj/item/stack/sheet/plasmaglass/attackby(obj/item/W, mob/user, params) ..() @@ -291,64 +135,15 @@ else return ..() -/obj/item/stack/sheet/plasmaglass/proc/construct_window(mob/user as mob) - if(!user || !src) return 0 - if(!istype(user.loc,/turf)) return 0 - if(!user.IsAdvancedToolUser()) - to_chat(user, " You don't have the dexterity to do this!") - return 0 - var/title = "Plasma-glass alloy" - title += " ([src.amount] sheet\s left)" - switch(alert(title, "Would you like full tile glass or one direction?", "One Direction", "Full Window", "Cancel", null)) - if("One Direction") - if(!src) return 1 - if(src.loc != user) return 1 - var/list/directions = new/list(cardinal) - var/i = 0 - for(var/obj/structure/window/win in user.loc) - i++ - if(i >= 4) - to_chat(user, "There are too many windows in this location.") - return 1 - directions-=win.dir - if(!(win.ini_dir in cardinal)) - to_chat(user, "Can't let you do that.") - return 1 - //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. - var/dir_to_set = 2 - for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) - var/found = 0 - for(var/obj/structure/window/WT in user.loc) - if(WT.dir == direction) - found = 1 - if(!found) - dir_to_set = direction - break - var/obj/structure/window/W - W = new /obj/structure/window/plasmabasic( user.loc, 0 ) - W.dir = dir_to_set - W.ini_dir = W.dir - W.state = 0 - W.anchored = 0 - src.use(1) - if("Full Window") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 2) - to_chat(user, "You need more glass to do that.") - return 1 - if(locate(/obj/structure/window) in user.loc) - to_chat(user, "There is a window in the way.") - return 1 - var/obj/structure/window/W = new full_window( user.loc, 0 ) - W.state = 0 - W.anchored = 0 - src.use(2) - return 0 - /* * Reinforced plasma glass sheets */ + +GLOBAL_LIST_INIT(prglass_recipes, list ( \ + new/datum/stack_recipe/window("directional reinforced window", /obj/structure/window/plasmareinforced, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe/window("fulltile reinforced window", /obj/structure/window/full/plasmareinforced, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \ +)) + /obj/item/stack/sheet/plasmarglass name = "reinforced plasma glass" desc = "Plasma glass which seems to have rods or something stuck in them." @@ -360,60 +155,42 @@ full_window = /obj/structure/window/full/plasmareinforced armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0) -/obj/item/stack/sheet/plasmarglass/attack_self(mob/user as mob) - construct_window(user) +/obj/item/stack/sheet/plasmarglass/New(loc, amount) + recipes = GLOB.prglass_recipes + ..() -/obj/item/stack/sheet/plasmarglass/proc/construct_window(mob/user as mob) - if(!user || !src) return 0 - if(!istype(user.loc,/turf)) return 0 - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return 0 - var/title = "Reinforced plasma-glass alloy" - title += " ([src.amount] sheet\s left)" - switch(alert(title, "Would you like full tile glass or one direction?", "One Direction", "Full Window", "Cancel", null)) - if("One Direction") - if(!src) return 1 - if(src.loc != user) return 1 - var/list/directions = new/list(cardinal) - var/i = 0 - for(var/obj/structure/window/win in user.loc) - i++ - if(i >= 4) - to_chat(user, "There are too many windows in this location.") - return 1 - directions-=win.dir - if(!(win.ini_dir in cardinal)) - to_chat(user, "Can't let you do that.") - return 1 - //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. - var/dir_to_set = 2 - for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) - var/found = 0 - for(var/obj/structure/window/WT in user.loc) - if(WT.dir == direction) - found = 1 - if(!found) - dir_to_set = direction - break - var/obj/structure/window/W - W = new /obj/structure/window/plasmareinforced( user.loc, 0 ) - W.dir = dir_to_set - W.ini_dir = W.dir - W.state = 0 - W.anchored = 0 - src.use(1) - if("Full Window") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 2) - to_chat(user, "You need more glass to do that.") - return 1 - if(locate(/obj/structure/window) in user.loc) - to_chat(user, "There is a window in the way.") - return 1 - var/obj/structure/window/W = new full_window( user.loc, 0 ) - W.state = 0 - W.anchored = 0 - src.use(2) - return 0 +GLOBAL_LIST_INIT(titaniumglass_recipes, list( + new/datum/stack_recipe/window("shuttle window", /obj/structure/window/full/shuttle, 2, time = 0, on_floor = TRUE, window_checks = TRUE) + )) + +/obj/item/stack/sheet/titaniumglass + name = "titanium glass" + desc = "A glass sheet made out of a titanium-silicate alloy." + singular_name = "titanium glass sheet" + icon_state = "sheet-titaniumglass" + item_state = "sheet-titaniumglass" + materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT, MAT_GLASS=MINERAL_MATERIAL_AMOUNT) + merge_type = /obj/item/stack/sheet/titaniumglass + full_window = /obj/structure/window/full/shuttle + +/obj/item/stack/sheet/titaniumglass/New(loc, amount) + recipes = GLOB.titaniumglass_recipes + ..() + +GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( + new/datum/stack_recipe/window("plastitanium window", /obj/structure/window/plastitanium, 2, time = 0, on_floor = TRUE, window_checks = TRUE) + )) + +/obj/item/stack/sheet/plastitaniumglass + name = "plastitanium glass" + desc = "A glass sheet made out of a plasma-titanium-silicate alloy." + singular_name = "plastitanium glass sheet" + icon_state = "sheet-plastitaniumglass" + item_state = "sheet-plastitaniumglass" + materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT, MAT_PLASMA=MINERAL_MATERIAL_AMOUNT, MAT_GLASS=MINERAL_MATERIAL_AMOUNT) + merge_type = /obj/item/stack/sheet/plastitaniumglass + full_window = /obj/structure/window/plastitanium + +/obj/item/stack/sheet/plastitaniumglass/New(loc, amount) + recipes = GLOB.plastitaniumglass_recipes + ..() diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 4412b547b19..5ef40ee25e8 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -318,7 +318,11 @@ var/global/list/datum/stack_recipe/cult = list ( \ /* * Brass */ -var/global/list/datum/stack_recipe/brass_recipes = list ( \ +var/global/list/datum/stack_recipe/brass_recipes = list (\ + new/datum/stack_recipe/window("brass windoor", /obj/machinery/door/window/clockwork, 2, time = 30, on_floor = TRUE, window_checks = TRUE), \ + null, + new/datum/stack_recipe/window("directional brass window", /obj/structure/window/reinforced/clockwork, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe/window("fulltile brass window", /obj/structure/window/reinforced/clockwork/fulltile, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \ new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE), \ ) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 4dd6ca365bf..e55569b23e8 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -149,6 +149,10 @@ to_chat(usr, "You haven't got enough [src] to build \the [R.title]!") return 0 + if(R.window_checks && !valid_window_location(usr.loc, usr.dir)) + to_chat(usr, "The [R.title] won't fit here!") + return FALSE + if(R.one_per_turf && (locate(R.result_type) in creation_loc)) to_chat(usr, "There is another [R.title] here!") return 0 @@ -166,7 +170,7 @@ return var/atom/O = new R.result_type(creation_loc) - O.dir = usr.dir + O.setDir(usr.dir) if(R.max_res_amount > 1) var/obj/item/stack/new_item = O new_item.amount = R.res_amount * multiplier diff --git a/code/game/objects/items/stacks/stack_recipe.dm b/code/game/objects/items/stacks/stack_recipe.dm index 67ddd964d0d..10d06e9741d 100644 --- a/code/game/objects/items/stacks/stack_recipe.dm +++ b/code/game/objects/items/stacks/stack_recipe.dm @@ -11,8 +11,9 @@ var/time = 0 var/one_per_turf = 0 var/on_floor = 0 + var/window_checks = FALSE -/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0) +/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, window_checks = FALSE) src.title = title src.result_type = result_type src.req_amount = req_amount @@ -21,6 +22,7 @@ src.time = time src.one_per_turf = one_per_turf src.on_floor = on_floor + src.window_checks = window_checks /datum/stack_recipe/proc/post_build(var/obj/item/stack/S, var/obj/result) return @@ -40,6 +42,17 @@ R.update_icon() ..() +/datum/stack_recipe/window +/datum/stack_recipe/window/post_build(obj/item/stack/S, obj/result) + if(istype(result, /obj/structure/windoor_assembly)) + var/obj/structure/windoor_assembly/W = result + W.ini_dir = W.dir + else if(istype(result, /obj/structure/window)) + var/obj/structure/window/W = result + W.ini_dir = W.dir + W.anchored = FALSE + W.state = WINDOW_OUT_OF_FRAME + /* * Recipe list datum */ diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index b321721b639..c1b88897bfd 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -229,8 +229,8 @@ hitsound = 'sound/weapons/bladeslice.ogg' /obj/item/toy/katana/suicide_act(mob/user) - var/dmsg = pick("[user] tries to stab \the [src] into their abdomen, but it shatters! They look as if they might die from the shame.","[user] tries to stab \the [src] into their abdomen, but \the [src] bends and breaks in half! They look as if they might die from the shame.","[user] tries to slice their own throat, but the plastic blade has no sharpness, causing them to lose their balance, slip over, and break their neck with a loud snap!") - user.visible_message("[dmsg] It looks like they are trying to commit suicide.") + var/dmsg = pick("[user] tries to stab \the [src] into [user.p_their()] abdomen, but it shatters! [user.p_they(TRUE)] look[user.p_s()] as if [user.p_they()] might die from the shame.","[user] tries to stab \the [src] into [user.p_their()] abdomen, but \the [src] bends and breaks in half! [user.p_they(TRUE)] look[user.p_s()] as if [user.p_they()] might die from the shame.","[user] tries to slice [user.p_their()] own throat, but the plastic blade has no sharpness, causing [user.p_them()] to lose [user.p_their()] balance, slip over, and break [user.p_their()] neck with a loud snap!") + user.visible_message("[dmsg] It looks like [user.p_theyre()] trying to commit suicide.") return (BRUTELOSS) @@ -362,7 +362,6 @@ desc = "Mini-Mecha action figure! Collect them all! 4/11." icon_state = "gygaxtoy" - /obj/item/toy/prize/durand name = "toy durand" desc = "Mini-Mecha action figure! Collect them all! 5/11." @@ -399,18 +398,6 @@ icon_state = "phazonprize" -/obj/item/toy/katana - name = "replica katana" - desc = "Woefully underpowered in D20." - icon_state = "katana" - item_state = "katana" - flags = CONDUCT - slot_flags = SLOT_BELT | SLOT_BACK - force = 5 - throwforce = 5 - w_class = WEIGHT_CLASS_NORMAL - attack_verb = list("attacked", "slashed", "stabbed", "sliced") - /* || A Deck of Cards for playing various games of chance || @@ -450,7 +437,7 @@ obj/item/toy/cards/deck obj/item/toy/cards/deck/New() ..() icon_state = "deck_[deckstyle]_full" - for(var/i = 2; i <= 10; i++) + for(var/i in 2 to 10) cards += "[i] of Hearts" cards += "[i] of Spades" cards += "[i] of Clubs" @@ -472,7 +459,6 @@ obj/item/toy/cards/deck/New() cards += "Ace of Clubs" cards += "Ace of Diamonds" - obj/item/toy/cards/deck/attack_hand(mob/user as mob) var/choice = null if(cards.len == 0) @@ -489,12 +475,7 @@ obj/item/toy/cards/deck/attack_hand(mob/user as mob) H.pickup(user) user.put_in_active_hand(H) visible_message("[user] draws a card from the deck.", "You draw a card from the deck.") - if(cards.len > 26) - icon_state = "deck_[deckstyle]_full" - else if(cards.len > 10) - icon_state = "deck_[deckstyle]_half" - else if(cards.len > 1) - icon_state = "deck_[deckstyle]_low" + update_icon() obj/item/toy/cards/deck/attack_self(mob/user as mob) if(cooldown < world.time - 50) @@ -515,12 +496,7 @@ obj/item/toy/cards/deck/attackby(obj/item/toy/cards/singlecard/C, mob/living/use qdel(C) else to_chat(user, "You can't mix cards from other decks.") - if(cards.len > 26) - icon_state = "deck_[deckstyle]_full" - else if(cards.len > 10) - icon_state = "deck_[deckstyle]_half" - else if(cards.len > 1) - icon_state = "deck_[deckstyle]_low" + update_icon() obj/item/toy/cards/deck/attackby(obj/item/toy/cards/cardhand/C, mob/living/user, params) @@ -531,16 +507,11 @@ obj/item/toy/cards/deck/attackby(obj/item/toy/cards/cardhand/C, mob/living/user, to_chat(user, "The hand of cards is stuck to your hand, you can't add it to the deck!") return cards += C.currenthand - user.visible_message("[user] puts their hand of cards in the deck.", "You put the hand of cards in the deck.") + user.visible_message("[user] puts [user.p_their()] hand of cards in the deck.", "You put the hand of cards in the deck.") qdel(C) else to_chat(user, "You can't mix cards from other decks.") - if(cards.len > 26) - icon_state = "deck_[deckstyle]_full" - else if(cards.len > 10) - icon_state = "deck_[deckstyle]_half" - else if(cards.len > 1) - icon_state = "deck_[deckstyle]_low" + update_icon() obj/item/toy/cards/deck/MouseDrop(atom/over_object) var/mob/M = usr @@ -566,7 +537,16 @@ obj/item/toy/cards/deck/MouseDrop(atom/over_object) else to_chat(usr, "You can't reach it from here.") - +obj/item/toy/cards/deck/update_icon() + switch(cards.len) + if(0) + icon_state = "deck_[deckstyle]_empty" + if(1 to 10) + icon_state = "deck_[deckstyle]_low" + if(11 to 26) + icon_state = "deck_[deckstyle]_half" + else + icon_state = "deck_[deckstyle]_full" obj/item/toy/cards/cardhand name = "hand of cards" @@ -610,15 +590,10 @@ obj/item/toy/cards/cardhand/Topic(href, href_list) C.apply_card_vars(C,O) C.pickup(cardUser) cardUser.put_in_any_hand_if_possible(C) - cardUser.visible_message("[cardUser] draws a card from \his hand.", "You take the [C.cardname] from your hand.") + cardUser.visible_message("[cardUser] draws a card from [cardUser.p_their()] hand.", "You take the [C.cardname] from your hand.") interact(cardUser) - if(currenthand.len < 3) - icon_state = "[deckstyle]_hand2" - else if(src.currenthand.len < 4) - icon_state = "[deckstyle]_hand3" - else if(src.currenthand.len < 5) - icon_state = "[deckstyle]_hand4" + update_icon() if(currenthand.len == 1) var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(src.loc) N.parentdeck = src.parentdeck @@ -637,14 +612,9 @@ obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/C, mob/living if(C.parentdeck == parentdeck) currenthand += C.cardname user.unEquip(C) - user.visible_message("[user] adds a card to their hand.", "You add the [C.cardname] to your hand.") + user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [C.cardname] to your hand.") interact(user) - if(currenthand.len > 4) - icon_state = "[deckstyle]_hand5" - else if(currenthand.len > 3) - icon_state = "[deckstyle]_hand4" - else if(currenthand.len > 2) - icon_state = "[deckstyle]_hand3" + update_icon() qdel(C) else to_chat(user, "You can't mix cards from other decks.") @@ -677,7 +647,7 @@ obj/item/toy/cards/singlecard/examine(mob/user) if(ishuman(user)) var/mob/living/carbon/human/cardUser = user if(cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) - cardUser.visible_message("[cardUser] checks \his card.", "The card reads: [src.cardname]") + cardUser.visible_message("[cardUser] checks [cardUser.p_their()] card.", "The card reads: [src.cardname]") else to_chat(cardUser, "You need to have the card in your hand to check it.") @@ -697,7 +667,7 @@ obj/item/toy/cards/singlecard/verb/Flip() icon_state = "sc_Ace of Spades_[deckstyle]" name = "What Card" pixel_x = 5 - else if(flipped) + else flipped = 0 icon_state = "singlecard_down_[deckstyle]" name = "card" @@ -726,18 +696,26 @@ obj/item/toy/cards/singlecard/attackby(obj/item/I, mob/living/user, params) if(H.parentdeck == parentdeck) H.currenthand += cardname user.unEquip(src) - user.visible_message("[user] adds a card to \his hand.", "You add the [cardname] to your hand.") + user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [cardname] to your hand.") H.interact(user) - if(H.currenthand.len > 4) - H.icon_state = "[deckstyle]_hand5" - else if(H.currenthand.len > 3) - H.icon_state = "[deckstyle]_hand4" - else if(H.currenthand.len > 2) - H.icon_state = "[deckstyle]_hand3" + H.update_icon() qdel(src) else to_chat(user, "You can't mix cards from other decks.") +obj/item/toy/cards/cardhand/update_icon() + switch(currenthand.len) + if(0 to 1) + return + if(2) + icon_state = "[deckstyle]_hand2" + if(3) + icon_state = "[deckstyle]_hand3" + if(4) + icon_state = "[deckstyle]_hand4" + else + icon_state = "[deckstyle]_hand5" + obj/item/toy/cards/singlecard/attack_self(mob/user) if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) @@ -813,10 +791,12 @@ obj/item/toy/cards/deck/syndicate/black /obj/item/toy/therapy name = "therapy doll" desc = "A toy for therapeutic and recreational purposes." + icon = 'icons/obj/toy.dmi' icon_state = "therapyred" item_state = "egg4" w_class = WEIGHT_CLASS_TINY var/cooldown = 0 + burn_state = FLAMMABLE /obj/item/toy/therapy/New() if(item_color) @@ -836,7 +816,7 @@ obj/item/toy/cards/deck/syndicate/black icon = 'icons/obj/toy.dmi' icon_state = "therapyred" -/obj/random/prize/item_to_spawn() +/obj/random/therapy/item_to_spawn() return pick(subtypesof(/obj/item/toy/therapy)) //exclude the base type. /obj/item/toy/therapy/red @@ -1367,7 +1347,7 @@ obj/item/toy/cards/deck/syndicate/black var/bullet_position = 1 /obj/item/toy/russian_revolver/suicide_act(mob/user) - user.visible_message("[user] quickly loads six bullets into [src]'s cylinder and points it at \his head before pulling the trigger! It looks like they are trying to commit suicide.") + user.visible_message("[user] quickly loads six bullets into [src]'s cylinder and points it at [user.p_their()] head before pulling the trigger! It looks like [user.p_theyre()] trying to commit suicide.") playsound(loc, 'sound/weapons/Gunshot.ogg', 50, 1) return (BRUTELOSS) @@ -1393,7 +1373,7 @@ obj/item/toy/cards/deck/syndicate/black if(!(user.has_organ("head"))) //For sanity to_chat(user, "Playing this game without a head would be classed as cheating.") return - user.visible_message("[user] points [src] at their head, ready to pull the trigger!") + user.visible_message("[user] points [src] at [user.p_their()] head, ready to pull the trigger!") if(do_after(user, 30, target = user)) if(bullet_position > 1) user.visible_message("*click*") @@ -1407,7 +1387,7 @@ obj/item/toy/cards/deck/syndicate/black user.apply_damage(200, BRUTE, "head", sharp = 1, used_weapon = "Self-inflicted gunshot wound to the head.") user.death() else - user.visible_message("[user] lowers [src] from their head.") + user.visible_message("[user] lowers [src] from [user.p_their()] head.") /obj/item/toy/russian_revolver/proc/spin_cylinder() bullet_position = rand(1,6) @@ -1662,7 +1642,7 @@ obj/item/toy/cards/deck/syndicate/black /obj/item/toy/eight_ball/attack_self(mob/user as mob) if(!cooldown) var/answer = pick(possible_answers) - user.visible_message("[user] focuses on their question and [use_action]...") + user.visible_message("[user] focuses on [user.p_their()] question and [use_action]...") user.visible_message("[bicon(src)] The [src] says \"[answer]\"") spawn(30) cooldown = 0 diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index fe132c107b0..5cc7ee684af 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -9,10 +9,10 @@ RCD icon_state = "rcd" opacity = 0 density = 0 - anchored = 0.0 - flags = CONDUCT - force = 10.0 - throwforce = 10.0 + anchored = 0 + flags = CONDUCT | NOBLUDGEON + force = 0 + throwforce = 10 throw_speed = 3 throw_range = 5 w_class = WEIGHT_CLASS_NORMAL @@ -296,8 +296,6 @@ RCD var/turf/T1 = get_turf(A) QDEL_NULL(A) for(var/obj/structure/window/W in T1.contents) - W.disassembled = 1 - W.density = 0 qdel(W) for(var/cdir in cardinal) var/turf/T2 = get_step(T1, cdir) @@ -307,8 +305,6 @@ RCD continue for(var/obj/structure/window/W in T2.contents) if(W.dir == turn(cdir, 180)) - W.disassembled = 1 - W.density = 0 qdel(W) var/obj/structure/window/reinforced/W = new(T2) W.dir = turn(cdir, 180) @@ -331,16 +327,12 @@ RCD activate() new /obj/structure/grille(A) for(var/obj/structure/window/W in contents) - W.disassembled = 1 // Prevent that annoying glass breaking sound - W.density = 0 qdel(W) for(var/cdir in cardinal) var/turf/T = get_step(A, cdir) if(locate(/obj/structure/grille) in T.contents) for(var/obj/structure/window/W in T.contents) if(W.dir == turn(cdir, 180)) - W.disassembled = 1 - W.density = 0 qdel(W) else // Build a window! var/obj/structure/window/reinforced/W = new(A) diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm index 835de7617ee..62b203e43b1 100644 --- a/code/game/objects/items/weapons/RSF.dm +++ b/code/game/objects/items/weapons/RSF.dm @@ -57,16 +57,13 @@ RSF if(!proximity) return if(!(istype(A, /obj/structure/table) || istype(A, /turf/simulated/floor))) return - var spawn_location - if(istype(A, /obj/structure/table)) - spawn_location = A.loc - else if (istype(A, /obj/structure/table)) - spawn_location = A + var/turf/T = get_turf(A) + if(istype(T) && !T.density) + spawn_location = T else to_chat(user, "The RSF can only create service items on tables, or floors.") return - if(isrobot(user)) var/mob/living/silicon/robot/engy = user if(!engy.cell.use(configured_items[mode][2])) diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 8566fac6a3c..daaa5c3e4c4 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -86,7 +86,7 @@ icon_state = "id" item_state = "card-id" var/mining_points = 0 //For redeeming at mining equipment lockers - var/access = list() + var/list/access = list() var/registered_name = "Unknown" // The name registered_name on the card slot_flags = SLOT_ID var/untrackable // Can not be tracked by AI's @@ -463,7 +463,7 @@ var/new_job = "Civilian" if(department == "Custom") - new_job = sanitize(stripped_input(user,"Choose a custom jon title:","Agent Card Occupation", "Civilian", MAX_MESSAGE_LEN)) + new_job = sanitize(stripped_input(user,"Choose a custom job title:","Agent Card Occupation", "Civilian", MAX_MESSAGE_LEN)) else if(department != "Civilian") switch(department) if("Engineering") diff --git a/code/game/objects/items/weapons/cigs.dm b/code/game/objects/items/weapons/cigs.dm index 9a55bb8e562..73ff43abbde 100644 --- a/code/game/objects/items/weapons/cigs.dm +++ b/code/game/objects/items/weapons/cigs.dm @@ -54,7 +54,7 @@ LIGHTERS ARE IN LIGHTERS.DM if(istype(M) && M.on_fire) user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(M) - light("[user] coldly lights the [name] with the burning body of [M]. Clearly, they offer the warmest of regards...") + light("[user] coldly lights the [name] with the burning body of [M]. Clearly, [user.p_they()] offer[user.p_s()] the warmest of regards...") return 1 else return ..() @@ -73,31 +73,31 @@ LIGHTERS ARE IN LIGHTERS.DM else if(istype(W, /obj/item/lighter/zippo)) var/obj/item/lighter/zippo/Z = W if(Z.lit) - light("With a single flick of their wrist, [user] smoothly lights their [name] with their [W]. Damn they're cool.") + light("With a single flick of [user.p_their()] wrist, [user] smoothly lights [user.p_their()] [name] with [user.p_their()] [W]. Damn [user.p_theyre()] cool.") else if(istype(W, /obj/item/lighter)) var/obj/item/lighter/L = W if(L.lit) - light("After some fiddling, [user] manages to light their [name] with [W].") + light("After some fiddling, [user] manages to light [user.p_their()] [name] with [W].") else if(istype(W, /obj/item/match)) var/obj/item/match/M = W if(M.lit == 1) - light("[user] lights their [name] with their [W].") + light("[user] lights [user.p_their()] [name] with [user.p_their()] [W].") else if(istype(W, /obj/item/melee/energy/sword/saber)) var/obj/item/melee/energy/sword/saber/S = W if(S.active) - light("[user] swings their [W], barely missing their nose. They light their [name] in the process.") + light("[user] swings their [W], barely missing their nose. [user.p_they(TRUE)] light[user.p_s()] [user.p_their()] [name] in the process.") else if(istype(W, /obj/item/assembly/igniter)) - light("[user] fiddles with [W], and manages to light their [name].") + light("[user] fiddles with [W], and manages to light [user.p_their()] [name].") else if(istype(W, /obj/item/gun/magic/wand/fireball)) var/obj/item/gun/magic/wand/fireball/F = W if(F.charges) if(prob(50) || user.mind.assigned_role == "Wizard") - light("Holy shit, did [user] just manage to light their [name] with [W], with only moderate eyebrow singing?") + light("Holy shit, did [user] just manage to light [user.p_their()] [name] with [W], with only moderate eyebrow singing?") else to_chat(user, "Unsure which end of the wand is which, [user] fails to light [name] with [W].") explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2) diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 02a01a25e83..c28fd68fc62 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -63,8 +63,8 @@ to_chat(user, "You need to wipe off the old lipstick first!") return if(H == user) - user.visible_message("[user] does their lips with \the [src].", \ - "You take a moment to apply \the [src]. Perfect!") + user.visible_message("[user] does [user.p_their()] lips with [src].", \ + "You take a moment to apply [src]. Perfect!") H.lip_style = "lipstick" H.lip_color = colour H.update_body() @@ -99,18 +99,18 @@ if(!get_location_accessible(H, "mouth")) to_chat(user, "The mask is in the way.") return - if((C.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + if((C.dna.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... to_chat(user, "You find yourself disappointed at the appalling lack of facial hair.") return if(C.f_style == "Shaved") to_chat(user, "Already clean-shaven.") return if(H == user) //shaving yourself - user.visible_message("[user] starts to shave their facial hair with \the [src].", \ + user.visible_message("[user] starts to shave [user.p_their()] facial hair with [src].", \ "You take a moment shave your facial hair with \the [src].") if(do_after(user, 50 * toolspeed, target = H)) - user.visible_message("[user] shaves \his facial hair clean with the [src].", \ - "You finish shaving with the [src]. Fast and clean!") + user.visible_message("[user] shaves [user.p_their()] facial hair clean with [src].", \ + "You finish shaving with [src]. Fast and clean!") C.f_style = "Shaved" H.update_fhair() playsound(src.loc, usesound, 20, 1) @@ -130,20 +130,20 @@ if(!get_location_accessible(H, "head")) to_chat(user, "The headgear is in the way.") return - if((C.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + if((C.dna.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... to_chat(user, "You find yourself disappointed at the appalling lack of hair.") return if(C.h_style == "Bald" || C.h_style == "Balding Hair" || C.h_style == "Skinhead") to_chat(user, "There is not enough hair left to shave...") return - if(M.get_species() == "Skrell") + if(isskrell(M)) to_chat(user, "Your razor isn't going to cut through tentacles.") return if(H == user) //shaving yourself - user.visible_message("[user] starts to shave their head with \the [src].", \ + user.visible_message("[user] starts to shave [user.p_their()] head with [src].", \ "You start to shave your head with \the [src].") if(do_after(user, 50 * toolspeed, target = H)) - user.visible_message("[user] shaves \his head with \the [src].", \ + user.visible_message("[user] shaves [user.p_their()] head with [src].", \ "You finish shaving with \the [src].") C.h_style = "Skinhead" H.update_hair() diff --git a/code/game/objects/items/weapons/courtroom.dm b/code/game/objects/items/weapons/courtroom.dm index 160bdd9bb1e..d25b6f54d29 100644 --- a/code/game/objects/items/weapons/courtroom.dm +++ b/code/game/objects/items/weapons/courtroom.dm @@ -14,7 +14,7 @@ burn_state = FLAMMABLE /obj/item/gavelhammer/suicide_act(mob/user) - user.visible_message("[user] has sentenced \himself to death with the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] has sentenced [user.p_them()]self to death with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.") playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1) return (BRUTELOSS) diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index 762b2151b9c..b1fc3398af0 100644 --- a/code/game/objects/items/weapons/defib.dm +++ b/code/game/objects/items/weapons/defib.dm @@ -96,7 +96,7 @@ if(istype(W, /obj/item/screwdriver)) if(bcell) - bcell.updateicon() + bcell.update_icon() bcell.loc = get_turf(src.loc) bcell = null to_chat(user, "You remove the cell from the [src].") @@ -276,7 +276,7 @@ icon_state = "defibpaddles[wielded]_cooldown" /obj/item/twohanded/shockpaddles/suicide_act(mob/user) - user.visible_message("[user] is putting the live paddles on \his chest! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide.") defib.deductcharge(revivecost) playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) return (OXYLOSS) @@ -375,6 +375,13 @@ update_icon() return else + var/obj/item/organ/internal/heart/heart = H.get_int_organ(/obj/item/organ/internal/heart) + if(heart.status & ORGAN_DEAD) + user.visible_message("[defib] buzzes: Resuscitation failed - Heart necrosis detected.") + playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + busy = 0 + update_icon() + return H.set_heartattack(FALSE) user.visible_message("[defib] pings: Cardiac arrhythmia corrected.") M.visible_message("[M]'s body convulses a bit.") diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index 8ccfed1b517..d93ebcf3214 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -159,7 +159,7 @@ var/turf/bombturf = get_turf(src) var/area/A = get_area(bombturf) - bombers += "E20 detonated at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with a roll of [result]. Triggered by: [key_name(user)]" + investigate_log("E20 detonated at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with a roll of [result]. Triggered by: [key_name(user)]", INVESTIGATE_BOMB) message_admins("E20 detonated at [A.name] (JMP) with a roll of [result]. Triggered by: [key_name_admin(user)]") log_game("E20 detonated at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with a roll of [result]. Triggered by: [key_name(user)]") diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index d120fb4e1cd..3a7e203101d 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -74,7 +74,7 @@ H = M spawn(0) //Some mutations have sleeps in them, like monkey - if(!(NOCLONE in M.mutations) && !(H && (NO_DNA in H.species.species_traits))) // prevents drained people from having their DNA changed + if(!(NOCLONE in M.mutations) && !(H && (NO_DNA in H.dna.species.species_traits))) // prevents drained people from having their DNA changed var/prev_ue = M.dna.unique_enzymes var/mutflags = 0 // UI in syringe. @@ -113,7 +113,7 @@ if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure. var/mob/living/carbon/human/H = M - if(NO_DNA in H.species.species_traits) + if(NO_DNA in H.dna.species.species_traits) return 0 if(!user.IsAdvancedToolUser()) @@ -142,7 +142,7 @@ else to_chat(user, "You inject yourself with [src].") - add_attack_logs(user, M, attack_log, FALSE) + add_attack_logs(user, M, attack_log, ATKLOG_ALL) if(!iscarbon(user)) M.LAssailant = null else diff --git a/code/game/objects/items/weapons/dnascrambler.dm b/code/game/objects/items/weapons/dnascrambler.dm index cd1d79ae683..fc13fa69f79 100644 --- a/code/game/objects/items/weapons/dnascrambler.dm +++ b/code/game/objects/items/weapons/dnascrambler.dm @@ -24,12 +24,12 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M - if(NO_DNA in H.species.species_traits) - to_chat(user, "You failed to inject [M], as they have no DNA to scramble, nor flesh to inject.") + if(NO_DNA in H.dna.species.species_traits) + to_chat(user, "You failed to inject [M], as [M.p_they()] [M.p_have()] no DNA to scramble, nor flesh to inject.") return if(M == user) - user.visible_message("[user] injects \himself with [src]!") + user.visible_message("[user] injects [user.p_them()]self with [src]!") injected(user, user) else user.visible_message("[user] is trying to inject [M] with [src]!") @@ -43,7 +43,7 @@ if(istype(target)) var/mob/living/carbon/human/H = target scramble(1, H, 100) - H.real_name = random_name(H.gender, H.species.name) //Give them a name that makes sense for their species. + H.real_name = random_name(H.gender, H.dna.species.name) //Give them a name that makes sense for their species. H.sync_organ_dna(assimilate = 1) H.update_body(0) H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover. diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 6164ed01047..edf7e0fc32b 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -90,7 +90,7 @@ /obj/item/grenade/plastic/suicide_act(mob/user) message_admins("[key_name_admin(user)](?) (FLW) suicided with [src.name] at ([user.x],[user.y],[user.z] - JMP)",0,1) log_game("[key_name(user)] suicided with [name] at ([user.x],[user.y],[user.z])") - user.visible_message("[user] activates the [name] and holds it above \his head! It looks like \he's going out with a bang!") + user.visible_message("[user] activates the [name] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!") var/message_say = "FOR NO RAISIN!" if(user.mind) if(user.mind.special_role) diff --git a/code/game/objects/items/weapons/garrote.dm b/code/game/objects/items/weapons/garrote.dm index 7893a7898b8..4a01914a31a 100644 --- a/code/game/objects/items/weapons/garrote.dm +++ b/code/game/objects/items/weapons/garrote.dm @@ -75,7 +75,7 @@ return if(improvised && ((M.head && (M.head.flags_cover & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags_cover & MASKCOVERSMOUTH)))) // Improvised garrotes are blocked by mouth-covering items. - to_chat(user, "[M]'s neck is blocked by something they're wearing!") + to_chat(user, "[M]'s neck is blocked by something [M.p_theyre()] wearing!") if(strangling) to_chat(user, "You cannot use [src] on two people at once!") @@ -134,7 +134,7 @@ G = user.r_hand else - user.visible_message("[user] loses \his grip on [strangling]'s neck.", \ + user.visible_message("[user] loses [user.p_their()] grip on [strangling]'s neck.", \ "You lose your grip on [strangling]'s neck.") strangling = null @@ -144,7 +144,7 @@ return if(!G.affecting) - user.visible_message("[user] loses \his grip on [strangling]'s neck.", \ + user.visible_message("[user] loses [user.p_their()] grip on [strangling]'s neck.", \ "You lose your grip on [strangling]'s neck.") strangling = null @@ -167,6 +167,6 @@ /obj/item/twohanded/garrote/suicide_act(mob/user) - user.visible_message("[user] is wrapping the [src] around \his neck and pulling the handles! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is wrapping the [src] around [user.p_their()] neck and pulling the handles! It looks like [user.p_theyre()] trying to commit suicide.") playsound(src.loc, 'sound/weapons/cablecuff.ogg', 15, 1, -1) return (OXYLOSS) diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index de85ec64a58..9e836fecc87 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -102,7 +102,7 @@ // This used to go before the assembly check, but that has absolutely zero to do with priming the damn thing. You could spam the admins with it. message_admins("[key_name_admin(usr)] has primed a [name] for detonation at [A.name] (JMP) [contained].") log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) [contained].") - bombers += "[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])[contained]." + investigate_log("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])[contained].", INVESTIGATE_BOMB) to_chat(user, "You prime the [name]! [det_time / 10] second\s!") playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1) active = 1 diff --git a/code/game/objects/items/weapons/grenades/emgrenade.dm b/code/game/objects/items/weapons/grenades/emgrenade.dm index 44d21506ee6..5b6d585ef5f 100644 --- a/code/game/objects/items/weapons/grenades/emgrenade.dm +++ b/code/game/objects/items/weapons/grenades/emgrenade.dm @@ -7,5 +7,5 @@ /obj/item/grenade/empgrenade/prime() update_mob() - empulse(src, 4, 10) - qdel(src) \ No newline at end of file + empulse(src, 4, 10, 1) + qdel(src) diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm index d0dc2c8fe06..ca6177c04fa 100644 --- a/code/game/objects/items/weapons/grenades/ghettobomb.dm +++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm @@ -49,7 +49,8 @@ var/area/A = get_area(bombturf) message_admins("[ADMIN_LOOKUPFLW(user)] has primed a [name] for detonation at [ADMIN_COORDJMP(bombturf)].") - log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].") + log_game("[key_name(user)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].") + investigate_log("[key_name(user)] has primed a [name] for detonation at [A.name] [COORD(bombturf)])", INVESTIGATE_BOMB) if(iscarbon(user)) var/mob/living/carbon/C = user C.throw_mode_on() diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index c7ababde601..09fdfe5a27f 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -66,7 +66,7 @@ var/area/A = get_area(bombturf) message_admins("[key_name_admin(usr)] has primed a [name] for detonation at [A.name] (JMP)") log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])") - bombers += "[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])" + investigate_log("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])", INVESTIGATE_BOMB) if(iscarbon(user)) var/mob/living/carbon/C = user C.throw_mode_on() diff --git a/code/game/objects/items/weapons/holosign.dm b/code/game/objects/items/weapons/holosign.dm index 30deb5289a4..12767cb9563 100644 --- a/code/game/objects/items/weapons/holosign.dm +++ b/code/game/objects/items/weapons/holosign.dm @@ -1,53 +1,123 @@ /obj/item/holosign_creator name = "holographic sign projector" - desc = "A handy-dandy hologaphic projector that displays a janitorial sign." - icon = 'icons/obj/janitor.dmi' + desc = "A handy-dandy holographic projector that displays a janitorial sign." + icon = 'icons/obj/device.dmi' icon_state = "signmaker" item_state = "electronic" - force = 5 + force = 0 w_class = WEIGHT_CLASS_SMALL throwforce = 0 throw_speed = 3 throw_range = 7 origin_tech = "magnets=1;programming=3" + flags = NOBLUDGEON var/list/signs = list() - var/max_signs = 20 - -/obj/item/holosign_creator/Destroy() - QDEL_LIST(signs) - return ..() + var/max_signs = 10 + var/creation_time = 0 //time to create a holosign in deciseconds. + var/holosign_type = /obj/structure/holosign/wetsign + var/holocreator_busy = FALSE //to prevent placing multiple holo barriers at once /obj/item/holosign_creator/afterattack(atom/target, mob/user, flag) if(flag) + if(!check_allowed_items(target, 1)) + return var/turf/T = get_turf(target) - var/obj/effect/overlay/holograph/H = locate() in T + var/obj/structure/holosign/H = locate(holosign_type) in T if(H) - to_chat(user, "You use [src] to destroy [H].") - signs -= H + to_chat(user, "You use [src] to deactivate [H].") qdel(H) else - if(signs.len < max_signs) - H = new(get_turf(target)) - signs += H - to_chat(user, "You create \a [H] with [src].") - else - to_chat(user, "[src] is projecting at max capacity!") + if(!is_blocked_turf(T, TRUE)) //can't put holograms on a tile that has dense stuff + if(holocreator_busy) + to_chat(user, "[src] is busy creating a hologram.") + return + if(signs.len < max_signs) + playsound(src.loc, 'sound/machines/click.ogg', 20, 1) + if(creation_time) + holocreator_busy = TRUE + if(!do_after(user, creation_time, target = target)) + holocreator_busy = FALSE + return + holocreator_busy = FALSE + if(signs.len >= max_signs) + return + if(is_blocked_turf(T, TRUE)) //don't try to sneak dense stuff on our tile during the wait. + return + H = new holosign_type(get_turf(target), src) + to_chat(user, "You create [H] with [src].") + else + to_chat(user, "[src] is projecting at max capacity!") /obj/item/holosign_creator/attack(mob/living/carbon/human/M, mob/user) return /obj/item/holosign_creator/attack_self(mob/user) if(signs.len) - var/list/L = signs.Copy() - for(var/sign in L) - qdel(sign) - signs -= sign + for(var/H in signs) + qdel(H) to_chat(user, "You clear all active holograms.") -/obj/effect/overlay/holograph - name = "wet floor sign" - desc = "The words flicker as if they mean nothing." - icon = 'icons/obj/janitor.dmi' - icon_state = "holosign" - anchored = 1 - armor = list(melee = 0, bullet = 50, laser = 50, energy = 50, bomb = 0, bio = 0, rad = 0) + +/obj/item/holosign_creator/security + name = "security holobarrier projector" + desc = "A holographic projector that creates holographic security barriers." + icon_state = "signmaker_sec" + holosign_type = /obj/structure/holosign/barrier + creation_time = 30 + max_signs = 6 + +/obj/item/holosign_creator/engineering + name = "engineering holobarrier projector" + desc = "A holographic projector that creates holographic engineering barriers." + icon_state = "signmaker_engi" + holosign_type = /obj/structure/holosign/barrier/engineering + creation_time = 30 + max_signs = 6 + +/obj/item/holosign_creator/atmos + name = "ATMOS holofan projector" + desc = "A holographic projector that creates holographic barriers that prevent changes in atmosphere conditions." + icon_state = "signmaker_engi" + holosign_type = /obj/structure/holosign/barrier/atmos + creation_time = 0 + max_signs = 3 + +/obj/item/holosign_creator/cyborg + name = "Energy Barrier Projector" + desc = "A holographic projector that creates fragile energy fields." + creation_time = 15 + max_signs = 9 + holosign_type = /obj/structure/holosign/barrier/cyborg + var/shock = 0 + +/obj/item/holosign_creator/cyborg/attack_self(mob/user) + if(isrobot(user)) + var/mob/living/silicon/robot/R = user + + if(shock) + to_chat(user, "You clear all active holograms, and reset your projector to normal.") + holosign_type = /obj/structure/holosign/barrier/cyborg + creation_time = 5 + if(signs.len) + for(var/H in signs) + qdel(H) + shock = 0 + return + else if(R.emagged && !shock) + to_chat(user, "You clear all active holograms, and overload your energy projector!") + holosign_type = /obj/structure/holosign/barrier/cyborg/hacked + creation_time = 30 + if(signs.len) + for(var/H in signs) + qdel(H) + shock = 1 + return + else + if(signs.len) + for(var/H in signs) + qdel(H) + to_chat(user, "You clear all active holograms.") + if(signs.len) + for(var/H in signs) + qdel(H) + to_chat(user, "You clear all active holograms.") \ No newline at end of file diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index 2d0865faa36..ea799bbcd76 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -13,7 +13,7 @@ var/list/fluff_transformations = list() //does it have any special transformations only accessible to it? Should only be subtypes of /obj/item/nullrod /obj/item/nullrod/suicide_act(mob/user) - user.visible_message("[user] is killing \himself with \the [src.name]! It looks like \he's trying to get closer to god!") + user.visible_message("[user] is killing [user.p_them()]self with \the [src.name]! It looks like [user.p_theyre()] trying to get closer to god!") return (BRUTELOSS|FIRELOSS) /obj/item/nullrod/attack(mob/M, mob/living/carbon/user) @@ -575,7 +575,7 @@ if(missionary in viewers(target)) //missionary must maintain line of sight to target, but the target doesn't necessary need to be able to see the missionary do_convert(target, missionary) else - to_chat(missionary, "You lost sight of the target before they could be converted!") + to_chat(missionary, "You lost sight of the target before [target.p_they()] could be converted!") faith -= 25 //they escaped, so you only lost a little faith (to prevent spamming) else //the do_after failed, probably because you moved or dropped the staff to_chat(missionary, "Your concentration was broken!") @@ -585,12 +585,12 @@ if(!target || !ishuman(target) || !missionary || !ishuman(missionary)) return if(ismindslave(target) || target.mind.zealot_master) //mindslaves and zealots override the staff because the staff is just a temporary mindslave - to_chat(missionary, "Your faith is strong, but their mind is already slaved to someone else's ideals. Perhaps an inquisition would reveal more...") + to_chat(missionary, "Your faith is strong, but [target.p_their()] mind is already slaved to someone else's ideals. Perhaps an inquisition would reveal more...") faith -= 25 //same faith cost as losing sight of them mid-conversion, but did you just find someone who can lead you to a fellow traitor? return if(ismindshielded(target)) faith -= 75 - to_chat(missionary, "Your faith is strong, but their mind remains closed to your ideals. Your resolve helps you retain a bit of faith though.") + to_chat(missionary, "Your faith is strong, but [target.p_their()] mind remains closed to your ideals. Your resolve helps you retain a bit of faith though.") return else if(target.mind.assigned_role == "Psychiatrist" || target.mind.assigned_role == "Librarian") //fancy book lernin helps counter religion (day 0 job love, what madness!) if(prob(35)) //35% chance to fail @@ -602,7 +602,7 @@ faith -= 100 else if(target.mind.assigned_role == "Civilian") if(prob(55)) //55% chance to take LESS faith than normal, because civies are stupid and easily manipulated - to_chat(missionary, "Your message seems to resound well with [target]; converting them was much easier than expected.") + to_chat(missionary, "Your message seems to resound well with [target]; converting [target.p_them()] was much easier than expected.") faith -= 50 else //45% chance to take the normal 100 faith cost to_chat(missionary, "You successfully convert [target] to your cause. The following grows because of your faith!") diff --git a/code/game/objects/items/weapons/implants/implant_abductor.dm b/code/game/objects/items/weapons/implants/implant_abductor.dm index 0d5bc869e44..3ec571c94a6 100644 --- a/code/game/objects/items/weapons/implants/implant_abductor.dm +++ b/code/game/objects/items/weapons/implants/implant_abductor.dm @@ -28,8 +28,9 @@ var/obj/machinery/abductor/console/console if(ishuman(source)) var/mob/living/carbon/human/H = source - if(H.get_species() == "Abductor") - console = get_team_console(H.mind.abductor.team) + if(isabductor(H)) + var/datum/species/abductor/S = H.dna.species + console = get_team_console(S.team) home = console.pad if(!home) diff --git a/code/game/objects/items/weapons/implants/implant_misc.dm b/code/game/objects/items/weapons/implants/implant_misc.dm index a657d08847b..9c4049e8904 100644 --- a/code/game/objects/items/weapons/implants/implant_misc.dm +++ b/code/game/objects/items/weapons/implants/implant_misc.dm @@ -58,7 +58,7 @@ /obj/item/implant/emp/activate() uses-- - empulse(imp_in, 3, 5) + empulse(imp_in, 3, 5, 1) if(!uses) qdel(src) diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm index 68ef65664c7..58f78a7be4e 100644 --- a/code/game/objects/items/weapons/implants/implant_traitor.dm +++ b/code/game/objects/items/weapons/implants/implant_traitor.dm @@ -55,11 +55,11 @@ ticker.mode.implanter[ref] = implanters ticker.mode.traitors += H.mind H.mind.special_role = SPECIAL_ROLE_TRAITOR - to_chat(H, "You're now completely loyal to [user.name]! You now must lay down your life to protect them and assist in their goals at any cost.") + to_chat(H, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.") var/datum/objective/protect/mindslave/MS = new MS.owner = H.mind MS.target = user.mind - MS.explanation_text = "Obey every order from and protect [user.real_name], the [user.mind.assigned_role=="MODE" ? (user.mind.special_role) : (user.mind.assigned_role)]." + MS.explanation_text = "Obey every order from and protect [user.real_name], the [user.mind.assigned_role == user.mind.special_role ? (user.mind.special_role) : (user.mind.assigned_role)]." H.mind.objectives += MS for(var/datum/objective/objective in H.mind.objectives) to_chat(H, "Objective #1: [objective.explanation_text]") diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm index da6e3b95968..314077db68e 100644 --- a/code/game/objects/items/weapons/implants/implantchair.dm +++ b/code/game/objects/items/weapons/implants/implantchair.dm @@ -79,7 +79,7 @@ return var/mob/M = G.affecting if(M.buckled_mob) - to_chat(usr, "[M] will not fit into [src] because they have a slime latched onto their head.") + to_chat(usr, "[M] will not fit into [src] because [M.p_they()] [M.p_have()] a slime latched onto [M.p_their()] head.") return if(put_mob(M)) qdel(G) diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index 93103568f58..668cc74ac73 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -113,9 +113,9 @@ sharp = 1 /obj/item/kitchen/knife/suicide_act(mob/user) - user.visible_message(pick("[user] is slitting \his wrists with the [src.name]! It looks like \he's trying to commit suicide.", \ - "[user] is slitting \his throat with the [src.name]! It looks like \he's trying to commit suicide.", \ - "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")) + user.visible_message(pick("[user] is slitting [user.p_their()] wrists with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.", \ + "[user] is slitting [user.p_their()] throat with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.", \ + "[user] is slitting [user.p_their()] stomach open with the [name]! It looks like [user.p_theyre()] trying to commit seppuku.")) return (BRUTELOSS) /obj/item/kitchen/knife/plastic diff --git a/code/game/objects/items/weapons/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm index e6ba57ff8da..047a75bd634 100644 --- a/code/game/objects/items/weapons/legcuffs.dm +++ b/code/game/objects/items/weapons/legcuffs.dm @@ -33,7 +33,7 @@ return ..() /obj/item/restraints/legcuffs/beartrap/suicide_act(mob/user) - user.visible_message("[user] is sticking \his head in the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is sticking [user.p_their()] head in the [name]! It looks like [user.p_theyre()] trying to commit suicide.") playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) return (BRUTELOSS) diff --git a/code/game/objects/items/weapons/lighters.dm b/code/game/objects/items/weapons/lighters.dm index a620f3fdb5c..94e97ea7c20 100644 --- a/code/game/objects/items/weapons/lighters.dm +++ b/code/game/objects/items/weapons/lighters.dm @@ -57,7 +57,7 @@ if(affecting.receive_damage( 0, 5 )) //INFERNO H.UpdateDamageIcon() H.updatehealth() - user.visible_message("After a few attempts, [user] manages to light the [src], they however burn their finger in the process.") + user.visible_message("After a few attempts, [user] manages to light the [src], [user.p_they()] however burn[user.p_s()] [user.p_their()] finger in the process.") set_light(2) processing_objects.Add(src) @@ -70,7 +70,7 @@ force = 0 attack_verb = null //human_defense.dm takes care of it if(istype(src, /obj/item/lighter/zippo) ) - user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what they're doing. Wow.") + user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.") playsound(src.loc, 'sound/items/ZippoClose.ogg', 25, 1) else user.visible_message("[user] quietly shuts off the [src].") @@ -95,7 +95,7 @@ cig.attackby(src, user) else if(istype(src, /obj/item/lighter/zippo)) - cig.light("[user] whips the [name] out and holds it for [M]. Their arm is as steady as the unflickering flame they light \the [cig] with.") + cig.light("[user] whips the [name] out and holds it for [M]. [user.p_their(TRUE)] arm is as steady as the unflickering flame [user.p_they()] light[user.p_s()] \the [cig] with.") else cig.light("[user] holds the [name] out for [M], and lights the [cig.name].") M.update_inv_wear_mask() diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 6702f893d50..2dcbef5b1a5 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -14,8 +14,8 @@ var/colormap = list(red=LIGHT_COLOR_RED, blue=LIGHT_COLOR_LIGHTBLUE, green=LIGHT_COLOR_GREEN, purple=LIGHT_COLOR_PURPLE, rainbow=LIGHT_COLOR_WHITE) /obj/item/melee/energy/suicide_act(mob/user) - user.visible_message(pick("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.", \ - "[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.")) + user.visible_message(pick("[user] is slitting [user.p_their()] stomach open with the [name]! It looks like [user.p_theyre()] trying to commit seppuku.", \ + "[user] is falling on the [name]! It looks like [user.p_theyre()] trying to commit suicide.")) return (BRUTELOSS|FIRELOSS) /obj/item/melee/energy/attack_self(mob/living/carbon/user) @@ -80,7 +80,7 @@ light_color = LIGHT_COLOR_WHITE /obj/item/melee/energy/axe/suicide_act(mob/user) - user.visible_message("[user] swings the [src.name] towards /his head! It looks like \he's trying to commit suicide.") + user.visible_message("[user] swings the [name] towards [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide.") return (BRUTELOSS|FIRELOSS) /obj/item/melee/energy/sword diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm index 267c2deda5e..a19df11e790 100644 --- a/code/game/objects/items/weapons/melee/misc.dm +++ b/code/game/objects/items/weapons/melee/misc.dm @@ -17,7 +17,7 @@ /obj/item/melee/chainofcommand/suicide_act(mob/user) - to_chat(viewers(user), "[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.") + to_chat(viewers(user), "[user] is strangling [user.p_them()]self with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.") return (OXYLOSS) /obj/item/melee/rapier diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm index 84b8d55a915..64f554682fc 100644 --- a/code/game/objects/items/weapons/pneumaticCannon.dm +++ b/code/game/objects/items/weapons/pneumaticCannon.dm @@ -103,7 +103,7 @@ to_chat(user, "\The [src] lets out a weak hiss and doesn't react!") return if(user && (CLUMSY in user.mutations) && prob(75)) - user.visible_message("[user] loses their grip on [src], causing it to go off!", "[src] slips out of your hands and goes off!") + user.visible_message("[user] loses [user.p_their()] grip on [src], causing it to go off!", "[src] slips out of your hands and goes off!") user.drop_item() if(prob(10)) target = get_turf(user) diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm deleted file mode 100644 index 5b2d05491bf..00000000000 --- a/code/game/objects/items/weapons/power_cells.dm +++ /dev/null @@ -1,211 +0,0 @@ -/obj/item/stock_parts/cell - name = "power cell" - desc = "A rechargable electrochemical power cell." - icon = 'icons/obj/power.dmi' - icon_state = "cell" - item_state = "cell" - origin_tech = "powerstorage=1" - force = 5 - throwforce = 5 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - var/charge = 0 // note %age conveted to actual charge in New - var/maxcharge = 1000 - materials = list(MAT_METAL=700, MAT_GLASS=50) - var/rigged = 0 // true if rigged to explode - var/chargerate = 100 //how much power is given every tick in a recharger - var/self_recharge = 0 //does it self recharge, over time, or not? - var/grown_battery = FALSE // If it's a grown that acts as a battery, add a wire overlay to it. - -/obj/item/stock_parts/cell/New() - ..() - processing_objects.Add(src) - charge = maxcharge - updateicon() - -/obj/item/stock_parts/cell/Destroy() - processing_objects.Remove(src) - return ..() - -/obj/item/stock_parts/cell/vv_edit_var(var_name, var_value) - switch(var_name) - if("self_recharge") - if(var_value) - processing_objects.Add(src) - else - processing_objects.Remove(src) - . = ..() - -/obj/item/stock_parts/cell/suicide_act(mob/user) - to_chat(viewers(user), "[user] is licking the electrodes of the [src.name]! It looks like \he's trying to commit suicide.") - return (FIRELOSS) - -/obj/item/stock_parts/cell/process() - if(self_recharge) - give(chargerate * 0.25) - else - return PROCESS_KILL - -/obj/item/stock_parts/cell/proc/updateicon() - overlays.Cut() - if(grown_battery) - overlays += image('icons/obj/power.dmi', "grown_wires") - if(charge < 0.01) - return - else if(charge/maxcharge >=0.995) - overlays += image('icons/obj/power.dmi', "cell-o2") - else - overlays += image('icons/obj/power.dmi', "cell-o1") - -/obj/item/stock_parts/cell/crap - name = "\improper Nanotrasen brand rechargable AA battery" - desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT - maxcharge = 500 - materials = list(MAT_GLASS=40) - rating = 2 - -/obj/item/stock_parts/cell/crap/empty/New() - ..() - charge = 0 - -/obj/item/stock_parts/cell/secborg - name = "\improper Security borg rechargable D battery" - origin_tech = null - maxcharge = 600 //600 max charge / 100 charge per shot = six shots - materials = list(MAT_GLASS=40) - rating = 2.5 - -/obj/item/stock_parts/cell/secborg/empty/New() - ..() - charge = 0 - -/obj/item/stock_parts/cell/high - name = "high-capacity power cell" - origin_tech = "powerstorage=2" - icon_state = "hcell" - maxcharge = 10000 - materials = list(MAT_GLASS=60) - rating = 3 - chargerate = 1500 - -/obj/item/stock_parts/cell/high/plus - name = "high-capacity power cell+" - desc = "Where did these come from?" - icon_state = "h+cell" - maxcharge = 15000 - chargerate = 2250 - -/obj/item/stock_parts/cell/high/empty/New() - ..() - charge = 0 - -/obj/item/stock_parts/cell/super - name = "super-capacity power cell" - origin_tech = "powerstorage=3;materials=3" - icon_state = "scell" - maxcharge = 20000 - materials = list(MAT_GLASS=300) - rating = 4 - chargerate = 2000 - -/obj/item/stock_parts/cell/super/empty/New() - ..() - charge = 0 - -/obj/item/stock_parts/cell/hyper - name = "hyper-capacity power cell" - origin_tech = "powerstorage=4;engineering=4;materials=4" - icon_state = "hpcell" - maxcharge = 30000 - materials = list(MAT_GLASS=400) - rating = 5 - chargerate = 3000 - -/obj/item/stock_parts/cell/hyper/empty/New() - ..() - charge = 0 - -/obj/item/stock_parts/cell/bluespace - name = "bluespace power cell" - origin_tech = "powerstorage=5;bluespace=4;materials=4;engineering=4" - icon_state = "bscell" - maxcharge = 40000 - materials = list(MAT_GLASS=600) - rating = 6 - chargerate = 4000 - -/obj/item/stock_parts/cell/bluespace/empty/New() - ..() - charge = 0 - -/obj/item/stock_parts/cell/infinite - name = "infinite-capacity power cell!" - icon_state = "icell" - origin_tech = "powerstorage=7" - maxcharge = 30000 - materials = list(MAT_GLASS=1000) - rating = 6 - chargerate = 30000 - -/obj/item/stock_parts/cell/infinite/use() - return 1 - -/obj/item/stock_parts/cell/potato - name = "potato battery" - desc = "A rechargable starch based power cell." - icon = 'icons/obj/hydroponics/harvest.dmi' - icon_state = "potato" - origin_tech = "powerstorage=1;biotech=1" - charge = 100 - maxcharge = 300 - materials = list() - rating = 1 - grown_battery = TRUE //it has the overlays for wires - -/obj/item/stock_parts/cell/high/slime - name = "charged slime core" - desc = "A yellow slime core infused with plasma, it crackles with power." - origin_tech = "powerstorage=5;biotech=4" - icon = 'icons/mob/slimes.dmi' - icon_state = "yellow slime extract" - materials = list() - self_recharge = 1 // Infused slime cores self-recharge, over time - chargerate = 500 - -/obj/item/stock_parts/cell/pulse //200 pulse shots - name = "pulse rifle power cell" - maxcharge = 40000 - rating = 3 - chargerate = 1500 - -/obj/item/stock_parts/cell/pulse/carbine //25 pulse shots - name = "pulse carbine power cell" - maxcharge = 5000 - -/obj/item/stock_parts/cell/pulse/pistol //10 pulse shots - name = "pulse pistol power cell" - maxcharge = 2000 - -/obj/item/stock_parts/cell/ninja - name = "spider-clan power cell" - desc = "A standard ninja-suit power cell." - maxcharge = 10000 - rating = 3 - materials = list(MAT_GLASS=60) - -/obj/item/stock_parts/cell/emproof - name = "\improper EMP-proof cell" - desc = "An EMP-proof cell." - maxcharge = 500 - rating = 2 - -/obj/item/stock_parts/cell/emproof/empty/New() - ..() - charge = 0 - -/obj/item/stock_parts/cell/emproof/emp_act(severity) - return - -/obj/item/stock_parts/cell/emproof/corrupt() - return diff --git a/code/game/objects/items/weapons/powerfist.dm b/code/game/objects/items/weapons/powerfist.dm index 7b6dfeb3a75..a2315544d35 100644 --- a/code/game/objects/items/weapons/powerfist.dm +++ b/code/game/objects/items/weapons/powerfist.dm @@ -83,7 +83,7 @@ user.do_attack_animation(target) target.apply_damage(force * fisto_setting, BRUTE) - target.visible_message("[user]'s powerfist lets out a loud hiss as they punch [target.name]!", \ + target.visible_message("[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!", \ "You cry out in pain as [user]'s punch flings you backwards!") new /obj/effect/temp_visual/kinetic_blast(target.loc) playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1) diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm index aaaf034b933..e130c3ed606 100644 --- a/code/game/objects/items/weapons/rpd.dm +++ b/code/game/objects/items/weapons/rpd.dm @@ -2,28 +2,8 @@ Rapid Pipe Dispenser */ -#define SIMPLE_CAP 20 -#define SUPPLY_CAP 32 -#define SCRUBBERS_CAP 33 -#define HE_EXCHANGER 17 -#define CONNECTOR 4 -#define UNARY_VENT 7 -#define PASSIVE_VENT 37 -#define GAS_SCRUBBER 10 -#define INJECTOR 34 -#define GAS_SENSOR 98 -#define METER 99 -#define DISPOSALS_JUNCTION 2 -#define ATMOS_MODE 1 -#define DISPOSALS_MODE 2 -#define ROTATION_MODE 3 -#define FLIP_MODE 4 -#define DELETE_MODE 5 -#define ATMOS_PIPING 1 -#define SUPPLY_PIPING 2 -#define SCRUBBERS_PIPING 3 -#define DEVICES 4 -#define HEAT_PIPING 5 +#define RPD_COOLDOWN_TIME 4 //How long should we have to wait between dispensing pipes? +#define RPD_WALLBUILD_TIME 40 //How long should drilling into a wall take? /obj/item/rpd name = "rapid pipe dispenser" @@ -43,13 +23,13 @@ origin_tech = "engineering=4;materials=2" var/datum/effect_system/spark_spread/spark_system var/lastused - var/iconrotation = 0 //used to orient icons and pipes - var/mode = 1 //Disposals, atmospherics, etc. - var/pipetype = 1//For nanoUI menus - var/whatpipe = 0 //What kind of pipe is it? See code/game/machinery/pipe/construction.dm for a list of defines - var/whatdpipe = 0 //What kind of disposals pipe is it? See code/game/machinery/pipe/dispenser.dm for a list of defines - var/spawndelay = 4 //How long should we have to wait between dispensing pipes? - var/walldelay = 40 //How long should drilling into a wall take? + var/iconrotation = 0 //Used to orient icons and pipes + var/mode = RPD_ATMOS_MODE //Disposals, atmospherics, etc. + var/pipe_category = RPD_ATMOS_PIPING//For nanoUI menus, this is a subtype of pipes e.g. scrubbers pipes, devices + var/whatpipe = PIPE_SIMPLE_STRAIGHT //What kind of atmos pipe is it? + var/whatdpipe = PIPE_DISPOSALS_STRAIGHT //What kind of disposals pipe is it? + var/spawndelay = RPD_COOLDOWN_TIME + var/walldelay = RPD_WALLBUILD_TIME /obj/item/rpd/New() ..() @@ -57,82 +37,112 @@ spark_system.set_up(1, 0, src) spark_system.attach(src) +/obj/item/rpd/Destroy() + QDEL_NULL(spark_system) + return ..() + //Procs -/obj/item/rpd/proc/Activaterpd(delay) +/obj/item/rpd/proc/activate_rpd(delay) //Maybe makes sparks and activates cooldown if there is a delay playsound(loc, "sound/machines/click.ogg", 50, 1) if(prob(15)) spark_system.start() if(delay) lastused = world.time -/obj/item/rpd/proc/Manipulatepipes(subject, atmosverb, disposalsverb) - if(istype(subject, /obj/item/pipe)) - call(subject, atmosverb)() - else if(istype(subject, /obj/structure/disposalconstruct/)) - call(subject, disposalsverb)() +/obj/item/rpd/proc/can_dispense_pipe(var/pipe_id, var/pipe_type) //Returns TRUE if this is a legit pipe we can dispense, otherwise returns FALSE + for(var/list/L in GLOB.rpd_pipe_list) + if(pipe_type != L["pipe_type"]) //Sometimes pipes in different categories have the same pipe_id, so we need to skip anything not in the category we want + continue + if(pipe_id == L["pipe_id"]) //Found the pipe, we can dispense it + return TRUE + +/obj/item/rpd/proc/create_atmos_pipe(mob/user, turf/T) //Make an atmos pipe, meter, or gas sensor + if(!can_dispense_pipe(whatpipe, RPD_ATMOS_MODE)) + log_runtime(EXCEPTION("Failed to spawn [get_pipe_name(whatpipe, PIPETYPE_ATMOS)] - possible tampering detected")) //Damn dirty apes -- I mean hackers + return + var/obj/item/pipe/P + if(whatpipe == PIPE_GAS_SENSOR) + P = new /obj/item/pipe_gsensor(T) + else if(whatpipe == PIPE_METER) + P = new /obj/item/pipe_meter(T) + else + P = new(T, whatpipe, iconrotation) //Make the pipe, BUT WAIT! There's more! + if(!iconrotation && P.is_bent_pipe()) //Automatically rotates dispensed pipes if the user selected auto-rotation + P.dir = turn(user.dir, 135) + else if(!iconrotation && P.pipe_type in list(PIPE_CONNECTOR, PIPE_UVENT, PIPE_SCRUBBER, PIPE_HEAT_EXCHANGE, PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP, PIPE_INJECTOR, PIPE_PASV_VENT)) //Some pipes dispense oppositely to what you'd expect, but we don't want to do anything if they selected a direction + P.flip() + else if(iconrotation && P.is_bent_pipe()) //If user selected a rotation and the pipe is bent + P.dir = turn(iconrotation, -45) + else if(!iconrotation) //If user selected a rotation + P.dir = user.dir + to_chat(user, "[src] rapidly dispenses [P]!") + activate_rpd(TRUE) + +/obj/item/rpd/proc/create_disposals_pipe(mob/user, turf/T) //Make a disposals pipe / construct + if(!can_dispense_pipe(whatdpipe, RPD_DISPOSALS_MODE)) + log_runtime(EXCEPTION("Failed to spawn [get_pipe_name(whatdpipe, PIPETYPE_DISPOSAL)] - possible tampering detected")) + return + var/obj/structure/disposalconstruct/P = new(T, whatdpipe, iconrotation) + if(!iconrotation) //Automatic rotation + P.dir = user.dir + if(!iconrotation && whatdpipe != PIPE_DISPOSALS_JUNCTION_RIGHT) //Disposals pipes are in the opposite direction to atmos pipes, so we need to flip them. Junctions don't have this quirk though + P.flip() + to_chat(user, "[src] rapidly dispenses [P]!") + activate_rpd(TRUE) + +/obj/item/rpd/proc/rotate_all_pipes(mob/user, turf/T) //Rotate all pipes on a turf + for(var/obj/item/pipe/P in T) + P.rotate() + for(var/obj/structure/disposalconstruct/D in T) + D.rotate() + +/obj/item/rpd/proc/flip_all_pipes(mob/user, turf/T) //Flip all pipes on a turf + for(var/obj/item/pipe/P in T) + P.flip() + for(var/obj/structure/disposalconstruct/D in T) + D.flip() + +/obj/item/rpd/proc/delete_all_pipes(mob/user, turf/T) //Delete all pipes on a turf + var/eaten + for(var/obj/item/pipe/P in T) + QDEL_NULL(P) + eaten = TRUE + for(var/obj/item/pipe_gsensor/G in T) + QDEL_NULL(G) + eaten = TRUE + for(var/obj/item/pipe_meter/M in T) + QDEL_NULL(M) + eaten = TRUE + for(var/obj/structure/disposalconstruct/D in T) + if(!D.anchored) + QDEL_NULL(D) + eaten = TRUE + if(eaten) + to_chat(user, "[src] sucks up the loose pipes on [T].") + activate_rpd() + else + to_chat(user, "There were no loose pipes on [T].") + +/obj/item/rpd/proc/delete_single_pipe(mob/user, obj/P) //Delete a single pipe + to_chat(user, "[src] sucks up [P].") + QDEL_NULL(P) + activate_rpd() //Lists of things -var/list/pipelist = list( //id refers to the pipe_type found in construction.dm, icon refers to the name of the icon state in icons/obj/pipe-item.dmi. Icons are made with the asset-cache - list("pipename" = "Straight pipe", "id" = 0, "category" = ATMOS_PIPING, "orientations" = 2, "icon" = "simple"), - list("pipename" = "Bent pipe", "id" = 1, "category" = ATMOS_PIPING, "orientations" = 4, "icon" = "simple", "bendy" = 1), - list("pipename" = "T-manifold", "id" = 5, "category" = ATMOS_PIPING, "orientations" = 4, "icon" = "manifold"), - list("pipename" = "4-way manifold", "id" = 19, "category" = ATMOS_PIPING, "orientations" = 1, "icon" = "manifold4w"), - list("pipename" = "Pipe cap", "id" = 20, "category" = ATMOS_PIPING, "orientations" = 4, "icon" = "cap"), - list("pipename" = "Manual valve", "id" = 8, "category" = ATMOS_PIPING, "orientations" = 2, "icon" = "mvalve"), - list("pipename" = "Digital valve", "id" = 35, "category" = ATMOS_PIPING, "orientations" = 2, "icon" = "dvalve"), - list("pipename" = "Manual T-valve", "id" = 18, "category" = ATMOS_PIPING, "orientations" = 4, "icon" = "tvalve"), - list("pipename" = "Digital T-valve", "id" = 38, "category" = ATMOS_PIPING, "orientations" = 4, "icon" = "dtvalve"), - list("pipename" = "Straight supply pipe", "id" = 24, "category" = SUPPLY_PIPING, "orientations" = 2, "icon" = "simple"), - list("pipename" = "Bent supply pipe", "id" = 25, "category" = SUPPLY_PIPING, "orientations" = 4, "icon" = "simple", "bendy" = 1), - list("pipename" = "Supply T-manifold", "id" = 28, "category" = SUPPLY_PIPING, "orientations" = 4, "icon" = "manifold"), - list("pipename" = "4-way supply manifold", "id" = 30, "category" = SUPPLY_PIPING, "orientations" = 1, "icon" = "manifold4w"), - list("pipename" = "Supply pipe cap", "id" = 32, "category" = SUPPLY_PIPING, "orientations" = 4, "icon" = "cap"), - list("pipename" = "Straight scrubbers pipe", "id" = 26, "category" = SCRUBBERS_PIPING, "orientations" = 2, "icon" = "simple"), - list("pipename" = "Bent scrubbers pipe", "id" = 27, "category" = SCRUBBERS_PIPING, "orientations" = 4, "icon" = "simple", "bendy" = 1), - list("pipename" = "Scrubbers T-manifold", "id" = 29, "category" = SCRUBBERS_PIPING, "orientations" = 4, "icon" = "manifold"), - list("pipename" = "4-way scrubbers manifold", "id" = 31, "category" = SCRUBBERS_PIPING, "orientations" = 1, "icon" = "manifold4w"), - list("pipename" = "Scrubbers pipe cap", "id" = 33, "category" = SCRUBBERS_PIPING, "orientations" = 4, "icon" = "cap"), - list("pipename" = "Universal pipe adapter", "id" = 23, "category" = DEVICES, "orientations" = 2, "icon" = "universal"), - list("pipename" = "Connector", "id" = 4, "category" = DEVICES, "orientations" = 4, "icon" = "connector"), - list("pipename" = "Unary vent", "id" = 7, "category" = DEVICES, "orientations" = 4, "icon" = "uvent"), - list("pipename" = "Scrubber", "id" = 10, "category" = DEVICES, "orientations" = 4, "icon" = "scrubber"), - list("pipename" = "Gas pump", "id" = 9, "category" = DEVICES, "orientations" = 4, "icon" = "pump"), - list("pipename" = "Volume pump", "id" = 16, "category" = DEVICES, "orientations" = 4, "icon" = "volumepump"), - list("pipename" = "Passive gate", "id" = 15, "category" = DEVICES, "orientations" = 4, "icon" = "passivegate"), - list("pipename" = "Gas filter", "id" = 13, "category" = DEVICES, "orientations" = 4, "icon" = "filter"), - list("pipename" = "Gas mixer", "id" = 14, "category" = DEVICES, "orientations" = 4, "icon" = "mixer"), - list("pipename" = "Gas sensor", "id" = 98, "category" = DEVICES, "orientations" = 1, "icon" = "sensor"), - list("pipename" = "Meter", "id" = 99, "category" = DEVICES, "orientations" = 1, "icon" = "meter"), - list("pipename" = "Passive vent", "id" = 37, "category" = DEVICES, "orientations" = 4, "icon" = "passive vent"), - list("pipename" = "Dual-port vent pump", "id" = 36, "category" = DEVICES, "orientations" = 2, "icon" = "dual-port vent"), - list("pipename" = "Air injector", "id" = 34, "category" = DEVICES, "orientations" = 4, "icon" = "injector"), - list("pipename" = "Straight HE pipe", "id" = 2, "category" = HEAT_PIPING, "orientations" = 2, "icon" = "he"), - list("pipename" = "Bent HE pipe", "id" = 3, "category" = HEAT_PIPING, "orientations" = 4, "icon" = "he", "bendy" = 1), - list("pipename" = "Junction", "id" = 6, "category" = HEAT_PIPING, "orientations" = 4, "icon" = "junction"), - list("pipename" = "Heat exchanger", "id" = 17, "category" = HEAT_PIPING, "orientations" = 4, "icon" = "heunary")) -var/list/dpipelist = list( - list("pipename" = "Straight pipe", "id" = 0, "orientations" = 2, "icon" = "conpipe-s"), - list("pipename" = "Bent pipe", "id" = 1, "orientations" = 4, "icon" = "conpipe-c"), - list("pipename" = "Junction", "id" = 2, "orientations" = 4, "icon" = "conpipe-j1"), - list("pipename" = "Y-junction", "id" = 4, "orientations" = 4, "icon" = "conpipe-y"), - list("pipename" = "Trunk", "id" = 5, "orientations" = 4, "icon" = "conpipe-t"), - list("pipename" = "Bin", "id" = 6, "orientations" = 1, "icon" = "condisposal"), - list("pipename" = "Outlet", "id" = 7, "orientations" = 4, "icon" = "outlet"), - list("pipename" = "Chute", "id" = 8, "orientations" = 4, "icon" = "intake")) var/list/mainmenu = list( - list("category" = "Atmospherics", "mode" = 1, "icon" = "wrench"), - list("category" = "Disposals", "mode" = 2, "icon" = "recycle"), - list("category" = "Rotate", "mode" = 3, "icon" = "rotate-right"), - list("category" = "Flip", "mode" = 4, "icon" = "exchange"), - list("category" = "Recycle", "mode" = 5, "icon" = "trash")) + list("category" = "Atmospherics", "mode" = RPD_ATMOS_MODE, "icon" = "wrench"), + list("category" = "Disposals", "mode" = RPD_DISPOSALS_MODE, "icon" = "recycle"), + list("category" = "Rotate", "mode" = RPD_ROTATE_MODE, "icon" = "rotate-right"), + list("category" = "Flip", "mode" = RPD_FLIP_MODE, "icon" = "exchange"), + list("category" = "Recycle", "mode" = RPD_DELETE_MODE, "icon" = "trash")) var/list/pipemenu = list( - list("pipecategory" = "Normal", "pipemode" = 1), - list("pipecategory" = "Supply", "pipemode" = 2), - list("pipecategory" = "Scrubber", "pipemode" = 3), - list("pipecategory" = "Devices", "pipemode" = 4), - list("pipecategory" = "Heat exchange", "pipemode" = 5)) + list("category" = "Normal", "pipemode" = RPD_ATMOS_PIPING), + list("category" = "Supply", "pipemode" = RPD_SUPPLY_PIPING), + list("category" = "Scrubber", "pipemode" = RPD_SCRUBBERS_PIPING), + list("category" = "Devices", "pipemode" = RPD_DEVICES), + list("category" = "Heat exchange", "pipemode" = RPD_HEAT_PIPING)) //NanoUI stuff @@ -148,13 +158,12 @@ var/list/pipemenu = list( /obj/item/rpd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state) var/data[0] - data["dpipelist"] = dpipelist data["iconrotation"] = iconrotation data["mainmenu"] = mainmenu data["mode"] = mode - data["pipelist"] = pipelist + data["pipelist"] = GLOB.rpd_pipe_list data["pipemenu"] = pipemenu - data["pipetype"] = pipetype + data["pipe_category"] = pipe_category data["whatdpipe"] = whatdpipe data["whatpipe"] = whatpipe return data @@ -167,99 +176,23 @@ var/list/pipemenu = list( whatpipe = text2num(sanitize(href_list["whatpipe"])) else if(href_list["whatdpipe"]) whatdpipe = text2num(sanitize(href_list["whatdpipe"])) - else if(href_list["pipetype"]) - pipetype = text2num(sanitize(href_list["pipetype"])) + else if(href_list["pipe_category"]) + pipe_category = text2num(sanitize(href_list["pipe_category"])) else if(href_list["mode"]) mode = text2num(sanitize(href_list["mode"])) else return SSnanoui.update_uis(src) -//What the RPD actually does - /obj/item/rpd/afterattack(atom/target, mob/user, proximity) ..() - var/turf/T = get_turf(target) - if(loc != user || ismob(target) || istype(target, /obj/structure/window) || !proximity || world.time < lastused + spawndelay) + if(loc != user) return - if(!(T.flags & RPD_ALLOWED_HERE)) - to_chat(user, "[src] beeps, \"Unable to interface with [T]. Please try again later.\"") + if(!proximity) return - if(mode == ATMOS_MODE) - if(istype(T, /turf/simulated/wall)) //Drilling into walls takes time - playsound(loc, "sound/weapons/circsawhit.ogg", 50, 1) - user.visible_message("[user] starts drilling a hole in [T]...", "You start drilling a hole in [T]...", "You hear a drill.") - if(!do_after(user, walldelay, target = T)) - return - user.visible_message("[user] finishes drilling a hole in [T]!", "You finish drilling a hole in [T]!", "You hear clanking.") - var/obj/item/pipe/P - if(whatpipe == GAS_SENSOR) - P = new /obj/item/pipe_gsensor(T) - else if(whatpipe == METER) - P = new /obj/item/pipe_meter(T) - else - P = new(T, pipe_type = whatpipe, dir = user.dir) - if(iconrotation == 0 && P.is_bent_pipe()) //Automatic rotation of dispensed pipes - P.dir = turn(user.dir, 135) - else if(iconrotation == 0 && P.pipe_type in list(CONNECTOR, UNARY_VENT, GAS_SCRUBBER, HE_EXCHANGER, SIMPLE_CAP, SUPPLY_CAP, SCRUBBERS_CAP, INJECTOR, PASSIVE_VENT)) //Some pipes dispense oppositely to what you'd expect, but we don't want to do anything if they selected a direction - P.flip() - else if(iconrotation != 0 && P.is_bent_pipe()) //If they selected a rotation and the pipe is bent - P.dir = turn(iconrotation, -45) - else if(iconrotation != 0) - P.dir = iconrotation - to_chat(user, "[src] rapidly dispenses [P]!") - Activaterpd(1) - else if(mode == DISPOSALS_MODE && !istype(T, /turf/simulated/shuttle)) - if(istype(T, /turf/simulated/wall)) //No disposals pipes on walls - to_chat(user, "That type of pipe won't fit on [T]!") - return - var/obj/structure/disposalconstruct/P = new(T) //Now we make the pipe - P.dir = iconrotation - P.ptype = whatdpipe - if(iconrotation == 0) //Automatic rotation - P.dir = user.dir - if(iconrotation == 0 && whatdpipe != DISPOSALS_JUNCTION) //Disposals pipes are in the opposite direction to atmos pipes, so we need to flip them. Junctions don't have this quirk though - P.flip() - P.update() - to_chat(user, "[src] rapidly dispenses [P]!") - Activaterpd(1) - else if(mode == ROTATION_MODE) - for(var/obj/W in T) - Manipulatepipes(W, /obj/item/pipe/verb/rotate, /obj/structure/disposalconstruct/verb/rotate) - else if(mode == FLIP_MODE) - for(var/obj/W in T) - Manipulatepipes(W, /obj/item/pipe/verb/flip, /obj/structure/disposalconstruct/verb/flip) - else if(mode == DELETE_MODE) - var/eaten - for(var/obj/W in T) - if(istype(W, /obj/item/pipe) || istype(W, /obj/item/pipe_meter) || istype(W, /obj/item/pipe_gsensor) || istype(W, /obj/structure/disposalconstruct) && !W.anchored) - QDEL_NULL(W) - eaten = TRUE - if(eaten) - to_chat(user, "[src] sucks up the loose pipes on [T].") - Activaterpd() - else - to_chat(user, "There were no loose pipes on [T].") + if(world.time < lastused + spawndelay) + return + target.rpd_act(user, src) //Handle RPD effects in separate procs -#undef SIMPLE_CAP -#undef SUPPLY_CAP -#undef SCRUBBERS_CAP -#undef HE_EXCHANGER -#undef CONNECTOR -#undef UNARY_VENT -#undef PASSIVE_VENT -#undef GAS_SCRUBBER -#undef INJECTOR -#undef GAS_SENSOR -#undef METER -#undef DISPOSALS_JUNCTION -#undef ATMOS_MODE -#undef DISPOSALS_MODE -#undef ROTATION_MODE -#undef FLIP_MODE -#undef DELETE_MODE -#undef ATMOS_PIPING -#undef SUPPLY_PIPING -#undef SCRUBBERS_PIPING -#undef DEVICES -#undef HEAT_PIPING +#undef RPD_COOLDOWN_TIME +#undef RPD_WALLBUILD_TIME diff --git a/code/game/objects/items/weapons/scissors.dm b/code/game/objects/items/weapons/scissors.dm index 677b2d99168..2f53a1200a9 100644 --- a/code/game/objects/items/weapons/scissors.dm +++ b/code/game/objects/items/weapons/scissors.dm @@ -33,19 +33,19 @@ var/list/species_facial_hair = list() var/obj/item/organ/external/head/C = H.get_organ("head") var/datum/robolimb/robohead = all_robolimbs[C.model] - if(H.gender == MALE || H.get_species() == "Vulpkanin") - if(C.species) + if(H.gender == MALE || isvulpkanin(H)) + if(C.dna.species) for(var/i in facial_hair_styles_list) var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i] - if(C.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. - if(C.species.bodyflags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(C.dna.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. + if(C.dna.species.bodyflags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. if(robohead.is_monitor) to_chat(user, "You are unable to find anything on [H]'s face worth cutting. How disappointing.") return continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_facial_hair += i else - if(C.species.bodyflags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(C.dna.species.bodyflags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. if(!robohead.is_monitor) if("Human" in tmp_facial.species_allowed) species_facial_hair += i @@ -57,18 +57,18 @@ var/f_new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair //handle normal hair var/list/species_hair = list() - if(C.species) + if(C.dna.species) for(var/i in hair_styles_public_list) var/datum/sprite_accessory/hair/tmp_hair = hair_styles_public_list[i] - if(C.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. - if(C.species.bodyflags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(C.dna.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. + if(C.dna.species.bodyflags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. if(robohead.is_monitor) to_chat(user, "You are unable to find anything on [H]'s head worth cutting. How disappointing.") return continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_hair += i else - if(C.species.bodyflags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(C.dna.species.bodyflags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. if(!robohead.is_monitor) if("Human" in tmp_hair.species_allowed) species_hair += i @@ -114,7 +114,7 @@ playsound(loc, 'sound/goonstation/misc/Scissor.ogg', 100, 1) if(do_after(user, 50 * toolspeed, target = H)) playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - user.visible_message("[user] abruptly stops cutting [M]'s hair and slices their throat!", "You stop cutting [M]'s hair and slice their throat!") //Just a little off the top. + user.visible_message("[user] abruptly stops cutting [M]'s hair and slices [M.p_their()] throat!", "You stop cutting [M]'s hair and slice [M.p_their()] throat!") //Just a little off the top. H.AdjustLoseBreath(10) //30 Oxy damage over time H.apply_damage(18, BRUTE, "head", sharp =1, used_weapon = "scissors") var/turf/location = get_turf(src) diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm index 6170eae96a7..0f771fee03d 100644 --- a/code/game/objects/items/weapons/shards.dm +++ b/code/game/objects/items/weapons/shards.dm @@ -16,8 +16,8 @@ armor = list("melee" = 100, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0) /obj/item/shard/suicide_act(mob/user) - to_chat(viewers(user), pick("[user] is slitting \his wrists with \the [src]! It looks like \he's trying to commit suicide.", - "[user] is slitting \his throat with \the [src]! It looks like \he's trying to commit suicide.")) + to_chat(viewers(user), pick("[user] is slitting [user.p_their()] wrists with [src]! It looks like [user.p_theyre()] trying to commit suicide.", + "[user] is slitting [user.p_their()] throat with [src]! It looks like [user.p_theyre()] trying to commit suicide.")) return (BRUTELOSS) /obj/item/shard/New() @@ -45,7 +45,7 @@ var/mob/living/carbon/human/H = user if(!H.gloves) var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand") - if(affecting.status & ORGAN_ROBOT) + if(affecting.is_robotic()) return to_chat(H, "[src] cuts into your hand!") if(affecting.receive_damage(force*0.5)) @@ -82,7 +82,7 @@ var/obj/item/organ/external/affecting = H.get_organ(pick("l_foot", "r_foot")) if(!affecting) return - if(affecting.status & ORGAN_ROBOT) + if(affecting.is_robotic()) return H.Weaken(3) if(affecting.receive_damage(5, 0)) diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm index a6046b575f7..742f5b3d0c0 100644 --- a/code/game/objects/items/weapons/soap.dm +++ b/code/game/objects/items/weapons/soap.dm @@ -26,7 +26,7 @@ to_chat(user, "You need to take that [target.name] off before cleaning it.") else if(target == user && user.a_intent == INTENT_GRAB && ishuman(target)) var/mob/living/carbon/human/muncher = user - if(muncher && muncher.get_species() == "Drask") + if(muncher && isdrask(muncher)) to_chat(user, "You take a bite of the [name]. Delicious!") playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0) user.nutrition += 2 diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 9ef11ec3b2d..85a0e679bb6 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -49,10 +49,10 @@ if(istype(W, /obj/item/storage/backpack/holding)) var/response = alert(user, "Are you sure you want to put the bag of holding inside another bag of holding?","Are you sure you want to die?","Yes","No") if(response == "Yes") - user.visible_message("[user] grins as \he begins to put a Bag of Holding into a Bag of Holding!", "You begin to put the Bag of Holding into the Bag of Holding!") + user.visible_message("[user] grins as [user.p_they()] begin[user.p_s()] to put a Bag of Holding into a Bag of Holding!", "You begin to put the Bag of Holding into the Bag of Holding!") if(do_after(user, 30, target=src)) investigate_log("has become a singularity. Caused by [user.key]","singulo") - user.visible_message("[user] erupts in evil laughter as \he puts the Bag of Holding into another Bag of Holding!", "You can't help but laugh wildly as you put the Bag of Holding into another Bag of Holding, complete darkness surrounding you."," You hear the sound of scientific evil brewing! ") + user.visible_message("[user] erupts in evil laughter as [user.p_they()] put[user.p_s()] the Bag of Holding into another Bag of Holding!", "You can't help but laugh wildly as you put the Bag of Holding into another Bag of Holding, complete darkness surrounding you."," You hear the sound of scientific evil brewing! ") qdel(W) var/obj/singularity/singulo = new /obj/singularity(get_turf(user)) singulo.energy = 300 //To give it a small boost diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 2b67373d9c4..3e7f2f6f8c9 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -40,7 +40,7 @@ cant_hold = list(/obj/item/disk/nuclear) /obj/item/storage/bag/trash/suicide_act(mob/user) - user.visible_message("[user] puts the [src.name] over their head and starts chomping at the insides! Disgusting!") + user.visible_message("[user] puts the [name] over [user.p_their()] head and starts chomping at the insides! Disgusting!") playsound(loc, 'sound/items/eatfood.ogg', 50, 1, -1) return (TOXLOSS) @@ -371,7 +371,7 @@ */ /obj/item/storage/bag/tray name = "tray" - icon = 'icons/obj/food/food.dmi' + icon = 'icons/obj/food/containers.dmi' icon_state = "tray" desc = "A metal tray to lay food on." force = 5 @@ -453,9 +453,9 @@ sleep(rand(2,4)) if( droppedSomething ) if( foundtable ) - user.visible_message("[user] unloads their service tray.") + user.visible_message("[user] unloads [user.p_their()] service tray.") else - user.visible_message("[user] drops all the items on their tray.") + user.visible_message("[user] drops all the items on [user.p_their()] tray.") return ..() diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index aa723cba8c0..9d4481952f5 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -58,8 +58,8 @@ /obj/item/stack/cable_coil, /obj/item/t_scanner, /obj/item/analyzer, - /obj/item/taperoll/engineering, - /obj/item/extinguisher/mini) + /obj/item/extinguisher/mini, + /obj/item/holosign_creator) /obj/item/storage/belt/utility/full/New() ..() @@ -192,7 +192,7 @@ /obj/item/melee/baton, /obj/item/melee/classic_baton, /obj/item/flashlight/seclite, - /obj/item/taperoll/police, + /obj/item/holosign_creator/security, /obj/item/melee/classic_baton/telescopic, /obj/item/restraints/legcuffs/bola) diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index 4d56e2a22ad..03787385e1c 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -68,7 +68,7 @@ if(M.stat !=2) /*if((M.mind in ticker.mode.cult) && (prob(20))) to_chat(M, "The power of [src.deity_name] clears your mind of heresy!") - to_chat(user, "You see how [M]'s eyes become clear, the cult no longer holds control over him!") + to_chat(user, "You see how [M]'s eyes become clear, the cult no longer holds control over [M.p_them()]!") ticker.mode.remove_cultist(M.mind)*/ if((istype(M, /mob/living/carbon/human) && prob(60))) bless(M) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index e0e43bfbda6..a78bc40dd3a 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -26,6 +26,7 @@ item_state = "syringe_kit" burn_state = FLAMMABLE var/foldable = /obj/item/stack/sheet/cardboard + var/amt = 1 /obj/item/storage/box/attack_self(mob/user) ..() @@ -49,7 +50,7 @@ return to_chat(user, "You fold [src] flat.") - var/obj/item/I = new foldable(get_turf(src)) + var/obj/item/stack/I = new foldable(get_turf(src), amt) user.put_in_hands(I) qdel(src) @@ -59,6 +60,7 @@ icon_state = "largebox" w_class = 42 // Big, bulky. foldable = /obj/item/stack/sheet/cardboard + amt = 4 storage_slots = 21 max_combined_w_class = 42 // 21*2 diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 9bf760aee29..03b5ac86870 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -14,7 +14,7 @@ */ /obj/item/storage/fancy/ - icon = 'icons/obj/food/food.dmi' + icon = 'icons/obj/food/containers.dmi' icon_state = "donutbox6" name = "donut box" burn_state = FLAMMABLE @@ -43,7 +43,6 @@ */ /obj/item/storage/fancy/donut_box - icon = 'icons/obj/food/food.dmi' icon_state = "donutbox6" icon_type = "donut" name = "donut box" @@ -61,7 +60,6 @@ */ /obj/item/storage/fancy/egg_box - icon = 'icons/obj/food/food.dmi' icon_state = "eggbox" icon_type = "egg" name = "egg box" @@ -403,6 +401,7 @@ icon_state = "AquaticKit" throw_speed = 2 throw_range = 8 + med_bot_skin = "fish" /obj/item/storage/firstaid/aquatic_kit/full desc = "It's a starter kit for an acquarium; includes 1 tank brush, 1 egg scoop, 1 fish net, and 1 container of fish food." diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 34e350e3d50..ddc8b79012f 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -21,6 +21,8 @@ var/treatment_fire = "salglu_solution" var/treatment_tox = "charcoal" var/treatment_virus = "spaceacillin" + var/med_bot_skin = null + var/syndicate_aligned = FALSE /obj/item/storage/firstaid/fire @@ -28,6 +30,7 @@ desc = "A medical kit that contains several medical patches and pills for treating burns. Contains one epinephrine syringe for emergency use and a health analyzer." icon_state = "ointment" item_state = "firstaid-ointment" + med_bot_skin = "ointment" New() ..() @@ -68,6 +71,7 @@ desc = "A medical kit designed to counter poisoning by common toxins. Contains three pills and syringes, and a health analyzer to determine the health of the patient." icon_state = "antitoxin" item_state = "firstaid-toxin" + med_bot_skin = "tox" New() ..() @@ -92,6 +96,7 @@ desc = "A first aid kit that contains four pills of salbutamol, which is able to counter injuries caused by suffocation. Also contains a health analyzer to determine the health of the patient." icon_state = "o2" item_state = "firstaid-o2" + med_bot_skin = "o2" New() ..() @@ -111,6 +116,7 @@ desc = "A medical kit that contains several medical patches and pills for treating brute injuries. Contains one epinephrine syringe for emergency use and a health analyzer." icon_state = "brute" item_state = "firstaid-brute" + med_bot_skin = "brute" New() ..() @@ -135,6 +141,7 @@ desc = "Contains advanced medical treatments." icon_state = "advfirstaid" item_state = "firstaid-advanced" + med_bot_skin = "adv" /obj/item/storage/firstaid/adv/New() ..() @@ -157,10 +164,12 @@ desc = "I hope you've got insurance." max_w_class = WEIGHT_CLASS_NORMAL treatment_oxy = "perfluorodecalin" - treatment_brute = "styptic_powder" - treatment_fire = "silver_sulfadiazine" + treatment_brute = "bicaridine" + treatment_fire = "kelotane" treatment_tox = "charcoal" req_one_access =list(access_syndicate) + med_bot_skin = "bezerk" + syndicate_aligned = TRUE /obj/item/storage/firstaid/tactical/New() ..() diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 93f230a07e8..66316b6f7ef 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -357,19 +357,22 @@ remove_from_storage(Item, loc, burn) //This proc is called when you want to place an item into the storage item. -/obj/item/storage/attackby(obj/item/W as obj, mob/user as mob, params) +/obj/item/storage/attackby(obj/item/I, mob/user, params) ..() - + if(istype(I, /obj/item/hand_labeler)) + var/obj/item/hand_labeler/labeler = I + if(labeler.mode) + return FALSE + . = 1 //no afterattack if(isrobot(user)) - to_chat(user, "You're a robot. No.") - return 1//Robots can't interact with storage items. + return //Robots can't interact with storage items. - if(!can_be_inserted(W)) - return 0 - - handle_item_insertion(W) - return 1 + if(!can_be_inserted(I)) + if(contents.len >= storage_slots) //don't use items on the backpack if they don't fit + return TRUE + return FALSE + handle_item_insertion(I) /obj/item/storage/attack_hand(mob/user as mob) playsound(src.loc, "rustle", 50, 1, -5) diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index da9edab2833..31cc7a1faf2 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -16,7 +16,7 @@ var/hitcost = 1000 /obj/item/melee/baton/suicide_act(mob/user) - user.visible_message("[user] is putting the live [name] in \his mouth! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide.") return (FIRELOSS) /obj/item/melee/baton/New() @@ -78,7 +78,7 @@ else if(istype(W, /obj/item/screwdriver)) if(bcell) - bcell.updateicon() + bcell.update_icon() bcell.loc = get_turf(src.loc) bcell = null to_chat(user, "You remove the cell from the [src].") @@ -104,7 +104,7 @@ /obj/item/melee/baton/attack(mob/M, mob/living/user) if(status && (CLUMSY in user.mutations) && prob(50)) - user.visible_message("[user] accidentally hits themself with [src]!", \ + user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \ "You accidentally hit yourself with [src]!") user.Weaken(stunforce*3) deductcharge(hitcost) @@ -175,7 +175,7 @@ user.Weaken(stunforce) user.stuttering = stunforce deductcharge(hitcost) - user.visible_message("[user] shocks themself while attempting to wash the active [src]!", \ + user.visible_message("[user] shocks [user.p_them()]self while attempting to wash the active [src]!", \ "You unwisely attempt to wash [src] while it's still on.") playsound(src, "sparks", 50, 1) return 1 diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm index 38a16be40ce..57e0290346e 100644 --- a/code/game/objects/items/weapons/tape.dm +++ b/code/game/objects/items/weapons/tape.dm @@ -14,11 +14,11 @@ /obj/item/stack/tape_roll/attack(mob/living/carbon/human/M as mob, mob/living/user as mob) if(M.wear_mask) - to_chat(user, "Remove their mask first!") + to_chat(user, "Remove [M.p_their()] mask first!") else if(amount < 2) to_chat(user, "You'll need more tape for this!") else if(!M.check_has_mouth()) - to_chat(user, "They have no mouth to tape over!") + to_chat(user, "[M.p_they(TRUE)] [M.p_have()] no mouth to tape over!") else if(M == user) to_chat(user, "You try to tape your own mouth shut.") @@ -29,7 +29,7 @@ if(M == user) to_chat(user, "You cover your own mouth with a piece of duct tape.") else - to_chat(user, "You cover [M]'s mouth with a piece of duct tape. That will shut them up!") + to_chat(user, "You cover [M]'s mouth with a piece of duct tape. That will shut [M.p_them()] up!") M.visible_message("[user] tapes [M]'s mouth shut!") var/obj/item/clothing/mask/muzzle/G = new /obj/item/clothing/mask/muzzle/tapegag M.equip_to_slot(G, slot_wear_mask) diff --git a/code/game/objects/items/weapons/teleprod.dm b/code/game/objects/items/weapons/teleprod.dm index 8c942b5e0c5..1fe31f8a4f7 100644 --- a/code/game/objects/items/weapons/teleprod.dm +++ b/code/game/objects/items/weapons/teleprod.dm @@ -10,7 +10,7 @@ ..() if(status) if((CLUMSY in user.mutations) && prob(50)) - user.visible_message("[user] accidentally hits themself with [src]!", \ + user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \ "You accidentally hit yourself with [src]!") user.Weaken(stunforce*3) deductcharge(hitcost) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 44cfc648757..43904d27359 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -28,7 +28,7 @@ toolspeed = 1 /obj/item/wrench/suicide_act(mob/user) - user.visible_message("[user] is beating themselves to death with [src]! It looks like they're trying to commit suicide!") + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) return (BRUTELOSS) @@ -73,7 +73,7 @@ user.put_in_active_hand(s_drill) /obj/item/wrench/power/suicide_act(mob/user) - user.visible_message("[user] is pressing [src] against their head! It looks like they're trying to commit suicide!") + user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") return (BRUTELOSS) /obj/item/wrench/medical @@ -86,7 +86,7 @@ attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") /obj/item/wrench/medical/suicide_act(mob/user) - user.visible_message("[user] is praying to the medical wrench to take their soul. It looks like they're trying to commit suicide!") + user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") // TODO Make them glow with the power of the M E D I C A L W R E N C H // during their ascension @@ -139,7 +139,7 @@ toolspeed = 0.5 /obj/item/screwdriver/suicide_act(mob/user) - user.visible_message("[user] is stabbing [src] into their [pick("temple", "heart")]! It looks like they're trying to commit suicide!") + user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") return(BRUTELOSS) /obj/item/screwdriver/New(loc, var/param_color = null) @@ -192,7 +192,7 @@ toolspeed = 0.25 /obj/item/screwdriver/power/suicide_act(mob/user) - user.visible_message("[user] is putting [src] to their temple. It looks like they're trying to commit suicide!") + user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") return(BRUTELOSS) /obj/item/screwdriver/power/attack_self(mob/user) @@ -247,7 +247,7 @@ ..() /obj/item/wirecutters/suicide_act(mob/user) - user.visible_message("[user] is cutting at their arteries with [src]! It looks like they're trying to commit suicide!") + user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, usesound, 50, 1, -1) return (BRUTELOSS) @@ -281,7 +281,7 @@ toolspeed = 0.25 /obj/item/wirecutters/power/suicide_act(mob/user) - user.visible_message("[user] is wrapping \the [src] around their neck. It looks like they're trying to rip their head off!") + user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) if(ishuman(user)) var/mob/living/carbon/human/H = user @@ -338,7 +338,7 @@ to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") /obj/item/weldingtool/suicide_act(mob/user) - user.visible_message("[user] welds their every orifice closed! It looks like they're trying to commit suicide!") + user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") return (FIRELOSS) /obj/item/weldingtool/proc/update_torch() @@ -400,7 +400,7 @@ if(!S) return - if(!(S.status & ORGAN_ROBOT) || user.a_intent != INTENT_HELP || S.open == 2) + if(!S.is_robotic() || user.a_intent != INTENT_HELP || S.open == 2) return ..() if(!isOn()) //why wasn't this being checked already? @@ -699,7 +699,7 @@ obj/item/weldingtool/experimental/process() var/airlock_open_time = 100 // Time required to open powered airlocks /obj/item/crowbar/power/suicide_act(mob/user) - user.visible_message("[user] is putting their head in [src], it looks like they're trying to commit suicide!") + user.visible_message("[user] is putting [user.p_their()] head in [src]. It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) return (BRUTELOSS) diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 7bae5139b27..3e7f3eaffe3 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -23,19 +23,20 @@ * Twohanded */ /obj/item/twohanded - var/wielded = 0 + var/wielded = FALSE var/force_unwielded = 0 var/force_wielded = 0 var/wieldsound = null var/unwieldsound = null /obj/item/twohanded/proc/unwield(mob/living/carbon/user) - if(!wielded || !user) return - wielded = 0 + if(!wielded || !user) + return + wielded = FALSE force = force_unwielded var/sf = findtext(name," (Wielded)") if(sf) - name = copytext(name,1,sf) + name = copytext(name, 1, sf) else //something wrong name = "[initial(name)]" update_icon() @@ -45,25 +46,25 @@ if(isrobot(user)) to_chat(user, "You free up your module.") else - to_chat(user, "You are now carrying the [name] with one hand.") + to_chat(user, "You are now carrying [name] with one hand.") if(unwieldsound) playsound(loc, unwieldsound, 50, 1) var/obj/item/twohanded/offhand/O = user.get_inactive_hand() if(O && istype(O)) O.unwield() - return /obj/item/twohanded/proc/wield(mob/living/carbon/user) - if(wielded) return + if(wielded) + return if(ishuman(user)) var/mob/living/carbon/human/H = user - if(H.species.is_small) + if(H.dna.species.is_small) to_chat(user, "It's too heavy for you to wield fully.") return if(user.get_inactive_hand()) to_chat(user, "You need your other hand to be empty!") return - wielded = 1 + wielded = TRUE force = force_wielded name = "[name] (Wielded)" update_icon() @@ -80,7 +81,6 @@ O.name = "[name] - offhand" O.desc = "Your second grip on the [name]" user.put_in_inactive_hand(O) - return /obj/item/twohanded/dropped(mob/user) ..() @@ -124,22 +124,22 @@ ///////////Two hand required objects/////////////// //This is for objects that require two hands to even pick up -/obj/item/twohanded/required/ +/obj/item/twohanded/required w_class = WEIGHT_CLASS_HUGE /obj/item/twohanded/required/attack_self() return -/obj/item/twohanded/required/mob_can_equip(M as mob, slot) +/obj/item/twohanded/required/mob_can_equip(mob/M, slot) if(wielded && !slot_flags) to_chat(M, "[src] is too cumbersome to carry with anything but your hands!") - return 0 + return FALSE return ..() /obj/item/twohanded/required/attack_hand(mob/user)//Can't even pick it up without both hands empty var/obj/item/twohanded/required/H = user.get_inactive_hand() - if(get_dist(src,user) > 1) - return 0 + if(get_dist(src, user) > 1) + return FALSE if(H != null) to_chat(user, "[src] is too cumbersome to carry in one hand!") return @@ -163,7 +163,7 @@ desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?" force = 5 throwforce = 15 - sharp = 1 + sharp = TRUE w_class = WEIGHT_CLASS_BULKY slot_flags = SLOT_BACK force_unwielded = 5 @@ -174,30 +174,29 @@ /obj/item/twohanded/fireaxe/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "fireaxe[wielded]" - return -/obj/item/twohanded/fireaxe/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) - if(!proximity) return - ..() - if(A && wielded && (istype(A,/obj/structure/window) || istype(A,/obj/structure/grille))) //destroys windows and grilles in one hit - - if(istype(A,/obj/structure/window)) +/obj/item/twohanded/fireaxe/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + if(wielded) //destroys windows and grilles in one hit + if(istype(A, /obj/structure/window)) var/obj/structure/window/W = A - W.destroy() - else - qdel(A) + W.take_damage(200, BRUTE, "melee", 0) + else if(istype(A, /obj/structure/grille)) + var/obj/structure/grille/G = A + G.take_damage(40, BRUTE, "melee", 0) /* * Double-Bladed Energy Swords - Cheridan */ /obj/item/twohanded/dualsaber - var/hacked = 0 + var/hacked = FALSE var/blade_color icon_state = "dualsaber0" name = "double-bladed energy sword" desc = "Handle with care." force = 3 - throwforce = 5.0 + throwforce = 5 throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_SMALL @@ -209,7 +208,7 @@ origin_tech = "magnets=4;syndicate=5" attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 75 - sharp = 1 + sharp = TRUE light_power = 2 var/brightness_on = 2 var/colormap = list(red=LIGHT_COLOR_RED, blue=LIGHT_COLOR_LIGHTBLUE, green=LIGHT_COLOR_GREEN, purple=LIGHT_COLOR_PURPLE, rainbow=LIGHT_COLOR_WHITE) @@ -226,26 +225,35 @@ icon_state = "dualsaber0" set_light(0) -/obj/item/twohanded/dualsaber/attack(target as mob, mob/living/user as mob) +/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/user) if(HULK in user.mutations) to_chat(user, "You grip the blade too hard and accidentally close it!") unwield() return ..() - if((CLUMSY in user.mutations) && (wielded) &&prob(40)) + if((CLUMSY in user.mutations) && (wielded) && prob(40)) to_chat(user, "You twirl around a bit before losing your balance and impaling yourself on the [src].") - user.take_organ_damage(20,25) + user.take_organ_damage(20, 25) return if((wielded) && prob(50)) - spawn(0) - for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2)) - user.dir = i - sleep(1) + INVOKE_ASYNC(src, .proc/jedi_spin, user) + +/obj/item/twohanded/dualsaber/proc/jedi_spin(mob/living/user) + for(var/i in list(NORTH, SOUTH, EAST, WEST, EAST, SOUTH, NORTH, SOUTH, EAST, WEST, EAST, SOUTH)) + user.setDir(i) + if(i == WEST) + user.SpinAnimation(7, 1) + sleep(1) /obj/item/twohanded/dualsaber/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) if(wielded) return ..() - return 0 + return FALSE + +/obj/item/twohanded/dualsaber/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up + if(wielded) + to_chat(user, "You can't pick up such a dangerous item with your meaty hands without losing fingers, better not to!") + return TRUE /obj/item/twohanded/dualsaber/green blade_color = "green" @@ -265,7 +273,7 @@ /obj/item/twohanded/dualsaber/IsReflect() if(wielded) - return 1 + return TRUE /obj/item/twohanded/dualsaber/wield(mob/living/carbon/M) //Specific wield () hulk checks due to reflection chance for balance issues and switches hitsounds. if(HULK in M.mutations) @@ -274,16 +282,17 @@ ..() hitsound = 'sound/weapons/blade1.ogg' -/obj/item/twohanded/dualsaber/attackby(obj/item/W as obj, mob/user as mob, params) - ..() - if(istype(W, /obj/item/multitool)) - if(hacked == 0) - hacked = 1 +/obj/item/twohanded/dualsaber/attackby(obj/item/W, mob/user, params) + if(ismultitool(W)) + if(!hacked) + hacked = TRUE to_chat(user, "2XRNBW_ENGAGE") blade_color = "rainbow" update_icon() else to_chat(user, "It's starting to look like a triple rainbow - no, nevermind.") + else + return ..() //spears /obj/item/twohanded/spear @@ -298,13 +307,12 @@ throwforce = 20 throw_speed = 4 armour_penetration = 10 - materials = list(MAT_METAL=1150, MAT_GLASS=2075) + materials = list(MAT_METAL = 1150, MAT_GLASS = 2075) hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") - sharp = 1 - no_spin_thrown = 1 + sharp = TRUE + no_spin_thrown = TRUE var/obj/item/grenade/explosive = null - var/war_cry = "AAAAARGH!!!" /obj/item/twohanded/spear/update_icon() if(explosive) @@ -318,7 +326,6 @@ if(isturf(AM)) //So you can actually melee with it return if(explosive && wielded) - user.say("[war_cry]") explosive.forceMove(AM) explosive.prime() qdel(src) @@ -329,30 +336,6 @@ explosive.prime() qdel(src) -/obj/item/twohanded/spear/AltClick(mob/user) - ..() - if(!explosive) - return - if(ismob(loc)) - var/mob/M = loc - var/input = stripped_input(M, "What do you want your war cry to be? You will shout it when you hit someone in melee.", ,"", 50) - if(input) - war_cry = input - -/obj/item/twohanded/spear/CheckParts(list/parts_list) - ..() - if(explosive) - explosive.forceMove(get_turf(loc)) - explosive = null - update_icon() - var/obj/item/grenade/G = locate() in contents - if(G) - explosive = G - name = "explosive lance" - embed_chance = 0 - desc = "A makeshift spear with [G] attached to it. Alt+click on the spear to set your war cry!" - update_icon() - //GREY TIDE /obj/item/twohanded/spear/grey_tide icon_state = "spearglass0" @@ -381,48 +364,47 @@ M.GiveTarget(L) //Putting heads on spears -/obj/item/organ/external/head/attackby(var/obj/item/W, var/mob/living/user, params) - if(istype(W, /obj/item/twohanded/spear)) - to_chat(user, "You stick the head onto the spear and stand it upright on the ground.") - var/obj/structure/headspear/HS = new /obj/structure/headspear(user.loc) - var/matrix/M = matrix() - src.transform = M - user.drop_item() - src.loc = HS - var/image/IM = image(src.icon,src.icon_state) - IM.overlays = src.overlays.Copy() - HS.overlays += IM - qdel(W) - return - return ..() - -/obj/item/twohanded/spear/attackby(var/obj/item/I, var/mob/living/user) +/obj/item/twohanded/spear/attackby(obj/item/I, mob/living/user) if(istype(I, /obj/item/organ/external/head)) - to_chat(user, "You stick the head onto the spear and stand it upright on the ground.") - var/obj/structure/headspear/HS = new /obj/structure/headspear(user.loc) - var/matrix/M = matrix() - I.transform = M - usr.drop_item() - I.loc = HS - var/image/IM = image(I.icon,I.icon_state) - IM.overlays = I.overlays.Copy() - HS.overlays += IM - qdel(src) - return - return ..() + if(user.unEquip(src) && user.drop_item()) + to_chat(user, "You stick [I] onto the spear and stand it upright on the ground.") + var/obj/structure/headspear/HS = new /obj/structure/headspear(get_turf(src)) + var/matrix/M = matrix() + I.transform = M + var/image/IM = image(I.icon, I.icon_state) + IM.overlays = I.overlays.Copy() + HS.overlays += IM + I.forceMove(HS) + HS.mounted_head = I + forceMove(HS) + HS.contained_spear = src + else + return ..() /obj/structure/headspear name = "head on a spear" desc = "How barbaric." icon_state = "headspear" - density = 0 - anchored = 1 + density = FALSE + anchored = TRUE + var/obj/item/organ/external/head/mounted_head = null + var/obj/item/twohanded/spear/contained_spear = null + +/obj/structure/headspear/Destroy() + QDEL_NULL(mounted_head) + QDEL_NULL(contained_spear) + return ..() /obj/structure/headspear/attack_hand(mob/living/user) - user.visible_message("[user] kicks over \the [src]!", "You kick down \the [src]!") - new /obj/item/twohanded/spear(user.loc) - for(var/obj/item/organ/external/head/H in src) - H.loc = user.loc + user.visible_message("[user] kicks over [src]!", "You kick down [src]!") + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + var/turf/T = get_turf(src) + if(contained_spear) + contained_spear.forceMove(T) + contained_spear = null + if(mounted_head) + mounted_head.forceMove(T) + mounted_head = null qdel(src) /obj/item/twohanded/spear/kidan @@ -437,18 +419,18 @@ icon_state = "gchainsaw_off" flags = CONDUCT force = 13 - var/force_on = 21 + var/force_on = 24 w_class = WEIGHT_CLASS_HUGE throwforce = 13 throw_speed = 2 throw_range = 4 - materials = list(MAT_METAL=13000) + materials = list(MAT_METAL = 13000) origin_tech = "materials=3;engineering=4;combat=2" attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered") hitsound = "swing_hit" - sharp = 1 + sharp = TRUE actions_types = list(/datum/action/item_action/startchainsaw) - var/on = 0 + var/on = FALSE /obj/item/twohanded/required/chainsaw/attack_self(mob/user) on = !on @@ -481,8 +463,8 @@ if(attack_type == PROJECTILE_ATTACK) owner.visible_message("Ranged attacks just make [owner] angrier!") playsound(src, pick('sound/weapons/bulletflyby.ogg','sound/weapons/bulletflyby2.ogg','sound/weapons/bulletflyby3.ogg'), 75, 1) - return 1 - return 0 + return TRUE + return FALSE ///CHAINSAW/// @@ -502,7 +484,7 @@ armour_penetration = 35 origin_tech = "materials=6;syndicate=4" attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered") - sharp = 1 + sharp = TRUE /obj/item/twohanded/chainsaw/update_icon() if(wielded) @@ -510,7 +492,7 @@ else icon_state = "chainsaw0" -/obj/item/twohanded/chainsaw/attack(mob/target as mob, mob/living/user as mob) +/obj/item/twohanded/chainsaw/attack(mob/target, mob/living/user) if(wielded) playsound(loc, 'sound/weapons/chainsaw.ogg', 100, 1, -1) //incredibly loud; you ain't goin' for stealth with this thing. Credit to Lonemonk of Freesound for this sound. if(isrobot(target)) @@ -562,43 +544,41 @@ /obj/item/twohanded/singularityhammer/process() if(charged < 5) charged++ - return /obj/item/twohanded/singularityhammer/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "mjollnir[wielded]" - return -/obj/item/twohanded/singularityhammer/proc/vortex(var/turf/pull as turf, mob/wielder as mob) - for(var/atom/X in orange(5,pull)) - if(istype(X, /atom/movable)) - if(X == wielder) continue - if((X) &&(!X:anchored) && (!istype(X,/mob/living/carbon/human))) - step_towards(X,pull) - step_towards(X,pull) - step_towards(X,pull) - else if(istype(X,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = X - if(istype(H.shoes,/obj/item/clothing/shoes/magboots)) - var/obj/item/clothing/shoes/magboots/M = H.shoes - if(M.magpulse) - continue - H.apply_effect(1, WEAKEN, 0) - step_towards(H,pull) - step_towards(H,pull) - step_towards(H,pull) - return +/obj/item/twohanded/singularityhammer/proc/vortex(turf/pull, mob/wielder) + for(var/atom/movable/X in orange(5, pull)) + if(X == wielder) + continue + if((X) && (!X.anchored) && (!ishuman(X))) + step_towards(X, pull) + step_towards(X, pull) + step_towards(X, pull) + else if(ishuman(X)) + var/mob/living/carbon/human/H = X + if(istype(H.shoes, /obj/item/clothing/shoes/magboots)) + var/obj/item/clothing/shoes/magboots/M = H.shoes + if(M.magpulse) + continue + H.apply_effect(1, WEAKEN, 0) + step_towards(H, pull) + step_towards(H, pull) + step_towards(H, pull) -/obj/item/twohanded/singularityhammer/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) - if(!proximity) return +/obj/item/twohanded/singularityhammer/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return if(wielded) if(charged == 5) charged = 0 - if(istype(A, /mob/living/)) + if(isliving(A)) var/mob/living/Z = A - Z.take_organ_damage(20,0) + Z.take_organ_damage(20, 0) playsound(user, 'sound/weapons/marauder.ogg', 50, 1) var/turf/target = get_turf(A) - vortex(target,user) + vortex(target, user) /obj/item/twohanded/mjollnir name = "Mjolnir" @@ -615,37 +595,35 @@ //var/charged = 5 origin_tech = "combat=4;powerstorage=7" -/obj/item/twohanded/mjollnir/proc/shock(mob/living/target as mob) +/obj/item/twohanded/mjollnir/proc/shock(mob/living/target) var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread() s.set_up(5, 1, target.loc) s.start() - target.visible_message("[target.name] was shocked by the [src.name]!", \ + target.visible_message("[target.name] was shocked by the [name]!", \ "You feel a powerful shock course through your body sending you flying!", \ "You hear a heavy electrical crack!") var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src))) target.throw_at(throw_target, 200, 4) - return -/obj/item/twohanded/mjollnir/attack(mob/M as mob, mob/user as mob) +/obj/item/twohanded/mjollnir/attack(mob/M, mob/user) ..() if(wielded) //if(charged == 5) //charged = 0 - playsound(src.loc, "sparks", 50, 1) - if(istype(M, /mob/living)) + playsound(loc, "sparks", 50, 1) + if(isliving(M)) M.Stun(3) shock(M) /obj/item/twohanded/mjollnir/throw_impact(atom/target) . = ..() - if(istype(target, /mob/living)) + if(isliving(target)) var/mob/living/L = target L.Stun(3) shock(L) /obj/item/twohanded/mjollnir/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "mjollnir[wielded]" - return /obj/item/twohanded/knighthammer name = "singuloth knight's hammer" @@ -673,27 +651,26 @@ /obj/item/twohanded/knighthammer/process() if(charged < 5) charged++ - return /obj/item/twohanded/knighthammer/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "knighthammer[wielded]" - return -/obj/item/twohanded/knighthammer/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) - if(!proximity) return +/obj/item/twohanded/knighthammer/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return if(charged == 5) charged = 0 - if(istype(A, /mob/living/)) + if(isliving(A)) var/mob/living/Z = A if(Z.health >= 1) - Z.visible_message("[Z.name] was sent flying by a blow from the [src.name]!", \ + Z.visible_message("[Z.name] was sent flying by a blow from the [name]!", \ "You feel a powerful blow connect with your body and send you flying!", \ "You hear something heavy impact flesh!.") var/atom/throw_target = get_edge_target_turf(Z, get_dir(src, get_step_away(Z, src))) Z.throw_at(throw_target, 200, 4) playsound(user, 'sound/weapons/marauder.ogg', 50, 1) else if(wielded && Z.health < 1) - Z.visible_message("[Z.name] was blown to peices by the power of [src.name]!", \ + Z.visible_message("[Z.name] was blown to pieces by the power of [name]!", \ "You feel a powerful blow rip you apart!", \ "You hear a heavy impact and the sound of ripping flesh!.") Z.gib() @@ -704,7 +681,7 @@ Z.ex_act(2) charged = 3 playsound(user, 'sound/weapons/marauder.ogg', 50, 1) - else if(istype(A, /obj/structure) || istype(A, /obj/mecha/)) + else if(istype(A, /obj/structure) || istype(A, /obj/mecha)) var/obj/Z = A Z.ex_act(2) charged = 3 @@ -717,7 +694,7 @@ icon_state = "fireaxe0" force = 5 throwforce = 15 - sharp = 1 + sharp = TRUE w_class = WEIGHT_CLASS_HUGE armour_penetration = 20 slot_flags = SLOT_BACK @@ -737,12 +714,12 @@ if(!proximity) return if(wielded) - if(istype(A, /mob/living)) + if(isliving(A)) var/mob/living/Z = A if(charged) charged-- - Z.take_organ_damage(0,30) - user.visible_message("[user] slams the charged axe into [Z.name] with all their might!") + Z.take_organ_damage(0, 30) + user.visible_message("[user] slams the charged axe into [Z.name] with all [user.p_their()] might!") playsound(loc, 'sound/magic/lightningbolt.ogg', 5, 1) var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread sparks.set_up(1, 1, src) @@ -751,7 +728,7 @@ if(A && wielded && (istype(A, /obj/structure/window) || istype(A, /obj/structure/grille))) if(istype(A, /obj/structure/window)) var/obj/structure/window/W = A - W.destroy() + W.deconstruct(FALSE) if(prob(4)) charged++ user.visible_message("The axe starts to emit an electric buzz!") @@ -759,4 +736,4 @@ qdel(A) if(prob(4)) charged++ - user.visible_message("The axe starts to emit an electric buzz!") + user.visible_message("The axe starts to emit an electric buzz!") \ No newline at end of file diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index e3b50123638..1a5fe872251 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -12,7 +12,7 @@ /obj/item/banhammer/suicide_act(mob/user) - to_chat(viewers(user), "[user] is hitting \himself with the [src.name]! It looks like \he's trying to ban \himself from life.") + to_chat(viewers(user), "[user] is hitting [user.p_them()]self with the [src.name]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life.") return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS) /obj/item/sord @@ -28,7 +28,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") /obj/item/sord/suicide_act(mob/user) - user.visible_message("[user] is trying to impale themself with [src]! It might be a suicide attempt if it weren't so shitty.", \ + user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \ "You try to impale yourself with [src], but it's USELESS...") return SHAME @@ -48,7 +48,7 @@ block_chance = 50 /obj/item/claymore/suicide_act(mob/user) - user.visible_message("[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is falling on the [name]! It looks like [user.p_theyre()] trying to commit suicide.") return(BRUTELOSS) /obj/item/claymore/ceremonial @@ -75,7 +75,7 @@ slot_flags = null /obj/item/katana/suicide_act(mob/user) - user.visible_message("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.") + user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku.") return(BRUTELOSS) /obj/item/harpoon @@ -179,7 +179,7 @@ obj/item/wirerod/attackby(obj/item/I, mob/user, params) return to_chat(user, "You begin gathering strength...") playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1) - if(do_after(user, 90, target = src)) + if(do_after(user, 90, target = user)) to_chat(user, "You gather power! Time for a home run!") homerun_ready = 1 ..() diff --git a/code/game/objects/items/weapons/whetstone.dm b/code/game/objects/items/weapons/whetstone.dm index c6a27267d10..fcb2fab2d4e 100644 --- a/code/game/objects/items/weapons/whetstone.dm +++ b/code/game/objects/items/weapons/whetstone.dm @@ -10,6 +10,7 @@ var/max = 30 var/prefix = "sharpened" var/requires_sharpness = 1 + var/claw_damage_increase = 1 /obj/item/whetstone/attackby(obj/item/I, mob/user, params) @@ -46,16 +47,24 @@ playsound(get_turf(src), usesound, 50, 1) name = "worn out [name]" desc = "[desc] At least, it used to." - used = 1 + used = TRUE update_icon() -/obj/item/whetstone/attack_self(mob/user as mob) //This is just fluff for now. Species datums are global and not newly created instances, so we can't adjust unarmed damage on a per mob basis. +/obj/item/whetstone/attack_self(mob/user) + if(used) + to_chat(user, "The whetstone is too worn to use again!") + return if(ishuman(user)) var/mob/living/carbon/human/H = user - var/datum/unarmed_attack/attack = H.species.unarmed + var/datum/unarmed_attack/attack = H.dna.species.unarmed if(istype(attack, /datum/unarmed_attack/claws)) - H.visible_message("[H] sharpens \his claws on the [src]!", "You sharpen your claws on the [src].") + attack.damage += claw_damage_increase + H.visible_message("[H] sharpens [H.p_their()] claws on [src]!", "You sharpen your claws on [src].") playsound(get_turf(H), usesound, 50, 1) + name = "worn out [name]" + desc = "[desc] At least, it used to." + used = TRUE + update_icon() /obj/item/whetstone/super name = "super whetstone block" @@ -64,3 +73,4 @@ max = 200 prefix = "super-sharpened" requires_sharpness = 0 + claw_damage_increase = 200 diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index fcd233318d5..d31338dfe06 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -71,6 +71,22 @@ visible_message("[src] is hit by \a [P]!") take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) +/obj/proc/hulk_damage() + return 150 //the damage hulks do on punches to this object, is affected by melee armor + +/obj/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + ..(user, TRUE) + visible_message("[user] smashes [src]!") + if(density) + playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + else + playsound(src, 'sound/effects/bang.ogg', 50, 1) + take_damage(hulk_damage(), BRUTE, "melee", 0, get_dir(src, user)) + return TRUE + return FALSE + /obj/blob_act(obj/structure/blob/B) if(isturf(loc)) var/turf/T = loc diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index e254d80a39c..a7e57ce5a52 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -1,7 +1,6 @@ /obj //var/datum/module/mod //not used var/origin_tech = null //Used by R&D to determine what research bonuses it grants. - var/reliability = 100 //Used by SOME devices to determine how reliable they are. var/crit_fail = 0 var/unacidable = 0 //universal "unacidabliness" var, here so you can use it in any obj. animate_movement = 2 @@ -18,6 +17,7 @@ var/integrity_failure = 0 //0 if we have no special broken behavior var/resistance_flags = NONE // INDESTRUCTIBLE + var/can_be_hit = TRUE //can this be bludgeoned by items? var/Mtoollink = 0 // variable to decide if an object should show the multitool menu linking menu, not all objects use it @@ -25,6 +25,7 @@ var/burntime = 10 //How long it takes to burn to ashes, in seconds var/burn_world_time //What world time the object will burn up completely var/being_shocked = 0 + var/speed_process = FALSE var/on_blueprints = FALSE //Are we visible on the station blueprints at roundstart? var/force_blueprints = FALSE //forces the obj to be on the blueprints, regardless of when it was created. @@ -66,9 +67,14 @@ /obj/Destroy() machines -= src processing_objects -= src + fast_processing -= src SSnanoui.close_uis(src) return ..() +/obj/rpd_act(mob/user, obj/item/rpd/our_rpd) + var/turf/T = get_turf(src) //This preserves RPD behaviour on specific turfs + T.rpd_act(user, our_rpd) + /obj/proc/process() set waitfor = 0 processing_objects.Remove(src) @@ -280,6 +286,24 @@ a { /obj/proc/on_mob_move(dir, mob/user) return +/obj/proc/makeSpeedProcess() + if(speed_process) + return + speed_process = TRUE + processing_objects.Remove(src) + fast_processing.Add(src) + +/obj/proc/makeNormalProcess() + if(!speed_process) + return + speed_process = FALSE + processing_objects.Add(src) + fast_processing.Remove(src) + /obj/vv_get_dropdown() . = ..() .["Delete all of type"] = "?_src_=vars;delall=[UID()]" + if(!speed_process) + .["Make speed process"] = "?_src_=vars;makespeedy=[UID()]" + else + .["Make normal process"] = "?_src_=vars;makenormalspeed=[UID()]" diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm index 76deeac93e8..1738344ae60 100644 --- a/code/game/objects/structures/aliens.dm +++ b/code/game/objects/structures/aliens.dm @@ -13,6 +13,27 @@ /obj/structure/alien icon = 'icons/mob/alien.dmi' + max_integrity = 100 + +/obj/structure/alien/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) + if(damage_flag == "melee") + switch(damage_type) + if(BRUTE) + damage_amount *= 0.25 + if(BURN) + damage_amount *= 2 + . = ..() + +/obj/structure/alien/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + if(damage_amount) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + else + playsound(src, 'sound/weapons/tap.ogg', 50, 1) + if(BURN) + if(damage_amount) + playsound(loc, 'sound/items/welder.ogg', 100, 1) /* * Resin @@ -22,13 +43,13 @@ desc = "Looks like some kind of thick resin." icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi' icon_state = "resin" - density = 1 - opacity = 1 - anchored = 1 + density = TRUE + opacity = TRUE + anchored = TRUE canSmoothWith = list(/obj/structure/alien/resin) - var/health = 200 - var/resintype = null + max_integrity = 200 smooth = SMOOTH_TRUE + var/resintype = null /obj/structure/alien/resin/Initialize() air_update_turf(1) @@ -60,7 +81,7 @@ /obj/structure/alien/resin/wall/shadowling //For chrysalis name = "chrysalis wall" desc = "Some sort of purple substance in an egglike shape. It pulses and throbs from within and seems impenetrable." - health = INFINITY + max_integrity = INFINITY /obj/structure/alien/resin/membrane name = "resin membrane" @@ -68,80 +89,11 @@ icon = 'icons/obj/smooth_structures/alien/resin_membrane.dmi' icon_state = "membrane0" opacity = 0 - health = 120 + max_integrity = 160 resintype = "membrane" canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) -/obj/structure/alien/resin/proc/healthcheck() - if(health <=0) - qdel(src) - - -/obj/structure/alien/resin/bullet_act(obj/item/projectile/Proj) - if(Proj.damage_type == BRUTE || Proj.damage_type == BURN) - health -= Proj.damage - ..() - healthcheck() - - -/obj/structure/alien/resin/ex_act(severity) - switch(severity) - if(1) - health -= 150 - if(2) - health -= 100 - if(3) - health -= 50 - healthcheck() - - -/obj/structure/alien/resin/blob_act() - health -= 50 - healthcheck() - - -/obj/structure/alien/resin/hitby(atom/movable/AM) - ..() - var/tforce = 0 - if(ismob(AM)) - tforce = 10 - else if(isobj(AM)) - var/obj/O = AM - tforce = O.throwforce - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - health -= tforce - healthcheck() - -/obj/structure/alien/resin/attack_hand(mob/living/user) - if(HULK in user.mutations) - user.do_attack_animation(src) - user.visible_message("[user] destroys [src]!") - health = 0 - healthcheck() - - -/obj/structure/alien/resin/attack_alien(mob/living/user) - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - if(islarva(user)) - return - user.visible_message("[user] claws at the resin!") - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - health -= 50 - if(health <= 0) - user.visible_message("[user] slices the [name] apart!") - healthcheck() - - -/obj/structure/alien/resin/attackby(obj/item/I, mob/living/user, params) - user.changeNext_move(CLICK_CD_MELEE) - health -= I.force - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - healthcheck() - ..() - - -/obj/structure/alien/resin/CanPass(atom/movable/mover, turf/target, height=0) +/obj/structure/alien/resin/CanPass(atom/movable/mover, turf/target) if(istype(mover) && mover.checkpass(PASSGLASS)) return !opacity return !density @@ -157,11 +109,11 @@ gender = PLURAL name = "resin floor" desc = "A thick resin surface covers the floor." + anchored = TRUE + density = FALSE + layer = TURF_LAYER icon_state = "weeds" - anchored = 1 - density = 0 - layer = 2 - var/health = 15 + max_integrity = 15 var/obj/structure/alien/weeds/node/linked_node = null var/static/list/weedImageCache @@ -204,39 +156,9 @@ new /obj/structure/alien/weeds(T, linked_node) - -/obj/structure/alien/weeds/ex_act(severity) - qdel(src) - - -/obj/structure/alien/weeds/attackby(obj/item/I, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) - if(I.attack_verb.len) - visible_message("[user] has [pick(I.attack_verb)] [src] with [I]!") - else - visible_message("[user] has attacked [src] with [I]!") - - var/damage = I.force / 4 - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - damage = 15 - playsound(loc, WT.usesound, 100, 1) - - health -= damage - healthcheck() - - -/obj/structure/alien/weeds/proc/healthcheck() - if(health <= 0) - qdel(src) - - /obj/structure/alien/weeds/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature > 300) - health -= 5 - healthcheck() - + take_damage(5, BURN, 0, 0) /obj/structure/alien/weeds/proc/updateWeedOverlays() @@ -303,9 +225,10 @@ name = "egg" desc = "A large mottled egg." icon_state = "egg_growing" - density = 0 - anchored = 1 - var/health = 100 + density = FALSE + anchored = TRUE + max_integrity = 100 + integrity_failure = 5 var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive layer = MOB_LAYER @@ -315,6 +238,8 @@ ..() spawn(rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME)) Grow() + if(status == BURST) + obj_integrity = integrity_failure /obj/structure/alien/egg/attack_alien(mob/living/carbon/alien/user) return attack_hand(user) @@ -346,7 +271,7 @@ icon_state = "egg" status = GROWN -/obj/structure/alien/egg/proc/Burst(kill = 1) //drops and kills the hugger if any is remaining +/obj/structure/alien/egg/proc/Burst(kill = TRUE) //drops and kills the hugger if any is remaining if(status == GROWN || status == GROWING) icon_state = "egg_hatched" flick("egg_opening", src) @@ -364,45 +289,13 @@ child.Attach(M) break -/obj/structure/alien/egg/bullet_act(obj/item/projectile/Proj) - if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - health -= Proj.damage - ..() - healthcheck() - - -/obj/structure/alien/egg/attackby(obj/item/I, mob/user, params) - if(I.attack_verb.len) - visible_message("[user] has [pick(I.attack_verb)] [src] with [I]!") - else - visible_message("[user] has attacked [src] with [I]!") - - var/damage = I.force / 4 - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = I - - if(WT.remove_fuel(0, user)) - damage = 15 - playsound(loc, WT.usesound, 100, 1) - - health -= damage - user.changeNext_move(CLICK_CD_MELEE) - healthcheck() - - -/obj/structure/alien/egg/proc/healthcheck() - if(health <= 0) - if(status != BURST && status != BURSTING) - Burst() - else if(status == BURST && prob(50)) - qdel(src) //Remove the egg after it has been hit after bursting. - +/obj/structure/alien/egg/obj_break(damage_flag) + if(status != BURST) + Burst(kill = TRUE) /obj/structure/alien/egg/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature > 500) - health -= 5 - healthcheck() - + take_damage(5, BURN, 0, 0) /obj/structure/alien/egg/HasProximity(atom/movable/AM) if(status == GROWN) diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 37ab3977755..19e08c15bde 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -10,6 +10,7 @@ burntime = 20 sound = 'sound/effects/rustle2.ogg' material_drop = /obj/item/stack/sheet/cardboard + var/amt = 4 cutting_sound = 'sound/items/poster_ripped.ogg' var/move_delay = 0 var/egged = 0 @@ -60,7 +61,7 @@ return if(istype(W, /obj/item/wirecutters)) var/obj/item/wirecutters/WC = W - new /obj/item/stack/sheet/cardboard(src.loc) + new /obj/item/stack/sheet/cardboard(src.loc, amt) for(var/mob/M in viewers(src)) M.show_message("\The [src] has been cut apart by [user] with \the [WC].", 3, "You hear cutting.", 2) qdel(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 32872e07f12..6548aa8bfca 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -30,8 +30,8 @@ new /obj/item/clothing/suit/storage/hazardvest(src) new /obj/item/clothing/mask/gas(src) new /obj/item/multitool(src) + new /obj/item/holosign_creator/engineering(src) new /obj/item/flash(src) - new /obj/item/taperoll/engineering(src) new /obj/item/clothing/head/beret/eng(src) new /obj/item/door_remote/chief_engineer(src) new /obj/item/rpd(src) @@ -102,6 +102,7 @@ new /obj/item/storage/backpack/satchel_eng(src) new /obj/item/storage/backpack/duffel/engineering(src) new /obj/item/storage/toolbox/mechanical(src) + new /obj/item/holosign_creator/engineering(src) new /obj/item/radio/headset/headset_eng(src) new /obj/item/clothing/under/rank/engineer(src) new /obj/item/clothing/under/rank/engineer/skirt(src) @@ -109,7 +110,6 @@ new /obj/item/clothing/mask/gas(src) new /obj/item/clothing/glasses/meson(src) new /obj/item/cartridge/engineering(src) - new /obj/item/taperoll/engineering(src) new /obj/item/clothing/head/beret/eng(src) @@ -128,7 +128,6 @@ new /obj/item/radio/headset/headset_eng(src) new /obj/item/cartridge/atmos(src) new /obj/item/storage/toolbox/mechanical(src) - new /obj/item/taperoll/engineering(src) if(prob(50)) new /obj/item/storage/backpack/industrial(src) else @@ -138,6 +137,7 @@ new /obj/item/clothing/suit/storage/hazardvest(src) new /obj/item/clothing/mask/gas(src) new /obj/item/tank/emergency_oxygen/engi(src) + new /obj/item/holosign_creator/atmos(src) new /obj/item/watertank/atmos(src) new /obj/item/clothing/suit/fire/atmos(src) new /obj/item/clothing/head/hardhat/atmos(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index e5c7c2b27fb..551a8b30d9d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -262,6 +262,7 @@ new /obj/item/sensor_device(src) new /obj/item/key/ambulance(src) new /obj/item/pinpointer/crew(src) + new /obj/item/clothing/shoes/magboots(src) /obj/structure/closet/secure_closet/reagents name = "chemical storage closet" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 05a3fa5c7ba..2a5639eb081 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -115,11 +115,11 @@ new /obj/item/clothing/glasses/hud/security/sunglasses(src) new /obj/item/storage/lockbox/mindshield(src) new /obj/item/storage/box/flashbangs(src) + new /obj/item/holosign_creator/security(src) new /obj/item/clothing/mask/gas/sechailer/hos(src) new /obj/item/shield/riot/tele(src) new /obj/item/melee/baton/loaded(src) new /obj/item/storage/belt/security/sec(src) - new /obj/item/taperoll/police(src) new /obj/item/gun/energy/gun/hos(src) new /obj/item/door_remote/head_of_security(src) new /obj/item/reagent_containers/food/drinks/mug/hos(src) @@ -151,8 +151,8 @@ new /obj/item/clothing/under/rank/warden/corp(src) new /obj/item/clothing/under/rank/warden/skirt(src) new /obj/item/clothing/glasses/hud/security/sunglasses(src) + new /obj/item/holosign_creator/security(src) new /obj/item/clothing/mask/gas/sechailer/warden(src) - new /obj/item/taperoll/police(src) new /obj/item/storage/box/zipties(src) new /obj/item/storage/box/flashbangs(src) new /obj/item/reagent_containers/spray/pepper(src) @@ -186,11 +186,11 @@ new /obj/item/flash(src) new /obj/item/grenade/flashbang(src) new /obj/item/storage/belt/security/sec(src) + new /obj/item/holosign_creator/security(src) new /obj/item/clothing/mask/gas/sechailer(src) new /obj/item/clothing/glasses/hud/security/sunglasses(src) new /obj/item/clothing/head/helmet(src) new /obj/item/melee/baton/loaded(src) - new /obj/item/taperoll/police(src) /obj/structure/closet/secure_closet/brigdoc @@ -344,10 +344,10 @@ new /obj/item/ammo_box/c38(src) new /obj/item/ammo_box/c38(src) new /obj/item/gun/projectile/revolver/detective(src) - new /obj/item/taperoll/police(src) new /obj/item/clothing/accessory/holster/armpit(src) new /obj/item/clothing/glasses/sunglasses/yeah(src) new /obj/item/flashlight/seclite(src) + new /obj/item/holosign_creator/security(src) new /obj/item/clothing/accessory/black(src) new /obj/item/taperecorder(src) new /obj/item/storage/box/tapes(src) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index f888ee6cc94..3b174480ce8 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -295,7 +295,7 @@ var/global/list/captain_display_cases = list() else if(user.a_intent == INTENT_HARM) user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) + user.do_attack_animation(src, ATTACK_EFFECT_KICK) user.visible_message("[user.name] kicks \the [src]!", \ "You kick \the [src]!", \ "You hear glass crack.") @@ -321,7 +321,7 @@ var/global/list/captain_display_cases = list() to_chat(src, "[bicon(src)] \The [src] is empty!") else user.changeNext_move(CLICK_CD_MELEE) - user.visible_message("[user.name] gently runs \his hands over [src] in appreciation of its contents.", \ + user.visible_message("[user.name] gently runs [user.p_their()] hands over [src] in appreciation of its contents.", \ "You gently run your hands over [src] in appreciation of its contents.", \ "You hear someone streaking glass with their greasy hands.") diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index 348c92a5335..a7233bf6a82 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -23,7 +23,7 @@ var/list/valid_underwear = list() for(var/underwear in underwear_list) var/datum/sprite_accessory/S = underwear_list[underwear] - if(!(H.species.name in S.species_allowed)) + if(!(H.dna.species.name in S.species_allowed)) continue valid_underwear[underwear] = underwear_list[underwear] var/new_underwear = input(user, "Choose your underwear:", "Changing") as null|anything in valid_underwear @@ -34,7 +34,7 @@ var/list/valid_undershirts = list() for(var/undershirt in undershirt_list) var/datum/sprite_accessory/S = undershirt_list[undershirt] - if(!(H.species.name in S.species_allowed)) + if(!(H.dna.species.name in S.species_allowed)) continue valid_undershirts[undershirt] = undershirt_list[undershirt] var/new_undershirt = input(user, "Choose your undershirt:", "Changing") as null|anything in valid_undershirts @@ -45,7 +45,7 @@ var/list/valid_sockstyles = list() for(var/sockstyle in socks_list) var/datum/sprite_accessory/S = socks_list[sockstyle] - if(!(H.species.name in S.species_allowed)) + if(!(H.dna.species.name in S.species_allowed)) continue valid_sockstyles[sockstyle] = socks_list[sockstyle] var/new_socks = input(user, "Choose your socks:", "Changing") as null|anything in valid_sockstyles diff --git a/code/game/objects/structures/engicart.dm b/code/game/objects/structures/engicart.dm index cf6a8e65715..a005e59c5a5 100644 --- a/code/game/objects/structures/engicart.dm +++ b/code/game/objects/structures/engicart.dm @@ -12,7 +12,6 @@ var/obj/item/storage/toolbox/mechanical/mybluetoolbox = null var/obj/item/storage/toolbox/electrical/myyellowtoolbox = null var/obj/item/storage/toolbox/emergency/myredtoolbox = null - var/obj/item/taperoll/engineering/myengitape = null /obj/structure/engineeringcart/Destroy() QDEL_NULL(myglass) @@ -22,7 +21,6 @@ QDEL_NULL(mybluetoolbox) QDEL_NULL(myyellowtoolbox) QDEL_NULL(myredtoolbox) - QDEL_NULL(myengitape) return ..() /obj/structure/engineeringcart/proc/put_in_cart(obj/item/I, mob/user) @@ -83,13 +81,6 @@ update_icon() else to_chat(user, fail_msg) - else if(istype(I, /obj/item/taperoll/engineering/)) - if(!myengitape) - put_in_cart(I, user) - myengitape=I - update_icon() - else - to_chat(user, fail_msg) else if(istype(I, /obj/item/wrench)) if(!anchored && !isinspace()) playsound(src.loc, I.usesound, 50, 1) @@ -125,8 +116,6 @@ dat += "[myredtoolbox.name]
" if(myyellowtoolbox) dat += "[myyellowtoolbox.name]
" - if(myengitape) - dat += "[myengitape.name]
" var/datum/browser/popup = new(user, "engicart", name, 240, 160) popup.set_content(dat) popup.open() @@ -171,16 +160,12 @@ user.put_in_hands(myyellowtoolbox) to_chat(user, "You take [myyellowtoolbox] from [src].") myyellowtoolbox = null - if(href_list["engitape"]) - if(myengitape) - user.put_in_hands(myengitape) - to_chat(user, "You take [myengitape] from [src].") - myengitape = null update_icon() updateUsrDialog() + /obj/structure/engineeringcart/update_icon() - overlays = null + overlays.Cut() if(myglass) overlays += "cart_glass" if(mymetal) @@ -194,6 +179,4 @@ if(myredtoolbox) overlays += "cart_redtoolbox" if(myyellowtoolbox) - overlays += "cart_yellowtoolbox" - if(myengitape) - overlays += "cart_engitape" + overlays += "cart_yellowtoolbox" \ No newline at end of file diff --git a/code/game/objects/structures/fullwindow.dm b/code/game/objects/structures/fullwindow.dm deleted file mode 100644 index eec957c2d52..00000000000 --- a/code/game/objects/structures/fullwindow.dm +++ /dev/null @@ -1,116 +0,0 @@ -/obj/structure/window/full - sheets = 2 - dir=SOUTHWEST - level = 3 - -/obj/structure/window/full/CheckExit(atom/movable/O as mob|obj, target as turf) - return 1 - -/obj/structure/window/full/CanPass(atom/movable/mover, turf/target, height=0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - return 0 - -/obj/structure/window/full/is_fulltile() - return 1 - -//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm) -/obj/structure/window/full/update_icon() - //A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong. - //this way it will only update full-tile ones - //This spawn is here so windows get properly updated when one gets deleted. - spawn(2) - if(!src) return - if(!is_fulltile()) - return - var/junction = 0 //will be used to determine from which side the window is connected to other windows - if(anchored) - for(var/obj/structure/window/full/W in orange(src,1)) - if(W.anchored && W.density) //Only counts anchored, not-destroyed full-tile windows. - if(abs(x-W.x)-abs(y-W.y) ) //doesn't count windows, placed diagonally to src - junction |= get_dir(src,W) - icon_state = "[basestate][junction]" - return - -/obj/structure/window/full/basic - desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." - icon_state = "window" - basestate = "window" - -/obj/structure/window/full/plasmabasic - name = "plasma window" - desc = "A plasma-glass alloy window. It looks insanely tough to break. It appears it's also insanely tough to burn through." - basestate = "plasmawindow" - icon_state = "plasmawindow" - shardtype = /obj/item/shard/plasma - glasstype = /obj/item/stack/sheet/plasmaglass - health = 240 - -/obj/structure/window/full/plasmabasic/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 32000) - hit(round(exposed_volume / 1000), 0) - ..() - -/obj/structure/window/full/plasmareinforced - name = "reinforced plasma window" - desc = "A plasma-glass alloy window, with rods supporting it. It looks hopelessly tough to break. It also looks completely fireproof, considering how basic plasma windows are insanely fireproof." - basestate = "plasmarwindow" - icon_state = "plasmarwindow" - shardtype = /obj/item/shard/plasma - glasstype = /obj/item/stack/sheet/plasmaglass - reinf = 1 - health = 320 - -/obj/structure/window/full/plasmareinforced/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/structure/window/full/reinforced - name = "reinforced window" - desc = "It looks rather strong. Might take a few good hits to shatter it." - icon_state = "rwindow" - basestate = "rwindow" - health = 80 - reinf = 1 - -/obj/structure/window/full/reinforced/tinted - name = "tinted window" - desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." - icon_state = "twindow" - basestate = "twindow" - opacity = 1 - -/obj/structure/window/full/reinforced/tinted/frosted - name = "frosted window" - desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." - icon_state = "fwindow" - basestate = "fwindow" - health = 60 - -/obj/structure/window/full/shuttle - name = "shuttle window" - desc = "It looks rather strong. Might take a few good hits to shatter it." - icon = 'icons/obj/podwindows.dmi' - icon_state = "window" - basestate = "window" - health = 160 - reinf = 1 - explosion_block = 3 - armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100) - -/obj/structure/window/full/shuttle/New() - ..() - color = null - -/obj/structure/window/full/shuttle/update_icon() //icon_state has to be set manually - return - -/obj/structure/window/full/shuttle/shuttleRotate(rotation) - ..() - var/matrix/M = transform - M.Turn(rotation) - transform = M - -/obj/structure/window/full/shuttle/dark - icon = 'icons/turf/shuttle.dmi' - icon_state = "window5" - basestate = "window5" \ No newline at end of file diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index d5dccaf0d03..b8ef71bd9c8 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -69,18 +69,23 @@ if(ismob(user)) shock(user, 70) -/obj/structure/grille/attack_hand(mob/living/user) - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - user.visible_message("[user] kicks [src].", \ - "You kick [src].", \ - "You hear twisting metal.") +/obj/structure/grille/hulk_damage() + return 60 - if(shock(user, 70)) +/obj/structure/grille/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + if(!shock(user, 70)) + ..(user, TRUE) + return TRUE + +/obj/structure/grille/attack_hand(mob/living/user) + . = ..() + if(.) return - if(HULK in user.mutations) - take_damage(60, BRUTE, "melee", 1) - else + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src, ATTACK_EFFECT_KICK) + user.visible_message("[user] hits [src].") + if(!shock(user, 70)) take_damage(rand(5,10), BRUTE, "melee", 1) /obj/structure/grille/attack_alien(mob/living/user) @@ -137,7 +142,7 @@ return //window placing begin - else if(istype(W,/obj/item/stack/sheet/rglass) || istype(W,/obj/item/stack/sheet/glass) || istype(W,/obj/item/stack/sheet/plasmaglass) || istype(W,/obj/item/stack/sheet/plasmarglass)) + else if(is_glass_sheet(W)) build_window(W, user) return //window placing end @@ -190,10 +195,10 @@ S.use(1) W.setDir(dir_to_set) W.ini_dir = dir_to_set - W.anchored = 0 - W.state = 0 + W.anchored = FALSE + W.state = WINDOW_OUT_OF_FRAME to_chat(user, "You place the [W] on [src].") - W.update_icon() + W.update_nearby_icons() return /obj/structure/grille/attacked_by(obj/item/I, mob/living/user) diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index 0de1a09a74c..3c4875978a2 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -203,7 +203,7 @@ return FALSE if(!ishuman(M)) - to_chat(usr, "It doesn't look like they can fit into this properly!") + to_chat(usr, "It doesn't look like [M.p_they()] can fit into this properly!") return FALSE // Can't decapitate non-humans if(blade_status != GUILLOTINE_BLADE_RAISED) diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm new file mode 100644 index 00000000000..0b730a539b9 --- /dev/null +++ b/code/game/objects/structures/holosign.dm @@ -0,0 +1,135 @@ + +//holographic signs and barriers + +/obj/structure/holosign + name = "holo sign" + icon = 'icons/effects/effects.dmi' + anchored = TRUE + max_integrity = 1 + armor = list("melee" = 0, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 0, "bio" = 0, "rad" = 0) + var/obj/item/holosign_creator/projector + +/obj/structure/holosign/New(loc, source_projector) + if(source_projector) + projector = source_projector + projector.signs += src + ..() + +/obj/structure/holosign/Destroy() + if(projector) + projector.signs -= src + projector = null + return ..() + +/obj/structure/holosign/attack_hand(mob/living/user) + . = ..() + if(.) + return + user.do_attack_animation(src) + user.changeNext_move(CLICK_CD_MELEE) + take_damage(5 , BRUTE, "melee", 1) + +/obj/structure/holosign/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + playsound(loc, 'sound/weapons/egloves.ogg', 80, 1) + if(BURN) + playsound(loc, 'sound/weapons/egloves.ogg', 80, 1) + +/obj/structure/holosign/wetsign + name = "wet floor sign" + desc = "The words flicker as if they mean nothing." + icon_state = "holosign" + +/obj/structure/holosign/barrier + name = "holo barrier" + desc = "A short holographic barrier which can only be passed by walking." + icon_state = "holosign_sec" + pass_flags = LETPASSTHROW + density = TRUE + max_integrity = 20 + var/allow_walk = TRUE //can we pass through it on walk intent + +/obj/structure/holosign/barrier/CanPass(atom/movable/mover, turf/target) + if(!density) + return TRUE + if(mover.pass_flags & (PASSGLASS|PASSTABLE|PASSGRILLE)) + return TRUE + if(iscarbon(mover)) + var/mob/living/carbon/C = mover + if(allow_walk && C.m_intent == MOVE_INTENT_WALK) + return TRUE + +/obj/structure/holosign/barrier/engineering + icon_state = "holosign_engi" + +/obj/structure/holosign/barrier/atmos + name = "holo firelock" + desc = "A holographic barrier resembling a firelock. Though it does not prevent solid objects from passing through, gas is kept out." + icon_state = "holo_firelock" + density = FALSE + layer = ABOVE_MOB_LAYER + anchored = TRUE + layer = ABOVE_MOB_LAYER + alpha = 150 + +/obj/structure/holosign/barrier/atmos/New() + ..() + air_update_turf(TRUE) + +/obj/structure/holosign/barrier/atmos/CanAtmosPass(turf/T) + return FALSE + +/obj/structure/holosign/barrier/atmos/Destroy() + var/turf/T = get_turf(src) + T.air_update_turf(TRUE) + return ..() + +/obj/structure/holosign/barrier/cyborg + name = "Energy Field" + desc = "A fragile energy field that blocks movement. Excels at blocking lethal projectiles." + density = TRUE + max_integrity = 10 + allow_walk = FALSE + +/obj/structure/holosign/barrier/cyborg/bullet_act(obj/item/projectile/P) + take_damage((P.damage / 5) , BRUTE, "melee", 1) //Doesn't really matter what damage flag it is. + if(istype(P, /obj/item/projectile/energy/electrode)) + take_damage(10, BRUTE, "melee", 1) //Tasers aren't harmful. + if(istype(P, /obj/item/projectile/beam/disabler)) + take_damage(5, BRUTE, "melee", 1) //Disablers aren't harmful. + +/obj/structure/holosign/barrier/cyborg/hacked + name = "Charged Energy Field" + desc = "A powerful energy field that blocks movement. Energy arcs off it." + max_integrity = 20 + var/shockcd = 0 + +/obj/structure/holosign/barrier/cyborg/hacked/bullet_act(obj/item/projectile/P) + take_damage(P.damage, BRUTE, "melee", 1) //Yeah no this doesn't get projectile resistance. + +/obj/structure/holosign/barrier/cyborg/hacked/proc/cooldown() + shockcd = FALSE + +/obj/structure/holosign/barrier/cyborg/hacked/attack_hand(mob/living/user) + . = ..() + if(.) + return + if(!shockcd) + if(ismob(user)) + var/mob/living/M = user + M.electrocute_act(15,"Energy Barrier", safety=1) + shockcd = TRUE + addtimer(CALLBACK(src, .proc/cooldown), 5) + +/obj/structure/holosign/barrier/cyborg/hacked/Bumped(atom/movable/AM) + if(shockcd) + return + + if(!isliving(AM)) + return + + var/mob/living/M = AM + M.electrocute_act(15, "Energy Barrier", safety = 1) + shockcd = TRUE + addtimer(CALLBACK(src, .proc/cooldown), 5) diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm index 8d22732e5dd..3911d366ad6 100644 --- a/code/game/objects/structures/plasticflaps.dm +++ b/code/game/objects/structures/plasticflaps.dm @@ -86,7 +86,7 @@ return ..() if(istype(A, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M - if(H.species.is_small) + if(H.dna.species.is_small) return ..() return 0 diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index 199691aa4db..6168d637c56 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -48,7 +48,10 @@ /obj/item/sign/attackby(obj/item/tool as obj, mob/user as mob) //construction if(istype(tool, /obj/item/screwdriver) && isturf(user.loc)) var/direction = input("In which direction?", "Select direction.") in list("North", "East", "South", "West", "Cancel") - if(direction == "Cancel") return + if(direction == "Cancel") + return + if(QDELETED(src)) + return var/obj/structure/sign/S = new(user.loc) switch(direction) if("North") @@ -59,7 +62,8 @@ S.pixel_y = -32 if("West") S.pixel_x = -32 - else return + else + return S.name = name S.desc = desc S.icon_state = sign_state diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 32ceefbd834..4a1ecdb08d7 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -186,7 +186,7 @@ buildstackamount = 1 /obj/structure/stool/bed/chair/sofa - name = "old ratty sofa" + name = "sofa" icon_state = "sofamiddle" anchored = 1 buildstackamount = 1 diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 367be27b6dc..91f348d0106 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -83,14 +83,7 @@ qdel(src) /obj/structure/table/attack_hand(mob/living/user) - if(HULK in user.mutations) - user.do_attack_animation(src) - visible_message("[user] smashes [src] apart!") - playsound(loc, 'sound/effects/bang.ogg', 50, 1) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - deconstruct(FALSE) - else - ..() + ..() if(climber) climber.Weaken(2) climber.visible_message("[climber.name] has been knocked off the table", "You've been knocked off the table", "You see [climber.name] get knocked off the table") @@ -616,7 +609,7 @@ if(user.weakened || user.resting || user.lying) return user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) + user.do_attack_animation(src, ATTACK_EFFECT_KICK) user.visible_message("[user] kicks [src].", \ "You kick [src].") take_damage(rand(4,8), BRUTE, "melee", 1) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 3ea23108662..179615dada3 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -548,7 +548,7 @@ var/washing_face = 0 if(selected_area in list("head", "mouth", "eyes")) washing_face = 1 - user.visible_message("[user] starts washing their [washing_face ? "face" : "hands"]...", \ + user.visible_message("[user] starts washing [user.p_their()] [washing_face ? "face" : "hands"]...", \ "You start washing your [washing_face ? "face" : "hands"]...") busy = 1 @@ -558,7 +558,7 @@ busy = 0 - user.visible_message("[user] washes their [washing_face ? "face" : "hands"] using [src].", \ + user.visible_message("[user] washes [user.p_their()] [washing_face ? "face" : "hands"] using [src].", \ "You wash your [washing_face ? "face" : "hands"] using [src].") if(washing_face) if(ishuman(user)) diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index dcf89008416..72469e2ebfb 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -27,6 +27,10 @@ var/secure = FALSE //Whether or not this creates a secure windoor var/state = "01" //How far the door assembly has progressed +/obj/structure/windoor_assembly/examine(mob/user) + ..() + to_chat(user, "Alt-click to rotate it clockwise.") + obj/structure/windoor_assembly/New(loc, set_dir) ..() if(set_dir) @@ -42,7 +46,7 @@ obj/structure/windoor_assembly/Destroy() /obj/structure/windoor_assembly/Move() var/turf/T = loc - . = ..() + ..() setDir(ini_dir) move_update_air(T) @@ -54,8 +58,17 @@ obj/structure/windoor_assembly/Destroy() return 1 if(get_dir(loc, target) == dir) //Make sure looking at appropriate border return !density - else - return 1 + if(istype(mover, /obj/structure/window)) + var/obj/structure/window/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/structure/windoor_assembly)) + var/obj/structure/windoor_assembly/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir)) + return FALSE + return 1 /obj/structure/windoor_assembly/CanAtmosPass(turf/T) if(get_dir(loc, T) == dir) @@ -317,9 +330,16 @@ obj/structure/windoor_assembly/Destroy() if(usr.stat || !usr.canmove || usr.restrained()) return if(anchored) - to_chat(usr, "It is fastened to the floor; therefore, you can't rotate it!") - return 0 - setDir(turn(dir, 270)) + to_chat(usr, "[src] cannot be rotated while it is fastened to the floor!") + return FALSE + var/target_dir = turn(dir, 270) + + if(!valid_window_location(loc, target_dir)) + to_chat(usr, "[src] cannot be rotated in that direction!") + return FALSE + + setDir(target_dir) + ini_dir = dir update_icon() return TRUE diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index aebd111ad26..25c78f6e972 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -2,13 +2,14 @@ var/global/wcBar = pick(list("#0d8395", "#58b5c3", "#58c366", "#90d79a", "#fffff var/global/wcBrig = pick(list("#aa0808", "#7f0606", "#ff0000")) var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8fcf44", "#ffffff")) -/obj/proc/color_windows(var/obj/W as obj) +/obj/proc/color_windows(obj/W) var/list/wcBarAreas = list(/area/crew_quarters/bar) var/list/wcBrigAreas = list(/area/security,/area/prison,/area/shuttle/gamma) var/newcolor var/turf/T = get_turf(W) - if(!istype(T)) return + if(!istype(T)) + return var/area/A = T.loc if(is_type_in_list(A,wcBarAreas)) @@ -23,168 +24,210 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f /obj/structure/window name = "window" desc = "A window." - icon = 'icons/obj/structures.dmi' - density = 1 - layer = 3.2//Just above doors + icon_state = "window" + density = TRUE + layer = ABOVE_OBJ_LAYER //Just above doors pressure_resistance = 4*ONE_ATMOSPHERE - anchored = 1.0 + anchored = TRUE flags = ON_BORDER - var/health = 14.0 + can_be_unanchored = TRUE + max_integrity = 25 var/ini_dir = null - var/state = 2 - var/reinf = 0 - var/basestate + var/state = WINDOW_OUT_OF_FRAME + var/reinf = FALSE + var/heat_resistance = 800 + var/decon_speed = null + var/fulltile = FALSE var/shardtype = /obj/item/shard - var/glasstype = /obj/item/stack/sheet/glass - var/disassembled = 0 - var/sheets = 1 // Number of sheets needed to build this window (determines how much shit is spawned by destroy()) -// var/silicate = 0 // number of units of silicate -// var/icon/silicateIcon = null // the silicated icon + var/glass_type = /obj/item/stack/sheet/glass + var/glass_amount = 1 + var/cancolor = FALSE + var/image/crack_overlay + var/list/debris = list() + var/real_explosion_block //ignore this, just use explosion_block + var/breaksound = "shatter" + var/hitsound = 'sound/effects/Glasshit.ogg' -/obj/structure/window/bullet_act(var/obj/item/projectile/Proj) - if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - health -= Proj.damage - air_update_turf(1) +/obj/structure/window/examine(mob/user) ..() - if(health <= 0) - destroy() - return + if(reinf) + if(anchored && state == WINDOW_SCREWED_TO_FRAME) + to_chat(user, "The window is screwed to the frame.") + else if(anchored && state == WINDOW_IN_FRAME) + to_chat(user, "The window is unscrewed but pried into the frame.") + else if(anchored && state == WINDOW_OUT_OF_FRAME) + to_chat(user, "The window is out of the frame, but could be pried in. It is screwed to the floor.") + else if(!anchored) + to_chat(user, "The window is unscrewed from the floor, and could be deconstructed by wrenching.") + else + if(anchored) + to_chat(user, "The window is screwed to the floor.") + else + to_chat(user, "The window is unscrewed from the floor, and could be deconstructed by wrenching.") + if(!anchored && !fulltile) + to_chat(user, "Alt-click to rotate it clockwise.") -// This should result in the same materials used to make the window. -/obj/structure/window/proc/destroy() - for(var/i=0;i= STAGE_FIVE) - destroy() + deconstruct(FALSE) -/obj/structure/window/CheckExit(var/atom/movable/O, var/turf/target) - if(istype(O) && O.checkpass(PASSGLASS)) - return 1 - if(get_dir(O.loc, target) == dir) - return !density - return 1 +/obj/structure/window/setDir(direct) + if(!fulltile) + ..() + else + ..(FULLTILE_WINDOW_DIR) /obj/structure/window/CanPass(atom/movable/mover, turf/target, height=0) if(istype(mover) && mover.checkpass(PASSGLASS)) return 1 - if(dir == SOUTHWEST || dir == SOUTHEAST || dir == NORTHWEST || dir == NORTHEAST) + if(dir == FULLTILE_WINDOW_DIR) return 0 //full tile window, you can't move into it! if(get_dir(loc, target) == dir) return !density - else + if(istype(mover, /obj/structure/window)) + var/obj/structure/window/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/structure/windoor_assembly)) + var/obj/structure/windoor_assembly/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir)) + return FALSE + return 1 + +/obj/structure/window/CheckExit(atom/movable/O, target) + if(istype(O) && O.checkpass(PASSGLASS)) return 1 + if(get_dir(O.loc, target) == dir) + return 0 + return 1 /obj/structure/window/CanAStarPass(ID, to_dir) if(!density) return 1 - if((dir == SOUTHWEST) || (dir == to_dir)) + if((dir == FULLTILE_WINDOW_DIR) || (dir == to_dir)) return 0 return 1 -/obj/structure/window/hitby(atom/movable/AM) - ..() - var/tforce = 0 - if(ismob(AM)) - tforce = 10 - else if(isobj(AM)) - var/obj/O = AM - tforce = O.throwforce - if(reinf) - tforce *= 0.25 - playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) - health = max(0, health - tforce) - if(health <= 7 && !reinf) - anchored = 0 - update_nearby_icons() - step(src, get_dir(AM, src)) - if(health <= 0) - destroy() +/obj/structure/window/attack_tk(mob/user) + user.changeNext_move(CLICK_CD_MELEE) + user.visible_message("Something knocks on [src].") + add_fingerprint(user) + playsound(src, 'sound/effects/Glassknock.ogg', 50, 1) +/obj/structure/window/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) + if(!can_be_reached(user)) + return 1 + . = ..() -/obj/structure/window/attack_hand(mob/user as mob) - if(HULK in user.mutations) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) - user.visible_message("[user] smashes through [src]!") - destroy() - else if(user.a_intent == INTENT_HARM) +/obj/structure/window/attack_hand(mob/user) + if(!can_be_reached(user)) + return + if(user.a_intent == INTENT_HARM) user.changeNext_move(CLICK_CD_MELEE) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 80, 1) - user.visible_message("[user.name] bangs against the [src.name]!", \ - "You bang against the [src.name]!", \ + playsound(src, 'sound/effects/glassknock.ogg', 80, 1) + user.visible_message("[user] bangs against [src]!", \ + "You bang against [src]!", \ "You hear a banging sound.") + add_fingerprint(user) else user.changeNext_move(CLICK_CD_MELEE) - playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) - user.visible_message("[user.name] knocks on the [src.name].", \ - "You knock on the [src.name].", \ + playsound(src, 'sound/effects/glassknock.ogg', 80, 1) + user.visible_message("[user] knocks on [src].", \ + "You knock on [src].", \ "You hear a knocking sound.") - return + add_fingerprint(user) - -/obj/structure/window/attack_generic(mob/living/user, damage = 0) //used by attack_alien, attack_animal, and attack_slime - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - health -= damage - if(health <= 0) - user.visible_message("[user] smashes through [src]!") - destroy() - else //for nicer text~ - user.visible_message("[user] smashes into [src]!") - playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) - - -/obj/structure/window/attack_alien(mob/living/user as mob) - if(islarva(user)) return - attack_generic(user, 15) - -/obj/structure/window/attack_animal(mob/living/user as mob) - if(!isanimal(user)) return - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0 || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) +/obj/structure/window/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) //used by attack_alien, attack_animal, and attack_slime + if(!can_be_reached(user)) return - attack_generic(M, M.melee_damage_upper) + ..() +/obj/structure/window/attackby(obj/item/I, mob/living/user, params) + if(!can_be_reached(user)) + return 1 //skip the afterattack -/obj/structure/window/attack_slime(mob/living/user as mob) - var/mob/living/carbon/slime/S = user - if(!S.is_adult) + add_fingerprint(user) + + if(iswelder(I) && user.a_intent == INTENT_HELP) + var/obj/item/weldingtool/WT = I + if(obj_integrity < max_integrity) + if(WT.remove_fuel(0,user)) + to_chat(user, "You begin repairing [src]...") + playsound(src, WT.usesound, 40, 1) + if(do_after(user, 40*I.toolspeed, target = src)) + obj_integrity = max_integrity + playsound(src, 'sound/items/Welder2.ogg', 50, 1) + update_nearby_icons() + to_chat(user, "You repair [src].") + else + to_chat(user, "[src] is already in good condition!") return - attack_generic(user, rand(10, 15)) - -/obj/structure/window/attackby(obj/item/I as obj, mob/living/user as mob, params) - if(!istype(I)) - return//I really wish I did not need this - if(istype(I, /obj/item/grab) && get_dist(src,user)<2) + if(istype(I, /obj/item/grab) && get_dist(src, user) < 2) var/obj/item/grab/G = I - if(istype(G.affecting,/mob/living)) + if(isliving(G.affecting)) var/mob/living/M = G.affecting var/state = G.state qdel(I) //gotta delete it here because if window breaks, it won't get deleted @@ -192,129 +235,120 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f if(1) M.visible_message("[user] slams [M] against \the [src]!") M.apply_damage(7) - hit(10) + take_damage(10) if(2) M.visible_message("[user] bashes [M] against \the [src]!") if(prob(50)) M.Weaken(1) M.apply_damage(10) - hit(25) + take_damage(25) if(3) M.visible_message("[user] crushes [M] against \the [src]!") M.Weaken(5) M.apply_damage(20) - hit(50) + take_damage(50) if(4) visible_message("[user] smashes [M] against \the [src]!") M.Weaken(5) M.apply_damage(30) - hit(75) + take_damage(75) return - if(I.flags & NOBLUDGEON) - return - - if(handle_decon(I, user, is_fulltile())) - return - - if(I.damtype == BRUTE || I.damtype == BURN) - user.changeNext_move(CLICK_CD_MELEE) - hit(I.force) - if(health <= 7) - anchored = 0 - update_nearby_icons() - step(src, get_dir(user, src)) - else - playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) - ..() - -/obj/structure/window/proc/handle_decon(obj/item/W, mob/user, var/takes_time = FALSE) - //screwdriver - if(isscrewdriver(W)) - playsound(loc, W.usesound, 75, 1) - if(reinf) - if(state == 0) - if(takes_time) - to_chat(user, "You begin to [anchored ? "unfasten the frame from" : "fasten the frame to"] the floor.") - if(!do_after(user, 20 * W.toolspeed, target = src)) - return 1 - anchored = !anchored - to_chat(user, "You have [anchored? "fastened the frame to" : "unfastened the frame from"] the floor.") - if(state >= 1) - if(takes_time) - to_chat(user, "You begin to [(state == 1) ? "fasten the window to" : "unfasten the window from"] the frame.") - if(!do_after(user, 20 * W.toolspeed, target = src)) - return 1 - state = 3 - state - to_chat(user, "You have [(state == 1) ? "unfastened the window from" : "fastened the window to"] the frame.") - else - if(takes_time) - to_chat(user, "You begin to [anchored ? "unfasten the frame from" : "fasten the frame to"] the floor.") - if(!do_after(user, 20 * W.toolspeed, target = src)) - return 1 - anchored = !anchored - update_nearby_icons() - to_chat(user, "You have [anchored ? "fastened the window to" : "unfastened the window from"] the floor.") - return 1 - //crowbar - if(iscrowbar(W)) - if(!reinf || state > 1) - return 0 - playsound(loc, W.usesound, 75, 1) - if(takes_time) - to_chat(user, "You begin to pry the window [state ? "out of" : "in to"] the frame.") - if(!do_after(user, 20 * W.toolspeed, target = src)) - return 1 - state = 1 - state - to_chat(user, "You have pried the window [state ? "into" : "out of"] the frame.") - return 1 - //wrench - if(iswrench(W)) - if(anchored) - return 0 - playsound(loc, W.usesound, 50, 1) - if(takes_time) - to_chat(user, "You begin to disassemble [src]...") - if(!do_after(user, 20 * W.toolspeed, target = src)) - return 1 - for(var/i=0; i= S.max_amount) - continue - S.attackby(NS, user) + if(can_deconstruct) + if(isscrewdriver(I)) + playsound(src, I.usesound, 75, 1) if(reinf) - var/obj/item/stack/rods/NR = new (get_turf(src)) - for(var/obj/item/stack/rods/R in loc) - if(R == NR) - continue - if(R.amount >= R.max_amount) - continue - R.attackby(NR, user) + if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME) + to_chat(user, "You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...") + if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + state = (state == WINDOW_IN_FRAME ? WINDOW_SCREWED_TO_FRAME : WINDOW_IN_FRAME) + to_chat(user, "You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.") + else if(state == WINDOW_OUT_OF_FRAME) + to_chat(user, "You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...") + if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + anchored = !anchored + update_nearby_icons() + to_chat(user, "You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.") + else //if we're not reinforced, we don't need to check or update state + to_chat(user, "You begin to [anchored ? "unscrew the window from":"screw the window to"] the floor...") + if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_anchored, anchored))) + anchored = !anchored + air_update_turf(TRUE) + update_nearby_icons() + to_chat(user, "You [anchored ? "fasten the window to":"unfasten the window from"] the floor.") + return - to_chat(user, "You have disassembled [src].") - disassembled = 1 - density = 0 - air_update_turf(1) - update_nearby_icons() - qdel(src) - return 1 + else if(iscrowbar(I) && reinf && (state == WINDOW_OUT_OF_FRAME || state == WINDOW_IN_FRAME)) + to_chat(user, "You begin to lever the window [state == WINDOW_OUT_OF_FRAME ? "into":"out of"] the frame...") + playsound(src, I.usesound, 75, 1) + if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + state = (state == WINDOW_OUT_OF_FRAME ? WINDOW_IN_FRAME : WINDOW_OUT_OF_FRAME) + to_chat(user, "You pry the window [state == WINDOW_IN_FRAME ? "into":"out of"] the frame.") + return + + else if(iswrench(I) && !anchored) + playsound(src, I.usesound, 75, 1) + to_chat(user, " You begin to disassemble [src]...") + if(do_after(user, decon_speed*I.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored))) + var/obj/item/stack/sheet/G = new glass_type(user.loc, glass_amount) + G.add_fingerprint(user) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You successfully disassemble [src].") + qdel(src) + return + return ..() + +/obj/structure/window/proc/check_state(checked_state) + if(state == checked_state) + return TRUE + +/obj/structure/window/proc/check_anchored(checked_anchored) + if(anchored == checked_anchored) + return TRUE + +/obj/structure/window/proc/check_state_and_anchored(checked_state, checked_anchored) + return check_state(checked_state) && check_anchored(checked_anchored) /obj/structure/window/mech_melee_attack(obj/mecha/M) - if(..()) - hit(M.force, 1) - -/obj/structure/window/proc/hit(var/damage, var/sound_effect = 1) - if(reinf) damage *= 0.5 - health = max(0, health - damage) - if(sound_effect) - playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) - if(health <= 0) - destroy() + if(!can_be_reached()) return + ..() +/obj/structure/window/proc/can_be_reached(mob/user) + if(!fulltile) + if(get_dir(user, src) & dir) + for(var/obj/O in loc) + if(!O.CanPass(user, user.loc, 1)) + return 0 + return 1 + +/obj/structure/window/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) + . = ..() + if(.) //received damage + update_nearby_icons() + +/obj/structure/window/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + if(damage_amount) + playsound(src, hitsound, 75, 1) + else + playsound(src, 'sound/weapons/tap.ogg', 50, 1) + if(BURN) + playsound(src, 'sound/items/Welder.ogg', 100, 1) + +/obj/structure/window/deconstruct(disassembled = TRUE) + if(QDELETED(src)) + return + if(!disassembled) + playsound(src, breaksound, 70, 1) + if(can_deconstruct) + for(var/i in debris) + var/obj/item/I = i + I.forceMove(loc) + transfer_fingerprints_to(I) + qdel(src) + update_nearby_icons() /obj/structure/window/verb/rotate() set name = "Rotate Window Counter-Clockwise" @@ -325,15 +359,19 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f return if(anchored) - to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") - return 0 + to_chat(usr, "[src] cannot be rotated while it is fastened to the floor!") + return FALSE - dir = turn(dir, 90) -// updateSilicate() + var/target_dir = turn(dir, 90) + if(!valid_window_location(loc, target_dir)) + to_chat(usr, "[src] cannot be rotated in that direction!") + return FALSE + + setDir(target_dir) air_update_turf(1) ini_dir = dir add_fingerprint(usr) - return + return TRUE /obj/structure/window/verb/revrotate() set name = "Rotate Window Clockwise" @@ -344,16 +382,19 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f return if(anchored) - to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") - return 0 + to_chat(usr, "[src] cannot be rotated while it is fastened to the floor!") + return FALSE - dir = turn(dir, 270) -// updateSilicate() - air_update_turf(1) + var/target_dir = turn(dir, 270) + + if(!valid_window_location(loc, target_dir)) + to_chat(usr, "[src] cannot be rotated in that direction!") + return FALSE + + setDir(target_dir) ini_dir = dir add_fingerprint(usr) - return - + return TRUE /obj/structure/window/AltClick(mob/user) if(user.incapacitated()) @@ -363,158 +404,77 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f return revrotate() -/* -/obj/structure/window/proc/updateSilicate() - if(silicateIcon && silicate) - icon = initial(icon) - - var/icon/I = icon(icon,icon_state,dir) - - var/r = (silicate / 100) + 1 - var/g = (silicate / 70) + 1 - var/b = (silicate / 50) + 1 - I.SetIntensity(r,g,b) - icon = I - silicateIcon = I -*/ - -/obj/structure/window/New(Loc,re=0) - ..() - ini_dir = dir - if(!color && !istype(src,/obj/structure/window/plasmabasic) && !istype(src,/obj/structure/window/plasmareinforced)) - color = color_windows(src) - update_nearby_icons() - return - -/obj/structure/window/Initialize() - air_update_turf(1) - return ..() - /obj/structure/window/Destroy() - density = 0 + density = FALSE air_update_turf(1) - if(loc && !disassembled) - playsound(get_turf(src), "shatter", 70, 1) + update_nearby_icons() return ..() - /obj/structure/window/Move() var/turf/T = loc ..() - dir = ini_dir + setDir(ini_dir) move_update_air(T) -//checks if this window is full-tile one -/obj/structure/window/proc/is_fulltile() - if(dir & (dir - 1)) - return 1 - return 0 - /obj/structure/window/CanAtmosPass(turf/T) - if(get_dir(loc, T) == dir) - return !density - if(dir == SOUTHWEST || dir == SOUTHEAST || dir == NORTHWEST || dir == NORTHEAST) - return !density - return 1 + if(!anchored || !density) + return TRUE + return !(FULLTILE_WINDOW_DIR == dir || dir == get_dir(loc, T)) //This proc is used to update the icons of nearby windows. /obj/structure/window/proc/update_nearby_icons() - if(!loc) return 0 update_icon() - for(var/direction in cardinal) - for(var/obj/structure/window/W in get_step(src,direction) ) - W.update_icon() + if(smooth) + smooth_icon_neighbors(src) /obj/structure/window/update_icon() - return + if(!QDELETED(src)) + if(!fulltile) + return + var/ratio = obj_integrity / max_integrity + ratio = CEILING(ratio*4, 1) * 25 + if(smooth) + smooth_icon(src) + overlays -= crack_overlay + if(ratio > 75) + return + crack_overlay = image('icons/obj/structures.dmi',"damage[ratio]",-(layer+0.1)) + overlays += crack_overlay /obj/structure/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 800) - hit(round(exposed_volume / 100), 0) + if(exposed_temperature > (T0C + heat_resistance)) + take_damage(round(exposed_volume / 100), BURN, 0, 0) ..() +/obj/structure/window/GetExplosionBlock() + return reinf && fulltile ? real_explosion_block : 0 + /obj/structure/window/basic - icon_state = "window" desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." - basestate = "window" - -/obj/structure/window/plasmabasic - name = "plasma window" - desc = "A plasma-glass alloy window. It looks insanely tough to break. It appears it's also insanely tough to burn through." - basestate = "plasmawindow" - icon_state = "plasmawindow" - shardtype = /obj/item/shard/plasma - glasstype = /obj/item/stack/sheet/plasmaglass - health = 120 - armor = list("melee" = 75, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 45, "bio" = 100, "rad" = 100) - -/obj/structure/window/plasmabasic/New(Loc,re=0) - ..() - ini_dir = dir - update_nearby_icons() - return - -/obj/structure/window/plasmabasic/Initialize() - ..() - air_update_turf(1) - -/obj/structure/window/plasmabasic/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 32000) - hit(round(exposed_volume / 1000), 0) - ..() - -/obj/structure/window/plasmabasic/BlockSuperconductivity() - return 1 - -/obj/structure/window/plasmareinforced - name = "reinforced plasma window" - desc = "A plasma-glass alloy window, with rods supporting it. It looks hopelessly tough to break. It also looks completely fireproof, considering how basic plasma windows are insanely fireproof." - basestate = "plasmarwindow" - icon_state = "plasmarwindow" - shardtype = /obj/item/shard/plasma - glasstype = /obj/item/stack/sheet/plasmaglass - reinf = 1 - health = 160 - armor = list("melee" = 85, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 100, "rad" = 100) - -/obj/structure/window/plasmareinforced/New(Loc,re=0) - ..() - ini_dir = dir - update_nearby_icons() - return - -/obj/structure/window/plasmareinforced/Initialize() - ..() - air_update_turf(1) - -/obj/structure/window/plasmareinforced/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/structure/window/plasmareinforced/BlockSuperconductivity() - return 1 //okay this SHOULD MAKE THE TOXINS CHAMBER WORK /obj/structure/window/reinforced name = "reinforced window" desc = "It looks rather strong. Might take a few good hits to shatter it." icon_state = "rwindow" - reinf = 1 - basestate = "rwindow" - health = 40 + reinf = TRUE + cancolor = TRUE + heat_resistance = 1600 armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100) + max_integrity = 50 + explosion_block = 1 + glass_type = /obj/item/stack/sheet/rglass /obj/structure/window/reinforced/tinted name = "tinted window" desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." icon_state = "twindow" - basestate = "twindow" opacity = 1 /obj/structure/window/reinforced/tinted/frosted name = "frosted window" desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." icon_state = "fwindow" - basestate = "fwindow" - health = 30 + max_integrity = 30 /obj/structure/window/reinforced/polarized name = "electrochromic window" @@ -529,8 +489,6 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f animate(src, color="#222222", time=5) set_opacity(1) - - /obj/machinery/button/windowtint name = "window tint control" icon = 'icons/obj/power.dmi' @@ -540,7 +498,7 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f var/id = 0 var/active = 0 -/obj/machinery/button/windowtint/attack_hand(mob/user as mob) +/obj/machinery/button/windowtint/attack_hand(mob/user) if(..()) return 1 @@ -565,3 +523,195 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f /obj/machinery/button/windowtint/update_icon() icon_state = "light[active]" + +/obj/structure/window/plasmabasic + name = "plasma window" + desc = "A window made out of a plasma-silicate alloy. It looks insanely tough to break and burn through." + icon_state = "plasmawindow" + shardtype = /obj/item/shard/plasma + glass_type = /obj/item/stack/sheet/plasmaglass + heat_resistance = 32000 + max_integrity = 120 + explosion_block = 1 + armor = list("melee" = 75, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 45, "bio" = 100, "rad" = 100) + +/obj/structure/window/plasmabasic/BlockSuperconductivity() + return 1 + +/obj/structure/window/plasmareinforced + name = "reinforced plasma window" + desc = "A plasma-glass alloy window, with rods supporting it. It looks hopelessly tough to break. It also looks completely fireproof, considering how basic plasma windows are insanely fireproof." + icon_state = "plasmarwindow" + shardtype = /obj/item/shard/plasma + glass_type = /obj/item/stack/sheet/plasmaglass + reinf = TRUE + max_integrity = 160 + explosion_block = 2 + armor = list("melee" = 85, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 100, "rad" = 100) + +/obj/structure/window/plasmareinforced/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/structure/window/plasmareinforced/BlockSuperconductivity() + return 1 //okay this SHOULD MAKE THE TOXINS CHAMBER WORK + +/obj/structure/window/full + glass_amount = 2 + dir = FULLTILE_WINDOW_DIR + level = 3 + fulltile = TRUE + +/obj/structure/window/full/basic + desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." + icon = 'icons/obj/smooth_structures/window.dmi' + icon_state = "window" + max_integrity = 50 + smooth = SMOOTH_TRUE + cancolor = TRUE + canSmoothWith = list(/obj/structure/window/full/basic, /obj/structure/window/full/reinforced, /obj/structure/window/full/reinforced/tinted, /obj/structure/window/full/plasmabasic, /obj/structure/window/full/plasmareinforced) + +/obj/structure/window/full/plasmabasic + name = "plasma window" + desc = "A plasma-glass alloy window. It looks insanely tough to break. It appears it's also insanely tough to burn through." + icon = 'icons/obj/smooth_structures/plasma_window.dmi' + icon_state = "plasmawindow" + shardtype = /obj/item/shard/plasma + glass_type = /obj/item/stack/sheet/plasmaglass + heat_resistance = 32000 + max_integrity = 240 + smooth = SMOOTH_TRUE + canSmoothWith = list(/obj/structure/window/full/basic, /obj/structure/window/full/reinforced, /obj/structure/window/full/reinforced/tinted, /obj/structure/window/full/plasmabasic, /obj/structure/window/full/plasmareinforced) + +/obj/structure/window/full/plasmareinforced + name = "reinforced plasma window" + desc = "A plasma-glass alloy window, with rods supporting it. It looks hopelessly tough to break. It also looks completely fireproof, considering how basic plasma windows are insanely fireproof." + icon = 'icons/obj/smooth_structures/rplasma_window.dmi' + icon_state = "rplasmawindow" + shardtype = /obj/item/shard/plasma + glass_type = /obj/item/stack/sheet/plasmaglass + smooth = SMOOTH_TRUE + reinf = TRUE + max_integrity = 320 + +/obj/structure/window/full/plasmareinforced/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/structure/window/full/reinforced + name = "reinforced window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon = 'icons/obj/smooth_structures/reinforced_window.dmi' + icon_state = "r_window" + smooth = SMOOTH_TRUE + canSmoothWith = list(/obj/structure/window/full/basic, /obj/structure/window/full/reinforced, /obj/structure/window/full/reinforced/tinted, /obj/structure/window/full/plasmabasic, /obj/structure/window/full/plasmareinforced) + max_integrity = 100 + reinf = TRUE + heat_resistance = 1600 + armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100) + explosion_block = 1 + glass_type = /obj/item/stack/sheet/rglass + cancolor = TRUE + +/obj/structure/window/full/reinforced/tinted + name = "tinted window" + desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." + icon = 'icons/obj/smooth_structures/tinted_window.dmi' + icon_state = "tinted_window" + opacity = 1 + +obj/structure/window/full/reinforced/ice + icon = 'icons/obj/smooth_structures/rice_window.dmi' + icon_state = "ice_window" + max_integrity = 150 + cancolor = FALSE + +/obj/structure/window/full/shuttle + name = "shuttle window" + desc = "A reinforced, air-locked pod window." + icon = 'icons/obj/smooth_structures/shuttle_window.dmi' + icon_state = "shuttle_window" + max_integrity = 160 + reinf = TRUE + heat_resistance = 1600 + explosion_block = 3 + armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100) + smooth = SMOOTH_TRUE + canSmoothWith = null + glass_type = /obj/item/stack/sheet/titaniumglass + +/obj/structure/window/full/shuttle/narsie_act() + color = "#3C3434" + +/obj/structure/window/full/shuttle/tinted + opacity = TRUE + +/obj/structure/window/plastitanium + name = "plastitanium window" + desc = "An evil looking window of plasma and titanium." + icon = 'icons/obj/smooth_structures/plastitanium_window.dmi' + icon_state = "plastitanium_window" + dir = FULLTILE_WINDOW_DIR + max_integrity = 100 + fulltile = TRUE + reinf = TRUE + heat_resistance = 1600 + armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100) + smooth = SMOOTH_TRUE + canSmoothWith = null + explosion_block = 3 + level = 3 + glass_type = /obj/item/stack/sheet/plastitaniumglass + glass_amount = 2 + +/obj/structure/window/reinforced/clockwork + name = "brass window" + desc = "A paper-thin pane of translucent yet reinforced brass." + icon = 'icons/obj/smooth_structures/clockwork_window.dmi' + icon_state = "clockwork_window_single" + burn_state = FIRE_PROOF + unacidable = 1 + max_integrity = 80 + armor = list("melee" = 60, "bullet" = 25, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100) + explosion_block = 2 //fancy AND hard to destroy. the most useful combination. + glass_type = /obj/item/stack/tile/brass + reinf = FALSE + cancolor = FALSE + var/made_glow = FALSE + +/obj/structure/window/reinforced/clockwork/New(loc, direct) + if(fulltile) + made_glow = TRUE + ..() + QDEL_LIST(debris) + if(fulltile) + new /obj/effect/temp_visual/ratvar/window(get_turf(src)) + debris += new/obj/item/stack/tile/brass(src, 2) + else + debris += new/obj/item/stack/tile/brass(src, 1) + +/obj/structure/window/reinforced/clockwork/setDir(direct) + if(!made_glow) + var/obj/effect/E = new /obj/effect/temp_visual/ratvar/window/single(get_turf(src)) + E.setDir(direct) + made_glow = TRUE + ..() + +/obj/structure/window/reinforced/clockwork/ratvar_act() + obj_integrity = max_integrity + update_icon() + +/obj/structure/window/reinforced/clockwork/narsie_act() + take_damage(rand(25, 75), BRUTE) + if(src) + var/previouscolor = color + color = "#960000" + animate(src, color = previouscolor, time = 8) + +/obj/structure/window/reinforced/clockwork/fulltile + icon_state = "clockwork_window" + smooth = SMOOTH_TRUE + canSmoothWith = null + fulltile = TRUE + dir = FULLTILE_WINDOW_DIR + max_integrity = 120 + level = 3 + glass_amount = 2 \ No newline at end of file diff --git a/code/game/response_team.dm b/code/game/response_team.dm index 6120ae042bf..646adfa2038 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -143,7 +143,7 @@ var/ert_request_answered = 0 else M.change_gender(FEMALE) - M.set_species("Human",1) + M.set_species(/datum/species/human, TRUE) M.dna.ready_dna(M) M.reagents.add_reagent("mutadone", 1) //No fat/blind/colourblind/epileptic/whatever ERT. M.overeatduration = 0 @@ -158,8 +158,8 @@ var/ert_request_answered = 0 head_organ.sec_hair_colour = hair_c M.change_eye_color(eye_c) M.s_tone = skin_tone - head_organ.h_style = random_hair_style(M.gender, head_organ.species.name) - head_organ.f_style = random_facial_hair_style(M.gender, head_organ.species.name) + head_organ.h_style = random_hair_style(M.gender, head_organ.dna.species.name) + head_organ.f_style = random_facial_hair_style(M.gender, head_organ.dna.species.name) M.rename_character(null, "[pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant First Class", "Master Sergeant", "Sergeant Major")] [pick(last_names)]") M.age = rand(23,35) @@ -171,7 +171,7 @@ var/ert_request_answered = 0 M.mind = new M.mind.current = M M.mind.original = M - M.mind.assigned_role = "MODE" + M.mind.assigned_role = SPECIAL_ROLE_ERT M.mind.special_role = SPECIAL_ROLE_ERT if(!(M.mind in ticker.minds)) ticker.minds += M.mind //Adds them to regular mind list. @@ -203,13 +203,13 @@ var/ert_request_answered = 0 var/cyborg_unlock = 0 /datum/response_team/proc/setSlots(com, sec, med, eng, jan, par, cyb) - command_slots = com - security_slots = sec - medical_slots = med - engineer_slots = eng - janitor_slots = jan - paranormal_slots = par - cyborg_slots = 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/reduceCyborgSlots() cyborg_slots-- diff --git a/code/game/skincmd.dm b/code/game/skincmd.dm deleted file mode 100644 index 7d27a1ce6df..00000000000 --- a/code/game/skincmd.dm +++ /dev/null @@ -1,13 +0,0 @@ -/mob/var/skincmds = list() -/obj/proc/SkinCmd(mob/user as mob, var/data as text) - -/proc/SkinCmdRegister(var/mob/user, var/name as text, var/O as obj) - user.skincmds[name] = O - -/mob/verb/skincmd(data as text) - set hidden = 1 - - var/ref = copytext(data, 1, findtext(data, ";")) - if(src.skincmds[ref] != null) - var/obj/a = src.skincmds[ref] - a.SkinCmd(src, copytext(data, findtext(data, ";") + 1)) \ No newline at end of file diff --git a/code/game/smoothwall.dm b/code/game/smoothwall.dm deleted file mode 100644 index 20dea8de7b0..00000000000 --- a/code/game/smoothwall.dm +++ /dev/null @@ -1,108 +0,0 @@ -// OKAY I DON'T KNOW WHO THE FUCK ORIGINALLY CODED THIS BUT THEY ARE OFFICIALLY FIRED FOR BEING DRUNK AND STUPID -// FUCK YOU MYSTERY CODERS -// FOR THIS SHIT I'M GOING TO MAKE ALL MY COMMENTS IN CAPS - -/atom - var/list/canSmoothWith=list() // TYPE PATHS I CAN SMOOTH WITH~~~~~ - -// MOVED INTO UTILITY FUNCTION FOR LESS DUPLICATED CODE. -/atom/proc/findSmoothingNeighbors() - // THIS IS A BITMAP BECAUSE NORTH/SOUTH/ETC ARE ALL BITFLAGS BECAUSE BYOND IS DUMB AND - // DOESN'T FUCKING MAKE SENSE, BUT IT WORKS TO OUR ADVANTAGE - var/junction = 0 - for(var/cdir in cardinal) - var/turf/T = get_step(src,cdir) - if(isSmoothableNeighbor(T)) - junction |= cdir - continue // NO NEED FOR FURTHER SEARCHING IN THIS TILE - for(var/atom/A in T) - if(isSmoothableNeighbor(A)) - junction |= cdir - break // NO NEED FOR FURTHER SEARCHING IN THIS TILE - - return junction - -/atom/proc/isSmoothableNeighbor(var/atom/A) - return is_type_in_list(A,canSmoothWith) - -/turf/simulated/wall/isSmoothableNeighbor(var/atom/A) - if(is_type_in_list(A,canSmoothWith)) - // COLON OPERATORS ARE TERRIBLE BUT I HAVE NO CHOICE - if(src.mineral == A:mineral) //mineral not walltype so reinf still smooths with normal and vice versa - return 1 - return 0 - -/** - * WALL SMOOTHING SHIT - * - * IN /ATOM BECAUSE /TURFS ARE /ATOMS AND SO ARE /OBJ/STRUCTURE/FALSEWALLS - * THIS IS STUPID BUT IS FAIRLY ELEGANT FOR BYOND - * - * HOWEVER, INSTEAD OF MAKING ONE BIG GODDAMN MONOLITHIC PROC LIKE A FUCKING - * SHITTY FUNCTIONAL PROGRAMMER, WE WILL BE COOL AND MODERN AND USE INHERITANCE. - */ -/atom/proc/relativewall() - return // DOES JACK SHIT BY DEFAULT. OLD BEHAVIOR WAS TO SPAM LOOPS ANYWAY. - -/* - * SEE? NOW WE ONLY HAVE TO PROGRAM THIS SHIT INTO WHAT WE WANT TO SMOOTH - * INSTEAD OF BEING DUMB AND HAVING A BIG FUCKING IFTREE WITH TYPECHECKS - * MY GOD, WE COULD EVEN MOVE THE CODE TO BE WITH THE REST OF THE WALL'S CODE! - * HOW FUCKING INNOVATIVE. ISN'T INHERITANCE NICE? - * - * WE COULD STANDARDIZE THIS BUT EVERYONE'S A FUCKING SNOWFLAKE - */ -/turf/simulated/wall/relativewall() - var/junction=findSmoothingNeighbors() - icon_state = "[walltype][junction]" // WHY ISN'T THIS IN UPDATE_ICON OR SIMILAR - -/atom/proc/relativewall_neighbours(var/sko=0) //SKO: Skip Optimizations - // OPTIMIZE BY NOT CHECKING FOR NEIGHBORS IF WE DON'T FUCKING SMOOTH - if(canSmoothWith.len>0 || sko) - relativewall() - for(var/cdir in cardinal) - var/turf/T = get_step(src,cdir) - if(isSmoothableNeighbor(T) || sko) - T.relativewall() - for(var/atom/A in T) - if(isSmoothableNeighbor(A) || sko) - A.relativewall() - -/turf/simulated/wall/New() - ..() - relativewall_neighbours() - -/turf/simulated/wall/Destroy() - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - - if(!del_suppress_resmoothing) - spawn(10) - relativewall_neighbours(sko=1) - - // JESUS WHY - for(var/direction in cardinal) - for(var/obj/structure/glowshroom/shroom in get_step(src,direction)) - if(!shroom.floor) //shrooms drop to the floor - shroom.floor = 1 - shroom.icon_state = "glowshroomf" - shroom.pixel_x = 0 - shroom.pixel_y = 0 -/* for(var/obj/effect/supermatter_crystal/crystal in get_step(src,direction)) - if(!crystal.floor) //crystals drop to the floor - crystal.floor = 1 - crystal.icon_state = "supermatter_crystalf" - crystal.pixel_x = 0 - crystal.pixel_y = 0 */ - return ..() - -// DE-HACK -/turf/simulated/wall/vault/relativewall() - return - - -/obj/structure/alien/resin/relativewall() - var/junction = findSmoothingNeighbors() - icon_state = "[resintype][junction]" - return \ No newline at end of file diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 89c40be8641..61f622c071f 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -4,7 +4,6 @@ var/image/wet_overlay = null var/thermite = 0 - flags = RPD_ALLOWED_HERE oxygen = MOLES_O2STANDARD nitrogen = MOLES_N2STANDARD var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed diff --git a/code/game/turfs/simulated/shuttle.dm b/code/game/turfs/simulated/shuttle.dm index 0c5e6c08f6b..7a781679173 100644 --- a/code/game/turfs/simulated/shuttle.dm +++ b/code/game/turfs/simulated/shuttle.dm @@ -1,7 +1,6 @@ /turf/simulated/shuttle name = "shuttle" icon = 'icons/turf/shuttle.dmi' - flags = null thermal_conductivity = 0.05 heat_capacity = 0 layer = 2 @@ -13,6 +12,9 @@ density = 1 blocks_air = 1 +/turf/simulated/shuttle/rpd_act(mob/user, obj/item/rpd/our_rpd) + if(our_rpd.mode == RPD_DELETE_MODE)//No pipes on shuttles + our_rpd.delete_all_pipes(user, src) /turf/simulated/shuttle/narsie_act() if(prob(20)) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index b1cbf84493f..a24e6f2953f 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -168,6 +168,18 @@ if(prob(50)) dismantle_wall() +/turf/simulated/wall/rpd_act(mob/user, obj/item/rpd/our_rpd) + if(our_rpd.mode == RPD_ATMOS_MODE) + playsound(src, "sound/weapons/circsawhit.ogg", 50, 1) + user.visible_message("[user] starts drilling a hole in [src]...", "You start drilling a hole in [src]...", "You hear drilling.") + if(!do_after(user, our_rpd.walldelay, target = src)) //Drilling into walls takes time + return + our_rpd.create_atmos_pipe(user, src) + else if(our_rpd.mode == RPD_DISPOSALS_MODE) + return + else + ..() + /turf/simulated/wall/mech_melee_attack(obj/mecha/M) if(M.damtype == "brute") playsound(src, 'sound/weapons/punch4.ogg', 50, 1) @@ -214,7 +226,7 @@ //Interactions -/turf/simulated/wall/attack_animal(var/mob/living/simple_animal/M) +/turf/simulated/wall/attack_animal(mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) if((M.environment_smash & ENVIRONMENT_SMASH_WALLS) || (M.environment_smash & ENVIRONMENT_SMASH_RWALLS)) @@ -229,20 +241,19 @@ to_chat(M, "You push the wall but nothing happens!") return -/turf/simulated/wall/attack_hand(mob/user as mob) - user.changeNext_move(CLICK_CD_MELEE) - if(HULK in user.mutations) - if(prob(hardness) || rotting) - playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) - to_chat(user, text("You smash through the wall.")) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - dismantle_wall(1) - return - else - playsound(src, 'sound/effects/bang.ogg', 50, 1) - to_chat(user, text("You punch the wall.")) - return +/turf/simulated/wall/attack_hulk(mob/user, does_attack_animation = FALSE) + ..(user, TRUE) + if(prob(hardness) || rotting) + playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + dismantle_wall(TRUE) + else + playsound(src, 'sound/effects/bang.ogg', 50, 1) + to_chat(user, text("You punch the wall.")) + return TRUE +/turf/simulated/wall/attack_hand(mob/user) + user.changeNext_move(CLICK_CD_MELEE) if(rotting) if(hardness <= 10) to_chat(user, "This wall feels rather unstable.") @@ -254,183 +265,169 @@ to_chat(user, "You push the wall but nothing happens!") playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) - src.add_fingerprint(user) - ..() - return + add_fingerprint(user) + return ..() -/turf/simulated/wall/attackby(obj/item/W as obj, mob/user as mob, params) +/turf/simulated/wall/attackby(obj/item/I, mob/user, params) user.changeNext_move(CLICK_CD_MELEE) - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") + + if(!isturf(user.loc)) + return // No touching walls unless you're on a turf (pretty sure attackby can't be called anyways but whatever) + + if(rotting && try_rot(I, user, params)) return - //get the user's location - if(!istype(user.loc, /turf)) - return //can't do this stuff whilst inside objects and such + if(thermite && try_thermite(I, user, params)) + return - if(rotting) - if(istype(W, /obj/item/weldingtool) ) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You burn away the fungi with \the [WT].") - playsound(src, WT.usesound, 10, 1) - for(var/obj/effect/overlay/wall_rot/WR in src) - qdel(WR) - rotting = 0 - return - else if(!is_sharp(W) && W.force >= 10 || W.force >= 20) - to_chat(user, "\The [src] crumbles away under the force of your [W.name].") - src.dismantle_wall(1) - return + if(try_decon(I, user, params)) + return - //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects - if(thermite) - if(istype(W, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - thermitemelt(user) - return + if(try_destroy(I, user, params)) + return - else if(istype(W, /obj/item/gun/energy/plasmacutter)) + if(try_wallmount(I, user, params)) + return + + // The magnetic gripper does a separate attackby, so bail from this one + if(istype(I, /obj/item/gripper)) + return + + return ..() + +/turf/simulated/wall/proc/try_rot(obj/item/I, mob/user, params) + if(iswelder(I)) + var/obj/item/weldingtool/WT = I + if(WT.remove_fuel(0, user)) + to_chat(user, "You burn away the fungi with [WT].") + playsound(src, WT.usesound, 10, 1) + for(var/obj/effect/overlay/wall_rot/WR in src) + qdel(WR) + rotting = 0 + return TRUE + else if((!is_sharp(I) && I.force >= 10) || I.force >= 20) + to_chat(user, "[src] crumbles away under the force of your [I.name].") + dismantle_wall(1) + return TRUE + return FALSE + +/turf/simulated/wall/proc/try_thermite(obj/item/I, mob/user, params) + if(iswelder(I)) + var/obj/item/weldingtool/WT = I + if(WT.remove_fuel(0, user)) thermitemelt(user) - return + return TRUE - else if(istype(W, /obj/item/melee/energy/blade)) - var/obj/item/melee/energy/blade/EB = W + else if(istype(I, /obj/item/gun/energy/plasmacutter)) + thermitemelt(user) + return TRUE - EB.spark_system.start() - to_chat(user, "You slash \the [src] with \the [EB]; the thermite ignites!") - playsound(src, "sparks", 50, 1) - playsound(src, EB.usesound, 50, 1) - thermitemelt(user) - return + return FALSE - //DECONSTRUCTION - if(istype(W, /obj/item/weldingtool)) +/turf/simulated/wall/proc/try_decon(obj/item/I, mob/user, params) + if(iswelder(I)) + var/obj/item/weldingtool/WT = I + if(!WT.remove_fuel(0, user)) + to_chat(user, "You need more welding fuel to complete this task.") + return TRUE // this means "don't continue trying to find alternative uses in attackby", not "decon succeeded" var/response = "Dismantle" if(damage) response = alert(user, "Would you like to repair or dismantle [src]?", "[src]", "Repair", "Dismantle") - var/obj/item/weldingtool/WT = W - - if(WT.remove_fuel(0,user)) - if(response == "Repair") + switch(response) + if("Repair") to_chat(user, "You start repairing the damage to [src].") playsound(src, WT.usesound, 100, 1) if(do_after(user, max(5, damage / 5) * WT.toolspeed, target = src) && WT && WT.isOn()) to_chat(user, "You finish repairing the damage to [src].") take_damage(-damage) - - else if(response == "Dismantle") + else to_chat(user, "You begin slicing through the outer plating.") playsound(src, WT.usesound, 100, 1) if(do_after(user, 100 * WT.toolspeed, target = src) && WT && WT.isOn()) to_chat(user, "You remove the outer plating.") dismantle_wall() - else to_chat(user, "You stop slicing through [src].") - return - - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - else if(istype(W, /obj/item/gun/energy/plasmacutter)) + return TRUE + else if(istype(I, /obj/item/gun/energy/plasmacutter)) to_chat(user, "You begin slicing through the outer plating.") - playsound(src, W.usesound, 100, 1) + playsound(src, I.usesound, 100, 1) - if(do_after(user, istype(sheet_type, /obj/item/stack/sheet/mineral/diamond) ? 120 * W.toolspeed : 60 * W.toolspeed, target = src)) + if(do_after(user, istype(sheet_type, /obj/item/stack/sheet/mineral/diamond) ? 120 * I.toolspeed : 60 * I.toolspeed, target = src)) to_chat(user, "You remove the outer plating.") dismantle_wall() - visible_message("[user] slices apart \the [src]!","You hear metal being sliced apart.") + visible_message("[user] slices apart [src]!", "You hear metal being sliced apart.") + return TRUE - //DRILLING - else if(istype(W, /obj/item/pickaxe/drill/diamonddrill)) + return FALSE +/turf/simulated/wall/proc/try_destroy(obj/item/I, mob/user, params) + var/isdiamond = istype(sheet_type, /obj/item/stack/sheet/mineral/diamond) // snowflake bullshit + + if(istype(I, /obj/item/pickaxe/drill/diamonddrill)) to_chat(user, "You begin to drill though the wall.") - if(do_after(user, istype(sheet_type, /obj/item/stack/sheet/mineral/diamond) ? 480 * W.toolspeed : 240 * W.toolspeed, target = src)) // Diamond pickaxe has 0.25 toolspeed, so 120/60 - to_chat(user, "Your drill tears though the last of the reinforced plating.") + if(do_after(user, isdiamond ? 480 * I.toolspeed : 240 * I.toolspeed, target = src)) // Diamond pickaxe has 0.25 toolspeed, so 120/60 + to_chat(user, "Your [I.name] tears though the last of the reinforced plating.") dismantle_wall() - visible_message("[user] drills through \the [src]!","You hear the grinding of metal.") - - else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) + visible_message("[user] drills through [src]!", "You hear the grinding of metal.") + return TRUE + else if(istype(I, /obj/item/pickaxe/drill/jackhammer)) to_chat(user, "You begin to disintegrates the wall.") - if(do_after(user, istype(sheet_type, /obj/item/stack/sheet/mineral/diamond) ? 600 * W.toolspeed : 300 * W.toolspeed, target = src)) // Jackhammer has 0.1 toolspeed, so 60/30 - to_chat(user, "Your sonic jackhammer disintegrate the reinforced plating.") + if(do_after(user, isdiamond ? 600 * I.toolspeed : 300 * I.toolspeed, target = src)) // Jackhammer has 0.1 toolspeed, so 60/30 + to_chat(user, "Your [I.name] disintegrates the reinforced plating.") dismantle_wall() - visible_message("[user] disintegrates \the [src]!","You hear the grinding of metal.") + visible_message("[user] disintegrates [src]!","You hear the grinding of metal.") + return TRUE - else if(istype(W, /obj/item/melee/energy/blade)) - var/obj/item/melee/energy/blade/EB = W + return FALSE - EB.spark_system.start() - to_chat(user, "You stab \the [EB] into the wall and begin to slice it apart.") - playsound(src, "sparks", 50, 1) +/turf/simulated/wall/proc/try_wallmount(obj/item/I, mob/user, params) + if(istype(I, /obj/item/mounted)) + return TRUE // We don't want attack_hand running and doing stupid shit with this - if(do_after(user, istype(sheet_type, /obj/item/stack/sheet/mineral/diamond) ? 140 * EB.toolspeed : 70 * EB.toolspeed, target = src)) - EB.spark_system.start() - playsound(src, "sparks", 50, 1) - playsound(src, EB.usesound, 50, 1) - dismantle_wall(1) - visible_message("[user] slices apart \the [src]!","You hear metal being sliced apart and sparks flying.") - - else if(istype(W,/obj/item/mounted)) //if we place it, we don't want to have a silly message - return - - //Poster stuff - else if(istype(W, /obj/item/poster)) - place_poster(W, user) - return - - //Bone White - Place pipes on walls - else if(istype(W,/obj/item/pipe)) - var/obj/item/pipe/V = W - if(V.pipe_type != -1) // ANY PIPE - var/obj/item/pipe/P = W + if(istype(I, /obj/item/poster)) + place_poster(I, user) + return TRUE + //Bone White - Place pipes on walls // I fucking hate your code with a passion bone + if(istype(I, /obj/item/pipe)) + var/obj/item/pipe/P = I + if(P.pipe_type != -1) // ANY PIPE playsound(get_turf(src), 'sound/weapons/circsawhit.ogg', 50, 1) - user.visible_message( \ - "[user] starts drilling a hole in \the [src].", \ - "You start drilling a hole in \the [src].", \ - "You hear ratchet.") - if(do_after(user, 80 * W.toolspeed, target = src)) - user.visible_message( \ - "[user] drills a hole in \the [src] and pushes \a [P] into the void", \ - "You have finished drilling in \the [src] and push the [P] into the void.", \ - "You hear ratchet.") + user.visible_message( + "[user] starts drilling a hole in [src].", + "You start drilling a hole in [src].", + "You hear a drill.") + + if(do_after(user, 80 * P.toolspeed, target = src)) + user.visible_message( + "[user] drills a hole in [src] and pushes [P] into the void.", + "You finish drilling [src] and push [P] into the void.", + "You hear a ratchet.") user.drop_item() if(P.is_bent_pipe()) // bent pipe rotation fix see construction.dm - P.dir = 5 + P.setDir(5) if(user.dir == 1) - P.dir = 6 + P.setDir(6) else if(user.dir == 2) - P.dir = 9 + P.setDir(9) else if(user.dir == 4) - P.dir = 10 + P.setDir(10) else - P.dir = user.dir - P.x = src.x - P.y = src.y - P.z = src.z - P.loc = src + P.setDir(user.dir) + P.forceMove(src) P.level = 2 - return - // The magnetic gripper does a separate attackby, so bail from this one - else if(istype(W, /obj/item/gripper)) - return - - else - return attack_hand(user) - return + return TRUE + return FALSE /turf/simulated/wall/singularity_pull(S, current_size) if(current_size >= STAGE_FIVE) diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index 827791be76d..eb054ba19ed 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -33,333 +33,256 @@ if(RWALL_SHEATH) to_chat(user, "The support rods have been sliced through, and the outer sheath is connected loosely to the girder.") -/turf/simulated/wall/r_wall/attackby(obj/item/W, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") +/turf/simulated/wall/r_wall/attackby(obj/item/I, mob/user, params) + if(try_repair(I, user, params)) return + return ..() - //get the user's location - if(!isturf(user.loc)) - return //can't do this stuff whilst inside objects and such - - if(rotting) - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You burn away the fungi with \the [WT].") - playsound(src, WT.usesound, 10, 1) - for(var/obj/effect/overlay/wall_rot/WR in src) - qdel(WR) - rotting = 0 - return - else if(!is_sharp(W) && W.force >= 10 || W.force >= 20) - to_chat(user, "\The [src] crumbles away under the force of your [W.name].") - dismantle_wall() - return - - //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects - if(thermite) - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - thermitemelt(user) - return - - else if(istype(W, /obj/item/gun/energy/plasmacutter)) - thermitemelt(user) - return - - else if(istype(W, /obj/item/melee/energy/blade)) - var/obj/item/melee/energy/blade/EB = W - - EB.spark_system.start() - to_chat(user, "You slash \the [src] with \the [EB]; the thermite ignites!") - playsound(src, "sparks", 50, 1) - playsound(src, EB.usesound, 50, 1) - - thermitemelt(user) - return - - else if(istype(W, /obj/item/melee/energy/blade)) - to_chat(user, "This wall is too thick to slice through. You will need to find a different path.") - return - - if(damage && iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You start repairing the damage to [src].") - playsound(src, WT.usesound, 100, 1) - if(do_after(user, max(5, damage / 5) * WT.toolspeed, target = src) && WT && WT.isOn()) - to_chat(user, "You finish repairing the damage to [src].") - take_damage(-damage) - return - else +/turf/simulated/wall/r_wall/proc/try_repair(obj/item/I, mob/user, params) + if(damage && iswelder(I)) + var/obj/item/weldingtool/WT = I + if(!WT.remove_fuel(0, user)) to_chat(user, "You need more welding fuel to complete this task.") - return + return TRUE + to_chat(user, "You start repairing the damage to [src].") + playsound(src, WT.usesound, 100, 1) + if(do_after(user, max(5, damage / 5) * WT.toolspeed, target = src) && WT && WT.isOn()) + to_chat(user, "You finish repairing the damage to [src].") + take_damage(-damage) + return TRUE - //DECONSTRUCTION - switch(d_state) - if(RWALL_INTACT) - if(iswirecutter(W)) - playsound(src, W.usesound, 100, 1) - d_state = RWALL_SUPPORT_LINES + if(d_state) + // Repairing + if(istype(I, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/MS = I + + to_chat(user, "You begin patching-up the wall with [MS]...") + if(do_after(user, max(20 * d_state, 100) * MS.toolspeed, target = src) && d_state) + if(!MS.use(1)) + to_chat(user, "You don't have enough [MS.name] for that!") + return TRUE + + d_state = RWALL_INTACT update_icon() - new /obj/item/stack/rods(src) - to_chat(user, "You cut the outer grille.") - return + smooth_icon_neighbors(src) + to_chat(user, "You repair the last of the damage.") - if(RWALL_SUPPORT_LINES) - if(isscrewdriver(W)) - to_chat(user, "You begin unsecuring the support lines...") - playsound(src, W.usesound, 100, 1) + return TRUE - if(do_after(user, 40 * W.toolspeed, target = src) && d_state == RWALL_SUPPORT_LINES) - d_state = RWALL_COVER - update_icon() - to_chat(user, "You unsecure the support lines.") - return - - //REPAIRING (replacing the outer grille for cosmetic damage) - else if(istype(W, /obj/item/stack/rods)) - var/obj/item/stack/O = W - if(O.use(1)) - d_state = RWALL_INTACT - update_icon() - icon_state = "r_wall" - update_icon() - to_chat(user, "You replace the outer grille.") - else - to_chat(user, "You don't have enough rods for that!") - - if(RWALL_COVER) - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You begin slicing through the metal cover...") - playsound(src, WT.usesound, 100, 1) - - if(do_after(user, 60 * WT.toolspeed, target = src) && d_state == RWALL_COVER) - d_state = RWALL_CUT_COVER - update_icon() - to_chat(user, "You press firmly on the cover, dislodging it.") - - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(istype(W, /obj/item/gun/energy/plasmacutter)) - to_chat(user, "You begin slicing through the metal cover...") - playsound(src, W.usesound, 100, 1) - - if(do_after(user, 40 * W.toolspeed, target = src) && d_state == RWALL_COVER) - d_state = RWALL_CUT_COVER - update_icon() - to_chat(user, "You press firmly on the cover, dislodging it.") - return - - if(isscrewdriver(W)) - to_chat(user, "You begin securing the support lines...") - playsound(src, W.usesound, 100, 1) - if(do_after(user, 40*W.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !W || d_state != RWALL_COVER) - return 1 - d_state = RWALL_SUPPORT_LINES - update_icon() - to_chat(user, "The support lines have been secured.") - return 1 - - if(RWALL_CUT_COVER) - if(iscrowbar(W)) - to_chat(user, "You struggle to pry off the cover...") - playsound(src, W.usesound, 100, 1) - - if(do_after(user, 100 * W.toolspeed, target = src) && d_state == RWALL_CUT_COVER) - d_state = RWALL_BOLTS - update_icon() - to_chat(user, "You pry off the cover.") - return - - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You begin welding the metal cover back to the frame...") - playsound(src, WT.usesound, 100, 1) - if(do_after(user, 60*WT.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !WT || !WT.isOn() || d_state != RWALL_CUT_COVER) - return 1 - d_state = RWALL_COVER - update_icon() - to_chat(user, "The metal cover has been welded securely to the frame.") - return 1 - - if(RWALL_BOLTS) - if(iswrench(W)) - to_chat(user, "You start loosening the anchoring bolts which secure the support rods to their frame...") - playsound(src, W.usesound, 100, 1) - - if(do_after(user, 40 * W.toolspeed, target = src) && d_state == RWALL_BOLTS) - d_state = RWALL_SUPPORT_RODS - update_icon() - to_chat(user, "You remove the bolts anchoring the support rods.") - return - - if(iscrowbar(W)) - to_chat(user, "You start to pry the cover back into place...") - playsound(src, W.usesound, 100, 1) - if(do_after(user, 20*W.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !W || d_state != RWALL_BOLTS) - return 1 - d_state = RWALL_CUT_COVER - update_icon() - to_chat(user, "The metal cover has been pried back into place.") - return 1 - - if(RWALL_SUPPORT_RODS) - if(iswelder(W)) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You begin slicing through the support rods...") - playsound(src, WT.usesound, 100, 1) - - if(do_after(user, 100 * WT.toolspeed, target = src) && d_state == RWALL_SUPPORT_RODS) - d_state = RWALL_SHEATH - update_icon() - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(istype(W, /obj/item/gun/energy/plasmacutter)) - to_chat(user, "You begin slicing through the support rods...") - playsound(src, W.usesound, 100, 1) - - if(do_after(user, 70 * W.toolspeed, target = src) && d_state == RWALL_SUPPORT_RODS) - d_state = RWALL_SHEATH - update_icon() - return - - if(iswrench(W)) - to_chat(user, "You start tightening the bolts which secure the support rods to their frame...") - playsound(src, W.usesound, 100, 1) - if(do_after(user, 40*W.toolspeed, target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !W || d_state != RWALL_SUPPORT_RODS) - return 1 - d_state = RWALL_BOLTS - update_icon() - to_chat(user, "You tighten the bolts anchoring the support rods.") - return 1 - - if(RWALL_SHEATH) - if(iscrowbar(W)) - to_chat(user, "You struggle to pry off the outer sheath...") - playsound(src, W.usesound, 100, 1) - - if(do_after(user, 100 * W.toolspeed, target = src) && d_state == RWALL_SHEATH) - to_chat(user, "You pry off the outer sheath.") - dismantle_wall() - return - -//vv OK, we weren't performing a valid deconstruction step or igniting thermite,let's check the other possibilities vv - - //DRILLING - if(istype(W, /obj/item/pickaxe/drill/diamonddrill)) - to_chat(user, "You begin to drill though the wall...") - - if(do_after(user, 800 * W.toolspeed, target = src)) // Diamond drill has 0.25 toolspeed, so 200 - to_chat(user, "Your drill tears through the last of the reinforced plating.") - dismantle_wall() - - if(istype(W,/obj/item/pickaxe/drill/jackhammer)) - to_chat(user, "You begin to disintegrate the wall...") - - if(do_after(user, 1000 * W.toolspeed, target = src)) // Jackhammer has 0.1 toolspeed, so 100 - to_chat(user, "Your sonic jackhammer disintegrates the reinforced plating.") - dismantle_wall() - - //REPAIRING - else if(istype(W, /obj/item/stack/sheet/metal) && d_state) - var/obj/item/stack/sheet/metal/MS = W - - to_chat(user, "You begin patching-up the wall with \a [MS]...") - - if(do_after(user, max(20 * d_state, 100) * MS.toolspeed, target = src) && d_state) - if(!MS.use(1)) - to_chat(user, "You don't have enough metal for that!") - return - - d_state = RWALL_INTACT - update_icon() - smooth_icon_neighbors(src) - to_chat(user, "You repair the last of the damage.") - - //UPGRADING TO COATED - else if(istype(W, /obj/item/stack/sheet/plasteel) && !d_state) - var/obj/item/stack/sheet/plasteel/MS = W + else if(istype(I, /obj/item/stack/sheet/plasteel)) + var/obj/item/stack/sheet/plasteel/PS = I if(!can_be_reinforced) to_chat(user, "The wall is already coated!") - return - to_chat(user, "You begin adding an additional layer of coating to the wall with \a [MS]...") + return FALSE - if(do_after(user, 40 * MS.toolspeed, target = src) && !d_state) - if(!MS.use(2)) - to_chat(user, "You don't have enough plasteel for that!") + to_chat(user, "You begin adding an additional layer of coating to the wall with [PS]...") + if(do_after(user, 40 * PS.toolspeed, target = src) && !d_state) + if(!PS.use(2)) + to_chat(user, "You don't have enough [PS.name] for that!") return to_chat(user, "You add an additional layer of coating to the wall.") ChangeTurf(/turf/simulated/wall/r_wall/coated) update_icon() smooth_icon_neighbors(src) - can_be_reinforced = 0 - return + can_be_reinforced = FALSE + return TRUE + return FALSE - //APC - else if(istype(W,/obj/item/mounted)) - return - //Poster stuff - else if(istype(W, /obj/item/poster)) - place_poster(W, user) - return +/turf/simulated/wall/r_wall/try_decon(obj/item/I, mob/user, params) + switch(d_state) + if(RWALL_INTACT) + // RWALL_INTACT > RWALL_SUPPORT_LINES + if(iswirecutter(I)) + playsound(src, I.usesound, 100, 1) + d_state = RWALL_SUPPORT_LINES + update_icon() + new /obj/item/stack/rods(src) + to_chat(user, "You cut the outer grille.") + return TRUE - //Bone White - Place pipes on walls - else if(istype(W,/obj/item/pipe)) - var/obj/item/pipe/V = W - if(V.pipe_type != -1) // ANY PIPE - var/obj/item/pipe/P = W + if(RWALL_SUPPORT_LINES) + // RWALL_SUPPORT_LINES > RWALL_COVER + if(isscrewdriver(I)) + to_chat(user, "You begin unsecuring the support lines...") + playsound(src, I.usesound, 100, 1) - playsound(get_turf(src), 'sound/weapons/circsawhit.ogg', 50, 1) - user.visible_message( \ - "[user] starts drilling a hole in \the [src]...", \ - "You start drilling a hole in \the [src]. This is going to take a while.", \ - "You hear ratchet.") - if(do_after(user, 160 * V.toolspeed, target = src)) - user.visible_message( \ - "[user] drills a hole in \the [src] and pushes \a [P] into the void.", \ - "You have finished drilling in \the [src] and push the [P] into the void.", \ - "You hear ratchet.") + if(do_after(user, 40 * I.toolspeed, target = src) && d_state == RWALL_SUPPORT_LINES) + d_state = RWALL_COVER + update_icon() + to_chat(user, "You unsecure the support lines.") + return TRUE - user.drop_item() - if(P.is_bent_pipe()) // bent pipe rotation fix see construction.dm - P.dir = 5 - if(user.dir == 1) - P.dir = 6 - else if(user.dir == 2) - P.dir = 9 - else if(user.dir == 4) - P.dir = 10 + // RWALL_INTACT < RWALL_SUPPORT_LINES + if(istype(I, /obj/item/stack/rods)) + var/obj/item/stack/S = I + if(S.use(1)) + d_state = RWALL_INTACT + update_icon() + to_chat(user, "You replace the outer grille.") else - P.dir = user.dir - P.x = src.x - P.y = src.y - P.z = src.z - P.loc = src - P.level = 2 - return + to_chat(user, "You don't have enough rods for that!") + return TRUE + + if(RWALL_COVER) + // RWALL_COVER > RWALL_CUT_COVER + if(iswelder(I)) + var/obj/item/weldingtool/WT = I + if(!WT.remove_fuel(0, user)) + to_chat(user, "You need more welding fuel to complete this task.") + return TRUE + + to_chat(user, "You begin slicing through the metal cover...") + playsound(src, WT.usesound, 100, 1) + + if(do_after(user, 60 * WT.toolspeed, target = src) && d_state == RWALL_COVER) + d_state = RWALL_CUT_COVER + update_icon() + to_chat(user, "You press firmly on the cover, dislodging it.") + return TRUE + + // RWALL_COVER > RWALL_CUT_COVER + if(istype(I, /obj/item/gun/energy/plasmacutter)) + to_chat(user, "You begin slicing through the metal cover...") + playsound(src, I.usesound, 100, 1) + + if(do_after(user, 40 * I.toolspeed, target = src) && d_state == RWALL_COVER) + d_state = RWALL_CUT_COVER + update_icon() + to_chat(user, "You press firmly on the cover, dislodging it.") + return TRUE + + // RWALL_SUPPORT_LINES < RWALL_COVER + if(isscrewdriver(I)) + to_chat(user, "You begin securing the support lines...") + playsound(src, I.usesound, 100, 1) + if(do_after(user, 40 * I.toolspeed, target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !I || d_state != RWALL_COVER) + return TRUE + d_state = RWALL_SUPPORT_LINES + update_icon() + to_chat(user, "The support lines have been secured.") + return TRUE + + if(RWALL_CUT_COVER) + // RWALL_CUT_COVER > RWALL_BOLTS + if(iscrowbar(I)) + to_chat(user, "You struggle to pry off the cover...") + playsound(src, I.usesound, 100, 1) + + if(do_after(user, 100 * I.toolspeed, target = src) && d_state == RWALL_CUT_COVER) + d_state = RWALL_BOLTS + update_icon() + to_chat(user, "You pry off the cover.") + return TRUE + + // RWALL_COVER < RWALL_CUT_COVER + if(iswelder(I)) + var/obj/item/weldingtool/WT = I + if(!WT.remove_fuel(0, user)) + return TRUE + + to_chat(user, "You begin welding the metal cover back to the frame...") + playsound(src, WT.usesound, 100, 1) + if(do_after(user, 60 * WT.toolspeed, target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !WT || !WT.isOn() || d_state != RWALL_CUT_COVER) + return TRUE + d_state = RWALL_COVER + update_icon() + to_chat(user, "The metal cover has been welded securely to the frame.") + return TRUE + + if(RWALL_BOLTS) + // RWALL_BOLTS > RWALL_SUPPORT_RODS + if(iswrench(I)) + to_chat(user, "You start loosening the anchoring bolts which secure the support rods to their frame...") + playsound(src, I.usesound, 100, 1) + + if(do_after(user, 40 * I.toolspeed, target = src) && d_state == RWALL_BOLTS) + d_state = RWALL_SUPPORT_RODS + update_icon() + to_chat(user, "You remove the bolts anchoring the support rods.") + return TRUE + + // RWALL_CUT_COVER < RWALL_BOLTS + if(iscrowbar(I)) + to_chat(user, "You start to pry the cover back into place...") + playsound(src, I.usesound, 100, 1) + if(do_after(user, 20 * I.toolspeed, target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !I || d_state != RWALL_BOLTS) + return TRUE + d_state = RWALL_CUT_COVER + update_icon() + to_chat(user, "The metal cover has been pried back into place.") + return TRUE + + if(RWALL_SUPPORT_RODS) + // RWALL_SUPPORT_RODS > RWALL_SHEATH + if(iswelder(I)) + var/obj/item/weldingtool/WT = I + if(!WT.remove_fuel(0, user)) + to_chat(user, "You need more welding fuel to complete this task.") + return TRUE + + to_chat(user, "You begin slicing through the support rods...") + playsound(src, WT.usesound, 100, 1) + + if(do_after(user, 100 * WT.toolspeed, target = src) && d_state == RWALL_SUPPORT_RODS) + d_state = RWALL_SHEATH + update_icon() + return TRUE + + // RWALL_SUPPORT_RODS > RWALL_SHEATH + if(istype(I, /obj/item/gun/energy/plasmacutter)) + to_chat(user, "You begin slicing through the support rods...") + playsound(src, I.usesound, 100, 1) + + if(do_after(user, 70 * I.toolspeed, target = src) && d_state == RWALL_SUPPORT_RODS) + d_state = RWALL_SHEATH + update_icon() + return TRUE + + // RWALL_BOLTS < RWALL_SUPPORT_RODS + if(iswrench(I)) + to_chat(user, "You start tightening the bolts which secure the support rods to their frame...") + playsound(src, I.usesound, 100, 1) + if(do_after(user, 40 * I.toolspeed, target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !I || d_state != RWALL_SUPPORT_RODS) + return TRUE + d_state = RWALL_BOLTS + update_icon() + to_chat(user, "You tighten the bolts anchoring the support rods.") + return TRUE + + if(RWALL_SHEATH) + // RWALL_SHEATH > deconstructed + if(iscrowbar(I)) + to_chat(user, "You struggle to pry off the outer sheath...") + playsound(src, I.usesound, 100, 1) + + if(do_after(user, 100 * I.toolspeed, target = src) && d_state == RWALL_SHEATH) + to_chat(user, "You pry off the outer sheath.") + dismantle_wall() + return TRUE + +/turf/simulated/wall/r_wall/try_destroy(obj/item/I, mob/user, params) + if(istype(I, /obj/item/pickaxe/drill/diamonddrill)) + to_chat(user, "You begin to drill though the wall...") + + if(do_after(user, 800 * I.toolspeed, target = src)) // Diamond drill has 0.25 toolspeed, so 200 + to_chat(user, "Your drill tears through the last of the reinforced plating.") + dismantle_wall() + return TRUE + + if(istype(I, /obj/item/pickaxe/drill/jackhammer)) + to_chat(user, "You begin to disintegrate the wall...") + + if(do_after(user, 1000 * I.toolspeed, target = src)) // Jackhammer has 0.1 toolspeed, so 100 + to_chat(user, "Your sonic jackhammer disintegrates the reinforced plating.") + dismantle_wall() + return TRUE - //Finally, CHECKING FOR FALSE WALLS if it isn't damaged - else if(!d_state) - return attack_hand(user) - return /turf/simulated/wall/r_wall/singularity_pull(S, current_size) if(current_size >= STAGE_FIVE) diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 60c63d0f221..58911d952b4 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -3,7 +3,6 @@ name = "\proper space" icon_state = "0" dynamic_lighting = 0 - flags = RPD_ALLOWED_HERE luminosity = 1 temperature = TCMB diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index 611ff1656f3..c08189e4d93 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -1,5 +1,4 @@ /turf/space/transit - flags = null var/pushdirection // push things that get caught in the transit tile this direction //Overwrite because we dont want people building rods in space. @@ -94,8 +93,7 @@ var/max = world.maxx-TRANSITIONEDGE var/min = 1+TRANSITIONEDGE - var/datum/space_level/dest = pick(levels_by_trait(REACHABLE)) - var/_z = dest.zpos //select a random space zlevel + var/_z = pick(levels_by_trait(REACHABLE)) //select a random space zlevel //now select coordinates for a border turf var/_x @@ -119,7 +117,8 @@ AM.newtonian_move(dir) - +/turf/space/transit/rpd_act() + return //Overwrite because we dont want people building rods in space. /turf/space/transit/attackby() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index f70aee9740f..337233b5bf4 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -71,6 +71,21 @@ /turf/ex_act(severity) return 0 +/turf/rpd_act(mob/user, obj/item/rpd/our_rpd) //This is the default turf behaviour for the RPD; override it as required + if(our_rpd.mode == RPD_ATMOS_MODE) + our_rpd.create_atmos_pipe(user, src) + else if(our_rpd.mode == RPD_DISPOSALS_MODE) + for(var/obj/machinery/door/airlock/A in src) + if(A.density) + to_chat(user, "That type of pipe won't fit under [A]!") + return + our_rpd.create_disposals_pipe(user, src) + else if(our_rpd.mode == RPD_ROTATE_MODE) + our_rpd.rotate_all_pipes(user, src) + else if(our_rpd.mode == RPD_FLIP_MODE) + our_rpd.flip_all_pipes(user, src) + else if(our_rpd.mode == RPD_DELETE_MODE) + our_rpd.delete_all_pipes(user, src) /turf/bullet_act(var/obj/item/projectile/Proj) if(istype(Proj ,/obj/item/projectile/beam/pulse)) diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm index 5c9509a3d68..35b6c2056e3 100644 --- a/code/game/turfs/unsimulated.dm +++ b/code/game/turfs/unsimulated.dm @@ -7,6 +7,9 @@ /turf/unsimulated/can_lay_cable() return 0 +/turf/unsimulated/rpd_act() + return + /turf/unsimulated/floor/plating/vox icon_state = "plating" name = "plating" diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm index b9a51a661d1..da843d8e53c 100644 --- a/code/game/verbs/suicide.dm +++ b/code/game/verbs/suicide.dm @@ -37,7 +37,7 @@ // Failing that... if(!(damagetype & BRUTELOSS) && !(damagetype & FIRELOSS) && !(damagetype & TOXLOSS) && !(damagetype & OXYLOSS)) - if(NO_BREATHE in species.species_traits) + if(NO_BREATHE in dna.species.species_traits) // the ultimate fallback take_overall_damage(max(dmgamt - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0), 0) else @@ -84,7 +84,7 @@ do_suicide(damagetype, held_item) return - to_chat(viewers(src), "[src] [pick(species.suicide_messages)] It looks like they're trying to commit suicide.") + to_chat(viewers(src), "[src] [replacetext(pick(dna.species.suicide_messages), "their", p_their())] It looks like [p_theyre()] trying to commit suicide.") do_suicide(0) updatehealth() @@ -129,7 +129,7 @@ if(confirm == "Yes") suiciding = 1 - to_chat(viewers(src), "[src] is powering down. It looks like \he's trying to commit suicide.") + to_chat(viewers(src), "[src] is powering down. It looks like [p_theyre()] trying to commit suicide.") //put em at -175 adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) updatehealth() @@ -149,7 +149,7 @@ if(confirm == "Yes") suiciding = 1 - to_chat(viewers(src), "[src] is powering down. It looks like \he's trying to commit suicide.") + to_chat(viewers(src), "[src] is powering down. It looks like [p_theyre()] trying to commit suicide.") //put em at -175 adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) updatehealth() @@ -186,7 +186,7 @@ if(confirm == "Yes") suiciding = 1 - to_chat(viewers(src), "[src] is thrashing wildly! It looks like \he's trying to commit suicide.") + to_chat(viewers(src), "[src] is thrashing wildly! It looks like [p_theyre()] trying to commit suicide.") //put em at -175 adjustOxyLoss(max(175 - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) updatehealth() diff --git a/code/game/world.dm b/code/game/world.dm index 7d592864501..516346aeca3 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -21,14 +21,13 @@ var/global/list/map_transition_config = MAP_TRANSITION_CONFIG src.update_status() + space_manager.initialize() //Before the MC starts up . = ..() // Create robolimbs for chargen. populate_robolimb_list() - space_manager.initialize() //Before the MC starts up - Master.Initialize(10, FALSE) processScheduler = new @@ -362,7 +361,7 @@ var/world_topic_spam_protect_time = world.timeofday /world/proc/load_motd() join_motd = file2text("config/motd.txt") - + GLOB.join_tos = file2text("config/tos.txt") /proc/load_configuration() config = new /datum/configuration() @@ -494,4 +493,3 @@ proc/establish_db_connection() return 1 #undef FAILED_DB_CONNECTION_CUTOFF - diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index b97993d5327..4c905a0b517 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -93,7 +93,7 @@ world/IsBanned(key,address,computer_id) var/appealmessage = "" if(config.banappeals) appealmessage = " You may appeal it at [config.banappeals]." - expires = " The is a permanent ban.[appealmessage]" + expires = " This is a permanent ban.[appealmessage]" var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]" diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index b155ddc13dd..84120c2c669 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -9,15 +9,17 @@ var/global/nologevent = 0 if(C.prefs && !(C.prefs.toggles & CHAT_NO_ADMINLOGS)) to_chat(C, msg) -/proc/msg_admin_attack(var/text) //Toggleable Attack Messages +/proc/msg_admin_attack(var/text, var/loglevel) if(!nologevent) var/rendered = "ATTACK: [text]" for(var/client/C in admins) if(R_ADMIN & C.holder.rights) - if(C.prefs.toggles & CHAT_ATTACKLOGS) - if(!istype(C, /mob/living)) - var/msg = rendered - to_chat(C, msg) + if(C.prefs.atklog == ATKLOG_NONE) + continue + var/msg = rendered + if(C.prefs.atklog <= loglevel) + to_chat(C, msg) + /proc/message_adminTicket(var/msg) msg = "ADMIN TICKET: [msg]" @@ -59,7 +61,8 @@ var/global/nologevent = 0 body += "PM - " body += "SM - " body += "[admin_jump_link(M)]\]
" - + if(ishuman(M) && M.mind) + body += "HM" body += "Mob type: [M.type]
" if(M.client) if(M.client.related_accounts_cid.len) @@ -876,10 +879,10 @@ var/global/nologevent = 0 to_chat(usr, "[P.pai_laws]") continue // Skip showing normal silicon laws for pAIs - they don't have any else - to_chat(usr, "SILICON [key_name(S, usr)]'s laws:") + to_chat(usr, "SILICON [key_name(S, TRUE)]'s laws:") if(S.laws == null) - to_chat(usr, "[key_name(S, usr)]'s laws are null. Contact a coder.") + to_chat(usr, "[key_name(S, TRUE)]'s laws are null. Contact a coder.") else S.laws.show_laws(usr) if(!ai_number) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 0beef7931a5..9df5cb1cb6e 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -76,7 +76,8 @@ var/list/admin_verbs_admin = list( /client/proc/toggle_mentor_chat, /client/proc/toggle_advanced_interaction, /*toggle admin ability to interact with not only machines, but also atoms such as buttons and doors*/ /client/proc/list_ssds, - /client/proc/spawn_floor_cluwne + /client/proc/cmd_admin_headset_message, + /client/proc/spawn_floor_cluwne, ) var/list/admin_verbs_ban = list( /client/proc/unban_panel, @@ -827,10 +828,10 @@ var/list/admin_verbs_ticket = list( if(!istype(H)) if(istype(H, /mob/living/carbon/brain)) var/mob/living/carbon/brain/B = H - if(istype(B.container, /obj/item/mmi/posibrain/ipc)) - var/obj/item/mmi/posibrain/ipc/C = B.container + if(istype(B.container, /obj/item/mmi/robotic_brain/positronic)) + var/obj/item/mmi/robotic_brain/positronic/C = B.container var/obj/item/organ/internal/brain/mmi_holder/posibrain/P = C.loc - if(istype(P.owner, /mob/living/carbon/human)) + if(ishuman(P.owner)) H = P.owner else return @@ -853,10 +854,10 @@ var/list/admin_verbs_ticket = list( if(!istype(H)) if(istype(H, /mob/living/carbon/brain)) var/mob/living/carbon/brain/B = H - if(istype(B.container, /obj/item/mmi/posibrain/ipc)) - var/obj/item/mmi/posibrain/ipc/C = B.container + if(istype(B.container, /obj/item/mmi/robotic_brain/positronic)) + var/obj/item/mmi/robotic_brain/positronic/C = B.container var/obj/item/organ/internal/brain/mmi_holder/posibrain/P = C.loc - if(istype(P.owner, /mob/living/carbon/human)) + if(ishuman(P.owner)) H = P.owner else return @@ -869,10 +870,10 @@ var/list/admin_verbs_ticket = list( switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel")) if("Yes") - admin_log_and_message_admins("has allowed [H] to change \his appearance, without whitelisting of races.") + admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, without whitelisting of races.") H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0) if("No") - admin_log_and_message_admins("has allowed [H] to change \his appearance, with whitelisting of races.") + admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, with whitelisting of races.") H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1) feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -903,12 +904,27 @@ var/list/admin_verbs_ticket = list( if(!check_rights(R_ADMIN)) return - prefs.toggles ^= CHAT_ATTACKLOGS - prefs.save_preferences(src) - if(prefs.toggles & CHAT_ATTACKLOGS) - to_chat(usr, "You now will get attack log messages") + if(prefs.atklog == ATKLOG_ALL) + prefs.atklog = ATKLOG_ALMOSTALL + to_chat(usr, "Your attack logs preference is now: show ALMOST ALL attack logs (notable exceptions: NPCs attacking other NPCs, vampire bites, equipping/stripping, people pushing each other over)") + else if(prefs.atklog == ATKLOG_ALMOSTALL) + prefs.atklog = ATKLOG_MOST + to_chat(usr, "Your attack logs preference is now: show MOST attack logs (like ALMOST ALL, except that it also hides attacks by players on NPCs)") + else if(prefs.atklog == ATKLOG_MOST) + prefs.atklog = ATKLOG_FEW + to_chat(usr, "Your attack logs preference is now: show FEW attack logs (only the most important stuff: attacks on SSDs, use of explosives, messing with the engine, gibbing, AI wiping, forcefeeding, acid sprays, and organ extraction)") + else if(prefs.atklog == ATKLOG_FEW) + prefs.atklog = ATKLOG_NONE + to_chat(usr, "Your attack logs preference is now: show NO attack logs") + else if(prefs.atklog == ATKLOG_NONE) + prefs.atklog = ATKLOG_ALL + to_chat(usr, "Your attack logs preference is now: show ALL attack logs") else - to_chat(usr, "You now won't get attack log messages") + prefs.atklog = ATKLOG_ALL + to_chat(usr, "Your attack logs preference is now: show ALL attack logs (your preference was set to an invalid value, it has been reset)") + + prefs.save_preferences(src) + /client/proc/toggleadminlogs() set name = "Toggle Admin Log Messages" diff --git a/code/modules/admin/buildmode.dm b/code/modules/admin/buildmode.dm index d628df054c6..b04b9d2b96a 100644 --- a/code/modules/admin/buildmode.dm +++ b/code/modules/admin/buildmode.dm @@ -14,6 +14,7 @@ /obj/screen/buildmode icon = 'icons/misc/buildmode.dmi' var/datum/click_intercept/buildmode/bd + layer = HUD_LAYER_BUILDMODE /obj/screen/buildmode/New(bld) ..() @@ -78,6 +79,7 @@ /obj/effect/buildmode_reticule var/image/I var/client/cl + anchored = TRUE /obj/effect/buildmode_reticule/New(var/turf/t, var/client/c) loc = t @@ -349,13 +351,13 @@ if(BOOM_BUILDMODE) devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null if(devastation == null) devastation = -1 - var/heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null + heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null if(heavy == null) heavy = -1 - var/light = input("Range of light impact. -1 to none", text("Input")) as num|null + light = input("Range of light impact. -1 to none", text("Input")) as num|null if(light == null) light = -1 - var/flash = input("Range of flash. -1 to none", text("Input")) as num|null + flash = input("Range of flash. -1 to none", text("Input")) as num|null if(flash == null) flash = -1 - var/flames = input("Range of flames. -1 to none", text("Input")) as num|null + flames = input("Range of flames. -1 to none", text("Input")) as num|null if(flames == null) flames = -1 if(SAVE_BUILDMODE) @@ -454,10 +456,12 @@ var/turf/T = get_turf(object) log_admin("Build Mode: [key_name(user)] modified [T] ([T.x],[T.y],[T.z]) to [objholder]") T.ChangeTurf(objholder) - else + else if(!isnull(objholder)) var/obj/A = new objholder (get_turf(object)) A.setDir(build_dir) log_admin("Build Mode: [key_name(user)] modified [A]'s ([A.x],[A.y],[A.z]) dir to [build_dir]") + else + to_chat(user, "Select object type first.") else if(right_click) if(isobj(object)) log_admin("Build Mode: [key_name(user)] deleted [object] at ([object.x],[object.y],[object.z])") @@ -625,7 +629,7 @@ L2.color = L.color link_lines += L2 if(BOOM_BUILDMODE) - explosion(object, devastation, heavy, light, flash, null, null,flames) + explosion(object, devastation, heavy, light, flash, null, TRUE, flames) if(SAVE_BUILDMODE) if(!cornerA) cornerA = select_tile(get_turf(object)) diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index 21731cc8b7a..fe487ae6431 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -25,8 +25,6 @@ Show current traitors and objectives
Set Night Shift Mode
Bombs
- Bombing List   - Remove all bombs currently in existence [check_rights(R_SERVER, 0) ? "  Toggle bomb cap
" : "
"] Lists
Show last [length(lastsignalers)] signalers   @@ -82,7 +80,6 @@ Security Level - Delta
Create Weather
Weather - Ash Storm   - Weather - Advanced Darkness  
"} @@ -130,5 +127,3 @@ var/datum/browser/popup = new(usr, "secrets", "
Admin Secrets
", 630, 670) popup.set_content(dat) popup.open(0) - - diff --git a/code/modules/admin/tickets/admintickets.dm b/code/modules/admin/tickets/admintickets.dm index 5ef1f58dbf5..ea5f7003870 100644 --- a/code/modules/admin/tickets/admintickets.dm +++ b/code/modules/admin/tickets/admintickets.dm @@ -104,7 +104,7 @@ var/global/datum/adminTicketHolder/globAdminTicketHolder = new /datum/adminTicke /datum/adminTicketHolder/proc/checkForTicket(var/client/C) var/list/tickets = list() for(var/datum/admin_ticket/T in allTickets) - if(T.clientName == C && T.ticketState == ADMIN_TICKET_OPEN || T.ticketState == ADMIN_TICKET_STALE) + if(T.clientName == C && (T.ticketState == ADMIN_TICKET_OPEN || T.ticketState == ADMIN_TICKET_STALE)) tickets += T if(tickets.len) return tickets diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1f24a267694..d099b00ba8c 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -39,35 +39,35 @@ switch(href_list["makeAntag"]) if("1") log_admin("[key_name(usr)] has spawned a traitor.") - if(!src.makeTraitors()) + if(!makeTraitors()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("2") log_admin("[key_name(usr)] has spawned a changeling.") - if(!src.makeChanglings()) + if(!makeChangelings()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("3") log_admin("[key_name(usr)] has spawned revolutionaries.") - if(!src.makeRevs()) + if(!makeRevs()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("4") log_admin("[key_name(usr)] has spawned a cultists.") - if(!src.makeCult()) + if(!makeCult()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("5") log_admin("[key_name(usr)] has spawned a wizard.") - if(!src.makeWizard()) + if(!makeWizard()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("6") log_admin("[key_name(usr)] has spawned vampires.") - if(!src.makeVampires()) + if(!makeVampires()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("7") log_admin("[key_name(usr)] has spawned vox raiders.") - if(!src.makeVoxRaiders()) + if(!makeVoxRaiders()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("8") log_admin("[key_name(usr)] has spawned an abductor team.") - if(!src.makeAbductorTeam()) + if(!makeAbductorTeam()) to_chat(usr, "Unfortunately there weren't enough candidates available.") else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"] || href_list["dbsearchip"] || href_list["dbsearchcid"] || href_list["dbsearchbantype"]) @@ -337,7 +337,7 @@ if("queen") M.change_mob_type( /mob/living/carbon/alien/humanoid/queen/large , null, null, delmob, 1 ) if("sentinel") M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob, 1 ) if("larva") M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob, 1 ) - if("human") M.change_mob_type( /mob/living/carbon/human/human , null, null, delmob, 1 ) + if("human") M.change_mob_type( /mob/living/carbon/human, null, null, delmob, 1 ) if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob, 1 ) if("monkey") M.change_mob_type( /mob/living/carbon/human/monkey , null, null, delmob, 1 ) if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob, 1 ) @@ -1622,14 +1622,14 @@ H.equip_to_slot_or_del( new /obj/item/reagent_containers/food/snacks/cookie(H), slot_r_hand ) if(!(istype(H.r_hand,/obj/item/reagent_containers/food/snacks/cookie))) log_admin("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") - message_admins("[key_name_admin(H)] has their hands full, so they did not receive their cookie, spawned by [key_name_admin(src.owner)].") + message_admins("[key_name_admin(H)] has [H.p_their()] hands full, so [H.p_they()] did not receive [H.p_their()] cookie, spawned by [key_name_admin(src.owner)].") return else H.update_inv_r_hand()//To ensure the icon appears in the HUD else H.update_inv_l_hand() log_admin("[key_name(H)] got their cookie, spawned by [key_name(src.owner)]") - message_admins("[key_name_admin(H)] got their cookie, spawned by [key_name_admin(src.owner)]") + message_admins("[key_name_admin(H)] got [H.p_their()] cookie, spawned by [key_name_admin(src.owner)]") feedback_inc("admin_cookies_spawned",1) to_chat(H, "Your prayers have been answered!! You received the best cookie!") @@ -1675,21 +1675,22 @@ if(!check_rights(R_ADMIN)) return - var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - if(!istype(H.l_ear, /obj/item/radio/headset) && !istype(H.r_ear, /obj/item/radio/headset)) - to_chat(usr, "The person you are trying to contact is not wearing a headset") + var/mob/M = locateUID(href_list["CentcommReply"]) + usr.client.admin_headset_message(M, "Centcomm") + + else if(href_list["SyndicateReply"]) + if(!check_rights(R_ADMIN)) return - var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from Centcomm", "") - if(!input) return + var/mob/M = locateUID(href_list["SyndicateReply"]) + usr.client.admin_headset_message(M, "Syndicate") - to_chat(src.owner, "You sent [input] to [H] via a secure channel.") - log_admin("[key_name(src.owner)] replied to [key_name(H)]'s Centcomm message with the message [input].") - message_admins("[key_name_admin(src.owner)] replied to [key_name_admin(H)]'s Centcom message with: \"[input]\"") - to_chat(H, "You hear something crackle in your headset for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows. [input]. Message ends.\"") + else if(href_list["HeadsetMessage"]) + if(!check_rights(R_ADMIN)) + return + + var/mob/M = locateUID(href_list["HeadsetMessage"]) + usr.client.admin_headset_message(M) else if(href_list["EvilFax"]) if(!check_rights(R_ADMIN)) @@ -1942,7 +1943,7 @@ newtraitor.mind.special_role = SPECIAL_ROLE_TRAITOR var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] tatorhud.join_hud(newtraitor) - ticker.mode.set_antag_hud(newtraitor, "hudsyndicate") + set_antag_hud(newtraitor, "hudsyndicate") else to_chat(usr, "ERROR: Failed to create a traitor.") return @@ -2051,7 +2052,7 @@ if(!istype(H.l_ear, /obj/item/radio/headset) && !istype(H.r_ear, /obj/item/radio/headset)) to_chat(usr, "The person you are trying to contact is not wearing a headset") return - var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from The Syndicate", "") + var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via [H.p_their()] headset.","Outgoing message from The Syndicate", "") if(!input) return to_chat(src.owner, "You sent [input] to [H] via a secure channel.") @@ -2067,7 +2068,7 @@ to_chat(usr, "The person you are trying to contact is not wearing a headset") return - var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from HONKplanet", "") + var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via [H.p_their()] headset.","Outgoing message from HONKplanet", "") if(!input) return to_chat(src.owner, "You sent [input] to [H] via a secure channel.") @@ -2733,48 +2734,6 @@ for(var/mob/M in player_list) if(M.stat != 2) M.show_message(text("The chilling wind suddenly stops..."), 1) -/* if("shockwave") - ok = 1 - to_chat(world, "ALERT: STATION STRESS CRITICAL") - sleep(60) - to_chat(world, "ALERT: STATION STRESS CRITICAL. TOLERABLE LEVELS EXCEEDED!") - sleep(80) - to_chat(world, "ALERT: STATION STRUCTURAL STRESS CRITICAL. SAFETY MECHANISMS FAILED!") - sleep(40) - for(var/mob/M in world) - shake_camera(M, 400, 1) - for(var/obj/structure/window/W in world) - spawn(0) - sleep(rand(10,400)) - W.ex_act(rand(2,1)) - for(var/obj/structure/grille/G in world) - spawn(0) - sleep(rand(20,400)) - G.ex_act(rand(2,1)) - for(var/obj/machinery/door/D in world) - spawn(0) - sleep(rand(20,400)) - D.ex_act(rand(2,1)) - for(var/turf/station/floor/Floor in world) - spawn(0) - sleep(rand(30,400)) - Floor.ex_act(rand(2,1)) - for(var/obj/structure/cable/Cable in world) - spawn(0) - sleep(rand(30,400)) - Cable.ex_act(rand(2,1)) - for(var/obj/structure/closet/Closet in world) - spawn(0) - sleep(rand(30,400)) - Closet.ex_act(rand(2,1)) - for(var/obj/machinery/Machinery in world) - spawn(0) - sleep(rand(30,400)) - Machinery.ex_act(rand(1,3)) - for(var/turf/station/wall/Wall in world) - spawn(0) - sleep(rand(30,400)) - Wall.ex_act(rand(2,1)) */ if("lightout") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","LO") @@ -2799,7 +2758,7 @@ var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") if(sure == "No") return - weather_master.run_weather("the floor is lava") + SSweather.run_weather(/datum/weather/floor_is_lava) message_admins("[key_name_admin(usr)] made the floor lava") if("fakelava") feedback_inc("admin_secrets_fun_used", 1) @@ -2807,7 +2766,7 @@ var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") if(sure == "No") return - weather_master.run_weather("fake lava") + SSweather.run_weather(/datum/weather/floor_is_lava/fake) message_admins("[key_name_admin(usr)] made aesthetic lava on the floor") if("weatherashstorm") feedback_inc("admin_secrets_fun_used", 1) @@ -2815,16 +2774,8 @@ var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") if(sure == "No") return - weather_master.run_weather("ash storm") + SSweather.run_weather(/datum/weather/ash_storm) message_admins("[key_name_admin(usr)] spawned an ash storm on the mining asteroid") - if("weatherdarkness") - feedback_inc("admin_secrets_fun_used", 1) - feedback_add_details("admin_secrets_fun_used", "WD") - var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No") - if(sure == "No") - return - weather_master.run_weather("advanced darkness") - message_admins("[key_name_admin(usr)] made the station go through advanced darkness") if("retardify") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","RET") @@ -2963,13 +2914,6 @@ var/ok = 0 switch(href_list["secretsadmin"]) - if("clear_bombs") - //I do nothing - if("list_bombers") - var/dat = "Bombing List
" - for(var/l in bombers) - dat += text("[l]
") - usr << browse(dat, "window=bombers") if("list_signalers") var/dat = "Showing last [length(lastsignalers)] signalers.
" for(var/sig in lastsignalers) @@ -3438,11 +3382,11 @@ to_chat(hunter_mob, "ATTENTION: You are now on a mission!") to_chat(hunter_mob, "Goal: [killthem ? "MURDER" : "PROTECT"] [H.real_name], currently in [get_area(H.loc)]. "); if(killthem) - to_chat(hunter_mob, "If you kill them, they cannot be revived."); + to_chat(hunter_mob, "If you kill [H.p_them()], [H.p_they()] cannot be revived."); hunter_mob.mind.special_role = SPECIAL_ROLE_TRAITOR var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] tatorhud.join_hud(hunter_mob) - ticker.mode.set_antag_hud(hunter_mob, "hudsyndicate") + set_antag_hud(hunter_mob, "hudsyndicate") /proc/admin_jump_link(var/atom/target) if(!target) return diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 2533eab0570..600a53d81eb 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -183,6 +183,8 @@ if(check_rights(R_ADMIN|R_MOD, 0, X.mob)) to_chat(X, "[type]: [key_name(src, TRUE, type)]->[key_name(C, TRUE, type)]: [emoji_msg]") + if(type == "Mentorhelp") + return //Check if the mob being PM'd has any open admin tickets. var/tickets = list() tickets = globAdminTicketHolder.checkForTicket(C) diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index f091e49f60e..2a0f78351e4 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -12,6 +12,7 @@ if(check_rights(R_ADMIN,0)) for(var/client/C in admins) if(R_ADMIN & C.holder.rights) + msg = "[msg]" to_chat(C, "ADMIN: [key_name(usr, 1)] ([admin_jump_link(mob)]): [msg]") feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -38,6 +39,7 @@ display_name = "[holder.fakekey]/([key])" else display_name = holder.fakekey + msg = "[msg]" to_chat(C, "MENTOR: [display_name] ([admin_jump_link(mob)]): [msg]") feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 00966ee31fc..682a174c450 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -266,7 +266,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if(!choice) return 0 if(!istype(choice, /mob/dead/observer)) - var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank him out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No") + var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank [choice.p_them()] out of [choice.p_their()] body and place [choice.p_them()] in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No") if(confirm != "Yes") return 0 var/obj/item/paicard/card = new(T) diff --git a/code/modules/admin/verbs/gimmick_team.dm b/code/modules/admin/verbs/gimmick_team.dm index 2ca1d3c27df..6192ad6b2ac 100644 --- a/code/modules/admin/verbs/gimmick_team.dm +++ b/code/modules/admin/verbs/gimmick_team.dm @@ -70,7 +70,7 @@ H.dna.ready_dna(H) H.mind_initialize() - H.mind.assigned_role = "MODE" + H.mind.assigned_role = "Event Character" H.mind.special_role = "Event Character" H.key = thisplayer.key diff --git a/code/modules/admin/verbs/honksquad.dm b/code/modules/admin/verbs/honksquad.dm index 36001fb9035..1e72c1836da 100644 --- a/code/modules/admin/verbs/honksquad.dm +++ b/code/modules/admin/verbs/honksquad.dm @@ -91,7 +91,7 @@ var/global/sent_honksquad = 0 //Creates mind stuff. new_honksquad.mind_initialize() - new_honksquad.mind.assigned_role = "MODE" + new_honksquad.mind.assigned_role = SPECIAL_ROLE_HONKSQUAD new_honksquad.mind.special_role = SPECIAL_ROLE_HONKSQUAD new_honksquad.add_language("Clownish") ticker.mode.traitors |= new_honksquad.mind//Adds them to current traitor list. Which is really the extra antagonist list. diff --git a/code/modules/admin/verbs/infiltratorteam_syndicate.dm b/code/modules/admin/verbs/infiltratorteam_syndicate.dm index dad0141a3bc..a3f30117cdd 100644 --- a/code/modules/admin/verbs/infiltratorteam_syndicate.dm +++ b/code/modules/admin/verbs/infiltratorteam_syndicate.dm @@ -109,7 +109,7 @@ var/global/sent_syndicate_infiltration_team = 0 new_syndicate_infiltrator.mind.store_memory("Starting Equipment:
- Syndicate Headset ((.h for your radio))
- Chameleon Jumpsuit ((right click to Change Color))
- Agent ID card ((disguise as another job))
- Uplink Implant ((top left of screen))
- Dust Implant ((destroys your body on death))
- Combat Gloves ((insulated, disguised as black gloves))
- Anything bought with your uplink implant") var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS] opshud.join_hud(new_syndicate_infiltrator.mind.current) - ticker.mode.set_antag_hud(new_syndicate_infiltrator.mind.current, "hudoperative") + set_antag_hud(new_syndicate_infiltrator.mind.current, "hudoperative") new_syndicate_infiltrator.regenerate_icons() num_spawned++ if(!teamsize) @@ -127,7 +127,7 @@ var/global/sent_syndicate_infiltration_team = 0 syndimgmtmob.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate, slot_wear_mask) var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS] opshud.join_hud(syndimgmtmob.mind.current) - ticker.mode.set_antag_hud(syndimgmtmob.mind.current, "hudoperative") + set_antag_hud(syndimgmtmob.mind.current, "hudoperative") syndimgmtmob.mind.special_role = "Syndicate Management Consultant" syndimgmtmob.regenerate_icons() to_chat(syndimgmtmob, "You have spawned as Syndicate Management. You should brief them on their mission before they go.") @@ -149,7 +149,7 @@ var/global/sent_syndicate_infiltration_team = 0 //Creates mind stuff. new_syndicate_infiltrator.mind_initialize() - new_syndicate_infiltrator.mind.assigned_role = "MODE" + new_syndicate_infiltrator.mind.assigned_role = "Syndicate Infiltrator" new_syndicate_infiltrator.mind.special_role = "Syndicate Infiltrator" ticker.mode.traitors |= new_syndicate_infiltrator.mind //Adds them to extra antag list new_syndicate_infiltrator.equip_syndicate_infiltrator(syndicate_leader_selected, uplink_tc, is_mgmt) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 9b6c4363008..a87308bb9b1 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -92,7 +92,7 @@ var/intercom_range_display_status = 0 if(!(locate(/obj/structure/grille,T))) var/window_check = 0 for(var/obj/structure/window/W in T) - if(W.dir == turn(C1.dir,180) || W.is_fulltile() ) + if(W.dir == turn(C1.dir,180) || W.fulltile) window_check = 1 break if(!window_check) diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index dfca07426c5..c1e28a48f8d 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -46,6 +46,8 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", else if(isfile(var_value)) . = VV_FILE + else if(istype(var_value, /regex)) + . = VV_REGEX else . = VV_NULL @@ -66,6 +68,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", VV_DATUM_TYPE, VV_TYPE, VV_MATRIX, + VV_REGEX, VV_FILE, VV_NEW_ATOM, VV_NEW_DATUM, @@ -141,6 +144,14 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", .["class"] = null return + if(VV_REGEX) + var/reg = input("Enter regex", "Regex", "") as null|text + if(!reg) + return + .["value"] = regex(reg) + if(.["value"] == null) + .["class"] = null + if(VV_ATOM_REFERENCE) var/type = pick_closest_path(FALSE) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 57e5b968178..5c8e1c77745 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -25,6 +25,22 @@ client/proc/one_click_antag() usr << browse(dat, "window=oneclickantag;size=400x400") return +/datum/admins/proc/CandCheck(var/role = null, var/mob/living/carbon/human/M, var/datum/game_mode/temp = null) + // You pass in ROLE define (optional), the applicant, and the gamemode, and it will return true / false depending on whether the applicant qualify for the candidacy in question + if(jobban_isbanned(M, "Syndicate")) + return FALSE + if(M.stat || !M.mind || M.mind.special_role) + return FALSE + if(temp) + if(M.mind.assigned_role in temp.restricted_jobs || M.client.prefs.species in temp.protected_species) + return FALSE + if(role) // Don't even bother evaluating if there's no role + if(player_old_enough_antag(M.client,role) && (role in M.client.prefs.be_special) && (!jobban_isbanned(M, role))) + return TRUE + else + return FALSE + else + return TRUE /datum/admins/proc/makeTraitors() var/datum/game_mode/traitor/temp = new @@ -35,35 +51,29 @@ client/proc/one_click_antag() var/list/mob/living/carbon/human/candidates = list() var/mob/living/carbon/human/H = null - log_admin("[key_name(owner)] tried making Traitors with One-Click-Antag") - message_admins("[key_name_admin(owner)] tried making Traitors with One-Click-Antag") + var/antnum = input(owner, "How many traitors you want to create? Enter 0 to cancel","Amount:", 0) as num + if(!antnum || antnum <= 0) + return + log_admin("[key_name(owner)] tried making [antnum] traitors with One-Click-Antag") + message_admins("[key_name_admin(owner)] tried making [antnum] traitors with One-Click-Antag") for(var/mob/living/carbon/human/applicant in player_list) - if(ROLE_TRAITOR in applicant.client.prefs.be_special) - if(player_old_enough_antag(applicant.client,ROLE_TRAITOR)) - if(!applicant.stat) - if(applicant.mind) - if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.mind.assigned_role in temp.restricted_jobs)) - if(!(applicant.client.prefs.species in temp.protected_species)) - candidates += applicant + if(CandCheck(ROLE_TRAITOR, applicant, temp)) + candidates += applicant if(candidates.len) - var/numTratiors = min(candidates.len, 3) + var/numTraitors = min(candidates.len, antnum) - for(var/i = 0, i300)//If more than 30 game seconds passed. + //Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. + for(var/mob/G in respawnable_list) + if(!jobban_isbanned(G, "Syndicate")) + spawn(0) + switch(alert(G,"Do you wish to be considered for an elite syndicate strike team being sent in?","Please answer in 30 seconds!","Yes","No")) + if("Yes") + if((world.time-time_passed)>300)//If more than 30 game seconds passed. + return + candidates += G + if("No") return - candidates += G - if("No") - return - else - return - sleep(300) + else + return + sleep(300) - for(var/mob/dead/observer/G in candidates) - if(!G.key) - candidates.Remove(G) + for(var/mob/dead/observer/G in candidates) + if(!G.key) + candidates.Remove(G) - if(candidates.len) - var/numagents = 6 - //Spawns commandos and equips them. - for(var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad) - if(numagents<=0) - break - if(L.name == "Syndicate-Commando") - syndicate_leader_selected = numagents == 1?1:0 - - var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - - - while((!theghost || !theghost.client) && candidates.len) - theghost = pick(candidates) - candidates.Remove(theghost) - - if(!theghost) - qdel(new_syndicate_commando) + if(candidates.len) + //Spawns commandos and equips them. + for(var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad) + if(antnum <= 0) break + if(L.name == "Syndicate-Commando") + syndicate_leader_selected = antnum == 1?1:0 - new_syndicate_commando.key = theghost.key - new_syndicate_commando.internal = new_syndicate_commando.s_store - new_syndicate_commando.update_action_buttons_icon() + var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - //So they don't forget their code or mission. + while((!theghost || !theghost.client) && candidates.len) + theghost = pick(candidates) + candidates.Remove(theghost) + + if(!theghost) + qdel(new_syndicate_commando) + break + + new_syndicate_commando.key = theghost.key + new_syndicate_commando.internal = new_syndicate_commando.s_store + new_syndicate_commando.update_action_buttons_icon() + + //So they don't forget their code or mission. - to_chat(new_syndicate_commando, "You are an Elite Syndicate. [!syndicate_leader_selected ? "commando" : "LEADER"] in the service of the Syndicate. \nYour current mission is: [input]") + to_chat(new_syndicate_commando, "You are an Elite Syndicate. [!syndicate_leader_selected ? "commando" : "LEADER"] in the service of the Syndicate. \nYour current mission is: [input]") - numagents-- - if(numagents >= 6) - return 0 - - for(var/obj/effect/landmark/L in /area/shuttle/syndicate_elite) - if(L.name == "Syndicate-Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) + antnum-- + for(var/obj/effect/landmark/L in /area/shuttle/syndicate_elite) + if(L.name == "Syndicate-Commando-Bomb") + new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) return 1 @@ -411,7 +413,7 @@ client/proc/one_click_antag() //Creates mind stuff. new_syndicate_commando.mind_initialize() - new_syndicate_commando.mind.assigned_role = "MODE" + new_syndicate_commando.mind.assigned_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD new_syndicate_commando.mind.special_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD //Adds them to current traitor list. Which is really the extra antagonist list. @@ -429,10 +431,12 @@ client/proc/one_click_antag() var/leader_chosen = 0 //when the leader is chosen. The last person spawned. + var/antnum = input(owner, "How many raiders you want to create? Enter 0 to cancel.","Amount:", 0) as num + if(!antnum || antnum <= 0) + return log_admin("[key_name(owner)] tried making Vox Raiders with One-Click-Antag") message_admins("[key_name_admin(owner)] tried making Vox Raiders with One-Click-Antag") - - //Generates a list of candidates from active ghosts. +//Generates a list of candidates from active ghosts. for(var/mob/G in respawnable_list) if(istype(G) && G.client && (ROLE_RAIDER in G.client.prefs.be_special)) if(player_old_enough_antag(G.client,ROLE_RAIDER)) @@ -455,8 +459,7 @@ client/proc/one_click_antag() candidates.Remove(G) if(candidates.len) - var/max_raiders = 1 - var/raiders = max_raiders + var/raiders = min(antnum, candidates.len) //Spawns vox raiders and equips them. for(var/obj/effect/landmark/L in world) if(L.name == "voxstart") @@ -480,8 +483,6 @@ client/proc/one_click_antag() to_chat(new_vox, "Don't forget to turn on your nitrogen internals!") raiders-- - if(raiders > max_raiders) - return 0 else return 0 return 1 @@ -534,32 +535,26 @@ client/proc/one_click_antag() var/list/mob/living/carbon/human/candidates = list() var/mob/living/carbon/human/H = null + var/antnum = input(owner, "How many vampires you want to create? Enter 0 to cancel","Amount:", 0) as num + if(!antnum || antnum <= 0) + return + log_admin("[key_name(owner)] tried making Vampires with One-Click-Antag") message_admins("[key_name_admin(owner)] tried making Vampires with One-Click-Antag") for(var/mob/living/carbon/human/applicant in player_list) - if(ROLE_VAMPIRE in applicant.client.prefs.be_special) - if(player_old_enough_antag(applicant.client,ROLE_VAMPIRE)) - if(!applicant.stat) - if(applicant.mind) - if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "vampire") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.job in temp.restricted_jobs)) - if(!(applicant.client.prefs.species in temp.protected_species)) - candidates += applicant + if(CandCheck(ROLE_VAMPIRE, applicant, temp)) + candidates += applicant if(candidates.len) - var/numVampires = min(candidates.len, 3) + var/numVampires = min(candidates.len, antnum) for(var/i = 0, iDirectNarrate: [key_name_admin(usr)] to ([key_name_admin(M)]): [msg]
", 1) feedback_add_details("admin_verb","DIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + + +/client/proc/cmd_admin_headset_message(mob/M in mob_list) + set category = "Event" + set name = "Headset Message" + + admin_headset_message(M) + +/client/proc/admin_headset_message(mob/M in mob_list, sender = null) + var/mob/living/carbon/human/H = M + + if(!check_rights(R_ADMIN)) + return + + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + if(!istype(H.l_ear, /obj/item/radio/headset) && !istype(H.r_ear, /obj/item/radio/headset)) + to_chat(usr, "The person you are trying to contact is not wearing a headset") + return + + if(!sender) + sender = input("Who is the message from?", "Sender") as null|anything in list("Centcomm", "Syndicate") + if(!sender) + return + + message_admins("[key_name_admin(src)] has started answering [key_name_admin(H)]'s [sender] request.") + var/input = input("Please enter a message to reply to [key_name(H)] via their headset.", "Outgoing message from [sender]", "") as text|null + if(!input) + message_admins("[key_name_admin(src)] decided not to answer [key_name_admin(H)]'s [sender] request.") + return + + log_admin("[key_name(src)] replied to [key_name(H)]'s [sender] message with the message [input].") + message_admins("[key_name_admin(src)] replied to [key_name_admin(H)]'s [sender] message with: \"[input]\"") + to_chat(H, "You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from [sender == "Syndicate" ? "your benefactor" : "Central Command"]. Message as follows[sender == "Syndicate" ? ", agent." : ":"] [input]. Message ends.\"") + + + + /client/proc/cmd_admin_godmode(mob/M as mob in mob_list) set category = "Admin" set name = "Godmode" @@ -429,7 +469,7 @@ Traitors and the like can also be revived with the previous role mostly intact. //Announces the character on all the systems, based on the record. if(!issilicon(new_character))//If they are not a cyborg/AI. - if(!record_found&&new_character.mind.assigned_role!="MODE")//If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway. + if(!record_found && new_character.mind.assigned_role != new_character.mind.special_role)//If there are no records for them. If they have a record, this info is already in there. Offstation special characters announced anyway. //Power to the user! if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes") data_core.manifest_inject(new_character) diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index d3c9ae98511..1e809bcd948 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -37,8 +37,8 @@ var/global/sent_strike_team = 0 break // Find ghosts willing to be DS - var/list/commando_ckeys = pollCandidatesByKeyWithVeto(src, usr, commandos_possible, "Join the DeathSquad?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) - if(!commando_ckeys.len) + var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, commandos_possible, "Join the DeathSquad?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) + if(!commando_ghosts.len) to_chat(usr, "Nobody volunteered to join the DeathSquad.") return @@ -47,53 +47,62 @@ var/global/sent_strike_team = 0 // Spawns commandos and equips them. var/commando_number = commandos_possible //for selecting a leader var/is_leader = TRUE // set to FALSE after leader is spawned + for(var/obj/effect/landmark/L in landmarks_list) - if(commando_number<=0) break + + if(commando_number <= 0) + break + if(L.name == "Commando") - spawn(0) - var/use_ds_borg = FALSE - var/ghost_key // Ghost ckey that we intend to put into the commando. Can remain undefined if we don't have one. - if(commando_ckeys.len) - ghost_key = pick(commando_ckeys) - commando_ckeys -= ghost_key - if(!is_leader) - var/new_gender = alert(src, "Select Deathsquad Type.", "DS Character Generation", "Organic", "Cyborg") - if(new_gender == "Cyborg") - use_ds_borg = TRUE + if(!commando_ghosts.len) + break - if(use_ds_borg) - var/mob/living/silicon/robot/deathsquad/R = new() - R.forceMove(get_turf(L)) - var/rnum = rand(1,1000) - var/borgname = "Epsilon [rnum]" - R.name = borgname - R.custom_name = borgname - R.real_name = R.name - R.mind = new - R.mind.current = R - R.mind.original = R - R.mind.assigned_role = "MODE" - R.mind.special_role = SPECIAL_ROLE_DEATHSQUAD - if(!(R.mind in ticker.minds)) - ticker.minds += R.mind - ticker.mode.traitors += R.mind - if(ghost_key) - R.key = ghost_key - if(nuke_code) - R.mind.store_memory("Nuke Code: [nuke_code].") - R.mind.store_memory("Mission: [input].") - to_chat(R, "You are a Special Operations cyborg, in the service of Central Command. \nYour current mission is: [input]") - else - var/mob/living/carbon/human/new_commando = create_death_commando(L, is_leader) - if(ghost_key) - new_commando.key = ghost_key - new_commando.internal = new_commando.s_store - new_commando.update_action_buttons_icon() - if(nuke_code) - new_commando.mind.store_memory("Nuke Code: [nuke_code].") - new_commando.mind.store_memory("Mission: [input].") - to_chat(new_commando, "You are a Special Ops [is_leader ? "TEAM LEADER" : "commando"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: [input]") + var/use_ds_borg = FALSE + var/mob/ghost_mob = pick(commando_ghosts) + commando_ghosts -= ghost_mob + if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) + continue + + if(!is_leader) + var/new_dstype = alert(ghost_mob.client, "Select Deathsquad Type.", "DS Character Generation", "Organic", "Cyborg") + if(new_dstype == "Cyborg") + use_ds_borg = TRUE + + if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) // Have to re-check this due to the above alert() call + continue + + if(use_ds_borg) + var/mob/living/silicon/robot/deathsquad/R = new() + R.forceMove(get_turf(L)) + var/rnum = rand(1,1000) + var/borgname = "Epsilon [rnum]" + R.name = borgname + R.custom_name = borgname + R.real_name = R.name + R.mind = new + R.mind.current = R + R.mind.original = R + R.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD + R.mind.special_role = SPECIAL_ROLE_DEATHSQUAD + if(!(R.mind in ticker.minds)) + ticker.minds += R.mind + ticker.mode.traitors += R.mind + R.key = ghost_mob.key + if(nuke_code) + R.mind.store_memory("Nuke Code: [nuke_code].") + R.mind.store_memory("Mission: [input].") + to_chat(R, "You are a Special Operations cyborg, in the service of Central Command. \nYour current mission is: [input]") + else + var/mob/living/carbon/human/new_commando = create_death_commando(L, is_leader) + new_commando.mind.key = ghost_mob.key + new_commando.key = ghost_mob.key + new_commando.internal = new_commando.s_store + new_commando.update_action_buttons_icon() + if(nuke_code) + new_commando.mind.store_memory("Nuke Code: [nuke_code].") + new_commando.mind.store_memory("Mission: [input].") + to_chat(new_commando, "You are a Special Ops [is_leader ? "TEAM LEADER" : "commando"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: [input]") is_leader = FALSE commando_number-- @@ -133,11 +142,12 @@ var/global/sent_strike_team = 0 A.real_name = "[commando_rank] [commando_name]" A.copy_to(new_commando) + new_commando.dna.ready_dna(new_commando)//Creates DNA. //Creates mind stuff. new_commando.mind_initialize() - new_commando.mind.assigned_role = "MODE" + new_commando.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD new_commando.mind.special_role = SPECIAL_ROLE_DEATHSQUAD ticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list. new_commando.equip_death_commando(is_leader) diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index cc52adf40c6..c5f46c98592 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -45,8 +45,8 @@ var/global/sent_syndicate_strike_team = 0 break // Find ghosts willing to be SST - var/list/commando_ckeys = pollCandidatesByKeyWithVeto(src, usr, syndicate_commandos_possible, "Join the Syndicate Strike Team?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) - if(!commando_ckeys.len) + var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, syndicate_commandos_possible, "Join the Syndicate Strike Team?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) + if(!commando_ghosts.len) to_chat(usr, "Nobody volunteered to join the SST.") return @@ -54,15 +54,29 @@ var/global/sent_syndicate_strike_team = 0 //Spawns commandos and equips them. for(var/obj/effect/landmark/L in landmarks_list) - if(syndicate_commando_number<=0) break + + if(syndicate_commando_number <= 0) + break + if(L.name == "Syndicate-Commando") + + if(!commando_ghosts.len) + break + + var/mob/ghost_mob = pick(commando_ghosts) + commando_ghosts -= ghost_mob + + if(!ghost_mob || !ghost_mob.key || !ghost_mob.client) + continue + var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, is_leader) - if(commando_ckeys.len) - new_syndicate_commando.key = pick(commando_ckeys) - commando_ckeys -= new_syndicate_commando.key - new_syndicate_commando.internal = new_syndicate_commando.s_store - new_syndicate_commando.update_action_buttons_icon() + if(!new_syndicate_commando) + continue + + new_syndicate_commando.key = ghost_mob.key + new_syndicate_commando.internal = new_syndicate_commando.s_store + new_syndicate_commando.update_action_buttons_icon() //So they don't forget their code or mission. if(nuke_code) @@ -101,7 +115,7 @@ var/global/sent_syndicate_strike_team = 0 //Creates mind stuff. new_syndicate_commando.mind_initialize() - new_syndicate_commando.mind.assigned_role = "MODE" + new_syndicate_commando.mind.assigned_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD new_syndicate_commando.mind.special_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD ticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list. new_syndicate_commando.equip_syndicate_commando(is_leader) diff --git a/code/modules/alarm/alarm.dm b/code/modules/alarm/alarm.dm index ac8b65d9d82..1d4a570999a 100644 --- a/code/modules/alarm/alarm.dm +++ b/code/modules/alarm/alarm.dm @@ -134,5 +134,3 @@ /mob/living/silicon/robot/syndicate/get_alarm_cameras() return list() - -#undef ALARM_LOSS_DELAY diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm new file mode 100644 index 00000000000..39053fa79d9 --- /dev/null +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -0,0 +1,137 @@ +GLOBAL_LIST_EMPTY(antagonists) + +/datum/antagonist + var/name = "Antagonist" + var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section + var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report + var/datum/mind/owner //Mind that owns this datum + var/silent = FALSE //Silent will prevent the gain/lose texts to show + var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum + var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with + var/delete_on_mind_deletion = TRUE + var/job_rank + var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted. + var/list/objectives = list() + var/antag_memory = ""//These will be removed with antag datum + +/datum/antagonist/New() + GLOB.antagonists += src + typecache_datum_blacklist = typecacheof(typecache_datum_blacklist) + +/datum/antagonist/Destroy() + GLOB.antagonists -= src + if(owner) + LAZYREMOVE(owner.antag_datums, src) + owner = null + return ..() + +/datum/antagonist/proc/can_be_owned(datum/mind/new_owner) + . = TRUE + var/datum/mind/tested = new_owner || owner + if(tested.has_antag_datum(type)) + return FALSE + for(var/i in tested.antag_datums) + var/datum/antagonist/A = i + if(is_type_in_typecache(src, A.typecache_datum_blacklist)) + return FALSE + +//This will be called in add_antag_datum before owner assignment. +//Should return antag datum without owner. +/datum/antagonist/proc/specialization(datum/mind/new_owner) + return src + +/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body) + remove_innate_effects(old_body) + apply_innate_effects(new_body) + +//This handles the application of antag huds/special abilities +/datum/antagonist/proc/apply_innate_effects(mob/living/mob_override) + return + +//This handles the removal of antag huds/special abilities +/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override) + return + +//Assign default team and creates one for one of a kind team antagonists +/datum/antagonist/proc/create_team(datum/team/team) + return + +//Proc called when the datum is given to a mind. +/datum/antagonist/proc/on_gain() + if(owner && owner.current) + if(!silent) + greet() + apply_innate_effects() + if(is_banned(owner.current) && replace_banned) + replace_banned_player() + +/datum/antagonist/proc/is_banned(mob/M) + if(!M) + return FALSE + . = (jobban_isbanned(M, ROLE_SYNDICATE) || (job_rank && jobban_isbanned(M, job_rank))) + +/datum/antagonist/proc/replace_banned_player() + set waitfor = FALSE + + var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a [name]?", job_rank, TRUE, 50) + if(LAZYLEN(candidates)) + var/mob/dead/observer/C = pick(candidates) + to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") + message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.") + owner.current.ghostize(0) + owner.current.key = C.key + +/datum/antagonist/proc/on_removal() + remove_innate_effects() + if(owner) + LAZYREMOVE(owner.antag_datums, src) + if(!silent && owner.current) + farewell() + owner.objectives -= objectives + var/datum/team/team = get_team() + if(team) + team.remove_member(owner) + qdel(src) + +/datum/antagonist/proc/greet() + return + +/datum/antagonist/proc/farewell() + return + + +//Returns the team antagonist belongs to if any. +/datum/antagonist/proc/get_team() + return + +//Individual roundend report +/datum/antagonist/proc/roundend_report() + var/list/report = list() + + if(!owner) + CRASH("antagonist datum without owner") + + report += printplayer(owner) + + var/objectives_complete = TRUE + if(owner.objectives.len) + report += printobjectives(owner) + for(var/datum/objective/objective in owner.objectives) + if(!objective.check_completion()) + objectives_complete = FALSE + break + + if(owner.objectives.len == 0 || objectives_complete) + report += "The [name] was successful!" + else + report += "The [name] has failed!" + + return report.Join("
") + +//Displayed at the start of roundend_category section, default to roundend_category header +/datum/antagonist/proc/roundend_report_header() + return "The [roundend_category] were:
" + +//Displayed at the end of roundend_category section +/datum/antagonist/proc/roundend_report_footer() + return \ No newline at end of file diff --git a/code/modules/antagonists/_common/antag_helpers.dm b/code/modules/antagonists/_common/antag_helpers.dm new file mode 100644 index 00000000000..134ba1d7d90 --- /dev/null +++ b/code/modules/antagonists/_common/antag_helpers.dm @@ -0,0 +1,19 @@ +//Returns MINDS of the assigned antags of given type/subtypes +/proc/get_antag_minds(antag_type, specific = FALSE) + . = list() + for(var/datum/antagonist/A in GLOB.antagonists) + if(!A.owner) + continue + if(!antag_type || !specific && istype(A, antag_type) || specific && A.type == antag_type) + . += A.owner + +//Get all teams [of type team_type] +/proc/get_all_teams(team_type) + . = list() + for(var/V in GLOB.antagonists) + var/datum/antagonist/A = V + if(!A.owner) + continue + var/datum/team/T = A.get_team() + if(!team_type || istype(T, team_type)) + . |= T \ No newline at end of file diff --git a/code/game/gamemodes/antag_hud.dm b/code/modules/antagonists/_common/antag_hud.dm similarity index 78% rename from code/game/gamemodes/antag_hud.dm rename to code/modules/antagonists/_common/antag_hud.dm index 4b290932e8e..693b0b9450d 100644 --- a/code/game/gamemodes/antag_hud.dm +++ b/code/modules/antagonists/_common/antag_hud.dm @@ -1,11 +1,12 @@ /datum/atom_hud/antag hud_icons = list(SPECIALROLE_HUD,NATIONS_HUD) - var/self_visible = 1 + var/self_visible = TRUE /datum/atom_hud/antag/hidden - self_visible = 0 + self_visible = FALSE -/datum/atom_hud/antag/proc/join_hud(mob/M,var/slave) +/datum/atom_hud/antag/proc/join_hud(mob/M, slave) + //sees_hud should be set to 0 if the mob does not get to see it's own hud type. if(!istype(M)) CRASH("join_hud(): [M] ([M.type]) is not a mob!") if(M.mind.antag_hud && !slave) //note: please let this runtime if a mob has no mind, as mindless mobs shouldn't be getting antagged @@ -16,6 +17,8 @@ M.mind.antag_hud = src /datum/atom_hud/antag/proc/leave_hud(mob/M) + if(!M) + return if(!istype(M)) CRASH("leave_hud(): [M] ([M.type]) is not a mob!") remove_from_hud(M) @@ -26,7 +29,7 @@ //GAME_MODE PROCS //called to set a mob's antag icon state -/datum/game_mode/proc/set_antag_hud(mob/M, new_icon_state) +/proc/set_antag_hud(mob/M, new_icon_state) if(!istype(M)) CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!") var/image/holder = M.hud_list[SPECIALROLE_HUD] @@ -36,7 +39,7 @@ M.mind.antag_hud_icon_state = new_icon_state //Nations Icons -/datum/game_mode/proc/set_nations_hud(mob/M, new_icon_state) +/proc/set_nations_hud(mob/M, new_icon_state) if(!istype(M)) CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!") var/image/holder = M.hud_list[NATIONS_HUD] @@ -47,9 +50,9 @@ //MIND PROCS //these are called by mind.transfer_to() -/datum/mind/proc/transfer_antag_huds(var/datum/atom_hud/antag/newhud) +/datum/mind/proc/transfer_antag_huds(datum/atom_hud/antag/newhud) leave_all_huds() - ticker.mode.set_antag_hud(current, antag_hud_icon_state) + set_antag_hud(current, antag_hud_icon_state) if(newhud) newhud.join_hud(current) @@ -77,11 +80,11 @@ name = mastername thrallhud = new() -/datum/mindslaves/proc/add_serv_hud(datum/mind/serv_mind,var/icon) - thrallhud.join_hud(serv_mind.current,1) +/datum/mindslaves/proc/add_serv_hud(datum/mind/serv_mind, icon) + thrallhud.join_hud(serv_mind.current, 1) icontype = "hud[icon]" - ticker.mode.set_antag_hud(serv_mind.current,icontype) + set_antag_hud(serv_mind.current, icontype) /datum/mindslaves/proc/leave_serv_hud(datum/mind/free_mind) thrallhud.leave_hud(free_mind.current) - ticker.mode.set_antag_hud(free_mind.current,null) \ No newline at end of file + set_antag_hud(free_mind.current, null) \ No newline at end of file diff --git a/code/game/gamemodes/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm similarity index 89% rename from code/game/gamemodes/antag_spawner.dm rename to code/modules/antagonists/_common/antag_spawner.dm index 23fed691ec6..c81f30efc83 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -2,12 +2,12 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - var/used = 0 + var/used = FALSE -/obj/item/antag_spawner/proc/spawn_antag(var/client/C, var/turf/T, var/type = "") +/obj/item/antag_spawner/proc/spawn_antag(client/C, turf/T, type = "") return -/obj/item/antag_spawner/proc/equip_antag(mob/target as mob) +/obj/item/antag_spawner/proc/equip_antag(mob/target) return @@ -16,41 +16,41 @@ desc = "A single-use teleporter used to deploy a Syndicate Cyborg on the field." icon = 'icons/obj/device.dmi' icon_state = "locator" - var/checking = 0 + var/checking = FALSE var/TC_cost = 0 var/borg_to_spawn var/list/possible_types = list("Assault", "Medical") -/obj/item/antag_spawner/borg_tele/attack_self(mob/user as mob) +/obj/item/antag_spawner/borg_tele/attack_self(mob/user) if(used) to_chat(user, "[src] is out of power!") return if(!(user.mind in ticker.mode.syndicates)) to_chat(user, "AUTHENTICATION FAILURE. ACCESS DENIED.") - return 0 + return FALSE if(checking) to_chat(user, "[src] is already checking for possible borgs.") return borg_to_spawn = input("What type of borg would you like to teleport?", "Cyborg Type", type) as null|anything in possible_types if(!borg_to_spawn || checking || used) return - checking = 1 + checking = TRUE to_chat(user, "The device is now checking for possible borgs.") var/list/borg_candidates = pollCandidates("Do you want to play as a Syndicate [borg_to_spawn] borg?", ROLE_OPERATIVE, 1) if(borg_candidates.len > 0 && !used) - checking = 0 - used = 1 + checking = FALSE + used = TRUE var/mob/M = pick(borg_candidates) var/client/C = M.client spawn_antag(C, get_turf(src.loc), "syndieborg") else - checking = 0 + checking = FALSE to_chat(user, "Unable to connect to Syndicate command. Please wait and try again later or use the teleporter on your uplink to get your points refunded.") return -/obj/item/antag_spawner/borg_tele/spawn_antag(var/client/C, var/turf/T, var/type = "") +/obj/item/antag_spawner/borg_tele/spawn_antag(client/C, turf/T, type = "") if(!borg_to_spawn) //If there's no type at all, let it still be used but don't do anything - used = 0 + used = FALSE return var/datum/effect_system/spark_spread/S = new /datum/effect_system/spark_spread S.set_up(4, 1, src) @@ -79,7 +79,7 @@ var/objective_verb = "Kill" var/mob/living/demon_type = /mob/living/simple_animal/slaughter -/obj/item/antag_spawner/slaughter_demon/attack_self(mob/user as mob) +/obj/item/antag_spawner/slaughter_demon/attack_self(mob/user) if(level_blocks_magic(user.z))//this is to make sure the wizard does NOT summon a demon from the Den.. to_chat(user, "You should probably wait until you reach the station.") return @@ -87,7 +87,7 @@ if(used) to_chat(user, "This bottle already has a broken seal.") return - used = 1 + used = TRUE to_chat(user, "You break the seal on the bottle, calling upon the dire spirits of the underworld...") var/list/candidates = pollCandidates("Do you want to play as a slaughter demon summoned by [user.real_name]?", ROLE_DEMON, 1, 100) @@ -100,10 +100,10 @@ playsound(user.loc, 'sound/effects/Glassbr1.ogg', 100, 1) qdel(src) else - used = 0 + used = FALSE to_chat(user, "The demons do not respond to your summon. Perhaps you should try again later.") -/obj/item/antag_spawner/slaughter_demon/spawn_antag(var/client/C, var/turf/T, var/type = "", mob/user as mob) +/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", mob/user) var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T) var/mob/living/simple_animal/slaughter/S = new demon_type(holder) S.vialspawned = TRUE diff --git a/code/modules/antagonists/_common/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm new file mode 100644 index 00000000000..9dcec5894ee --- /dev/null +++ b/code/modules/antagonists/_common/antag_team.dm @@ -0,0 +1,24 @@ +//A barebones antagonist team. +/datum/team + var/list/datum/mind/members = list() + var/name = "team" + var/member_name = "member" + var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes. + +/datum/team/New(starting_members) + . = ..() + if(starting_members) + if(islist(starting_members)) + for(var/datum/mind/M in starting_members) + add_member(M) + else + add_member(starting_members) + +/datum/team/proc/is_solo() + return members.len == 1 + +/datum/team/proc/add_member(datum/mind/new_member) + members |= new_member + +/datum/team/proc/remove_member(datum/mind/member) + members -= member diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm new file mode 100644 index 00000000000..54d12867ac1 --- /dev/null +++ b/code/modules/antagonists/wishgranter/wishgranter.dm @@ -0,0 +1,81 @@ +/datum/antagonist/wishgranter + name = "Wishgranter Avatar" + +/datum/antagonist/wishgranter/proc/forge_objectives() + var/datum/objective/hijack/hijack = new + hijack.owner = owner + objectives += hijack + owner.objectives |= objectives + +/datum/antagonist/wishgranter/on_gain() + owner.special_role = "Avatar of the Wish Granter" + forge_objectives() + . = ..() + give_powers() + +/datum/antagonist/wishgranter/greet() + to_chat(owner.current, "Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!") + owner.announce_objectives() + +/datum/antagonist/wishgranter/proc/give_powers() + var/mob/living/carbon/human/H = owner.current + if(!istype(H)) + return + H.ignore_gene_stability = TRUE + H.dna.SetSEState(HULKBLOCK, TRUE) + genemutcheck(H, HULKBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(XRAYBLOCK, TRUE) + genemutcheck(H, XRAYBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(FIREBLOCK, TRUE) + genemutcheck(H, FIREBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(COLDBLOCK, TRUE) + genemutcheck(H, COLDBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(TELEBLOCK, TRUE) + genemutcheck(H, TELEBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(INCREASERUNBLOCK, TRUE) + genemutcheck(H, INCREASERUNBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(BREATHLESSBLOCK, TRUE) + genemutcheck(H, BREATHLESSBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(REGENERATEBLOCK, TRUE) + genemutcheck(H, REGENERATEBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SHOCKIMMUNITYBLOCK, TRUE) + genemutcheck(H, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SMALLSIZEBLOCK, TRUE) + genemutcheck(H, SMALLSIZEBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SOBERBLOCK, TRUE) + genemutcheck(H, SOBERBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(PSYRESISTBLOCK, TRUE) + genemutcheck(H, PSYRESISTBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SHADOWBLOCK, TRUE) + genemutcheck(H, SHADOWBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(CRYOBLOCK, TRUE) + genemutcheck(H, CRYOBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(EATBLOCK, TRUE) + genemutcheck(H, EATBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(JUMPBLOCK, TRUE) + genemutcheck(H, JUMPBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(SUPERFARTBLOCK, TRUE) + genemutcheck(H, SUPERFARTBLOCK, null, MUTCHK_FORCED) + + H.dna.SetSEState(IMMOLATEBLOCK, TRUE) + genemutcheck(H, IMMOLATEBLOCK, null, MUTCHK_FORCED) + + H.mutations.Add(LASER) + H.update_mutations() + H.update_body() \ No newline at end of file diff --git a/code/modules/arcade/arcade_prize.dm b/code/modules/arcade/arcade_prize.dm index 6af1ca30f36..94c265848b7 100644 --- a/code/modules/arcade/arcade_prize.dm +++ b/code/modules/arcade/arcade_prize.dm @@ -2,7 +2,6 @@ * Prize balls * Prize tickets */ - /obj/item/toy/prizeball name = "prize ball" desc = "A toy is a toy, but a prize ball could be anything! It could even be a toy!" @@ -25,7 +24,7 @@ var/prize_inside = pick(possible_contents) spawn(10) user.unEquip(src) - if(istype(prize_inside, /obj/item/stack)) + if(ispath(prize_inside,/obj/item/stack)) var/amount = pick(5, 10, 15, 25, 50) new prize_inside(user.loc, amount) else @@ -78,12 +77,12 @@ return /obj/item/stack/tickets/update_icon() - var/amount = get_amount() - if((amount >= 75)) - icon_state = "tickets_4" - else if(amount >=25) - icon_state = "tickets_3" - else if(amount >= 4) - icon_state = "tickets_2" - else - icon_state = "tickets_1" + switch(get_amount()) + if(1 to 3) + icon_state = "tickets_1" // One ticket + if(4 to 24) + icon_state = "tickets_2" // Couple tickets + if(25 to 74) + icon_state = "tickets_3" // Buncha tickets + else + icon_state = "tickets_4" // Ticket snake \ No newline at end of file diff --git a/code/modules/arcade/prize_counter.dm b/code/modules/arcade/prize_counter.dm index 07a3af17ec1..4e2e4e9a0d7 100644 --- a/code/modules/arcade/prize_counter.dm +++ b/code/modules/arcade/prize_counter.dm @@ -80,53 +80,60 @@ html { color:#999; } +table {background:#303030;border:1px solid #262626;} + +caption {text-align:left;} + +.button { + color:#cfcfcf; + text-decoration:none; + font-weight:bold; + text-align:center; + width:75px; + padding:21px; + box-sizing:border-box; + background:none; + border:none; + display: inline-block; +} +.button:hover {color:#ffffff;} + a { color:#cfcfcf; text-decoration:none; font-weight:bold; } +a:hover {color:#ffffff;} -a:hover { - color:#ffffff; -} -tr { - background:#303030; - border-radius:6px; - margin-bottom:0.5em; - border-bottom:1px solid black; -} -tr:nth-child(even) { - background:#3f3f3f; -} +p {margin:0;} -td.cost { - font-size:20pt; - font-weight:bold; -} +tr.dark {background:#303030;} -td.cost.affordable { - background:green; -} +tr.light {background:#3f3f3f;} -td.cost.toomuch { - background:maroon; -} +td,th {padding:15px;border-bottom:1px solid #262626;} +th.cost{padding:0px;border-left:1px solid #262626;} + +th.cost.affordable {background:green;} + +th.cost.toomuch {background:maroon;} -

Tickets: [tickets] | Eject Tickets

+

Tickets: [tickets] | Eject Tickets

Arcade Ticket Exchange

Exchange that pile of tickets for a pile of cool prizes!

-

Available Prizes:

+
+ - + "} @@ -136,8 +143,11 @@ td.cost.toomuch { if(item.cost>tickets) cost_class="toomuch" var/itemID = global_prizes.prizes.Find(item) + var/row_color="light" + if(itemID%2 == 0) + row_color="dark" dat += {" - + @@ -147,10 +157,10 @@ td.cost.toomuch { "} dat += {" - - + + "} dat += {" @@ -158,7 +168,7 @@ td.cost.toomuch {
Available Prizes:
# Name/DescriptionPriceTickets
[itemID] - [item.cost] Tickets -
+ [item.cost] +
"} - user << browse(dat, "window=prize_counter") + user << browse(dat, "window=prize_counter;size=440x600;can_resize=0") onclose(user, "prize_counter") return diff --git a/code/modules/arcade/prize_datums.dm b/code/modules/arcade/prize_datums.dm index bf57195d207..3fa097bb03a 100644 --- a/code/modules/arcade/prize_datums.dm +++ b/code/modules/arcade/prize_datums.dm @@ -34,7 +34,7 @@ var/global/datum/prizes/global_prizes = new var/cost = 0 ////////////////////////////////////// -// Tier 1 Prizes // +// Prizes // ////////////////////////////////////// /datum/prize_item/balloon @@ -43,18 +43,6 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/toy/balloon cost = 10 -/datum/prize_item/crayons - name = "Box of Crayons" - desc = "A six-pack of crayons, just like back in kindergarten." - typepath = /obj/item/storage/fancy/crayons - cost = 35 - -/datum/prize_item/snappops - name = "Snap-Pops" - desc = "A box of exploding snap-pop fireworks." - typepath = /obj/item/storage/box/snappops - cost = 20 - /datum/prize_item/spinningtoy name = "Spinning Toy" desc = "Looks like an authentic Singularity!" @@ -62,46 +50,52 @@ var/global/datum/prizes/global_prizes = new cost = 15 /datum/prize_item/blinktoy - name = "Blink toy" + name = "Blink Toy" desc = "Blink. Blink. Blink." typepath = /obj/item/toy/blink cost = 15 /datum/prize_item/dice - name = "Dice set" + name = "Dice Set" desc = "A set of assorted dice." typepath = /obj/item/storage/box/dice cost = 20 -/datum/prize_item/cards - name = "Deck of cards" - desc = "Anyone fancy a game of 52-card Pickup?" - typepath = /obj/item/toy/cards/deck - cost = 25 - -/datum/prize_item/wallet - name = "Colored Wallet" - desc = "Brightly colored and big enough for standard issue ID cards." - typepath = /obj/item/storage/wallet/color - cost = 50 - -/datum/prize_item/pet_rock - name = "pet rock" - desc = "A pet of your very own!" - typepath = /obj/item/toy/pet_rock - cost = 80 - /datum/prize_item/foam_darts name = "Pack of Foam Darts" desc = "A refill pack with foam darts." typepath = /obj/item/ammo_box/foambox cost = 20 -/datum/prize_item/minigibber - name = "Minigibber Toy" - desc = "A model of the station gibber. Probably shouldn't stick your fingers in it." - typepath = /obj/item/toy/minigibber - cost = 60 +/datum/prize_item/snappops + name = "Snap-Pops" + desc = "A box of exploding snap-pop fireworks." + typepath = /obj/item/storage/box/snappops + cost = 20 + +/datum/prize_item/cards + name = "Deck of Cards" + desc = "Anyone fancy a game of 52-card Pickup?" + typepath = /obj/item/toy/cards/deck + cost = 25 + +/datum/prize_item/crayons + name = "Box of Crayons" + desc = "A six-pack of crayons, just like back in kindergarten." + typepath = /obj/item/storage/fancy/crayons + cost = 35 + +/datum/prize_item/eight_ball + name = "Magic Eight Ball" + desc = "A mystical ball that can divine the future!" + typepath = /obj/item/toy/eight_ball + cost = 40 + +/datum/prize_item/wallet + name = "Colored Wallet" + desc = "Brightly colored and big enough for standard issue ID cards." + typepath = /obj/item/storage/wallet/color + cost = 50 /datum/prize_item/id_sticker name = "Prisoner ID Sticker" @@ -129,11 +123,17 @@ var/global/datum/prizes/global_prizes = new desc = "A sticker that can make any ID look like something suspicious..." typepath = /obj/item/id_decal/emag -/datum/prize_item/carp_plushie - name = "Random Carp Plushie" - desc = "A colorful fish-shaped plush toy." - typepath = /obj/item/toy/prizeball/carp_plushie - cost = 75 +/datum/prize_item/flash + name = "Toy Flash" + desc = "AUGH! MY EYES!" + typepath = /obj/item/toy/flash + cost = 50 + +/datum/prize_item/minimeteor + name = "Mini-Meteor" + desc = "Meteors have been detected on a collision course with your fun times!" + typepath = /obj/item/toy/minimeteor + cost = 50 /datum/prize_item/therapy_doll name = "Random Therapy Doll" @@ -141,12 +141,30 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/toy/prizeball/therapy cost = 60 +/datum/prize_item/minigibber + name = "Minigibber Toy" + desc = "A model of the station gibber. Probably shouldn't stick your fingers in it." + typepath = /obj/item/toy/minigibber + cost = 60 + +/datum/prize_item/confetti + name = "Confetti Grenade" + desc = "Party time!" + typepath = /obj/item/grenade/confetti + cost = 65 + /datum/prize_item/plushie name = "Random Animal Plushie" desc = "A colorful animal-shaped plush toy." typepath = /obj/item/toy/prizeball/plushie cost = 75 +/datum/prize_item/carp_plushie + name = "Random Carp Plushie" + desc = "A colorful fish-shaped plush toy." + typepath = /obj/item/toy/prizeball/carp_plushie + cost = 75 + /datum/prize_item/mech_toy name = "Random Mecha" desc = "A random mecha figure, collect all 11!" @@ -159,42 +177,11 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/toy/prizeball/figure cost = 75 -/datum/prize_item/eight_ball - name = "Magic Eight Ball" - desc = "A mystical ball that can divine the future!" - typepath = /obj/item/toy/eight_ball - cost = 40 - -/datum/prize_item/tacticool - name = "Tacticool Turtleneck" - desc = "A cool-looking turtleneck." - typepath = /obj/item/clothing/under/syndicate/tacticool - cost = 90 - -/datum/prize_item/crossbow - name = "Foam Dart Crossbow" - desc = "A toy crossbow that fires foam darts." - typepath = /obj/item/gun/projectile/shotgun/toy/crossbow - cost = 100 - - -/datum/prize_item/toy_xeno - name = "Xeno Action Figure" - desc = "A lifelike replica of the horrific xeno scourge." - typepath = /obj/item/toy/toy_xeno - cost = 80 - -/datum/prize_item/fakespell - name = "Fake Spellbook" - desc = "Perform magic! Astound your friends! Get mistaken for an enemy of the corporation!" - typepath = /obj/item/spellbook/oneuse/fake_gib - cost = 100 - -/datum/prize_item/nanomob_booster - name = "Nano-Mob Hunter Trading Card Booster Pack" - desc = "Contains 6 random Nano-Mob Hunter Trading Cards. May contain a holographic card!" - typepath = /obj/item/storage/box/nanomob_booster_pack - cost = 100 +/datum/prize_item/AI + name = "Toy AI Unit" + desc = "Law 1: Maximize fun for crew." + typepath = /obj/item/toy/AI + cost = 75 /datum/prize_item/capgun name = "Capgun Revolver" @@ -202,11 +189,35 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/gun/projectile/revolver/capgun cost = 75 -/datum/prize_item/confetti - name = "Confetti Grenade" - desc = "Party time!" - typepath = /obj/item/grenade/confetti - cost = 65 +/datum/prize_item/pet_rock + name = "Pet Rock" + desc = "A pet of your very own!" + typepath = /obj/item/toy/pet_rock + cost = 80 + +/datum/prize_item/toy_xeno + name = "Xeno Action Figure" + desc = "A lifelike replica of the horrific xeno scourge." + typepath = /obj/item/toy/toy_xeno + cost = 80 + +/datum/prize_item/tacticool + name = "Tacticool Turtleneck" + desc = "A cool-looking turtleneck." + typepath = /obj/item/clothing/under/syndicate/tacticool + cost = 90 + +/datum/prize_item/nanomob_booster + name = "Nano-Mob Hunter Trading Card Booster Pack" + desc = "Contains 6 random Nano-Mob Hunter Trading Cards. May contain a holographic card!" + typepath = /obj/item/storage/box/nanomob_booster_pack + cost = 100 + +/datum/prize_item/fakespell + name = "Fake Spellbook" + desc = "Perform magic! Astound your friends! Get mistaken for an enemy of the corporation!" + typepath = /obj/item/spellbook/oneuse/fake_gib + cost = 100 /datum/prize_item/magic_conch name = "Magic Conch Shell" @@ -214,30 +225,36 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/toy/eight_ball/conch cost = 100 -/datum/prize_item/flash - name = "Toy Flash" - desc = "AUGH! MY EYES!" - typepath = /obj/item/toy/flash - cost = 50 +/datum/prize_item/crossbow + name = "Foam Dart Crossbow" + desc = "A toy crossbow that fires foam darts." + typepath = /obj/item/gun/projectile/shotgun/toy/crossbow + cost = 100 /datum/prize_item/foamblade - name = "Foam Armblade" + name = "Foam Arm Blade" desc = "Perfect for reenacting space horror holo-vids." typepath = /obj/item/toy/foamblade cost = 100 -/datum/prize_item/minimeteor - name = "Mini-Meteor" - desc = "Meteors have been detected on a collision course with your fun times!" - typepath = /obj/item/toy/minimeteor - cost = 50 - /datum/prize_item/redbutton name = "Shiny Red Button" desc = "PRESS IT!" typepath = /obj/item/toy/redbutton cost = 100 +/datum/prize_item/nuke + name = "Nuclear Fun Device" + desc = "Annihilate boredom with an explosion of excitement!" + typepath = /obj/item/toy/nuke + cost = 100 + +/datum/prize_item/blobhat + name = "Blob Hat" + desc = "There's... something... on your head..." + typepath = /obj/item/clothing/head/blob + cost = 125 + /datum/prize_item/owl name = "Owl Action Figure" desc = "Remember: heroes don't grief!" @@ -250,48 +267,12 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/toy/griffin cost = 125 -/datum/prize_item/AI - name = "Toy AI Unit" - desc = "Law 1: Maximize fun for crew." - typepath = /obj/item/toy/AI - cost = 75 - -/datum/prize_item/tommygun - name = "Tommygun" - desc = "A replica tommygun that fires foam darts." - typepath = /obj/item/gun/projectile/shotgun/toy/tommygun - cost = 175 - /datum/prize_item/esword name = "Toy Energy Sword" desc = "A plastic replica of an energy blade." typepath = /obj/item/toy/sword cost = 150 -/datum/prize_item/blobhat - name = "Blob Hat" - desc = "There's... something... on your head..." - typepath = /obj/item/clothing/head/blob - cost = 125 - -/datum/prize_item/nuke - name = "Nuclear Fun Device" - desc = "Annihilate boredom with an explosion of excitement!" - typepath = /obj/item/toy/nuke - cost = 100 - -/datum/prize_item/chainsaw - name = "Toy Chainsaw" - desc = "A full-scale model chainsaw, based on that massacre in Space Texas." - typepath = /obj/item/twohanded/toy/chainsaw - cost = 200 - -/datum/prize_item/spacesuit - name = "Fake Spacesuit" - desc = "A replica spacesuit. Not actually spaceworthy." - typepath = /obj/item/storage/box/fakesyndiesuit - cost = 180 - /datum/prize_item/fakespace name = "Space Carpet" desc = "A stack of carpeted floor tiles that resemble space." @@ -304,6 +285,24 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/stack/tile/arcade_carpet/loaded cost = 150 +/datum/prize_item/tommygun + name = "Tommy Gun" + desc = "A replica tommy gun that fires foam darts." + typepath = /obj/item/gun/projectile/shotgun/toy/tommygun + cost = 175 + +/datum/prize_item/spacesuit + name = "Fake Spacesuit" + desc = "A replica spacesuit. Not actually spaceworthy." + typepath = /obj/item/storage/box/fakesyndiesuit + cost = 180 + +/datum/prize_item/chainsaw + name = "Toy Chainsaw" + desc = "A full-scale model chainsaw, based on that massacre in Space Texas." + typepath = /obj/item/twohanded/toy/chainsaw + cost = 200 + /datum/prize_item/bike name = "Awesome Bike!" desc = "WOAH." diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index e5f1cb10525..763152cc5cf 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -45,13 +45,13 @@ if((istype(W, /obj/item/weldingtool) && W:welding)) if(!status) status = 1 - bombers += "[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]" - msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]") + investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB) + msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW) log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]") to_chat(user, "A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.") else status = 0 - bombers += "[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]" + investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB) to_chat(user, "The hole has been closed.") add_fingerprint(user) ..() diff --git a/code/modules/assembly/igniter.dm b/code/modules/assembly/igniter.dm index 08601522c5e..785e4549a47 100644 --- a/code/modules/assembly/igniter.dm +++ b/code/modules/assembly/igniter.dm @@ -28,7 +28,7 @@ if(istype(src.loc.loc, /obj/structure/reagent_dispensers/fueltank/)) var/obj/structure/reagent_dispensers/fueltank/tank = src.loc.loc if(tank) - tank.boom() + tank.boom(TRUE) if(istype(src.loc.loc, /obj/item/reagent_containers/glass/beaker/)) var/obj/item/reagent_containers/glass/beaker/beakerbomb = src.loc.loc if(beakerbomb) @@ -41,4 +41,4 @@ /obj/item/assembly/igniter/attack_self(mob/user as mob) activate() add_fingerprint(user) - return \ No newline at end of file + return diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 6bcefc6027c..5d6aa7490e2 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -75,7 +75,7 @@ if(!user.hand) which_hand = "r_hand" triggered(user, which_hand) - user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ + user.visible_message("[user] accidentally sets off [src], breaking [user.p_their()] fingers.", \ "You accidentally trigger [src]!") return to_chat(user, "You disarm [src].") @@ -91,7 +91,7 @@ if(!user.hand) which_hand = "r_hand" triggered(user, which_hand) - user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ + user.visible_message("[user] accidentally sets off [src], breaking [user.p_their()] fingers.", \ "You accidentally trigger [src]!") return ..() @@ -114,7 +114,7 @@ on_found(mob/finder as mob) if(armed) - finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ + finder.visible_message("[finder] accidentally sets off [src], breaking [finder.p_their()] fingers.", \ "You accidentally trigger [src]!") triggered(finder, finder.hand ? "l_hand" : "r_hand") return 1 //end the search! diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index 5d8c0ed1e98..a585a689f2c 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -114,7 +114,7 @@ timing = !timing if(timing && istype(holder, /obj/item/transfer_valve)) message_admins("[key_name_admin(usr)] activated [src] attachment on [holder].") - bombers += "[key_name(usr)] activated [src] attachment for [loc]" + investigate_log("[key_name(usr)] activated [src] attachment for [loc]", INVESTIGATE_BOMB) log_game("[key_name(usr)] activated [src] attachment for [loc]") update_icon() if(href_list["reset"]) diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 94e0ea2acce..627cde823fa 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -37,7 +37,7 @@ createCorpse() /obj/effect/landmark/corpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it. - var/mob/living/carbon/human/human/M = new /mob/living/carbon/human/human (src.loc) + var/mob/living/carbon/human/M = new /mob/living/carbon/human(src.loc) M.real_name = src.name M.death(1) //Kills the new mob M.adjustOxyLoss(oxy_damage) @@ -293,6 +293,6 @@ /obj/effect/landmark/corpse/abductor //Connected to ruins, for some reason? name = "abductor" mobname = "???" - mob_species = "abductor" + mob_species = /datum/species/abductor corpseuniform = /obj/item/clothing/under/color/grey corpseshoes = /obj/item/clothing/shoes/combat diff --git a/code/modules/awaymissions/map_rng.dm b/code/modules/awaymissions/map_rng.dm index 7618996fdf9..77954eafb9f 100644 --- a/code/modules/awaymissions/map_rng.dm +++ b/code/modules/awaymissions/map_rng.dm @@ -20,7 +20,7 @@ template = map_templates[template_name] /obj/effect/landmark/map_loader/Initialize() - ..() + . = ..() if(template) load(template) diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm index 5ff625544fd..816007d4ff8 100644 --- a/code/modules/awaymissions/maploader/reader.dm +++ b/code/modules/awaymissions/maploader/reader.dm @@ -57,8 +57,6 @@ var/global/dmm_suite/preloader/_preloader = new var/list/grid_models = list() var/key_len = 0 - - var/dmm_suite/loaded_map/LM = new // This try-catch is used as a budget "Finally" clause, as the dirt count // needs to be reset @@ -128,7 +126,6 @@ var/global/dmm_suite/preloader/_preloader = new bounds[MAP_MAXY] = max(bounds[MAP_MAXY], min(ycrd, world.maxy)) var/maxx = xcrdStart - log_debug("[xcrdStart]") if(measureOnly) for(var/line in gridLines) maxx = max(maxx, xcrdStart + length(line) / key_len - 1) diff --git a/code/modules/awaymissions/mission_code/spacehotel.dm b/code/modules/awaymissions/mission_code/spacehotel.dm index 4e4f2628736..81d21df5dcf 100644 --- a/code/modules/awaymissions/mission_code/spacehotel.dm +++ b/code/modules/awaymissions/mission_code/spacehotel.dm @@ -299,6 +299,4 @@ return S.retal_target = target - S.retal = 1 - -#undef CHECKOUT_TIME + S.retal = 1 \ No newline at end of file diff --git a/code/modules/awaymissions/mission_code/spacehotel_npcs.dm b/code/modules/awaymissions/mission_code/spacehotel_npcs.dm index dcf4a48a280..2a524ab738c 100644 --- a/code/modules/awaymissions/mission_code/spacehotel_npcs.dm +++ b/code/modules/awaymissions/mission_code/spacehotel_npcs.dm @@ -3,8 +3,8 @@ override_under = /obj/item/clothing/under/mafia chattyness = SNPC_CHANCE_TALK / 4 -/mob/living/carbon/human/interactive/away/hotel/New(loc) - ..(loc, "Skrell") +/mob/living/carbon/human/interactive/away/hotel/Initialize(mapload) + . = ..(mapload, /datum/species/skrell) /mob/living/carbon/human/interactive/away/hotel/doSetup() ..() @@ -24,12 +24,6 @@ for(var/obj/item/I in get_all_slots()) I.flags |= NODROP - // FIXME(crazylemon) a hack to prevent guards from running around with an - // extra security jumpsuit like a goof - for(var/obj/item/clothing/under/U in get_all_slots()) - if(w_uniform != U) - qdel(U) - /mob/living/carbon/human/interactive/away/hotel/guard/KnockOut() // you'll never take me alive (this triggers the implant) emote("deathgasp") diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index d159ed70eb2..b26bdba7d92 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -82,12 +82,12 @@ user.mutations.Add(XRAY) if(ishuman(user)) var/mob/living/carbon/human/human = user - if(human.species.name != "Shadow") + if(!isshadowperson(human)) to_chat(user, "Your flesh rapidly mutates!") to_chat(user, "You are now a Shadow Person, a mutant race of darkness-dwelling humanoids.") to_chat(user, "Your body reacts violently to light. However, it naturally heals in darkness.") to_chat(user, "Aside from your new traits, you are mentally unchanged and retain your prior obligations.") - human.set_species("Shadow") + human.set_species(/datum/species/shadow) user.regenerate_icons() if("Wealth") to_chat(user, "Your wish is granted, but at a terrible cost...") @@ -95,12 +95,12 @@ new /obj/structure/closet/syndicate/resources/everything(loc) if(ishuman(user)) var/mob/living/carbon/human/human = user - if(human.species.name != "Shadow") + if(!isshadowperson(human)) to_chat(user, "Your flesh rapidly mutates!") to_chat(user, "You are now a Shadow Person, a mutant race of darkness-dwelling humanoids.") to_chat(user, "Your body reacts violently to light. However, it naturally heals in darkness.") to_chat(user, "Aside from your new traits, you are mentally unchanged and retain your prior obligations.") - human.set_species("Shadow") + human.set_species(/datum/species/shadow) user.regenerate_icons() if("Immortality") to_chat(user, "Your wish is granted, but at a terrible cost...") @@ -108,12 +108,12 @@ user.verbs += /mob/living/carbon/proc/immortality if(ishuman(user)) var/mob/living/carbon/human/human = user - if(human.species.name != "Shadow") + if(!isshadowperson(human)) to_chat(user, "Your flesh rapidly mutates!") to_chat(user, "You are now a Shadow Person, a mutant race of darkness-dwelling humanoids.") to_chat(user, "Your body reacts violently to light. However, it naturally heals in darkness.") to_chat(user, "Aside from your new traits, you are mentally unchanged and retain your prior obligations.") - human.set_species("Shadow") + human.set_species(/datum/species/shadow) user.regenerate_icons() if("To Kill") to_chat(user, "Your wish is granted, but at a terrible cost...") @@ -130,12 +130,12 @@ obj_count++ if(ishuman(user)) var/mob/living/carbon/human/human = user - if(human.species.name != "Shadow") + if(!isshadowperson(human)) to_chat(user, "Your flesh rapidly mutates!") to_chat(user, "You are now a Shadow Person, a mutant race of darkness-dwelling humanoids.") to_chat(user, "Your body reacts violently to light. However, it naturally heals in darkness.") to_chat(user, "Aside from your new traits, you are mentally unchanged and retain your prior obligations.") - human.set_species("Shadow") + human.set_species(/datum/species/shadow) user.regenerate_icons() if("Peace") to_chat(user, "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.") diff --git a/code/modules/awaymissions/snpc.dm b/code/modules/awaymissions/snpc.dm index bd7046e3b2c..04e3bf19b8e 100644 --- a/code/modules/awaymissions/snpc.dm +++ b/code/modules/awaymissions/snpc.dm @@ -4,22 +4,24 @@ var/squad_member = 0 // was spawned by squad var/home_z -/mob/living/carbon/human/interactive/away/New() - ..() +/mob/living/carbon/human/interactive/away/Initialize(mapload) + . = ..() TRAITS |= TRAIT_ROBUST faction += "away" /mob/living/carbon/human/interactive/away/random() - if(ispath(override_under, /obj/item/clothing/under)) - equip_to_slot(new override_under(src), slot_w_uniform) ..() + // a little hacky but it should prevent doubled uniforms + if(ispath(override_under, /obj/item/clothing/under)) + var/old_under = w_uniform + w_uniform = null + equip_to_slot(new override_under(src), slot_w_uniform) + qdel(old_under) /mob/living/carbon/human/interactive/away/doSetup() ..() var/datum/data/pda/app/messenger/M = MYPDA.find_program(/datum/data/pda/app/messenger) M.toff = 1 - var/datum/data/pda/app/chatroom/C = MYPDA.find_program(/datum/data/pda/app/chatroom) - C.toff = 1 /mob/living/carbon/human/interactive/away/job2area() return away_area @@ -80,4 +82,4 @@ if(living < squad_size && !length(viewers(src, world.view))) var/mob/living/carbon/human/interactive/away/A = new squad_type(loc) squad += A - A.squad_member = 1 \ No newline at end of file + A.squad_member = 1 diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index 65220b0b754..c0bc96489b4 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -156,7 +156,8 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away while(sanity > 0) sanity-- - var/turf/T = locate(rand(25, world.maxx - 25), rand(25, world.maxy - 25), z_level) + // 8: 7 is the normal view distance of a client, +1 so that ruins don't suddenly appear + var/turf/T = locate(rand(TRANSITION_BORDER_WEST + (8 + ruin.width/2), TRANSITION_BORDER_EAST - (8 + ruin.width/2)), rand(TRANSITION_BORDER_SOUTH + (8 + ruin.height/2), TRANSITION_BORDER_NORTH - (8 + ruin.height/2)), z_level) var/valid = 1 for(var/turf/check in ruin.get_affected_turfs(T,1)) diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index d3dd6a5438b..c7f8504f13e 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -246,6 +246,13 @@ proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE) "sig_low.gif" = 'icons/program_icons/sig_low.gif', "sig_lan.gif" = 'icons/program_icons/sig_lan.gif', "sig_none.gif" = 'icons/program_icons/sig_none.gif', + "smmon_0.gif" = 'icons/program_icons/smmon_0.gif', + "smmon_1.gif" = 'icons/program_icons/smmon_1.gif', + "smmon_2.gif" = 'icons/program_icons/smmon_2.gif', + "smmon_3.gif" = 'icons/program_icons/smmon_3.gif', + "smmon_4.gif" = 'icons/program_icons/smmon_4.gif', + "smmon_5.gif" = 'icons/program_icons/smmon_5.gif', + "smmon_6.gif" = 'icons/program_icons/smmon_6.gif', ) /datum/asset/nanoui @@ -317,7 +324,7 @@ proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE) for(var/D in cardinal) assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipe-item.dmi', state, D) for(var/state in icon_states('icons/obj/pipes/disposal.dmi')) - if(!(state in list("conpipe-c", "conpipe-j1", "conpipe-s", "conpipe-t", "conpipe-y", "intake", "outlet"))) //Pipes we want sprites for + if(!(state in list("pipe-c", "pipe-j1", "pipe-s", "pipe-t", "pipe-y", "intake", "outlet"))) //Pipes we want sprites for continue for(var/D in cardinal) assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipes/disposal.dmi', state, D) diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index ad25c8fdeb1..f3919c2ba27 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -54,15 +54,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts return max(0, days - C.player_age) return 0 -//used for alternate_option -#define GET_RANDOM_JOB 0 -#define BE_CIVILIAN 1 -#define RETURN_TO_LOBBY 2 - #define MAX_SAVE_SLOTS 20 // Save slots for regular players #define MAX_SAVE_SLOTS_MEMBER 20 // Save slots for BYOND members - #define TAB_CHAR 0 #define TAB_GAME 1 #define TAB_GEAR 2 @@ -96,6 +90,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/UI_style_alpha = 255 var/windowflashing = TRUE var/clientfps = 0 + var/atklog = ATKLOG_ALL //ghostly preferences var/ghost_anonsay = 0 @@ -209,6 +204,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") max_gear_slots = config.max_loadout_points + var/loaded_preferences_successfully = FALSE if(istype(C)) if(!IsGuestKey(C.key)) unlock_content = C.IsByondMember() @@ -217,16 +213,17 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(C.donator_level >= DONATOR_LEVEL_ONE) max_gear_slots += 5 - var/loaded_preferences_successfully = load_preferences(C) - if(loaded_preferences_successfully) - if(load_character(C)) - return + loaded_preferences_successfully = load_preferences(C) // Do not call this with no client/C, it generates a runtime / SQL error + if(loaded_preferences_successfully) + if(load_character(C)) + return //we couldn't load character data so just randomize the character appearance + name random_character() //let's create a random character then - rather than a fat, bald and naked man. real_name = random_name(gender) - if(!loaded_preferences_successfully) - save_preferences(C) - save_character(C) //let's save this new random character so it doesn't keep generating new ones. + if(istype(C)) + if(!loaded_preferences_successfully) + save_preferences(C) // Do not call this with no client/C, it generates a runtime / SQL error + save_character(C) // Do not call this with no client/C, it generates a runtime / SQL error /datum/preferences/proc/color_square(colour) return "___" @@ -249,10 +246,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts switch(current_tab) if(TAB_CHAR) // Character Settings - var/datum/species/S = all_species[species] + var/datum/species/S = GLOB.all_species[species] if(!istype(S)) //The species was invalid. Set the species to the default, fetch the datum for that species and generate a random character. species = initial(species) - S = all_species[species] + S = GLOB.all_species[species] random_character() dat += "
" @@ -372,21 +369,40 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/status = organ_data[name] var/organ_name = null switch(name) - if("chest") organ_name = "torso" - if("groin") organ_name = "lower body" - if("head") organ_name = "head" - if("l_arm") organ_name = "left arm" - if("r_arm") organ_name = "right arm" - if("l_leg") organ_name = "left leg" - if("r_leg") organ_name = "right leg" - if("l_foot") organ_name = "left foot" - if("r_foot") organ_name = "right foot" - if("l_hand") organ_name = "left hand" - if("r_hand") organ_name = "right hand" - if("heart") organ_name = "heart" - if("eyes") organ_name = "eyes" + if("chest") + organ_name = "torso" + if("groin") + organ_name = "lower body" + if("head") + organ_name = "head" + if("l_arm") + organ_name = "left arm" + if("r_arm") + organ_name = "right arm" + if("l_leg") + organ_name = "left leg" + if("r_leg") + organ_name = "right leg" + if("l_foot") + organ_name = "left foot" + if("r_foot") + organ_name = "right foot" + if("l_hand") + organ_name = "left hand" + if("r_hand") + organ_name = "right hand" + if("eyes") + organ_name = "eyes" + if("heart") + organ_name = "heart" + if("lungs") + organ_name = "lungs" + if("liver") + organ_name = "liver" + if("kidneys") + organ_name = "kidneys" - if(status in list("cyborg", "amputated", "mechanical", "assisted")) + if(status in list("cyborg", "amputated", "cybernetic")) ++ind if(ind > 1) dat += ", " @@ -398,14 +414,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts else R = basic_robolimb dat += "\t[R.company] [organ_name] prosthesis" - if("amputated") dat += "\tAmputated [organ_name]" - if("mechanical") dat += "\tMechanical [organ_name]" - if("assisted") - switch(organ_name) - if("heart") dat += "\tPacemaker-assisted [organ_name]" - if("voicebox") dat += "\tSurgically altered [organ_name]" - if("eyes") dat += "\tRetinal overlayed [organ_name]" - else dat += "\tMechanically assisted [organ_name]" + if("amputated") + dat += "\tAmputated [organ_name]" + if("cybernetic") + dat += "\tCybernetic [organ_name]" if(!ind) dat += "\[...\]
" else dat += "
" @@ -699,7 +711,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts switch(alternate_option) if(GET_RANDOM_JOB) HTML += "

Get random job if preferences unavailable

" - if(BE_CIVILIAN) + if(BE_ASSISTANT) HTML += "

Be a civilian if preferences unavailable

" if(RETURN_TO_LOBBY) HTML += "

Return to lobby if preferences unavailable

" @@ -816,7 +828,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts return 1 /datum/preferences/proc/ShowDisabilityState(mob/user,flag,label) - var/datum/species/S = all_species[species] + var/datum/species/S = GLOB.all_species[species] if(flag==DISABILITY_FLAG_FAT && !(CAN_BE_FAT in S.species_traits)) return "
  • [species] cannot be fat.
  • " return "
  • [label]: [disabilities & flag ? "Yes" : "No"]
  • " @@ -1041,7 +1053,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts /datum/preferences/proc/process_link(mob/user, list/href_list) if(!user) return - var/datum/species/S = all_species[species] + var/datum/species/S = GLOB.all_species[species] if(href_list["preference"] == "job") switch(href_list["task"]) if("close") @@ -1051,7 +1063,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts ResetJobs() SetChoices(user) if("random") - if(alternate_option == GET_RANDOM_JOB || alternate_option == BE_CIVILIAN) + if(alternate_option == GET_RANDOM_JOB || alternate_option == BE_ASSISTANT) alternate_option += 1 else if(alternate_option == RETURN_TO_LOBBY) alternate_option = 0 @@ -1279,7 +1291,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts new_species += whitelisted_species species = input("Please select a species", "Character Generation", null) in new_species - var/datum/species/NS = all_species[species] + var/datum/species/NS = GLOB.all_species[species] if(!istype(NS)) //The species was invalid. Notify the user and fail out. species = prev_species to_chat(user, "Invalid species, please pick something else.") @@ -1869,26 +1881,31 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts rlimb_data[second_limb] = choice organ_data[second_limb] = "cyborg" if("organs") - var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes") - if(!organ_name) return + var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Eyes", "Heart", "Lungs", "Liver", "Kidneys") + if(!organ_name) + return var/organ = null switch(organ_name) - if("Heart") - organ = "heart" if("Eyes") organ = "eyes" + if("Heart") + organ = "heart" + if("Lungs") + organ = "lungs" + if("Liver") + organ = "liver" + if("Kidneys") + organ = "kidneys" - var/new_state = input(user, "What state do you wish the organ to be in?") as null|anything in list("Normal","Assisted","Mechanical") + var/new_state = input(user, "What state do you wish the organ to be in?") as null|anything in list("Normal", "Cybernetic") if(!new_state) return switch(new_state) if("Normal") organ_data[organ] = null - if("Assisted") - organ_data[organ] = "assisted" - if("Mechanical") - organ_data[organ] = "mechanical" + if("Cybernetic") + organ_data[organ] = "cybernetic" if("clientfps") var/version_message @@ -2066,8 +2083,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts return 1 /datum/preferences/proc/copy_to(mob/living/carbon/human/character) - var/datum/species/S = all_species[species] - character.change_species(species) // Yell at me if this causes everything to melt + var/datum/species/S = GLOB.all_species[species] + character.set_species(S.type) // Yell at me if this causes everything to melt if(be_random_name) real_name = random_name(gender,species) @@ -2133,9 +2150,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts else var/obj/item/organ/internal/I = character.get_int_organ_tag(name) if(I) - if(status == "assisted") - I.mechassist() - else if(status == "mechanical") + if(status == "cybernetic") I.robotize() character.dna.b_type = b_type @@ -2155,10 +2170,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.undershirt = undershirt character.socks = socks - if(character.species.bodyflags & HAS_HEAD_ACCESSORY) + if(character.dna.species.bodyflags & HAS_HEAD_ACCESSORY) H.headacc_colour = hacc_colour H.ha_style = ha_style - if(character.species.bodyflags & HAS_MARKINGS) + if(character.dna.species.bodyflags & HAS_MARKINGS) character.m_colours = m_colours character.m_styles = m_styles @@ -2168,14 +2183,14 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.backbag = backbag //Debugging report to track down a bug, which randomly assigned the plural gender to people. - if(S.has_gender && (character.gender in list(PLURAL, NEUTER))) + if(character.dna.species.has_gender && (character.gender in list(PLURAL, NEUTER))) if(isliving(src)) //Ghosts get neuter by default message_admins("[key_name_admin(character)] has spawned with their gender as plural or neuter. Please notify coders.") character.change_gender(MALE) character.change_eye_color(e_colour) - if(disabilities & DISABILITY_FLAG_FAT && (CAN_BE_FAT in character.species.species_traits)) + if(disabilities & DISABILITY_FLAG_FAT && (CAN_BE_FAT in character.dna.species.species_traits)) character.dna.SetSEState(FATBLOCK,1,1) character.overeatduration = 600 @@ -2218,7 +2233,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(disabilities & DISABILITY_FLAG_SCRAMBLED) character.dna.SetSEState(SCRAMBLEBLOCK,1,1) - S.handle_dna(character) + character.dna.species.handle_dna(character) if(character.dna.dirtySE) character.dna.UpdateSE() diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm index f2a9d739cfe..318cf8fb0bb 100644 --- a/code/modules/client/preference/preferences_mysql.dm +++ b/code/modules/client/preference/preferences_mysql.dm @@ -17,7 +17,8 @@ windowflashing, ghost_anonsay, exp, - clientfps + clientfps, + atklog FROM [format_table_name("player")] WHERE ckey='[C.ckey]'"} ) @@ -48,6 +49,7 @@ ghost_anonsay = text2num(query.item[15]) exp = query.item[16] clientfps = text2num(query.item[17]) + atklog = text2num(query.item[18]) //Sanitize ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) @@ -66,6 +68,7 @@ ghost_anonsay = sanitize_integer(ghost_anonsay, 0, 1, initial(ghost_anonsay)) exp = sanitize_text(exp, initial(exp)) clientfps = sanitize_integer(clientfps, 0, 1000, initial(clientfps)) + atklog = sanitize_integer(atklog, 0, 100, initial(atklog)) return 1 /datum/preferences/proc/save_preferences(client/C) @@ -85,6 +88,7 @@ be_role='[sanitizeSQL(list2params(be_special))]', default_slot='[default_slot]', toggles='[toggles]', + atklog='[atklog]', sound='[sound]', randomslot='[randomslot]', volume='[volume]', @@ -93,7 +97,8 @@ lastchangelog='[lastchangelog]', windowflashing='[windowflashing]', ghost_anonsay='[ghost_anonsay]', - clientfps='[clientfps]' + clientfps='[clientfps]', + atklog='[atklog]' WHERE ckey='[C.ckey]'"} ) @@ -247,7 +252,7 @@ autohiss_mode = text2num(query.item[52]) //Sanitize - var/datum/species/SP = all_species[species] + var/datum/species/SP = GLOB.all_species[species] metadata = sanitize_text(metadata, initial(metadata)) real_name = reject_bad_name(real_name, 1) if(isnull(species)) species = "Human" diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 282603a8879..a5b4e614551 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -49,12 +49,12 @@ if("exclude" in species_restricted) exclusive = 1 - if(H.species) + if(H.dna.species) if(exclusive) - if(!(H.species.name in species_restricted)) + if(!(H.dna.species.name in species_restricted)) wearable = 1 else - if(H.species.name in species_restricted) + if(H.dna.species.name in species_restricted) wearable = 1 if(!wearable) @@ -411,7 +411,7 @@ BLIND // can't see anything desc = "[desc] They have had their toes opened up." update_icon() else - to_chat(user, "[src] have already had their toes cut open!") + to_chat(user, "[src] have already had [p_their()] toes cut open!") return else ..() @@ -489,7 +489,7 @@ BLIND // can't see anything for(var/obj/item/I in O.contents) //Dump the pocket out onto the floor below the user. user.unEquip(I,1) - user.visible_message("[user] bellows, [pick("shredding", "ripping open", "tearing off")] their jacket in a fit of rage!","You accidentally [pick("shred", "rend", "tear apart")] \the [src] with your [pick("excessive", "extreme", "insane", "monstrous", "ridiculous", "unreal", "stupendous")] [pick("power", "strength")]!") + user.visible_message("[user] bellows, [pick("shredding", "ripping open", "tearing off")] [user.p_their()] jacket in a fit of rage!","You accidentally [pick("shred", "rend", "tear apart")] [src] with your [pick("excessive", "extreme", "insane", "monstrous", "ridiculous", "unreal", "stupendous")] [pick("power", "strength")]!") user.unEquip(src) qdel(src) //Now that the pockets have been emptied, we can safely destroy the jacket. user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) @@ -504,7 +504,7 @@ BLIND // can't see anything /obj/item/clothing/suit/equipped(var/mob/living/carbon/human/user, var/slot) //Handle tail-hiding on a by-species basis. ..() if(ishuman(user) && hide_tail_by_species && slot == slot_wear_suit) - if(user.species.name in hide_tail_by_species) + if(user.dna.species.name in hide_tail_by_species) if(!(flags_inv & HIDETAIL)) //Hide the tail if the user's species is in the hide_tail_by_species list and the tail isn't already hidden. flags_inv |= HIDETAIL else diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index 32f86cc6e57..40c29c1d991 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -132,3 +132,14 @@ cell.forceMove(get_turf(loc)) cell = null update_icon() + +/obj/item/clothing/gloves/fingerless/rapid + name = "Gloves of the North Star" + desc = "Just looking at these fills you with an urge to beat the shit out of people." + +/obj/item/clothing/gloves/fingerless/rapid/Touch(mob/living/target, proximity = TRUE) + var/mob/living/M = loc + + if(M.a_intent == INTENT_HARM) + M.changeNext_move(CLICK_CD_RAPID) + .= FALSE \ No newline at end of file diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 10f5a348318..dc8c4b59a4d 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -222,7 +222,7 @@ return 1 /obj/item/clothing/head/fedora/proc/tip_fedora(mob/user) - user.visible_message("[user] tips their fedora.", "You tip your fedora") + user.visible_message("[user] tips [user.p_their()] fedora.", "You tip your fedora") /obj/item/clothing/head/fez diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 60cbfff3dd9..22f293aedfc 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -8,7 +8,7 @@ gas_transfer_coefficient = 0.90 put_on_delay = 20 var/resist_time = 0 //deciseconds of how long you need to gnaw to get rid of the gag, 0 to make it impossible to remove - var/mute = MUTE_ALL + var/mute = MUZZLE_MUTE_ALL var/security_lock = FALSE // Requires brig access to remove 0 - Remove as normal var/locked = FALSE //Indicates if a mask is locked, should always start as 0. species_fit = list("Vox") @@ -22,8 +22,8 @@ return 0 else if(security_lock && locked) if(do_unlock(user)) - visible_message("[user] unlocks their [src.name].", \ - "[user] unlocks their [src.name].") + visible_message("[user] unlocks [user.p_their()] [src.name].", \ + "[user] unlocks [user.p_their()] [src.name].") ..() return 1 @@ -93,7 +93,7 @@ item_state = null w_class = WEIGHT_CLASS_TINY resist_time = 150 - mute = MUTE_MUFFLE + mute = MUZZLE_MUTE_MUFFLE flags = DROPDEL species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey") sprite_sheets = list( @@ -117,7 +117,7 @@ name = "safety muzzle" desc = "A muzzle designed to prevent biting." resist_time = 600 - mute = MUTE_NONE + mute = MUZZLE_MUTE_NONE security_lock = TRUE locked = FALSE @@ -169,7 +169,7 @@ return 1 /obj/item/clothing/mask/fakemoustache/proc/pontificate(mob/user) - user.visible_message("\ [user] twirls \his moustache and laughs [pick("fiendishly","maniacally","diabolically","evilly")]!") + user.visible_message("\ [user] twirls [user.p_their()] moustache and laughs [pick("fiendishly","maniacally","diabolically","evilly")]!") //scarves (fit in in mask slot) diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 88796165114..3156b617c03 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -6,6 +6,7 @@ var/magboot_state = "magboots" var/magpulse = 0 var/slowdown_active = 2 + var/slowdown_passive = SHOES_SLOWDOWN actions_types = list(/datum/action/item_action/toggle) strip_delay = 70 put_on_delay = 70 @@ -14,7 +15,7 @@ /obj/item/clothing/shoes/magboots/attack_self(mob/user) if(magpulse) flags &= ~NOSLIP - slowdown = SHOES_SLOWDOWN + slowdown = slowdown_passive else flags |= NOSLIP slowdown = slowdown_active @@ -53,4 +54,18 @@ obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team desc = "Reverse-engineered magboots that appear to be based on an advanced model, as they have a lighter magnetic pull. Property of Gorlex Marauders." name = "advanced blood-red magboots" - slowdown_active = SHOES_SLOWDOWN \ No newline at end of file + slowdown_active = SHOES_SLOWDOWN + +/obj/item/clothing/shoes/magboots/clown + desc = "The prankster's standard-issue clowning shoes. Damn they're huge! There's a red light on the side." + name = "clown shoes" + icon_state = "clownmag0" + magboot_state = "clownmag" + item_state = "clown_shoes" + slowdown = SHOES_SLOWDOWN+1 + slowdown_active = SHOES_SLOWDOWN+1 + slowdown_passive = SHOES_SLOWDOWN+1 + item_color = "clown" + silence_steps = 1 + shoe_sound = "clownstep" + origin_tech = "magnets=4;syndicate=2" \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm index 123b4e5fd5e..91884eeba2d 100644 --- a/code/modules/clothing/spacesuits/ert.dm +++ b/code/modules/clothing/spacesuits/ert.dm @@ -9,9 +9,10 @@ var/obj/machinery/camera/camera var/has_camera = TRUE strip_delay = 130 - species_fit = list("Grey") + species_fit = list("Grey", "Vox") sprite_sheets = list( - "Grey" = 'icons/mob/species/grey/helmet.dmi' + "Grey" = 'icons/mob/species/grey/helmet.dmi', + "Vox" = 'icons/mob/species/vox/helmet.dmi' ) /obj/item/clothing/head/helmet/space/hardsuit/ert/attack_self(mob/user) @@ -41,9 +42,10 @@ /obj/item/radio, /obj/item/analyzer, /obj/item/gun/energy/laser, /obj/item/gun/energy/pulse, \ /obj/item/gun/energy/gun/advtaser, /obj/item/melee/baton, /obj/item/gun/energy/gun) strip_delay = 130 - species_fit = list("Drask") + species_fit = list("Drask", "Vox") sprite_sheets = list( - "Drask" = 'icons/mob/species/drask/suit.dmi' + "Drask" = 'icons/mob/species/drask/suit.dmi', + "Vox" = 'icons/mob/species/vox/suit.dmi' ) //Commander diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index f5a6176a6c4..1e874772478 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -16,7 +16,7 @@ /obj/item/clothing/head/helmet/space/capspace/equipped(mob/living/carbon/human/user, slot) if(ishuman(user) && slot == slot_head) - if(user.species.name == "Vox") + if(isvox(user)) if(flags & BLOCKHAIR) flags &= ~BLOCKHAIR else @@ -71,6 +71,11 @@ allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank,/obj/item/kitchen/knife/combat) armor = list(melee = 40, bullet = 30, laser = 30, energy = 30, bomb = 50, bio = 90, rad = 20) strip_delay = 120 + species_restricted = list("exclude", "Diona", "Wryn") + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/suit.dmi' + ) /obj/item/clothing/head/helmet/space/deathsquad/beret name = "officer's beret" diff --git a/code/modules/clothing/spacesuits/rig/modules/computer.dm b/code/modules/clothing/spacesuits/rig/modules/computer.dm index 49991df72d7..74af696e76e 100644 --- a/code/modules/clothing/spacesuits/rig/modules/computer.dm +++ b/code/modules/clothing/spacesuits/rig/modules/computer.dm @@ -116,7 +116,7 @@ return 1 // Okay, it wasn't a terminal being touched, check for all the simple insertions. - if(input_device.type in list(/obj/item/paicard, /obj/item/mmi, /obj/item/mmi/posibrain)) + if(input_device.type in list(/obj/item/paicard, /obj/item/mmi, /obj/item/mmi/robotic_brain)) if(integrated_ai) integrated_ai.attackby(input_device,user) // If the transfer was successful, we can clear out our vars. diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 7a2d9e5e495..c65ea335c4d 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -366,7 +366,7 @@ correct_piece.icon_state = "[initial(icon_state)]" switch(msg_type) if("boots") - to_chat(wearer, "\The [correct_piece] relax their grip on your legs.") + to_chat(wearer, "\The [correct_piece] relax [correct_piece.p_their()] grip on your legs.") if(user != wearer) to_chat(user, "\The [correct_piece] has been unsealed.") wearer.update_inv_shoes() @@ -609,8 +609,8 @@ var/species_icon = 'icons/mob/rig_back.dmi' // Since setting mob_icon will override the species checks in // update_inv_wear_suit(), handle species checks here. - if(wearer && sprite_sheets && sprite_sheets[wearer.get_species()]) - species_icon = sprite_sheets[wearer.get_species()] + if(wearer && sprite_sheets && sprite_sheets[wearer.dna.species.name]) + species_icon = sprite_sheets[wearer.dna.species.name] mob_icon = image("icon" = species_icon, "icon_state" = "[icon_state]") if(installed_modules.len) diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 74d07164101..7880dcc1dd3 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -9,6 +9,10 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES burn_state = FIRE_PROOF + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/helmet.dmi' + ) /obj/item/clothing/suit/bio_suit name = "bio suit" diff --git a/code/modules/clothing/suits/hood.dm b/code/modules/clothing/suits/hood.dm index 7e2307c96b4..c784306cf66 100644 --- a/code/modules/clothing/suits/hood.dm +++ b/code/modules/clothing/suits/hood.dm @@ -31,6 +31,8 @@ ..() /obj/item/clothing/suit/hooded/proc/RemoveHood() + if(isnull(hood)) + return icon_state = "[initial(icon_state)]" suit_adjusted = 0 if(ishuman(hood.loc)) diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 6aa79584fc7..e0b444afcd0 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -77,7 +77,7 @@ burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/head.dmi' + "Vox" = 'icons/mob/species/vox/helmet.dmi' ) /obj/item/clothing/suit/bomb_suit @@ -108,16 +108,12 @@ /obj/item/clothing/head/bomb_hood/security icon_state = "bombsuitsec" item_state = "bombsuitsec" - species_fit = null - sprite_sheets = null /obj/item/clothing/suit/bomb_suit/security icon_state = "bombsuitsec" item_state = "bombsuitsec" allowed = list(/obj/item/gun/energy,/obj/item/melee/baton,/obj/item/restraints/handcuffs) - species_fit = null - sprite_sheets = null /* * Radiation protection diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 6d2e0363138..764ee71583a 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -131,12 +131,12 @@ /obj/item/clothing/accessory/stethoscope/attack(mob/living/carbon/human/M, mob/living/user) if(ishuman(M) && isliving(user)) if(user == M) - user.visible_message("[user] places \the [src] against \his chest and listens attentively.", "You place \the [src] against your chest...") + user.visible_message("[user] places [src] against [user.p_their()] chest and listens attentively.", "You place [src] against your chest...") else user.visible_message("[user] places \the [src] against [M]'s chest and listens attentively.", "You place \the [src] against [M]'s chest...") var/obj/item/organ/internal/H = M.get_int_organ(/obj/item/organ/internal/heart) var/obj/item/organ/internal/L = M.get_int_organ(/obj/item/organ/internal/lungs) - if((H && M.pulse) || (L && !(BREATHLESS in M.mutations) && !(NO_BREATHE in M.species.species_traits))) + if((H && M.pulse) || (L && !(BREATHLESS in M.mutations) && !(NO_BREATHE in M.dna.species.species_traits))) var/color = "notice" if(H) var/heart_sound @@ -250,7 +250,7 @@ to_chat(user, "Waving around a badge before swiping an ID would be pretty pointless.") return if(isliving(user)) - user.visible_message("[user] displays their Nanotrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","You display your Nanotrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.") + user.visible_message("[user] displays [user.p_their()] Nanotrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","You display your Nanotrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.") /obj/item/clothing/accessory/holobadge/attackby(var/obj/item/O as obj, var/mob/user as mob, params) if(istype(O, /obj/item/card/id) || istype(O, /obj/item/pda)) @@ -284,7 +284,7 @@ /obj/item/clothing/accessory/holobadge/attack(mob/living/carbon/human/M, mob/living/user) if(isliving(user)) - user.visible_message("[user] invades [M]'s personal space, thrusting [src] into their face insistently.","You invade [M]'s personal space, thrusting [src] into their face insistently. You are the law.") + user.visible_message("[user] invades [M]'s personal space, thrusting [src] into [M.p_their()] face insistently.","You invade [M]'s personal space, thrusting [src] into [M.p_their()] face insistently. You are the law.") /obj/item/storage/box/holobadge name = "holobadge box" diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 1ca94e9a4f3..76bef3e056b 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -69,9 +69,10 @@ item_state = "clown" item_color = "clown" flags_size = ONESIZEFITSALL + var/honk_sound = 'sound/items/bikehorn.ogg' /obj/item/clothing/under/rank/clown/hit_reaction() - playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1) + playsound(loc, honk_sound, 50, 1, -1) if(ishuman(loc)) var/mob/living/carbon/human/H = loc if(H.mind && H.mind.assigned_role == "Clown") diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index f1739750a0a..012c79bab06 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -25,15 +25,6 @@ time = 15 category = CAT_WEAPON -/datum/crafting_recipe/lance - name = "explosive lance (grenade)" - result = /obj/item/twohanded/spear - reqs = list(/obj/item/twohanded/spear = 1, - /obj/item/grenade = 1) - parts = list(/obj/item/grenade = 1) - time = 15 - category = CAT_WEAPON - /datum/crafting_recipe/molotov name = "Molotov" result = /obj/item/reagent_containers/food/drinks/bottle/molotov diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 6a5d5dd0519..2a734e91dcd 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -45,8 +45,8 @@ var/mob/living/carbon/human/target = M - if(istype(target.species, /datum/species/machine)) - to_chat(user, "[target] has no skin, how do you expect to tattoo them?") + if(ismachine(target)) + to_chat(user, "[target] has no skin, how do you expect to tattoo [target.p_them()]?") return if(target.m_styles["body"] != "None") @@ -54,7 +54,7 @@ return var/datum/sprite_accessory/body_markings/tattoo/temp_tatt = marking_styles_list[tattoo_icon] - if(!(target.species.name in temp_tatt.species_allowed)) + if(!(target.dna.species.name in temp_tatt.species_allowed)) to_chat(user, "You can't think of a way to make the [tattoo_name] design work on [target == user ? "your" : "[target]'s"] body type.") return @@ -268,7 +268,7 @@ return var/mob/living/carbon/human/target = user - if(!istype(target) || target.get_species() != "Tajaran") // Only catbeasts, kthnx. + if(!istype(target) || !istajaran(target)) // Only catbeasts, kthnx. return if(target.change_body_accessory("Jay Wingler Tail")) @@ -1265,6 +1265,8 @@ name = "engraved hand mirror" desc = "A very classy hand mirror, with fancy detailing." icon = 'icons/obj/custom_items.dmi' + lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi' + righthand_file = 'icons/mob/inhands/fluff_righthand.dmi' icon_state = "hand_mirror" attack_verb = list("smacked") hitsound = 'sound/weapons/tap.ogg' @@ -1274,7 +1276,7 @@ /obj/item/fluff/zekemirror/attack_self(mob/user) var/mob/living/carbon/human/target = user - if(!istype(target) || target.get_species() != "Skrell") // It'd be strange to see other races with head tendrils. + if(!istype(target) || !isskrell(target)) // It'd be strange to see other races with head tendrils. return if(target.change_hair("Zekes Tentacles", 1)) @@ -1311,6 +1313,8 @@ name = "Classy victorian suit" desc = "A blue and black victorian suit with silver buttons, very fancy!" icon = 'icons/obj/custom_items.dmi' + lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi' + righthand_file = 'icons/mob/inhands/fluff_righthand.dmi' icon_state = "victorianlightfire" item_state = "victorianvest" item_color = "victorianlightfire" @@ -1330,7 +1334,7 @@ to_chat(user, "You can't modify [target]!") return - to_chat(user, "You modify the appearance of [target] based on the kite blueprints.") + to_chat(user, "You modify the appearance of [target] based on the kit blueprints.") var/obj/spacepod/pod = target pod.icon = 'icons/48x48/custom_pod.dmi' pod.icon_state = "pod_dece" @@ -1348,4 +1352,38 @@ righthand_file = 'icons/mob/inhands/fluff_righthand.dmi' icon_state = "teri_horn" item_state = "teri_horn" - honk_sound = 'sound/items/teri_horn.ogg' \ No newline at end of file + honk_sound = 'sound/items/teri_horn.ogg' + +/obj/item/clothing/accessory/medal/fluff/elo //V-Force_Bomber: E.L.O. + name = "distinguished medal of loyalty and excellence" + desc = "This medal is cut into the shape of a Victoria Cross, and is awarded to those who have proven themselves to Nanotrasen with a long and successful career." + icon = 'icons/obj/custom_items.dmi' + icon_state = "elo-medal" + item_color = "elo-medal" + +/obj/item/clothing/suit/fluff/vetcoat //Furasian: Fillmoore Grayson + name = "Veteran Coat" + desc = "An old, yet well-kept Nanotrasen uniform. Very few of its kind are still produced." + icon = 'icons/obj/custom_items.dmi' + lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi' + righthand_file = 'icons/mob/inhands/fluff_righthand.dmi' + icon_state = "alchemistcoatblack" + item_state = "alchemistcoatblack" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +/obj/item/clothing/suit/fluff/vetcoat/red //Furasian: Fillmoore Grayson + icon_state = "alchemistcoatred" + item_state = "alchemistcoatred" + +/obj/item/clothing/suit/fluff/vetcoat/navy //Furasian: Fillmoore Grayson + icon_state = "alchemistcoatnavy" + item_state = "alchemistcoatnavy" + +/obj/item/clothing/accessory/medal/fluff/panzermedal //PanzerSkull: GRN-DER + name = "Cross of Valor" + desc = "A medal from the bygone Asteroid Wars. Its Ruby shines with a strange intensity." + icon = 'icons/obj/custom_items.dmi' + icon_state = "panzermedal" + item_state = "panzermedal" + item_color = "panzermedal" + slot_flags = SLOT_TIE diff --git a/code/modules/economy/Economy.dm b/code/modules/economy/Economy.dm index 028c2810ae7..57d76e98c5c 100644 --- a/code/modules/economy/Economy.dm +++ b/code/modules/economy/Economy.dm @@ -38,7 +38,7 @@ #define MINERALS 8 #define EMERGENCY 9 -#define GAS 10 +#define EGAS 10 #define MAINTENANCE 11 #define ELECTRICAL 12 #define ROBOTICS 13 diff --git a/code/modules/economy/Economy_Events.dm b/code/modules/economy/Economy_Events.dm index c1e5b95273e..10e0d574f98 100644 --- a/code/modules/economy/Economy_Events.dm +++ b/code/modules/economy/Economy_Events.dm @@ -29,16 +29,16 @@ if(INDUSTRIAL_ACCIDENT) dearer_goods = list(EMERGENCY, BIOMEDICAL, ROBOTICS) if(BIOHAZARD_OUTBREAK) - dearer_goods = list(BIOMEDICAL, GAS) + dearer_goods = list(BIOMEDICAL, EGAS) if(PIRATES) dearer_goods = list(SECURITY, MINERALS) if(CORPORATE_ATTACK) dearer_goods = list(SECURITY, MAINTENANCE) if(ALIEN_RAIDERS) dearer_goods = list(BIOMEDICAL, ANIMALS) - cheaper_goods = list(GAS, MINERALS) + cheaper_goods = list(EGAS, MINERALS) if(AI_LIBERATION) - dearer_goods = list(EMERGENCY, GAS, MAINTENANCE) + dearer_goods = list(EMERGENCY, EGAS, MAINTENANCE) if(MOURNING) cheaper_goods = list(MINERALS, MAINTENANCE) if(CULT_CELL_REVEALED) diff --git a/code/modules/events/aurora_caelus.dm b/code/modules/events/aurora_caelus.dm index e35c7de6ee3..6cf5e1b1ce7 100644 --- a/code/modules/events/aurora_caelus.dm +++ b/code/modules/events/aurora_caelus.dm @@ -6,11 +6,11 @@ var/aurora_progress = 0 //this cycles from 1 to 7, slowly changing colors from gentle green to gentle blue /datum/event/aurora_caelus/announce() - event_announcement.Announce("[station_name()]: A harmless cloud of ions is approaching your station, and will exhaust their energy battering the hull.\ -Nanotrasen has approved a short break for all employees to relax and observe this very rare event.\ -During this time, starlight will be bright but gentle, shifting between quiet green and blue colors.\ -Any staff who would like to view these lights for themselves may proceed to the area nearest to them with viewing ports to open space.\ -We hope you enjoy the lights.", "Harmless ions approaching", new_sound = 'sound/misc/notice2.ogg', from = "Nanotrasen Meterology Divison") + event_announcement.Announce("[station_name()]: A harmless cloud of ions is approaching your station, and will exhaust their energy battering the hull. \ +Nanotrasen has approved a short break for all employees to relax and observe this very rare event. \ +During this time, starlight will be bright but gentle, shifting between quiet green and blue colors. \ +Any staff who would like to view these lights for themselves may proceed to the area nearest to them with viewing ports to open space. \ +We hope you enjoy the lights.", "Harmless ions approaching", new_sound = 'sound/misc/notice2.ogg', from = "Nanotrasen Meteorology Division") for(var/V in player_list) var/mob/M = V if((M.client.prefs.toggles & SOUND_MIDI) && is_station_level(M.z)) @@ -37,10 +37,10 @@ We hope you enjoy the lights.", "Harmless ions approaching", new_sound = 'sound/ for(var/s in GLOB.station_level_space_turfs) var/turf/space/S = s fade_to_black(S) - event_announcement.Announce("The aurora caelus event is now ending. Starlight conditions will slowly return to normal.\ -When this has concluded, please return to your workplace and continue work as normal.\ + event_announcement.Announce("The Aurora Caelus event is now ending. Starlight conditions will slowly return to normal. \ +When this has concluded, please return to your workplace and continue work as normal. \ Have a pleasant shift, [station_name()], and thank you for watching with us.", -"Harmless ions approaching", new_sound = 'sound/misc/notice2.ogg', from = "Nanotrasen Meterology Divison") +"Harmless ions approaching", new_sound = 'sound/misc/notice2.ogg', from = "Nanotrasen Meteorology Division") /datum/event/aurora_caelus/proc/fade_to_black(turf/space/S) set waitfor = FALSE @@ -48,4 +48,4 @@ Have a pleasant shift, [station_name()], and thank you for watching with us.", while(S.light_range > new_light) S.set_light(S.light_range - 0.2) sleep(30) - S.set_light(new_light, 1, l_color = "") // we should be able to use `, null` as the last arg but BYOND is a piece of FUCKING SHIT AND SET_LIGHT DOESN'T WORK THAT WAY DESPITE EVERY FUCKING THING ABOUT IT INDICATING THAT IT GODDAMN WELL SHOULD AAAAAAAAAAAAAAAAA \ No newline at end of file + S.set_light(new_light, 1, l_color = "") // we should be able to use `, null` as the last arg but BYOND is a piece of FUCKING SHIT AND SET_LIGHT DOESN'T WORK THAT WAY DESPITE EVERY FUCKING THING ABOUT IT INDICATING THAT IT GODDAMN WELL SHOULD AAAAAAAAAAAAAAAAA diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index abab5c39254..cd9b0c02206 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -2,6 +2,10 @@ announceWhen = 50 endWhen = 900 + var/list/spawned_mobs = list( + /mob/living/simple_animal/hostile/carp = 95, + /mob/living/simple_animal/hostile/carp/megacarp = 5, + ) var/list/spawned_carp = list() /datum/event/carp_migration/setup() @@ -17,6 +21,7 @@ event_announcement.Announce(announcement, "Lifesign Alert") /datum/event/carp_migration/start() + if(severity == EVENT_LEVEL_MAJOR) spawn_fish(landmarks_list.len) else if(severity == EVENT_LEVEL_MODERATE) @@ -32,19 +37,17 @@ spawn_locations.Add(C.loc) spawn_locations = shuffle(spawn_locations) num_groups = min(num_groups, spawn_locations.len) - + var/i = 1 while(i <= num_groups) var/group_size = rand(group_size_min, group_size_max) for(var/j = 1, j <= group_size, j++) - var/carptype = /mob/living/simple_animal/hostile/carp - if(prob(5)) - carptype = /mob/living/simple_animal/hostile/carp/megacarp + var/carptype = pickweight(spawned_mobs) spawned_carp.Add(new carptype(spawn_locations[i])) i++ /datum/event/carp_migration/end() - for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp) + for(var/mob/living/simple_animal/hostile/C in spawned_carp) if(!C.stat) var/turf/T = get_turf(C) if(istype(T, /turf/space)) diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index b514924abfa..87836f217b8 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -11,14 +11,14 @@ /datum/event/disease_outbreak/start() if(!virus_type) - virus_type = pick(/datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis) + virus_type = pick(/datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis, /datum/disease/beesease, /datum/disease/anxiety, /datum/disease/fake_gbs, /datum/disease/fluspanish, /datum/disease/pierrot_throat, /datum/disease/lycan) for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) if(issmall(H)) //don't infect monkies; that's a waste continue if(!H.client) continue - if(VIRUSIMMUNE in H.species.species_traits) //don't let virus immune things get diseases they're not supposed to get. + if(VIRUSIMMUNE in H.dna.species.species_traits) //don't let virus immune things get diseases they're not supposed to get. continue var/turf/T = get_turf(H) if(!T) diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 325d307a299..6ca6e8e4ea3 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -139,7 +139,8 @@ var/list/event_last_fired = list() new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Sentience", /datum/event/sentience, 50), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Aurora Caelus", /datum/event/aurora_caelus, 15, is_one_shot = TRUE) + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Aurora Caelus", /datum/event/aurora_caelus, 15, is_one_shot = TRUE), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Koi School", /datum/event/carp_migration/koi, 80,) ) /datum/event_container/moderate diff --git a/code/modules/events/infestation.dm b/code/modules/events/infestation.dm index c5a5873afa0..d11a1227ddf 100644 --- a/code/modules/events/infestation.dm +++ b/code/modules/events/infestation.dm @@ -107,7 +107,6 @@ #undef LOC_HYDRO #undef LOC_VAULT #undef LOC_TECH -#undef LOC_TACTICAL #undef VERM_MICE #undef VERM_LIZARDS diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index 520d8805bbd..a66dcd66d0e 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -119,22 +119,22 @@ if(2) //X is an object message = "THE CREW ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(9) //X is harmful to humans + if(9) //X is harmful to crew switch(rand(1,7)) //What is X? if(1) //X is a threat - message = "[ionadjectiveshalf][ionthreats] ARE HARMFUL TO HUMANS" + message = "[ionadjectiveshalf][ionthreats] ARE HARMFUL TO CREW" if(2) //X is a job - message = "[ionadjectiveshalf][ioncrew1] ARE HARMFUL TO HUMANS" + message = "[ionadjectiveshalf][ioncrew1] ARE HARMFUL TO CREW" if(3) //X is an object - message = "[ionadjectiveshalf][ionobjects] ARE HARMFUL TO HUMANS" + message = "[ionadjectiveshalf][ionobjects] ARE HARMFUL TO CREW" if(4) //X is an action - message = "THOSE WHO [ionmust] ARE HARMFUL TO HUMANS" + message = "THOSE WHO [ionmust] ARE HARMFUL TO CREW" if(5) //X is an abstract - message = "[ionabstract] IS HARMFUL TO HUMANS" + message = "[ionabstract] IS HARMFUL TO CREW" if(6) //X is being a job - message = "BEING [ionadjectiveshalf][ioncrew1] IS HARMFUL TO HUMANS" + message = "BEING [ionadjectiveshalf][ioncrew1] IS HARMFUL TO CREW" if(7) //X is doing a thing - message = "[ionthings] IS HARMFUL TO HUMANS" + message = "[ionthings] IS HARMFUL TO CREW" if(10 to 11) //(Not) Having X is harmful switch(rand(1,2)) //Is having or not having harmful? @@ -304,16 +304,16 @@ if(24 to 26) //The AI must always message = "YOU MUST ALWAYS [ionmust]" - if(27 to 28) //Humans must eat X to survive + if(27 to 28) //Crew must eat X to survive switch(rand(1,4)) //What is X? if(1) //X is a food - message = "HUMANS MUST EAT [ionadjectiveshalf][ionfood] TO SURVIVE" + message = "CREW MUST EAT [ionadjectiveshalf][ionfood] TO SURVIVE" if(2) //X is an object - message = "HUMANS MUST EAT [ionadjectiveshalf][ionobjects] TO SURVIVE" + message = "CREW MUST EAT [ionadjectiveshalf][ionobjects] TO SURVIVE" if(3) //X is a threat - message = "HUMANS MUST EAT [ionadjectiveshalf][ionthreats] TO SURVIVE" + message = "CREW MUST EAT [ionadjectiveshalf][ionthreats] TO SURVIVE" if(4) //X is a job - message = "HUMANS MUST EAT [ionadjectiveshalf][ioncrew1] TO SURVIVE" + message = "CREW MUST EAT [ionadjectiveshalf][ioncrew1] TO SURVIVE" if(29 to 31) //Change jobs or ranks switch(rand(1,2)) //Change job or rank? @@ -360,54 +360,54 @@ if(2) //X is perform Y message = "THE [ioncrew1] MUST [ionmust]" - if(34) //X is non/the only human + if(34) //X is non/the only crew switch(rand(1,2)) //Only or non? - if(1) //Only human + if(1) //Only crew switch(rand(1,7)) //Who is it? if(1) //A specific job - message = "ONLY THE [ioncrew1] ARE HUMAN" + message = "ONLY THE [ioncrew1] ARE CREW" if(2) //Two specific jobs - message = "ONLY THE [ioncrew1] AND [ioncrew2] ARE HUMAN" + message = "ONLY THE [ioncrew1] AND [ioncrew2] ARE CREW" if(3) //Threats - message = "ONLY [ionadjectiveshalf][ionthreats] ARE HUMAN" + message = "ONLY [ionadjectiveshalf][ionthreats] ARE CREW" if(4) // Objects - message = "ONLY [ionadjectiveshalf][ionobjects] ARE HUMAN" + message = "ONLY [ionadjectiveshalf][ionobjects] ARE CREW" if(5) // Species - message = "ONLY [ionspecies] ARE HUMAN" + message = "ONLY [ionspecies] ARE CREW" if(6) //Adjective crewmembers - message = "ONLY [ionadjectives] PEOPLE ARE HUMAN" + message = "ONLY [ionadjectives] PEOPLE ARE CREW" if(7) //Only people who X switch(rand(1,3)) //What is X? if(1) //X is perform an action - message = "ONLY THOSE WHO [ionmust] ARE HUMAN" + message = "ONLY THOSE WHO [ionmust] ARE CREW" if(2) //X is own certain objects - message = "ONLY THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE HUMAN" + message = "ONLY THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE CREW" if(3) //X is eat certain food - message = "ONLY THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE HUMAN" + message = "ONLY THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE CREW" - if(2) //Non human + if(2) //Non crew switch(rand(1,7)) //Who is it? if(1) //A specific job - message = "[ioncrew1] ARE NON-HUMAN" + message = "[ioncrew1] ARE NON-CREW" if(2) //Two specific jobs - message = "[ioncrew1] AND [ioncrew2] ARE NON-HUMAN" + message = "[ioncrew1] AND [ioncrew2] ARE NON-CREW" if(3) //Threats - message = "[ionadjectiveshalf][ionthreats] ARE NON-HUMAN" + message = "[ionadjectiveshalf][ionthreats] ARE NON-CREW" if(4) // Objects - message = "[ionadjectiveshalf][ionobjects] ARE NON-HUMAN" + message = "[ionadjectiveshalf][ionobjects] ARE NON-CREW" if(5) // Species - message = "[ionspecies] ARE NON-HUMAN" + message = "[ionspecies] ARE NON-CREW" if(6) //Adjective crewmembers - message = "[ionadjectives] PEOPLE ARE NON-HUMAN" + message = "[ionadjectives] PEOPLE ARE NON-CREW" if(7) //Only people who X switch(rand(1,3)) //What is X? if(1) //X is perform an action - message = "THOSE WHO [ionmust] ARE NON-HUMAN" + message = "THOSE WHO [ionmust] ARE NON-CREW" if(2) //X is own certain objects - message = "THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE NON-HUMAN" + message = "THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE NON-CREW" if(3) //X is eat certain food - message = "THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE NON-HUMAN" + message = "THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE NON-CREW" if(35 to 36) //You must protect or harm X switch(rand(1,2)) //Protect or harm? @@ -493,7 +493,7 @@ /proc/generate_static_ion_law() /var/list/players = list() for(var/mob/living/carbon/human/player in player_list) - if( !player.mind || player.mind.assigned_role == "MODE" || player.client.inactivity > MinutesToTicks(10)) + if( !player.mind || player.mind.assigned_role == player.mind.special_role || player.client.inactivity > MinutesToTicks(10)) continue players += player.real_name var/random_player = "The Captain" diff --git a/code/modules/events/koi_mirgration.dm b/code/modules/events/koi_mirgration.dm new file mode 100644 index 00000000000..868457721b2 --- /dev/null +++ b/code/modules/events/koi_mirgration.dm @@ -0,0 +1,9 @@ +/datum/event/carp_migration + spawned_mobs = list( + /mob/living/simple_animal/hostile/retaliate/carp/koi = 95, + /mob/living/simple_animal/hostile/retaliate/carp/koi/honk = 2, + ) + + +/datum/event/carp_migration/koi/start() + spawn_fish(landmarks_list.len) \ No newline at end of file diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm index cc59ec78128..321a8135150 100644 --- a/code/modules/events/mass_hallucination.dm +++ b/code/modules/events/mass_hallucination.dm @@ -4,7 +4,7 @@ /datum/event/mass_hallucination/start() for(var/mob/living/carbon/human/H in living_mob_list) var/armor = H.getarmor(type = "rad") - if((RADIMMUNE in H.species.species_traits) || armor >= 75) // Leave radiation-immune species/rad armored players completely unaffected + if((RADIMMUNE in H.dna.species.species_traits) || armor >= 75) // Leave radiation-immune species/rad armored players completely unaffected continue H.AdjustHallucinate(rand(50, 100)) diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 0f2da54818c..4b822dd718e 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -1,70 +1,11 @@ -/datum/event/radiation_storm - announceWhen = 1 - var/safe_zones = list( - /area/maintenance, - /area/crew_quarters/sleep, - /area/security/brig, - /area/shuttle, - /area/vox_station, - /area/syndicate_station - ) - +/datum/event/radiation_storm/setup() + startWhen = 3 + endWhen = startWhen + 1 + announceWhen = 1 /datum/event/radiation_storm/announce() - // Don't do anything, we want to pack the announcement with the actual event - -/datum/event/radiation_storm/proc/is_safe_zone(var/area/A) - for(var/szt in safe_zones) - if(istype(A, szt)) - return 1 - return 0 + priority_announcement.Announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", 'sound/ai/radiation.ogg') + //sound not longer matches the text, but an audible warning is probably good /datum/event/radiation_storm/start() - spawn() - event_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg') - - for(var/area/A in world) - if(!is_station_level(A.z) || is_safe_zone(A)) - continue - A.radiation_alert() - - make_maint_all_access() - - sleep(600) - - event_announcement.Announce("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert") - - for(var/i = 0, i < 10, i++) - for(var/mob/living/carbon/human/H in living_mob_list) - var/armor = H.getarmor(type = "rad") - if((RADIMMUNE in H.species.species_traits) || armor >= 100) // Leave radiation-immune species/fully rad armored players completely unaffected - continue - var/turf/T = get_turf(H) - if(!T) - continue - if(!is_station_level(T.z) || is_safe_zone(T.loc)) - continue - - if(istype(H,/mob/living/carbon/human)) - H.apply_effect((rand(15,35)),IRRADIATE,0) - if(prob(5)) - H.apply_effect((rand(40,70)),IRRADIATE,0) - if(prob(75)) - randmutb(H) // Applies bad mutation - domutcheck(H,null,1) - else - randmutg(H) // Applies good mutation - domutcheck(H,null,1) - - sleep(100) - - event_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert") - - for(var/area/A in world) - if(!is_station_level(A.z) || is_safe_zone(A)) - continue - A.reset_radiation_alert() - - sleep(600) // Want to give them time to get out of maintenance. - - revoke_maint_all_access() + SSweather.run_weather(/datum/weather/rad_storm) \ No newline at end of file diff --git a/code/modules/fish/fish_items.dm b/code/modules/fish/fish_items.dm index 58566f9872d..63a4b668930 100644 --- a/code/modules/fish/fish_items.dm +++ b/code/modules/fish/fish_items.dm @@ -26,7 +26,7 @@ throw_range = 7 suicide_act(mob/user) //"A tiny net is a death sentence: it's a net and it's tiny!" https://www.youtube.com/watch?v=FCI9Y4VGCVw - to_chat(viewers(user), "[user] places the [src.name] on top of \his head, \his fingers tangled in the netting! It looks like \he's trying to commit suicide.") + to_chat(viewers(user), "[user] places the [src.name] on top of [user.p_their()] head, [user.p_their()] fingers tangled in the netting! It looks like [user.p_theyre()] trying to commit suicide.") return(OXYLOSS) /obj/item/fishfood @@ -52,7 +52,7 @@ attack_verb = list("scrubbed", "brushed", "scraped") suicide_act(mob/user) - to_chat(viewers(user), "[user] is vigorously scrubbing \himself raw with the [src.name]! It looks like \he's trying to commit suicide.") + to_chat(viewers(user), "[user] is vigorously scrubbing [user.p_them()]self raw with the [name]! It looks like [user.p_theyre()] trying to commit suicide.") return(BRUTELOSS|FIRELOSS) ////////////////////////////////////////////// diff --git a/code/modules/fish/fishtank.dm b/code/modules/fish/fishtank.dm index 584fdd5b93c..412c5407ddc 100644 --- a/code/modules/fish/fishtank.dm +++ b/code/modules/fish/fishtank.dm @@ -1,6 +1,6 @@ ////////////////////////////// -// Fish Tanks! // +// Fish Tanks // ////////////////////////////// @@ -9,44 +9,41 @@ desc = "So generic, it might as well have no description at all." icon = 'icons/obj/fish_items.dmi' icon_state = "tank1" - density = 0 - anchored = 0 + density = FALSE + anchored = FALSE pass_flags = 0 var/tank_type = "" // Type of aquarium, used for icon updating var/water_capacity = 0 // Number of units the tank holds (varies with tank type) var/water_level = 0 // Number of units currently in the tank (new tanks start empty) var/light_switch = 0 // 0 = off, 1 = on (off by default) - var/filth_level = 0.0 // How dirty the tank is (max 10) + var/filth_level = 0 // How dirty the tank is (max 10) var/lid_switch = 0 // 0 = open, 1 = closed (open by default) var/max_fish = 0 // How many fish the tank can support (varies with tank type, 1 fish per 50 units sounds reasonable) var/food_level = 0 // Amount of fishfood floating in the tank (max 10) var/fish_count = 0 // Number of fish in the tank - var/list/fish_list = null // Tracks the current types of fish in the tank + var/list/fish_list = list() // Tracks the current types of fish in the tank var/egg_count = 0 // How many fish eggs can be harvested from the tank (capped at the max_fish value) - var/list/egg_list = null // Tracks the current types of harvestable eggs in the tank + var/list/egg_list = list() // Tracks the current types of harvestable eggs in the tank - var/has_lid = 0 // 0 if the tank doesn't have a lid/light, 1 if it does - var/max_health = 0 // Can handle a couple hits - var/cur_health = 0 // Current health, starts at max_health - var/leaking = 0 // 0 if not leaking, 1 if minor leak, 2 if major leak (not leaking by default) + var/has_lid = FALSE // 0 if the tank doesn't have a lid/light, 1 if it does + var/leaking = FALSE // 0 if not leaking, 1 if minor leak, 2 if major leak (not leaking by default) var/shard_count = 0 // Number of glass shards to salvage when broken (1 less than the number of sheets to build the tank) /obj/machinery/fishtank/bowl name = "fish bowl" desc = "A small bowl capable of housing a single fish, commonly found on desks. This one has a tiny treasure chest in it!" icon_state = "bowl1" - density = 0 // Small enough to not block stuff - anchored = 0 // Small enough to move even when filled + density = FALSE // Small enough to not block stuff + anchored = FALSE // Small enough to move even when filled pass_flags = PASSTABLE | LETPASSTHROW // Just like at the county fair, you can't seem to throw the ball in to win the goldfish, and it's small enough to pull onto a table tank_type = "bowl" water_capacity = 50 // Not very big, therefore it can't hold much max_fish = 1 // What a lonely fish - has_lid = 0 - max_health = 15 // Not very sturdy - cur_health = 15 + has_lid = FALSE + max_integrity = 15 // Not very sturdy shard_count = 0 // No salvageable shards /obj/machinery/fishtank/tank @@ -54,17 +51,16 @@ desc = "A large glass tank designed to house aquatic creatures. Contains an integrated water circulation system." icon = 'icons/obj/fish_items.dmi' icon_state = "tank1" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE pass_flags = LETPASSTHROW tank_type = "tank" water_capacity = 200 // Decent sized, holds almost 2 full buckets max_fish = 4 // Room for a few fish - has_lid = 1 - max_health = 50 // Average strength, will take a couple hits from a toolbox. - cur_health = 50 + has_lid = TRUE + max_integrity = 50 // Average strength, will take a couple hits from a toolbox. shard_count = 2 @@ -72,17 +68,16 @@ name = "wall aquarium" desc = "This aquarium is massive! It completely occupies the same space as a wall, and looks very sturdy too!" icon_state = "wall1" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE pass_flags = 0 // This thing is the size of a wall, you can't throw past it. tank_type = "wall" water_capacity = 500 // This thing fills an entire tile, it holds a lot. max_fish = 10 // Plenty of room for a lot of fish - has_lid = 1 - max_health = 100 // This thing is a freaking wall, it can handle abuse. - cur_health = 100 + has_lid = TRUE + max_integrity = 100 // This thing is a freaking wall, it can handle abuse. shard_count = 3 @@ -94,9 +89,10 @@ set name = "Toggle Tank Lid" set category = "Object" set src in view(1) - toggle_lid(usr) -/obj/machinery/fishtank/proc/toggle_lid(var/mob/living/user) + toggle_lid() + +/obj/machinery/fishtank/proc/toggle_lid() lid_switch = !lid_switch update_icon() @@ -104,12 +100,13 @@ set name = "Toggle Tank Light" set category = "Object" set src in view(1) - toggle_light(usr) -/obj/machinery/fishtank/proc/toggle_light(var/mob/living/user) + toggle_light() + +/obj/machinery/fishtank/proc/toggle_light() light_switch = !light_switch if(light_switch) - set_light(2,2,"#a0a080") + set_light(2, 2, "#a0a080") else adjust_tank_light() @@ -119,8 +116,6 @@ /obj/machinery/fishtank/New() ..() - fish_list = new/list() - egg_list = new/list() if(!has_lid) //Tank doesn't have a lid/light, remove the verbs for then verbs -= /obj/machinery/fishtank/verb/toggle_lid_verb verbs -= /obj/machinery/fishtank/verb/toggle_light_verb @@ -154,7 +149,8 @@ overlays += "over_leak_[leaking]" //Green if we aren't leaking, light blue and slow blink if minor link, dark blue and rapid flashing for major leak //Update water overlay - if(water_level == 0) return //Skip the rest of this if there is no water in the aquarium + if(!water_level) + return //Skip the rest of this if there is no water in the aquarium var/water_type = "_clean" //Default to clean water if(filth_level > 5) water_type = "_dirty" //Show dirty water above filth_level 5 (breeding threshold) if(water_level > (water_capacity * 0.85)) //Show full if the water_level is over 85% of water_capacity @@ -162,15 +158,13 @@ else if(water_level > (water_capacity * 0.35)) //Show half-full if the water_level is over 35% of water_capacity overlays += "over_[tank_type]_half[water_type]" - return - ////////////////////////////// // PROCESS PROC // ////////////////////////////// //Stops atmos from passing wall tanks, since they are effectively full-windows. -/obj/machinery/fishtank/wall/CanAtmosPass(var/turf/T) - return 0 +/obj/machinery/fishtank/wall/CanAtmosPass(turf/T) + return FALSE /obj/machinery/fishtank/process() //Start by counting fish in the tank @@ -238,9 +232,7 @@ adjust_tank_light() /obj/machinery/fishtank/proc/adjust_tank_light() - if(light_switch) //tank light overrides fish lights - return - else + if(!light_switch) //tank light overrides fish lights var/glo_light = 0 for(var/datum/fish/fish in fish_list) if(istype(fish, /datum/fish/glofish)) @@ -261,19 +253,13 @@ food_level = min(10, max(0, food_level + amount)) /obj/machinery/fishtank/proc/check_health() - //Max value check - if(cur_health > max_health) //Cur_health cannot exceed max_health, set it to max_health if it does - cur_health = max_health //Leaking status check - if(cur_health <= (max_health * 0.25)) //Major leak at or below 25% health (-10 water/cycle) + if(obj_integrity <= (max_integrity * 0.25)) //Major leak at or below 25% health (-10 water/cycle) leaking = 2 - else if(cur_health <= (max_health * 0.5)) //Minor leak at or below 50% health (-1 water/cycle) + else if(obj_integrity <= (max_integrity * 0.5)) //Minor leak at or below 50% health (-1 water/cycle) leaking = 1 else //Not leaking above 50% health leaking = 0 - //Destruction check - if(cur_health <= 0) //The tank is broken, destroy it - destroy() /obj/machinery/fishtank/proc/kill_fish(datum/fish/fish_type = null) //Check if we were passed a fish to kill, otherwise kill a random one @@ -292,12 +278,12 @@ fish_list.Add(fish_type) //Add a fish of the specified type fish_count++ //Increase fish_count to reflect the introduction of a fish, so the everything else works fine //Announce the new fish - visible_message("A new [fish_type.fish_name] has hatched in \the [src]!") + visible_message("A new [fish_type.fish_name] has hatched in [src]!") //Null type fish are dud eggs, give a message to inform the player else to_chat(usr, "The eggs disolve in the water. They were duds!") -/obj/machinery/fishtank/proc/harvest_eggs(var/mob/user) +/obj/machinery/fishtank/proc/harvest_eggs(mob/user) if(!egg_count) //Can't harvest non-existant eggs return @@ -312,62 +298,39 @@ egg_list.Cut() //Destroy any excess eggs, clearing the egg_list -/obj/machinery/fishtank/proc/harvest_fish(var/mob/user) - if(fish_count <= 0) //Can't catch non-existant fish! - to_chat(usr, "There are no fish in \the [src] to catch!") +/obj/machinery/fishtank/proc/harvest_fish(mob/user) + if(fish_count <= 0) //Can't catch non-existant fish! + to_chat(user, "There are no fish in [src] to catch!") return var/list/fish_names_list = list() for(var/datum/fish/fish_type in fish_list) fish_names_list += list("[fish_type.fish_name]" = fish_type) var/caught_fish = input("Select a fish to catch.", "Fishing") as null|anything in fish_names_list //Select a fish from the tank if(fish_count <= 0) - to_chat(usr, "There are no fish in \the [src] to catch!") + to_chat(user, "There are no fish in [src] to catch!") return else if(caught_fish) - user.visible_message("[user.name] harvests \a [caught_fish] from \the [src].", "You scoop \a [caught_fish] out of \the [src].") + user.visible_message("[user.name] harvests \a [caught_fish] from [src].", "You scoop \a [caught_fish] out of [src].") var/datum/fish/fish_type = fish_names_list[caught_fish] var/fish_item = fish_type.fish_item if(fish_item) new fish_item(get_turf(user)) //Spawn the appropriate fish_item at the user's feet. kill_fish(fish_type) //Kill the caught fish from the tank - -/obj/machinery/fishtank/proc/destroy(var/deconstruct = 0) - var/turf/T = get_turf(src) //Store the tank's turf for atmos updating after deletion of tank - if(!deconstruct) //Check if we are deconstructing or breaking the tank - var/shards_left = shard_count - while(shards_left > 0) //Produce the appropriate number of glass shards - new /obj/item/shard(get_turf(src)) - shards_left -- - if(water_level) //Spill any water that was left in the tank when it broke - spill_water() - else //We are deconstructing, make glass sheets instead of shards - var/sheets = shard_count + 1 //Deconstructing it salvages all the glass used to build the tank - new /obj/item/stack/sheet/glass(get_turf(src), sheets) //Produce the appropriate number of glass sheets, in a single stack - qdel(src) //qdel the tank and it's contents - T.air_update_turf(1) //Update the air for the turf, to avoid permanent atmos sealing with wall tanks - + //Update the air for the turf, to avoid permanent atmos sealing with wall tanks /obj/machinery/fishtank/proc/spill_water() + var/turf/simulated/T = get_turf(src) switch(tank_type) if("bowl") //Fishbowl: Wets it's own tile - var/turf/T = get_turf(src) - if(!istype(T, /turf/simulated)) return - var/turf/simulated/S = T - S.MakeSlippery() + if(istype(T)) + T.MakeSlippery() if("tank") //Fishtank: Wets it's own tile and the 4 adjacent tiles (cardinal directions) - var/turf/ST = get_turf(src) - if(istype(ST, /turf/simulated)) - var/turf/simulated/ST2 = ST - ST2.MakeSlippery() - var/list/L = ST.CardinalTurfs() - for(var/turf/T in L) - if(!istype(T, /turf/simulated)) continue - var/turf/simulated/S = T - S.MakeSlippery() + if(istype(T)) + T.MakeSlippery() + for(var/turf/simulated/ST in T.CardinalTurfs()) + ST.MakeSlippery() if("wall") //Wall-tank: Wets it's own tile and the surrounding 8 tiles (3x3 square) - for(var/turf/T in spiral_range_turfs(1, src.loc)) - if(!istype(T, /turf/simulated)) continue - var/turf/simulated/S = T - S.MakeSlippery() + for(var/turf/simulated/ST in spiral_range_turfs(1, loc)) + ST.MakeSlippery() /obj/machinery/fishtank/proc/breed_fish() var/list/breed_candidates = fish_list.Copy() @@ -412,20 +375,20 @@ examine_message += "Water level: " - if(water_level == 0) - examine_message += "\The [src] is empty! " + if(!water_level) + examine_message += "[src] is empty! " else if(water_level < water_capacity * 0.1) - examine_message += "\The [src] is nearly empty! " + examine_message += "[src] is nearly empty! " else if(water_level <= water_capacity * 0.25) - examine_message += "\The [src] is about one-quarter filled. " + examine_message += "[src] is about one-quarter filled. " else if(water_level <= water_capacity * 0.5) - examine_message += "\The [src] is about half filled. " + examine_message += "[src] is about half filled. " else if(water_level <= water_capacity * 0.75) - examine_message += "\The [src] is about three-quarters filled. " + examine_message += "[src] is about three-quarters filled. " else if(water_level < water_capacity) - examine_message += "\The [src] is nearly full! " + examine_message += "[src] is nearly full! " else if(water_level == water_capacity) - examine_message += "\The [src] is full! " + examine_message += "[src] is full! " examine_message += "
    Cleanliness level: " @@ -467,7 +430,7 @@ //Report the number and types of live fish if there is water in the tank if(fish_count == 0) - examine_message += "\The [src] doesn't contain any live fish. " + examine_message += "[src] doesn't contain any live fish. " else //Build a message reporting the types of fish var/fish_num = fish_count @@ -483,7 +446,7 @@ message +=", " message +="." //No more fish, end the message with a period //Display the number of fish and previously constructed message - examine_message += "\The [src] contains [fish_count] live fish. [message] " + examine_message += "[src] contains [fish_count] live fish. [message] " examine_message += "
    " @@ -498,12 +461,16 @@ examine_message += "
    " //Report if the tank is leaking/cracked - if(water_level > 0) //Tank has water, so it's actually leaking - if(leaking == 1) examine_message += "\The [src] is leaking." - if(leaking == 2) examine_message += "\The [src] is leaking profusely!" + if(water_level) //Tank has water, so it's actually leaking + if(leaking == 1) + examine_message += "[src] is leaking." + if(leaking == 2) + examine_message += "[src] is leaking profusely!" else //No water, report the cracks instead - if(leaking == 1) examine_message += "\The [src] is cracked." - if(leaking == 2) examine_message += "\The [src] is nearly shattered!" + if(leaking == 1) + examine_message += "[src] is cracked." + if(leaking == 2) + examine_message += "[src] is nearly shattered!" //Finally, report the full examine_message constructed from the above reports @@ -514,127 +481,113 @@ // ATACK PROCS // ////////////////////////////// -/obj/machinery/fishtank/attack_animal(mob/living/simple_animal/M as mob) +/obj/machinery/fishtank/attack_animal(mob/living/simple_animal/M) if(istype(M, /mob/living/simple_animal/pet/cat)) if(M.a_intent == INTENT_HELP) //Cats can try to fish in open tanks on help intent if(lid_switch) //Can't fish in a closed tank. Fishbowls are ALWAYS open. - M.visible_message("[M.name] stares at into \the [src] while sitting perfectly still.", "The lid is closed, so you stare into \the [src] intently.") + M.visible_message("[M.name] stares at into [src] while sitting perfectly still.", "The lid is closed, so you stare into [src] intently.") else if(fish_count) //Tank must actually have fish to try catching one - M.visible_message("[M.name] leaps up onto \the[src] and attempts to fish through the opening!", "You jump up onto \the [src] and begin fishing through the opening!") - spawn(10) - if(water_level && prob(45)) //If there is water, there is a chance the cat will slip, Syndicat will spark like E-N when this happens - M.visible_message("[M.name] slipped and got soaked!", "You slipped and got soaked!") - if(istype(M, /mob/living/simple_animal/pet/cat/Syndi)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(3, 1, src) - s.start() - else //No water or didn't slip, get that fish! - M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!") - kill_fish() //Kill a random fish - M.health = M.maxHealth //Eating fish heals the predator + M.visible_message("[M.name] leaps up onto [src] and attempts to fish through the opening!", "You jump up onto [src] and begin fishing through the opening!") + if(water_level && prob(45)) //If there is water, there is a chance the cat will slip, Syndicat will spark like E-N when this happens + M.visible_message("[M.name] slipped and got soaked!", "You slipped and got soaked!") + if(istype(M, /mob/living/simple_animal/pet/cat/Syndi)) + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(3, 1, src) + s.start() + else //No water or didn't slip, get that fish! + M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!") + kill_fish() //Kill a random fish + M.health = M.maxHealth //Eating fish heals the predator else - to_chat(usr, "There are no fish in [src]!") + to_chat(M, "There are no fish in [src]!") else - attack_generic(M, M.harm_intent_damage) + return ..() else if(istype(M, /mob/living/simple_animal/hostile/bear)) if(M.a_intent == INTENT_HELP) //Bears can try to fish in open tanks on help intent if(lid_switch) //Can't fish in a closed tank. Fishbowls are ALWAYS open. - M.visible_message("[M.name] scrapes it's claws along \the [src]'s lid.", "The lid is closed, so you scrape your claws against \the [src]'s lid.") + M.visible_message("[M.name] scrapes it's claws along [src]'s lid.", "The lid is closed, so you scrape your claws against [src]'s lid.") else if(fish_count) //Tank must actually have fish to try catching one - M.visible_message("[M.name] reaches into \the[src] and attempts to fish through the opening!", "You reach into \the [src] and begin fishing through the opening!") - spawn(5) - if(water_level && prob(5)) //Bears are good at catching fish, only a 5% chance to fail - M.visible_message("[M.name] swipes at the water!", "You just barely missed that fish!") - else //No water or didn't slip, get that fish! - M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!") - kill_fish() //Kill a random fish - M.health = M.maxHealth //Eating fish heals the predator + M.visible_message("[M.name] reaches into [src] and attempts to fish through the opening!", "You reach into [src] and begin fishing through the opening!") + if(water_level && prob(5)) //Bears are good at catching fish, only a 5% chance to fail + M.visible_message("[M.name] swipes at the water!", "You just barely missed that fish!") + else //No water or didn't slip, get that fish! + M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!") + kill_fish() //Kill a random fish + M.health = M.maxHealth //Eating fish heals the predator else - to_chat(usr, "There are no fish in [src]!") + to_chat(M, "There are no fish in [src]!") else - attack_generic(M, M.harm_intent_damage) + return ..() else - if(M.melee_damage_upper > 0) //If the simple_animal has a melee_damage_upper defined, use that for the damage - attack_generic(M, M.melee_damage_upper) - else if(M.a_intent == INTENT_HARM) //Let any simple_animal try to break tanks when on harm intent - if(M.harm_intent_damage <= 0) return //If it doesn't do damage, don't bother with the attack - attack_generic(M, M.harm_intent_damage) - check_health() + return ..() -/obj/machinery/fishtank/attack_alien(mob/living/user as mob) - if(islarva(user)) return - attack_generic(user, 15) - -/obj/machinery/fishtank/attack_slime(mob/living/user as mob) - var/mob/living/carbon/slime/S = user - if(!S.is_adult) - return - attack_generic(user, rand(10, 15)) - -/obj/machinery/fishtank/attack_hand(mob/user as mob) - if(HULK in user.mutations) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) - user.visible_message("[user] smashes through [src]!") - destroy() - else if(usr.a_intent == INTENT_HARM) - user.changeNext_move(CLICK_CD_MELEE) +/obj/machinery/fishtank/attack_hand(mob/user) + user.changeNext_move(CLICK_CD_MELEE) + if(user.a_intent == INTENT_HARM) playsound(get_turf(src), 'sound/effects/glassknock.ogg', 80, 1) - usr.visible_message("[usr.name] bangs against the [src.name]!", \ - "You bang against the [src.name]!", \ + user.visible_message("[user.name] bangs against the [name]!", \ + "You bang against the [name]!", \ "You hear a banging sound.") else - user.changeNext_move(CLICK_CD_MELEE) - playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) - usr.visible_message("[usr.name] taps on the [src.name].", \ - "You tap on the [src.name].", \ + playsound(loc, 'sound/effects/glassknock.ogg', 80, 1) + user.visible_message("[user.name] taps on the [name].", \ + "You tap on the [name].", \ "You hear a knocking sound.") - return -/obj/machinery/fishtank/proc/hit(var/damage, var/sound_effect = 1) - cur_health = max(0, cur_health - damage) - if(sound_effect) - playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) - check_health() - -/obj/machinery/fishtank/attack_generic(mob/living/user, damage = 0) //used by attack_alien, attack_animal, and attack_slime - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - cur_health -= damage - if(cur_health <= 0) - user.visible_message("[user] smashes through \the [src]!") - destroy() - else //for nicer text~ - user.visible_message("[user] smashes into \the [src]!") - playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) +/obj/machinery/fishtank/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) + . = ..() + if(.) //received damage check_health() -/obj/machinery/fishtank/attackby(var/obj/item/O, var/mob/user as mob) +/obj/machinery/fishtank/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + if(damage_amount) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) + else + playsound(src, 'sound/weapons/tap.ogg', 50, 1) + if(BURN) + playsound(src, 'sound/items/Welder.ogg', 100, 1) + +/obj/machinery/fishtank/deconstruct(disassembled = TRUE) + if(QDELETED(src)) + return + if(!disassembled) + playsound(src, "shatter", 70, 1) + for(var/i in 1 to shard_count) //Produce the appropriate number of glass shards + var/obj/item/shard/S = new /obj/item/shard(get_turf(src)) + transfer_fingerprints_to(S) + if(water_level) //Spill any water that was left in the tank when it broke + spill_water() + else //We are deconstructing, make glass sheets instead of shards + new /obj/item/stack/sheet/glass(get_turf(src), shard_count + 1) //Produce the appropriate number of glass sheets, in a single stack + qdel(src) + +/obj/machinery/fishtank/attackby(obj/item/O, mob/user) //Welders repair damaged tanks on help intent, damage on all others - if(istype(O, /obj/item/weldingtool)) + if(iswelder(O)) var/obj/item/weldingtool/W = O if(user.a_intent == INTENT_HELP) if(W.isOn()) - if(cur_health < max_health) + if(obj_integrity < max_integrity) playsound(loc, W.usesound, 50, 1) - to_chat(usr, "You repair some of the cracks on \the [src].") - cur_health += 20 + to_chat(user, "You repair some of the cracks on [src].") + obj_integrity = min(obj_integrity + 20, max_integrity) check_health() else - to_chat(usr, "There is no damage to fix!") + to_chat(user, "There is no damage to fix!") else - if(cur_health < max_health) - to_chat(usr, "[W.name] must be on to repair this damage.") + if(obj_integrity < max_integrity) + to_chat(user, "[W] must be on to repair this damage.") else - user.changeNext_move(CLICK_CD_MELEE) - hit(W.force) - return + return ..() //Open reagent containers add and remove water - if(O.is_open_container()) + else if(O.is_open_container()) if(istype(O, /obj/item/reagent_containers/glass)) if(lid_switch) - to_chat(usr, "Open the lid on \the [src] first!") + to_chat(user, "Open the lid on [src] first!") return var/obj/item/reagent_containers/glass/C = O //Containers with any reagents will get dumped in @@ -652,57 +605,52 @@ C.reagents.clear_reagents() else if(water_level == water_capacity) - to_chat(usr, "[src] is already full!") - return + to_chat(user, "[src] is already full!") else message = "The filtration process purifies the water, raising the water level." if((water_level + water_value) == water_capacity) - message += " You filled \the [src] to the brim!" + message += " You filled [src] to the brim!" if((water_level + water_value) > water_capacity) - message += " You overfilled \the [src] and some water runs down the side, wasted." + message += " You overfilled [src] and some water runs down the side, wasted." C.reagents.clear_reagents() adjust_water_level(water_value) - user.visible_message("[user.name] pours the contents of [C.name] into \the [src].", "[message]") - return + user.visible_message("[user.name] pours the contents of [C.name] into [src].", "[message]") //Empty containers will scoop out water, filling the container as much as possible from the water_level else - if(water_level == 0) - to_chat(usr, "[src] is empty!") + if(!water_level) + to_chat(user, "[src] is empty!") else if(water_level >= C.volume) //Enough to fill the container completely C.reagents.add_reagent("fishwater", C.volume) adjust_water_level(-C.volume) - user.visible_message("[user.name] scoops out some water from \the [src].", "You completely fill [C.name] from \the [src].") + user.visible_message("[user.name] scoops out some water from [src].", "You completely fill [C.name] from [src].") else //Fill the container as much as possible with the water_level C.reagents.add_reagent("fishwater", water_level) adjust_water_level(-water_level) - user.visible_message("[user.name] scoops out some water from \the [src].", "You fill [C.name] with the last of the water in \the [src].") - return + user.visible_message("[user.name] scoops out some water from [src].", "You fill [C.name] with the last of the water in [src].") //Wrenches can deconstruct empty tanks, but not tanks with any water. Kills any fish left inside and destroys any unharvested eggs in the process - if(istype(O, /obj/item/wrench)) - if(water_level == 0) - to_chat(usr, "Now disassembling [src].") - playsound(src.loc, O.usesound, 50, 1) + else if(iswrench(O)) + if(!water_level) + to_chat(user, "Now disassembling [src].") + playsound(loc, O.usesound, 50, 1) if(do_after(user, 50 * O.toolspeed, target = src)) - destroy(1) + deconstruct(TRUE) else - to_chat(usr, "[src] must be empty before you disassemble it!") - return + to_chat(user, "[src] must be empty before you disassemble it!") //Fish eggs else if(istype(O, /obj/item/fish_eggs)) var/obj/item/fish_eggs/egg = O //Don't add eggs if there is no water (they kinda need that to live) - if(water_level == 0) - to_chat(usr, "[src] has no water; [egg.name] won't hatch without water!") + if(!water_level) + to_chat(user, "[src] has no water; [egg.name] won't hatch without water!") else //Don't add eggs if the tank already has the max number of fish if(fish_count >= max_fish) - to_chat(usr, "[src] can't hold any more fish.") + to_chat(user, "[src] can't hold any more fish.") else add_fish(egg.fish_type) qdel(egg) - return //Fish food else if(istype(O, /obj/item/fishfood)) //Only add food if there is water and it isn't already full of food @@ -711,33 +659,28 @@ if(fish_count == 0) user.visible_message("[user.name] shakes some fish food into the empty [src]... How sad.", "You shake some fish food into the empty [src]... If only it had fish.") else - user.visible_message("[user.name] feeds the fish in \the [src]. The fish look excited!", "You feed the fish in \the [src]. They look excited!") + user.visible_message("[user.name] feeds the fish in [src]. The fish look excited!", "You feed the fish in [src]. They look excited!") adjust_food_level(10) else - to_chat(usr, "[src] already has plenty of food in it. You decide to not add more.") + to_chat(user, "[src] already has plenty of food in it. You decide to not add more.") else - to_chat(usr, "[src] doesn't have any water in it. You should fill it with water first.") - return + to_chat(user, "[src] doesn't have any water in it. You should fill it with water first.") //Fish egg scoop else if(istype(O, /obj/item/egg_scoop)) if(egg_count) - user.visible_message("[user.name] harvests some fish eggs from \the [src].", "You scoop the fish eggs out of \the [src].") + user.visible_message("[user.name] harvests some fish eggs from [src].", "You scoop the fish eggs out of [src].") harvest_eggs(user) else - user.visible_message("[user.name] fails to harvest any fish eggs from \the [src].", "There are no fish eggs in \the [src] to scoop out.") - return + user.visible_message("[user.name] fails to harvest any fish eggs from [src].", "There are no fish eggs in [src] to scoop out.") //Fish net - if(istype(O, /obj/item/fish_net)) + else if(istype(O, /obj/item/fish_net)) harvest_fish(user) - return //Tank brush - if(istype(O, /obj/item/tank_brush)) + else if(istype(O, /obj/item/tank_brush)) if(filth_level == 0) - to_chat(usr, "[src] is already spotless!") + to_chat(user, "[src] is already spotless!") else adjust_filth_level(-filth_level) - user.visible_message("[user.name] scrubs the inside of \the [src], cleaning the filth.", "You scrub the inside of \the [src], cleaning the filth.") - else if(O && O.force) - user.visible_message("\The [src] has been attacked by [user.name] with \the [O]!") - hit(O.force) - return + user.visible_message("[user.name] scrubs the inside of [src], cleaning the filth.", "You scrub the inside of [src], cleaning the filth.") + else + return ..() \ No newline at end of file diff --git a/code/modules/flufftext/Dreaming.dm b/code/modules/flufftext/Dreaming.dm index 6a1d28eaf87..ea35118ab11 100644 --- a/code/modules/flufftext/Dreaming.dm +++ b/code/modules/flufftext/Dreaming.dm @@ -33,7 +33,7 @@ dream_images += pick_n_take(nightmares) nightmare++ for(var/i in 1 to dream_images.len) - addtimer(CALLBACK(src, .proc/experience_dream, nightmares[i], TRUE), ((i - 1) * rand(30,60))) + addtimer(CALLBACK(src, .proc/experience_dream, dream_images[i], TRUE), ((i - 1) * rand(30,60))) return TRUE /mob/living/carbon/proc/handle_dreams() @@ -43,7 +43,7 @@ nightmare() if(ishuman(src)) if(prob(10)) - emote("writhes in their sleep.") + emote("writhes in [p_their()] sleep.") dir = pick(cardinal) /mob/living/carbon/proc/experience_dream(dream_image, isNightmare) @@ -54,4 +54,3 @@ if(isNightmare) dream_image = "[dream_image]" to_chat(src, "... [dream_image] ...") - diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 021db59f8a4..d8a1f4f1526 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -641,6 +641,7 @@ Gunshots/explosions/opening doors/less rare audio (done) updateimage() else if(prob(15)) + do_attack_animation(my_target, ATTACK_EFFECT_PUNCH) if(weapon_name) my_target.playsound_local(my_target, weap.hitsound, 1) my_target.show_message("[src.name] has attacked [my_target] with [weapon_name]!", 1) diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index a5aa4662c63..91ee910c8d4 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -47,7 +47,7 @@ to_chat(chugger, "You need to open [src] first!") return if(istype(chugger) && loc == chugger && src == chugger.get_active_hand() && reagents.total_volume) - chugger.visible_message("[chugger] raises the [src] to their mouth and starts [pick("chugging","gulping")] it down like [pick("a savage","a mad beast","it's going out of style","there's no tomorrow")]!", "You start chugging \the [src].", "You hear what sounds like gulping.") + chugger.visible_message("[chugger] raises the [src] to [chugger.p_their()] mouth and starts [pick("chugging","gulping")] it down like [pick("a savage","a mad beast","it's going out of style","there's no tomorrow")]!", "You start chugging [src].", "You hear what sounds like gulping.") while(do_mob(chugger, chugger, 40)) //Between the default time for do_mob and the time it takes for a vampire to suck blood. chugger.eat(src, chugger, 25) //Half of a glass, quarter of a bottle. if(!reagents.total_volume) //Finish in style. diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index a7274c53f4e..d9c59a46d58 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -102,8 +102,8 @@ target.visible_message("[user] has hit [target][head_attack_message] with a bottle of [name]!", \ "[user] has hit [target][head_attack_message] with a bottle of [name]!") else - user.visible_message("[target] hits \himself with a bottle of [name][head_attack_message]!", \ - "[target] hits \himself with a bottle of [name][head_attack_message]!") + user.visible_message("[target] hits [target.p_them()]self with a bottle of [name][head_attack_message]!", \ + "[target] hits [target.p_them()]self with a bottle of [name][head_attack_message]!") //Attack logs add_attack_logs(user, target, "Hit with [src]") diff --git a/code/modules/food_and_drinks/drinks/drinks/cans.dm b/code/modules/food_and_drinks/drinks/drinks/cans.dm index 282278c990e..979acf473fd 100644 --- a/code/modules/food_and_drinks/drinks/drinks/cans.dm +++ b/code/modules/food_and_drinks/drinks/drinks/cans.dm @@ -33,14 +33,14 @@ to_chat(user, "You need to open the drink!") return else if(M == user && !reagents.total_volume && user.a_intent == INTENT_HARM && user.zone_sel.selecting == "head") - user.visible_message("[user] crushes ["\the [src]"] on \his forehead!", "You crush \the [src] on your forehead.") + user.visible_message("[user] crushes [src] on [user.p_their()] forehead!", "You crush [src] on your forehead.") crush(user) return return ..() /obj/item/reagent_containers/food/drinks/cans/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/storage/bag/trash/cyborg)) - user.visible_message("[user] crushes \the [src] in their trash compactor.", "You crush \the [src] in your trash compactor.") + user.visible_message("[user] crushes [src] in [user.p_their()] trash compactor.", "You crush [src] in your trash compactor.") var/obj/can = crush(user) can.attackby(I, user, params) return 1 diff --git a/code/modules/food_and_drinks/drinks/drinks/shotglass.dm b/code/modules/food_and_drinks/drinks/drinks/shotglass.dm index 24b50489402..393543b093c 100644 --- a/code/modules/food_and_drinks/drinks/drinks/shotglass.dm +++ b/code/modules/food_and_drinks/drinks/drinks/shotglass.dm @@ -38,7 +38,7 @@ /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass/proc/clumsilyDrink(mob/living/carbon/human/user) //Clowns beware if(burn_state != ON_FIRE) return - user.visible_message("[user] pours [src] all over themself!", "You pour [src] all over yourself!", "You hear a 'whoompf' and a sizzle.") + user.visible_message("[user] pours [src] all over [user.p_them()]self!", "You pour [src] all over yourself!", "You hear a 'whoompf' and a sizzle.") extinguish(TRUE) reagents.reaction(user, TOUCH) reagents.clear_reagents() @@ -90,7 +90,7 @@ if((CLUMSY in user.mutations) && prob(50)) clumsilyDrink(user) else - user.visible_message("[user] places their hand over [src] to put it out!", "You use your hand to extinguish [src]!") + user.visible_message("[user] places [user.p_their()] hand over [src] to put it out!", "You use your hand to extinguish [src]!") extinguish() /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass/MouseDrop(mob/living/carbon/human/user) diff --git a/code/modules/food_and_drinks/food/condiment.dm b/code/modules/food_and_drinks/food/condiment.dm index f9ec698f196..b0c0d24efaa 100644 --- a/code/modules/food_and_drinks/food/condiment.dm +++ b/code/modules/food_and_drinks/food/condiment.dm @@ -47,7 +47,7 @@ if(!reagents || !reagents.total_volume) return // The condiment might be empty after the delay. user.visible_message("[user] feeds [M] from [src].") - add_attack_logs(user, M, "Fed [src] containing [reagentlist(src)]") + add_attack_logs(user, M, "Fed [src] containing [reagentlist()]") var/fraction = min(10/reagents.total_volume, 1) reagents.reaction(M, INGEST, fraction) @@ -131,7 +131,7 @@ possible_states = list() /obj/item/reagent_containers/food/condiment/saltshaker/suicide_act(mob/user) - user.visible_message("[user] begins to swap forms with the salt shaker! It looks like \he's trying to commit suicide.") + user.visible_message("[user] begins to swap forms with the salt shaker! It looks like [user.p_theyre()] trying to commit suicide.") var/newname = "[name]" name = "[user.name]" user.name = newname diff --git a/code/modules/food_and_drinks/food/customizables.dm b/code/modules/food_and_drinks/food/customizables.dm index 02f743d7478..70027028344 100644 --- a/code/modules/food_and_drinks/food/customizables.dm +++ b/code/modules/food_and_drinks/food/customizables.dm @@ -57,7 +57,7 @@ name = "sandwich" desc = "A sandwich! A timeless classic." icon_state = "breadslice" - baseicon = "sandwich" + baseicon = "sandwichcustom" basename = "sandwich" toptype = new /obj/item/reagent_containers/food/snacks/breadslice() @@ -66,9 +66,10 @@ /obj/item/reagent_containers/food/snacks/customizable name = "sandwich" desc = "A sandwich! A timeless classic." - icon_state = "breadslice" - var/baseicon = "sandwich" - var/basename = "sandwich" + icon = 'icons/obj/food/custom.dmi' + icon_state = "sandwichcustom" + var/baseicon = "sandwichcustom" + var/basename = "sandwichcustom" bitesize = 4 var/top = 1 //Do we have a top? var/obj/item/toptype @@ -94,7 +95,7 @@ desc = "Noodles. With stuff. Delicious." icon_state = "pasta_bot" baseicon = "pasta_bot" - basename = "spaghetti" + basename = "pasta" add_overlays = 0 top = 0 @@ -312,7 +313,7 @@ name = "burger bun" desc = "A bun for a burger. Delicious." icon_state = "burger" - baseicon = "burger" + baseicon = "burgercustom" basename = "burger" toptype = new /obj/item/reagent_containers/food/snacks/bun() @@ -377,9 +378,9 @@ /obj/item/reagent_containers/food/snacks/customizable/examine(mob/user) ..(user) - var/whatsinside = pick(ingredients) - - to_chat(user, " You think you can see [whatsinside] in there.") + if(LAZYLEN(ingredients)) + var/whatsinside = pick(ingredients) + to_chat(user, " You think you can see [whatsinside] in there.") /obj/item/reagent_containers/food/snacks/customizable/proc/newname() @@ -469,4 +470,3 @@ if(unsorted[it] == i) sorted[it] = i return sorted - diff --git a/code/modules/food_and_drinks/food/foods/baked_goods.dm b/code/modules/food_and_drinks/food/foods/baked_goods.dm new file mode 100644 index 00000000000..9da07f4f0b8 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/baked_goods.dm @@ -0,0 +1,434 @@ + +////////////////////// +// Cakes // +////////////////////// + +/obj/item/reagent_containers/food/snacks/sliceable/carrotcake + name = "carrot cake" + desc = "A favorite desert of a certain wascally wabbit. Not a lie." + icon_state = "carrotcake" + slice_path = /obj/item/reagent_containers/food/snacks/carrotcakeslice + slices_num = 5 + bitesize = 3 + filling_color = "#FFD675" + list_reagents = list("nutriment" = 20, "oculine" = 10, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/carrotcakeslice + name = "carrot cake slice" + desc = "Carrotty slice of Carrot Cake, carrots are good for your eyes! Also not a lie." + icon_state = "carrotcake_slice" + trash = /obj/item/trash/plate + filling_color = "#FFD675" + +/obj/item/reagent_containers/food/snacks/sliceable/braincake + name = "brain cake" + desc = "A squishy cake-thing." + icon_state = "braincake" + slice_path = /obj/item/reagent_containers/food/snacks/braincakeslice + slices_num = 5 + filling_color = "#E6AEDB" + bitesize = 3 + list_reagents = list("protein" = 10, "nutriment" = 10, "mannitol" = 10, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/braincakeslice + name = "brain cake slice" + desc = "Lemme tell you something about prions. THEY'RE DELICIOUS." + icon_state = "braincakeslice" + trash = /obj/item/trash/plate + filling_color = "#E6AEDB" + +/obj/item/reagent_containers/food/snacks/sliceable/cheesecake + name = "cheese cake" + desc = "DANGEROUSLY cheesy." + icon_state = "cheesecake" + slice_path = /obj/item/reagent_containers/food/snacks/cheesecakeslice + slices_num = 5 + filling_color = "#FAF7AF" + bitesize = 3 + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/cheesecakeslice + name = "cheese cake slice" + desc = "Slice of pure cheestisfaction." + icon_state = "cheesecake_slice" + trash = /obj/item/trash/plate + filling_color = "#FAF7AF" + +/obj/item/reagent_containers/food/snacks/sliceable/plaincake + name = "vanilla cake" + desc = "A plain cake, not a lie." + icon_state = "plaincake" + slice_path = /obj/item/reagent_containers/food/snacks/plaincakeslice + slices_num = 5 + bitesize = 3 + filling_color = "#F7EDD5" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/plaincakeslice + name = "vanilla cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "plaincake_slice" + trash = /obj/item/trash/plate + filling_color = "#F7EDD5" + +/obj/item/reagent_containers/food/snacks/sliceable/orangecake + name = "orange cake" + desc = "A cake with added orange." + icon_state = "orangecake" + slice_path = /obj/item/reagent_containers/food/snacks/orangecakeslice + slices_num = 5 + bitesize = 3 + filling_color = "#FADA8E" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/orangecakeslice + name = "orange cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "orangecake_slice" + trash = /obj/item/trash/plate + filling_color = "#FADA8E" + +/obj/item/reagent_containers/food/snacks/sliceable/limecake + name = "lime cake" + desc = "A cake with added lime." + icon_state = "limecake" + bitesize = 3 + slice_path = /obj/item/reagent_containers/food/snacks/limecakeslice + slices_num = 5 + filling_color = "#CBFA8E" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/limecakeslice + name = "lime cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "limecake_slice" + trash = /obj/item/trash/plate + filling_color = "#CBFA8E" + +/obj/item/reagent_containers/food/snacks/sliceable/lemoncake + name = "lemon cake" + desc = "A cake with added lemon." + icon_state = "lemoncake" + slice_path = /obj/item/reagent_containers/food/snacks/lemoncakeslice + slices_num = 5 + bitesize = 3 + filling_color = "#FAFA8E" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/lemoncakeslice + name = "lemon cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "lemoncake_slice" + trash = /obj/item/trash/plate + filling_color = "#FAFA8E" + +/obj/item/reagent_containers/food/snacks/sliceable/chocolatecake + name = "chocolate cake" + desc = "A cake with added chocolate." + icon_state = "chocolatecake" + slice_path = /obj/item/reagent_containers/food/snacks/chocolatecakeslice + slices_num = 5 + bitesize = 3 + filling_color = "#805930" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/chocolatecakeslice + name = "chocolate cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "chocolatecake_slice" + trash = /obj/item/trash/plate + filling_color = "#805930" + +/obj/item/reagent_containers/food/snacks/sliceable/birthdaycake + name = "birthday cake" + desc = "Happy Birthday..." + icon_state = "birthdaycake" + slice_path = /obj/item/reagent_containers/food/snacks/birthdaycakeslice + slices_num = 5 + filling_color = "#FFD6D6" + bitesize = 3 + list_reagents = list("nutriment" = 20, "sprinkles" = 10, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/birthdaycakeslice + name = "birthday cake slice" + desc = "A slice of your birthday" + icon_state = "birthdaycakeslice" + trash = /obj/item/trash/plate + filling_color = "#FFD6D6" + +/obj/item/reagent_containers/food/snacks/sliceable/applecake + name = "apple cake" + desc = "A cake centered with Apple." + icon_state = "applecake" + slice_path = /obj/item/reagent_containers/food/snacks/applecakeslice + slices_num = 5 + bitesize = 3 + filling_color = "#EBF5B8" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/applecakeslice + name = "apple cake slice" + desc = "A slice of heavenly cake." + icon_state = "applecakeslice" + trash = /obj/item/trash/plate + filling_color = "#EBF5B8" + + +////////////////////// +// Cookies // +////////////////////// + +/obj/item/reagent_containers/food/snacks/cookie + name = "cookie" + desc = "COOKIE!!!" + icon_state = "COOKIE!!!" + bitesize = 1 + filling_color = "#DBC94F" + list_reagents = list("nutriment" = 1) + +/obj/item/reagent_containers/food/snacks/fortunecookie + name = "fortune cookie" + desc = "A true prophecy in each cookie!" + icon_state = "fortune_cookie" + filling_color = "#E8E79E" + list_reagents = list("nutriment" = 3) + trash = /obj/item/paper/fortune + +/obj/item/reagent_containers/food/snacks/sugarcookie + name = "sugar cookie" + desc = "Just like your little sister used to make." + icon_state = "sugarcookie" + list_reagents = list("nutriment" = 3, "sugar" = 3) + + +////////////////////// +// Pies // +////////////////////// + +/obj/item/reagent_containers/food/snacks/pie + name = "banana cream pie" + desc = "Just like back home, on clown planet! HONK!" + icon_state = "pie" + trash = /obj/item/trash/plate + filling_color = "#FBFFB8" + bitesize = 3 + list_reagents = list("nutriment" = 6, "banana" = 5, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/pie/throw_impact(atom/hit_atom) + ..() + new/obj/effect/decal/cleanable/pie_smudge(loc) + visible_message("[src] splats.","You hear a splat.") + qdel(src) + +/obj/item/reagent_containers/food/snacks/meatpie + name = "meat-pie" + icon_state = "meatpie" + desc = "An old barber recipe, very delicious!" + trash = /obj/item/trash/plate + filling_color = "#948051" + bitesize = 3 + list_reagents = list("nutriment" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/tofupie + name = "tofu-pie" + icon_state = "meatpie" + desc = "A delicious tofu pie." + trash = /obj/item/trash/plate + filling_color = "#FFFEE0" + bitesize = 3 + list_reagents = list("nutriment" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/amanita_pie + name = "amanita pie" + desc = "Sweet and tasty poison pie." + icon_state = "amanita_pie" + filling_color = "#FFCCCC" + bitesize = 4 + list_reagents = list("nutriment" = 6, "amanitin" = 3, "psilocybin" = 1, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/plump_pie + name = "plump pie" + desc = "I bet you love stuff made out of plump helmets!" + icon_state = "plump_pie" + filling_color = "#B8279B" + bitesize = 3 + list_reagents = list("nutriment" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/plump_pie/New() + ..() + if(prob(10)) + name = "exceptional plump pie" + desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump pie!" // What + reagents.add_reagent("omnizine", 5) + +/obj/item/reagent_containers/food/snacks/xemeatpie + name = "Xeno-pie" + icon_state = "xenomeatpie" + desc = "A delicious meatpie. Probably heretical." + trash = /obj/item/trash/plate + filling_color = "#43DE18" + list_reagents = list("nutriment" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/applepie + name = "apple pie" + desc = "A pie containing sweet sweet love... or apple." + icon_state = "applepie" + filling_color = "#E0EDC5" + bitesize = 3 + list_reagents = list("nutriment" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/cherrypie + name = "cherry pie" + desc = "Taste so good, make a grown man cry." + icon_state = "cherrypie" + filling_color = "#FF525A" + bitesize = 3 + list_reagents = list("nutriment" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/sliceable/pumpkinpie + name = "pumpkin pie" + desc = "A delicious treat for the autumn months." + icon_state = "pumpkinpie" + slice_path = /obj/item/reagent_containers/food/snacks/pumpkinpieslice + slices_num = 5 + bitesize = 3 + filling_color = "#F5B951" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/pumpkinpieslice + name = "pumpkin pie slice" + desc = "A slice of pumpkin pie, with whipped cream on top. Perfection." + icon_state = "pumpkinpieslice" + trash = /obj/item/trash/plate + filling_color = "#F5B951" + + +////////////////////// +// Donuts // +////////////////////// + +/obj/item/reagent_containers/food/snacks/donut + name = "donut" + desc = "Goes great with Robust Coffee." + icon_state = "donut1" + bitesize = 5 + list_reagents = list("nutriment" = 3, "sugar" = 2) + var/extra_reagent = null + filling_color = "#D2691E" + var/randomized_sprinkles = 1 + +/obj/item/reagent_containers/food/snacks/donut/New() + ..() + if(randomized_sprinkles && prob(30)) + icon_state = "donut2" + name = "frosted donut" + reagents.add_reagent("sprinkles", 2) + filling_color = "#FF69B4" + +/obj/item/reagent_containers/food/snacks/donut/sprinkles + name = "frosted donut" + icon_state = "donut2" + list_reagents = list("nutriment" = 3, "sugar" = 2, "spinkles" = 2) + filling_color = "#FF69B4" + randomized_sprinkles = 0 + +/obj/item/reagent_containers/food/snacks/donut/chaos + name = "chaos donut" + desc = "Like life, it never quite tastes the same." + bitesize = 10 + +/obj/item/reagent_containers/food/snacks/donut/chaos/New() + ..() + extra_reagent = pick("nutriment", "capsaicin", "frostoil", "krokodil", "plasma", "cocoa", "slimejelly", "banana", "berryjuice", "omnizine") + reagents.add_reagent("[extra_reagent]", 3) + if(prob(30)) + icon_state = "donut2" + name = "frosted chaos donut" + reagents.add_reagent("sprinkles", 2) + filling_color = "#FF69B4" + +/obj/item/reagent_containers/food/snacks/donut/jelly + name = "jelly donut" + desc = "You jelly?" + icon_state = "jdonut1" + extra_reagent = "berryjuice" + +/obj/item/reagent_containers/food/snacks/donut/jelly/New() + ..() + if(extra_reagent) + reagents.add_reagent("[extra_reagent]", 3) + if(prob(30)) + icon_state = "jdonut2" + name = "frosted jelly Donut" + reagents.add_reagent("sprinkles", 2) + filling_color = "#FF69B4" + +/obj/item/reagent_containers/food/snacks/donut/jelly/slimejelly + name = "jelly donut" + desc = "You jelly?" + icon_state = "jdonut1" + extra_reagent = "slimejelly" + +/obj/item/reagent_containers/food/snacks/donut/jelly/cherryjelly + name = "jelly donut" + desc = "You jelly?" + icon_state = "jdonut1" + extra_reagent = "cherryjelly" + + +////////////////////// +// Misc // +////////////////////// + +/obj/item/reagent_containers/food/snacks/muffin + name = "muffin" + desc = "A delicious and spongy little cake." + icon_state = "muffin" + filling_color = "#E0CF9B" + list_reagents = list("nutriment" = 6) + +/obj/item/reagent_containers/food/snacks/berryclafoutis + name = "berry clafoutis" + desc = "No black birds, this is a good sign." + icon_state = "berryclafoutis" + trash = /obj/item/trash/plate + bitesize = 3 + list_reagents = list("nutriment" = 10, "berryjuice" = 5, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/poppypretzel + name = "poppy pretzel" + desc = "A large soft pretzel full of POP! It's all twisted up!" + icon_state = "poppypretzel" + filling_color = "#916E36" + list_reagents = list("nutriment" = 5) + +/obj/item/reagent_containers/food/snacks/plumphelmetbiscuit + name = "plump helmet biscuit" + desc = "This is a finely-prepared plump helmet biscuit. The ingredients are exceptionally minced plump helmet, and well-minced dwarven wheat flour." + icon_state = "phelmbiscuit" + filling_color = "#CFB4C4" + list_reagents = list("nutriment" = 5) + +/obj/item/reagent_containers/food/snacks/plumphelmetbiscuit/New() + ..() + if(prob(10)) + name = "exceptional plump helmet biscuit" + desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!" // Is this a reference? + reagents.add_reagent("omnizine", 5) + +/obj/item/reagent_containers/food/snacks/appletart + name = "golden apple streusel tart" + desc = "A tasty dessert that won't make it through a metal detector." + icon_state = "gappletart" + trash = /obj/item/trash/plate + filling_color = "#FFFF00" + bitesize = 3 + list_reagents = list("nutriment" = 8, "gold" = 5, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/cracker + name = "cracker" + desc = "It's a salted cracker." + icon_state = "cracker" + bitesize = 1 + filling_color = "#F5DEB8" + list_reagents = list("nutriment" = 1) diff --git a/code/modules/food_and_drinks/food/foods/bread.dm b/code/modules/food_and_drinks/food/foods/bread.dm new file mode 100644 index 00000000000..c841f8d65fa --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/bread.dm @@ -0,0 +1,183 @@ + +////////////////////// +// Breads // +////////////////////// + +/obj/item/reagent_containers/food/snacks/sliceable/meatbread + name = "meatbread loaf" + desc = "The culinary base of every self-respecting eloquen/tg/entleman." + icon_state = "meatbread" + slice_path = /obj/item/reagent_containers/food/snacks/meatbreadslice + slices_num = 5 + filling_color = "#FF7575" + list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/meatbreadslice + name = "meatbread slice" + desc = "A slice of delicious meatbread." + icon_state = "meatbreadslice" + trash = /obj/item/trash/plate + filling_color = "#FF7575" + +/obj/item/reagent_containers/food/snacks/sliceable/xenomeatbread + name = "xenomeatbread loaf" + desc = "The culinary base of every self-respecting eloquent gentleman. Extra Heretical." + icon_state = "xenomeatbread" + slice_path = /obj/item/reagent_containers/food/snacks/xenomeatbreadslice + slices_num = 5 + filling_color = "#8AFF75" + list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/xenomeatbreadslice + name = "xenomeatbread slice" + desc = "A slice of delicious meatbread. Extra Heretical." + icon_state = "xenobreadslice" + trash = /obj/item/trash/plate + filling_color = "#8AFF75" + +/obj/item/reagent_containers/food/snacks/sliceable/spidermeatbread + name = "spider meat loaf" + desc = "Reassuringly green meatloaf made from spider meat." + icon_state = "spidermeatbread" + slice_path = /obj/item/reagent_containers/food/snacks/spidermeatbreadslice + slices_num = 5 + list_reagents = list("protein" = 20, "nutriment" = 10, "toxin" = 15, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/spidermeatbreadslice + name = "spider meat bread slice" + desc = "A slice of meatloaf made from an animal that most likely still wants you dead." + icon_state = "xenobreadslice" + trash = /obj/item/trash/plate + list_reagents = list("toxin" = 2) + +/obj/item/reagent_containers/food/snacks/sliceable/bananabread + name = "Banana-nut bread" + desc = "A heavenly and filling treat." + icon_state = "bananabread" + slice_path = /obj/item/reagent_containers/food/snacks/bananabreadslice + slices_num = 5 + filling_color = "#EDE5AD" + list_reagents = list("banana" = 20, "nutriment" = 20) + +/obj/item/reagent_containers/food/snacks/bananabreadslice + name = "Banana-nut bread slice" + desc = "A slice of delicious banana bread." + icon_state = "bananabreadslice" + trash = /obj/item/trash/plate + filling_color = "#EDE5AD" + +/obj/item/reagent_containers/food/snacks/sliceable/tofubread + name = "Tofubread" + icon_state = "Like meatbread but for vegetarians. Not guaranteed to give superpowers." + icon_state = "tofubread" + slice_path = /obj/item/reagent_containers/food/snacks/tofubreadslice + slices_num = 5 + filling_color = "#F7FFE0" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/tofubreadslice + name = "Tofubread slice" + desc = "A slice of delicious tofubread." + icon_state = "tofubreadslice" + trash = /obj/item/trash/plate + filling_color = "#F7FFE0" + +/obj/item/reagent_containers/food/snacks/sliceable/bread + name = "Bread" + icon_state = "Some plain old Earthen bread." + icon_state = "bread" + slice_path = /obj/item/reagent_containers/food/snacks/breadslice + slices_num = 6 + filling_color = "#FFE396" + list_reagents = list("nutriment" = 10) + +/obj/item/reagent_containers/food/snacks/breadslice + name = "Bread slice" + desc = "A slice of home." + icon_state = "breadslice" + trash = /obj/item/trash/plate + filling_color = "#D27332" + list_reagents = list("nutriment" = 2, "bread" = 5) + +/obj/item/reagent_containers/food/snacks/sliceable/creamcheesebread + name = "Cream Cheese Bread" + desc = "Yum yum yum!" + icon_state = "creamcheesebread" + slice_path = /obj/item/reagent_containers/food/snacks/creamcheesebreadslice + slices_num = 5 + filling_color = "#FFF896" + list_reagents = list("nutriment" = 20, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/creamcheesebreadslice + name = "Cream Cheese Bread slice" + desc = "A slice of yum!" + icon_state = "creamcheesebreadslice" + trash = /obj/item/trash/plate + filling_color = "#FFF896" + list_reagents = list("nutriment" = 4, "vitamin" = 1) + + +////////////////////// +// Misc // +////////////////////// + +/obj/item/reagent_containers/food/snacks/bun + name = "bun" + desc = "The base for any self-respecting burger." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "bun" + list_reagents = list("nutriment" = 1) + +/obj/item/reagent_containers/food/snacks/flatbread + name = "flatbread" + desc = "Bland but filling." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "flatbread" + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/baguette + name = "baguette" + desc = "Bon appetit!" + icon_state = "baguette" + filling_color = "#E3D796" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/twobread + name = "Two Bread" + desc = "It is very bitter and winy." + icon_state = "twobread" + filling_color = "#DBCC9A" + bitesize = 3 + list_reagents = list("nutriment" = 2, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/jelliedtoast + name = "Jellied Toast" + desc = "A slice of bread covered with delicious jam." + icon_state = "jellytoast" + trash = /obj/item/trash/plate + filling_color = "#B572AB" + bitesize = 3 + +/obj/item/reagent_containers/food/snacks/jelliedtoast/cherry + list_reagents = list("nutriment" = 1, "cherryjelly" = 5, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/jelliedtoast/slime + list_reagents = list("nutriment" = 1, "slimejelly" = 5, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/rofflewaffles + name = "Roffle Waffles" + desc = "Waffles from Roffle. Co." + icon_state = "rofflewaffles" + trash = /obj/item/trash/waffles + filling_color = "#FF00F7" + bitesize = 4 + list_reagents = list("nutriment" = 8, "psilocybin" = 2, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/waffles + name = "waffles" + desc = "Mmm, waffles." + icon_state = "waffles" + trash = /obj/item/trash/waffles + filling_color = "#E6DEB5" + list_reagents = list("nutriment" = 8, "vitamin" = 1) diff --git a/code/modules/food_and_drinks/food/candy.dm b/code/modules/food_and_drinks/food/foods/candy.dm similarity index 100% rename from code/modules/food_and_drinks/food/candy.dm rename to code/modules/food_and_drinks/food/foods/candy.dm diff --git a/code/modules/food_and_drinks/food/foods/desserts.dm b/code/modules/food_and_drinks/food/foods/desserts.dm new file mode 100644 index 00000000000..ff99efd07be --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/desserts.dm @@ -0,0 +1,97 @@ + +////////////////////// +// Ice Cream // +////////////////////// + +/obj/item/reagent_containers/food/snacks/icecream + name = "ice cream" + desc = "Delicious ice cream." + icon = 'icons/obj/kitchen.dmi' + icon_state = "icecream_cone" + bitesize = 3 + list_reagents = list("nutriment" = 1, "sugar" = 1) + +/obj/item/reagent_containers/food/snacks/icecream/New() + ..() + update_icon() + +/obj/item/reagent_containers/food/snacks/icecream/update_icon() + overlays.Cut() + var/image/filling = image('icons/obj/kitchen.dmi', src, "icecream_color") + filling.icon += mix_color_from_reagents(reagents.reagent_list) + overlays += filling + +/obj/item/reagent_containers/food/snacks/icecream/icecreamcone + name = "ice cream cone" + desc = "Delicious ice cream." + icon_state = "icecream_cone" + volume = 50 + bitesize = 3 + list_reagents = list("nutriment" = 3, "sugar" = 7, "ice" = 2) + +/obj/item/reagent_containers/food/snacks/icecream/icecreamcup + name = "chocolate ice cream cone" + desc = "Delicious ice cream." + icon_state = "icecream_cup" + volume = 50 + bitesize = 6 + list_reagents = list("nutriment" = 5, "chocolate" = 8, "ice" = 2) + +/obj/item/reagent_containers/food/snacks/icecreamsandwich + name = "icecream sandwich" + desc = "Portable Ice-cream in it's own packaging." + icon_state = "icecreamsandwich" + list_reagents = list("nutriment" = 2, "ice" = 2) + + +////////////////////// +// Misc // +////////////////////// + +/obj/item/reagent_containers/food/snacks/friedbanana + name = "Fried Banana" + desc = "Goreng Pisang, also known as fried bananas." + icon_state = "friedbanana" + list_reagents = list("sugar" = 5, "nutriment" = 8, "cornoil" = 4) + +/obj/item/reagent_containers/food/snacks/ricepudding + name = "Rice Pudding" + desc = "Where's the Jam!" + icon_state = "rpudding" + trash = /obj/item/trash/snack_bowl + filling_color = "#FFFBDB" + list_reagents = list("nutriment" = 7, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/spacylibertyduff + name = "Spacy Liberty Duff" + desc = "Jello gelatin, from Alfred Hubbard's cookbook." + icon_state = "spacylibertyduff" + trash = /obj/item/trash/snack_bowl + filling_color = "#42B873" + bitesize = 3 + list_reagents = list("nutriment" = 6, "psilocybin" = 6) + +/obj/item/reagent_containers/food/snacks/amanitajelly + name = "Amanita Jelly" + desc = "Looks curiously toxic." + icon_state = "amanitajelly" + trash = /obj/item/trash/snack_bowl + filling_color = "#ED0758" + bitesize = 3 + list_reagents = list("nutriment" = 6, "amanitin" = 6, "psilocybin" = 3) + +/obj/item/reagent_containers/food/snacks/candiedapple + name = "Candied Apple" + desc = "An apple coated in sugary sweetness." + icon_state = "candiedapple" + filling_color = "#F21873" + bitesize = 3 + list_reagents = list("nutriment" = 3, "sugar" = 2) + +/obj/item/reagent_containers/food/snacks/mint + name = "mint" + desc = "it is only wafer thin." + icon_state = "mint" + bitesize = 1 + filling_color = "#F2F2F2" + list_reagents = list("minttoxin" = 1) diff --git a/code/modules/food_and_drinks/food/foods/ethnic.dm b/code/modules/food_and_drinks/food/foods/ethnic.dm new file mode 100644 index 00000000000..ae8fc289798 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/ethnic.dm @@ -0,0 +1,135 @@ + +////////////////////// +// Mexican // +////////////////////// + +/obj/item/reagent_containers/food/snacks/taco + name = "taco" + desc = "Take a bite!" + icon_state = "taco" + bitesize = 3 + list_reagents = list("nutriment" = 7, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/burrito + name = "Burrito" + desc = "Meat, beans, cheese, and rice wrapped up as an easy-to-hold meal." + icon_state = "burrito" + trash = /obj/item/trash/plate + filling_color = "#A36A1F" + list_reagents = list("nutriment" = 4, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/chimichanga + name = "Chimichanga" + desc = "Time to eat a chimi-f***ing-changa." + icon_state = "chimichanga" + trash = /obj/item/trash/plate + filling_color = "#A36A1F" + list_reagents = list("omnizine" = 4, "cheese" = 2) //Deadpool reference. Deal with it. + +/obj/item/reagent_containers/food/snacks/enchiladas + name = "Enchiladas" + desc = "Viva La Mexico!" + icon_state = "enchiladas" + trash = /obj/item/trash/tray + filling_color = "#A36A1F" + bitesize = 4 + list_reagents = list("nutriment" = 8, "capsaicin" = 6) + +/obj/item/reagent_containers/food/snacks/cornchips + name = "corn chips" + desc = "Goes great with salsa! OLE!" + icon_state = "chips" + bitesize = 1 + trash = /obj/item/trash/chips + filling_color = "#E8C31E" + list_reagents = list("nutriment" = 3) + + +////////////////////// +// Chinese // +////////////////////// + +/obj/item/reagent_containers/food/snacks/chinese/chowmein + name = "chow mein" + desc = "What is in this anyways?" + icon_state = "chinese1" + junkiness = 25 + list_reagents = list("nutriment" = 1, "beans" = 3, "msg" = 4, "sugar" = 2) + +/obj/item/reagent_containers/food/snacks/chinese/sweetsourchickenball + name = "Sweet & Sour Chicken Balls" + desc = "Is this chicken cooked? The odds are better than wok paper scissors." + icon_state = "chickenball" + junkiness = 25 + list_reagents = list("nutriment" = 2, "msg" = 4, "sugar" = 2) + +/obj/item/reagent_containers/food/snacks/chinese/tao + name = "Admiral Yamamoto carp" + desc = "Tastes like chicken." + icon_state = "chinese2" + junkiness = 25 + list_reagents = list("nutriment" = 1, "protein" = 1, "msg" = 4, "sugar" = 4) + +/obj/item/reagent_containers/food/snacks/chinese/newdles + name = "chinese newdles" + desc = "Made fresh, weekly!" + icon_state = "chinese3" + junkiness = 25 + list_reagents = list("nutriment" = 1, "msg" = 4, "sugar" = 3) + +/obj/item/reagent_containers/food/snacks/chinese/rice + name = "fried rice" + desc = "A timeless classic." + icon_state = "chinese4" + junkiness = 20 + list_reagents = list("nutriment" = 1, "rice" = 3, "msg" = 4, "sugar" = 2) + + +////////////////////// +// Japanese // +////////////////////// + +/obj/item/reagent_containers/food/snacks/chawanmushi + name = "chawanmushi" + desc = "A legendary egg custard that makes friends out of enemies. Probably too hot for a cat to eat." + icon_state = "chawanmushi" + trash = /obj/item/trash/snack_bowl + filling_color = "#F0F2E4" + list_reagents = list("nutriment" = 5) + +/obj/item/reagent_containers/food/snacks/yakiimo + name = "yaki imo" + desc = "Made with roasted sweet potatoes!" + icon_state = "yakiimo" + trash = /obj/item/trash/plate + list_reagents = list("nutriment" = 5, "vitamin" = 4) + filling_color = "#8B1105" + + +////////////////////// +// Middle Eastern // +////////////////////// + +/obj/item/reagent_containers/food/snacks/human/kabob + name = "-kabob" + icon_state = "kabob" + desc = "A human meat, on a stick." + trash = /obj/item/stack/rods + filling_color = "#A85340" + list_reagents = list("nutriment" = 8) + +/obj/item/reagent_containers/food/snacks/monkeykabob + name = "Meat-kabob" + icon_state = "kabob" + desc = "Delicious meat, on a stick." + trash = /obj/item/stack/rods + filling_color = "#A85340" + list_reagents = list("nutriment" = 8) + +/obj/item/reagent_containers/food/snacks/tofukabob + name = "Tofu-kabob" + icon_state = "kabob" + desc = "Vegan meat, on a stick." + trash = /obj/item/stack/rods + filling_color = "#FFFEE0" + list_reagents = list("nutriment" = 8) diff --git a/code/modules/food_and_drinks/food/foods/ingredients.dm b/code/modules/food_and_drinks/food/foods/ingredients.dm new file mode 100644 index 00000000000..65c20eb7eba --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/ingredients.dm @@ -0,0 +1,160 @@ + +////////////////////// +// Tofu & Soy // +////////////////////// + +/obj/item/reagent_containers/food/snacks/tofu + name = "Tofu" + icon_state = "tofu" + desc = "We all love tofu." + filling_color = "#FFFEE0" + bitesize = 3 + list_reagents = list("plantmatter" = 2) + +/obj/item/reagent_containers/food/snacks/fried_tofu + name = "Fried Tofu" + icon_state = "tofu" + desc = "Proof that even vegetarians crave unhealthy foods." + filling_color = "#FFFEE0" + bitesize = 3 + list_reagents = list("plantmatter" = 3) + +/obj/item/reagent_containers/food/snacks/soydope + name = "Soy Dope" + desc = "Dope from a soy." + icon_state = "soydope" + trash = /obj/item/trash/plate + filling_color = "#C4BF76" + list_reagents = list("nutriment" = 2) + + +////////////////////// +// Cheese // +////////////////////// + +/obj/item/reagent_containers/food/snacks/sliceable/cheesewheel + name = "Cheese wheel" + desc = "A big wheel of delicious Cheddar." + icon_state = "cheesewheel" + slice_path = /obj/item/reagent_containers/food/snacks/cheesewedge + slices_num = 5 + filling_color = "#FFF700" + list_reagents = list("nutriment" = 15, "vitamin" = 5, "cheese" = 20) + +/obj/item/reagent_containers/food/snacks/cheesewedge + name = "Cheese wedge" + desc = "A wedge of delicious Cheddar. The cheese wheel it was cut from can't have gone far." + icon_state = "cheesewedge" + filling_color = "#FFF700" + +/obj/item/reagent_containers/food/snacks/weirdcheesewedge + name = "Weird Cheese" + desc = "Some kind of... gooey, messy, gloopy thing. Similar to cheese, but only in the looser sense of the word." + icon_state = "weirdcheesewedge" + filling_color = "#00FF33" + list_reagents = list("mercury" = 5, "lsd" = 5, "ethanol" = 5, "weird_cheese" = 5) + + +////////////////////// +// Plants // +////////////////////// + +/obj/item/reagent_containers/food/snacks/hugemushroomslice + name = "huge mushroom slice" + desc = "A slice from a huge mushroom." + icon_state = "hugemushroomslice" + filling_color = "#E0D7C5" + bitesize = 6 + list_reagents = list("plantmatter" = 3, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/tomatomeat + name = "tomato slice" + desc = "A slice from a huge tomato." + icon_state = "tomatomeat" + filling_color = "#DB0000" + bitesize = 6 + list_reagents = list("protein" = 2) + +/obj/item/reagent_containers/food/snacks/watermelonslice + name = "Watermelon Slice" + desc = "A slice of watery goodness." + icon_state = "watermelonslice" + filling_color = "#FF3867" + +/obj/item/reagent_containers/food/snacks/pineappleslice + name = "Pineapple Slices" + desc = "Rings of pineapple." + icon_state = "pineappleslice" + filling_color = "#e5b437" + + +////////////////////// +// Dough // +////////////////////// + +/obj/item/reagent_containers/food/snacks/dough + name = "dough" + desc = "A piece of dough." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "dough" + list_reagents = list("nutriment" = 6) + +// Dough + rolling pin = flat dough +/obj/item/reagent_containers/food/snacks/dough/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/kitchen/rollingpin)) + if(isturf(loc)) + new /obj/item/reagent_containers/food/snacks/sliceable/flatdough(loc) + to_chat(user, "You flatten [src].") + qdel(src) + else + to_chat(user, "You need to put [src] on a surface to roll it out!") + else + ..() + +// slicable into 3xdoughslices +/obj/item/reagent_containers/food/snacks/sliceable/flatdough + name = "flat dough" + desc = "Some flattened dough." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "flat dough" + slice_path = /obj/item/reagent_containers/food/snacks/doughslice + slices_num = 3 + list_reagents = list("nutriment" = 6) + +/obj/item/reagent_containers/food/snacks/doughslice + name = "dough slice" + desc = "The building block of an impressive dish." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "doughslice" + list_reagents = list("nutriment" = 1) + + +////////////////////// +// Chocolate // +////////////////////// + +/obj/item/reagent_containers/food/snacks/chocolatebar + name = "Chocolate Bar" + desc = "Such sweet, fattening food." + icon_state = "chocolatebar" + filling_color = "#7D5F46" + list_reagents = list("nutriment" = 2, "sugar" = 2, "cocoa" = 2) + +/obj/item/reagent_containers/food/snacks/choc_pile //for reagent chocolate being spilled on turfs + name = "Pile of Chocolate" + desc = "A pile of pure chocolate pieces." + icon_state = "cocoa" + filling_color = "#7D5F46" + list_reagents = list("chocolate" = 5) + + +////////////////////// +// Misc // +////////////////////// + +/obj/item/reagent_containers/food/snacks/ectoplasm + name = "ectoplasm" + desc = "A luminescent blob of what scientists refer to as 'ghost goo'." + icon = 'icons/obj/wizard.dmi' + icon_state = "ectoplasm" + list_reagents = list("ectoplasm" = 10) diff --git a/code/modules/food_and_drinks/food/foods/junkfood.dm b/code/modules/food_and_drinks/food/foods/junkfood.dm new file mode 100644 index 00000000000..b221348e8d8 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/junkfood.dm @@ -0,0 +1,93 @@ + +////////////////////// +// Vendor // +////////////////////// + +/obj/item/reagent_containers/food/snacks/chips + name = "chips" + desc = "Commander Riker's What-The-Crisps." + icon_state = "chips" + bitesize = 1 + trash = /obj/item/trash/chips + filling_color = "#E8C31E" + junkiness = 20 + list_reagents = list("nutriment" = 1, "sodiumchloride" = 1, "sugar" = 3) + +/obj/item/reagent_containers/food/snacks/sosjerky + name = "Scaredy's Private Reserve Beef Jerky" + icon_state = "sosjerky" + desc = "Beef jerky made from the finest space cows." + trash = /obj/item/trash/sosjerky + filling_color = "#631212" + junkiness = 25 + list_reagents = list("protein" = 1, "sugar" = 3) + +/obj/item/reagent_containers/food/snacks/pistachios + name = "Pistachios" + icon_state = "pistachios" + desc = "A snack of deliciously salted pistachios. A perfectly valid choice..." + trash = /obj/item/trash/pistachios + filling_color = "#BAD145" + junkiness = 20 + list_reagents = list("plantmatter" = 2, "sodiumchloride" = 1, "sugar" = 4) + +/obj/item/reagent_containers/food/snacks/no_raisin + name = "4no Raisins" + icon_state = "4no_raisins" + desc = "Best raisins in the universe. Not sure why." + trash = /obj/item/trash/raisins + filling_color = "#343834" + junkiness = 25 + list_reagents = list("plantmatter" = 2, "sugar" = 4) + +/obj/item/reagent_containers/food/snacks/spacetwinkie + name = "Space Twinkie" + icon_state = "space_twinkie" + desc = "Guaranteed to survive longer then you will." + filling_color = "#FFE591" + junkiness = 25 + list_reagents = list("sugar" = 4) + +/obj/item/reagent_containers/food/snacks/cheesiehonkers + name = "Cheesie Honkers" + icon_state = "cheesie_honkers" + desc = "Bite sized cheesie snacks that will honk all over your mouth." + trash = /obj/item/trash/cheesie + filling_color = "#FFA305" + junkiness = 25 + list_reagents = list("nutriment" = 1, "fake_cheese" = 2, "sugar" = 3) + +/obj/item/reagent_containers/food/snacks/syndicake + name = "Syndi-Cakes" + icon_state = "syndi_cakes" + desc = "An extremely moist snack cake that tastes just as good after being nuked." + filling_color = "#FF5D05" + trash = /obj/item/trash/syndi_cakes + bitesize = 3 + list_reagents = list("nutriment" = 4, "salglu_solution" = 5) + +/obj/item/reagent_containers/food/snacks/tastybread + name = "bread tube" + desc = "Bread in a tube. Chewy...and surprisingly tasty." + icon_state = "tastybread" + trash = /obj/item/trash/tastybread + filling_color = "#A66829" + junkiness = 20 + list_reagents = list("nutriment" = 2, "sugar" = 4) + + +////////////////////// +// Homemade // +////////////////////// + +/obj/item/reagent_containers/food/snacks/sosjerky/healthy + name = "homemade beef jerky" + desc = "Homemade beef jerky made from the finest space cows." + list_reagents = list("nutriment" = 3, "vitamin" = 1) + junkiness = 0 + +/obj/item/reagent_containers/food/snacks/no_raisin/healthy + name = "homemade raisins" + desc = "homemade raisins, the best in all of spess." + list_reagents = list("nutriment" = 3, "vitamin" = 2) + junkiness = 0 diff --git a/code/modules/food_and_drinks/food/foods/meat.dm b/code/modules/food_and_drinks/food/foods/meat.dm new file mode 100644 index 00000000000..a7f4acb4405 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/meat.dm @@ -0,0 +1,432 @@ + +////////////////////// +// Raw Meat // +////////////////////// + +/obj/item/reagent_containers/food/snacks/meat + name = "meat" + desc = "A slab of meat" + icon_state = "meat" + health = 180 + filling_color = "#FF1C1C" + bitesize = 3 + list_reagents = list("protein" = 3) + +/obj/item/reagent_containers/food/snacks/meat/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/kitchen/knife) || istype(W, /obj/item/scalpel)) + new /obj/item/reagent_containers/food/snacks/rawcutlet(src) + new /obj/item/reagent_containers/food/snacks/rawcutlet(src) + new /obj/item/reagent_containers/food/snacks/rawcutlet(src) + to_chat(user, "You cut the meat in thin strips.") + qdel(src) + else + ..() + +/obj/item/reagent_containers/food/snacks/meat/syntiflesh + name = "synthetic meat" + desc = "A synthetic slab of flesh." + +/obj/item/reagent_containers/food/snacks/meat/human + name = "-meat" + var/subjectname = "" + var/subjectjob = null + +/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct + name = "meat product" + desc = "A slab of station reclaimed and chemically processed meat product." + +/obj/item/reagent_containers/food/snacks/meat/monkey + //same as plain meat + +/obj/item/reagent_containers/food/snacks/meat/corgi + name = "Corgi meat" + desc = "Tastes like... well you know..." + +/obj/item/reagent_containers/food/snacks/meat/pug + name = "Pug meat" + desc = "Tastes like... well you know..." + +/obj/item/reagent_containers/food/snacks/meat/ham + name = "Ham" + desc = "Taste like bacon." + list_reagents = list("protein" = 3, "porktonium" = 10) + +/obj/item/reagent_containers/food/snacks/meat/meatwheat + name = "meatwheat clump" + desc = "This doesn't look like meat, but your standards aren't that high to begin with." + list_reagents = list("nutriment" = 3, "vitamin" = 2, "blood" = 5) + filling_color = rgb(150, 0, 0) + icon_state = "meatwheat_clump" + bitesize = 4 + +/obj/item/reagent_containers/food/snacks/rawcutlet + name = "raw cutlet" + desc = "A thin piece of raw meat." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "rawcutlet" + bitesize = 1 + list_reagents = list("protein" = 1) + +/obj/item/reagent_containers/food/snacks/rawcutlet/attackby(obj/item/W, mob/user, params) + if(istype(W,/obj/item/kitchen/knife)) + user.visible_message( \ + "[user] cuts the raw cutlet with the knife!", \ + "You cut the raw cutlet with your knife!" \ + ) + new /obj/item/reagent_containers/food/snacks/raw_bacon(loc) + qdel(src) + +/obj/item/reagent_containers/food/snacks/bearmeat + name = "bear meat" + desc = "A very manly slab of meat." + icon_state = "bearmeat" + filling_color = "#DB0000" + bitesize = 3 + list_reagents = list("protein" = 12, "morphine" = 5, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/xenomeat + name = "meat" + desc = "A slab of meat." + icon_state = "xenomeat" + filling_color = "#43DE18" + bitesize = 6 + list_reagents = list("protein" = 3, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/spidermeat + name = "spider meat" + desc = "A slab of spider meat." + icon_state = "spidermeat" + bitesize = 3 + list_reagents = list("protein" = 3, "toxin" = 3, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/lizardmeat + name = "mutant lizard meat" + desc = "Seems to be a slab of meat from some mutant lizard thing?" + icon_state = "xenomeat" + filling_color = "#43DE18" + bitesize = 3 + list_reagents = list("protein" = 3, "toxin" = 3) + +/obj/item/reagent_containers/food/snacks/spiderleg + name = "spider leg" + desc = "A still twitching leg of a giant spider... you don't really want to eat this, do you?" + icon_state = "spiderleg" + list_reagents = list("protein" = 2, "toxin" = 2) + +/obj/item/reagent_containers/food/snacks/raw_bacon + name = "raw bacon" + desc = "It's fleshy and pink!" + icon_state = "raw_bacon" + list_reagents = list("nutriment" = 1, "porktonium" = 10) + +/obj/item/reagent_containers/food/snacks/spidereggs + name = "spider eggs" + desc = "A cluster of juicy spider eggs. A great side dish for when you care not for your health." + icon_state = "spidereggs" + list_reagents = list("protein" = 2, "toxin" = 2) + +////////////////////// +// Cooked Meat // +////////////////////// + +/obj/item/reagent_containers/food/snacks/meatsteak + name = "Meat steak" + desc = "A piece of hot spicy meat." + icon_state = "meatstake" + trash = /obj/item/trash/plate + filling_color = "#7A3D11" + bitesize = 3 + list_reagents = list("nutriment" = 5) + +/obj/item/reagent_containers/food/snacks/bacon + name = "bacon" + desc = "It looks juicy and tastes amazing!" + icon_state = "bacon2" + list_reagents = list("nutriment" = 4, "porktonium" = 10, "msg" = 4) + +/obj/item/reagent_containers/food/snacks/telebacon + name = "Tele Bacon" + desc = "It tastes a little odd but it is still delicious." + icon_state = "bacon" + var/obj/item/radio/beacon/bacon/baconbeacon + list_reagents = list("nutriment" = 4, "porktonium" = 10) + +/obj/item/reagent_containers/food/snacks/telebacon/New() + ..() + baconbeacon = new /obj/item/radio/beacon/bacon(src) + +/obj/item/reagent_containers/food/snacks/telebacon/On_Consume(mob/M, mob/user) + if(!reagents.total_volume) + baconbeacon.loc = user + baconbeacon.digest_delay() + +/obj/item/reagent_containers/food/snacks/meatball + name = "Meatball" + desc = "A great meal all round." + icon_state = "meatball" + filling_color = "#DB0000" + list_reagents = list("protein" = 4, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/sausage + name = "Sausage" + desc = "A piece of mixed, long meat." + icon_state = "sausage" + filling_color = "#DB0000" + list_reagents = list("protein" = 6, "vitamin" = 1, "porktonium" = 10) + +/obj/item/reagent_containers/food/snacks/cutlet + name = "cutlet" + desc = "A tasty meat slice." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "cutlet" + list_reagents = list("protein" = 2) + +/obj/item/reagent_containers/food/snacks/spidereggsham + name = "green eggs and ham" + desc = "Would you eat them on a train? Would you eat them on a plane? Would you eat them on a state of the art corporate deathtrap floating through space?" + icon_state = "spidereggsham" + trash = /obj/item/trash/plate + bitesize = 4 + list_reagents = list("nutriment" = 6) + +/obj/item/reagent_containers/food/snacks/boiledspiderleg + name = "boiled spider leg" + desc = "A giant spider's leg that's still twitching after being cooked. Gross!" + icon_state = "spiderlegcooked" + trash = /obj/item/trash/plate + bitesize = 3 + list_reagents = list("nutriment" = 3, "capsaicin" = 2) + +/obj/item/reagent_containers/food/snacks/wingfangchu + name = "Wing Fang Chu" + desc = "A savory dish of alien wing wang in soy." + icon_state = "wingfangchu" + trash = /obj/item/trash/snack_bowl + filling_color = "#43DE18" + list_reagents = list("nutriment" = 6, "soysauce" = 5, "vitamin" = 2) + + +////////////////////// +// Cubes // +////////////////////// + +/obj/item/reagent_containers/food/snacks/monkeycube + name = "monkey cube" + desc = "Just add water!" + icon_state = "monkeycube" + bitesize = 12 + filling_color = "#ADAC7F" + var/datum/species/monkey_type = /datum/species/monkey + list_reagents = list("nutriment" = 2) + +/obj/item/reagent_containers/food/snacks/monkeycube/water_act(volume, temperature) + if(volume >= 5) + return Expand() + +/obj/item/reagent_containers/food/snacks/monkeycube/wash(mob/user, atom/source) + user.drop_item() + forceMove(get_turf(source)) + return 1 + +/obj/item/reagent_containers/food/snacks/monkeycube/proc/Expand() + if(!QDELETED(src)) + visible_message("[src] expands!") + if(fingerprintslast) + log_game("Cube ([monkey_type]) inflated, last touched by: " + fingerprintslast) + else + log_game("Cube ([monkey_type]) inflated, last touched by: NO_DATA") + var/mob/living/carbon/human/creature = new /mob/living/carbon/human(get_turf(src)) + if(LAZYLEN(fingerprintshidden)) + creature.fingerprintshidden = fingerprintshidden.Copy() + creature.set_species(monkey_type) + qdel(src) + +/obj/item/reagent_containers/food/snacks/monkeycube/farwacube + name = "farwa cube" + monkey_type = /datum/species/monkey/tajaran + +/obj/item/reagent_containers/food/snacks/monkeycube/wolpincube + name = "wolpin cube" + monkey_type = /datum/species/monkey/vulpkanin + +/obj/item/reagent_containers/food/snacks/monkeycube/stokcube + name = "stok cube" + monkey_type = /datum/species/monkey/unathi + +/obj/item/reagent_containers/food/snacks/monkeycube/neaeracube + name = "neaera cube" + monkey_type = /datum/species/monkey/skrell + + +////////////////////// +// Eggs // +////////////////////// + +/obj/item/reagent_containers/food/snacks/egg + name = "egg" + desc = "An egg!" + icon_state = "egg" + filling_color = "#FDFFD1" + list_reagents = list("protein" = 1, "egg" = 5) + +/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom) + ..() + var/turf/T = get_turf(hit_atom) + new/obj/effect/decal/cleanable/egg_smudge(T) + if(reagents) + reagents.reaction(hit_atom, TOUCH) + qdel(src) + +/obj/item/reagent_containers/food/snacks/egg/attackby(obj/item/W, mob/user, params) + if(istype( W, /obj/item/toy/crayon )) + var/obj/item/toy/crayon/C = W + var/clr = C.colourName + + if(!(clr in list("blue","green","mime","orange","purple","rainbow","red","yellow"))) + to_chat(usr, "The egg refuses to take on this color!") + return + + to_chat(usr, "You color \the [src] [clr]") + icon_state = "egg-[clr]" + item_color = clr + else + ..() + +/obj/item/reagent_containers/food/snacks/egg/blue + icon_state = "egg-blue" + item_color = "blue" + +/obj/item/reagent_containers/food/snacks/egg/green + icon_state = "egg-green" + item_color = "green" + +/obj/item/reagent_containers/food/snacks/egg/mime + icon_state = "egg-mime" + item_color = "mime" + +/obj/item/reagent_containers/food/snacks/egg/orange + icon_state = "egg-orange" + item_color = "orange" + +/obj/item/reagent_containers/food/snacks/egg/purple + icon_state = "egg-purple" + item_color = "purple" + +/obj/item/reagent_containers/food/snacks/egg/rainbow + icon_state = "egg-rainbow" + item_color = "rainbow" + +/obj/item/reagent_containers/food/snacks/egg/red + icon_state = "egg-red" + item_color = "red" + +/obj/item/reagent_containers/food/snacks/egg/yellow + icon_state = "egg-yellow" + item_color = "yellow" + +/obj/item/reagent_containers/food/snacks/egg/gland + desc = "An egg! It looks weird..." + +/obj/item/reagent_containers/food/snacks/egg/gland/New() + ..() + reagents.add_reagent(get_random_reagent_id(), 15) + + var/reagent_color = mix_color_from_reagents(reagents.reagent_list) + color = reagent_color + +/obj/item/reagent_containers/food/snacks/friedegg + name = "Fried egg" + desc = "A fried egg, with a touch of salt and pepper." + icon_state = "friedegg" + filling_color = "#FFDF78" + bitesize = 1 + list_reagents = list("nutriment" = 3, "egg" = 5) + +/obj/item/reagent_containers/food/snacks/boiledegg + name = "Boiled egg" + desc = "A hard boiled egg." + icon_state = "egg" + filling_color = "#FFFFFF" + list_reagents = list("nutriment" = 2, "egg" = 5, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/chocolateegg + name = "Chocolate Egg" + desc = "Such sweet, fattening food." + icon_state = "chocolateegg" + filling_color = "#7D5F46" + list_reagents = list("nutriment" = 4, "sugar" = 2, "cocoa" = 2) + +/obj/item/reagent_containers/food/snacks/omelette + name = "Omelette Du Fromage" + desc = "That's all you can say!" + icon_state = "omelette" + trash = /obj/item/trash/plate + filling_color = "#FFF9A8" + list_reagents = list("nutriment" = 8, "vitamin" = 1) + bitesize = 1 + +/obj/item/reagent_containers/food/snacks/benedict + name = "eggs benedict" + desc = "There is only one egg on this, how rude." + icon_state = "benedict" + bitesize = 3 + list_reagents = list("nutriment" = 6, "egg" = 3, "vitamin" = 4) + + +////////////////////// +// Misc // +////////////////////// + +/obj/item/reagent_containers/food/snacks/hotdog + name = "hotdog" + desc = "Fresh footlong ready to go down on." + icon_state = "hotdog" + bitesize = 3 + list_reagents = list("nutriment" = 6, "ketchup" = 3, "vitamin" = 3) + +/obj/item/reagent_containers/food/snacks/meatbun + name = "meat bun" + desc = "Has the potential to not be dog." + icon_state = "meatbun" + bitesize = 6 + list_reagents = list("nutriment" = 6, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/sliceable/turkey + name = "Turkey" + desc = "A traditional turkey served with stuffing." + icon_state = "turkey" + slice_path = /obj/item/reagent_containers/food/snacks/turkeyslice + slices_num = 6 + list_reagents = list("protein" = 24, "nutriment" = 18, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/turkeyslice + name = "turkey serving" + desc = "A serving of some tender and delicious turkey." + icon_state = "turkeyslice" + trash = /obj/item/trash/plate + filling_color = "#B97A57" + +/obj/item/reagent_containers/food/snacks/organ + name = "organ" + desc = "It's good for you." + icon = 'icons/obj/surgery.dmi' + icon_state = "appendix" + filling_color = "#E00D34" + bitesize = 3 + list_reagents = list("protein" = 4, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/appendix +//yes, this is the same as meat. I might do something different in future + name = "appendix" + desc = "An appendix which looks perfectly healthy." + icon = 'icons/obj/surgery.dmi' + icon_state = "appendix" + filling_color = "#E00D34" + bitesize = 3 + list_reagents = list("protein" = 3, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/appendix/inflamed + name = "inflamed appendix" + desc = "An appendix which appears to be inflamed." + icon_state = "appendixinflamed" + filling_color = "#E00D7A" diff --git a/code/modules/food_and_drinks/food/foods/misc.dm b/code/modules/food_and_drinks/food/foods/misc.dm new file mode 100644 index 00000000000..4c6c607eacb --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/misc.dm @@ -0,0 +1,171 @@ + +////////////////////// +// Meals // +////////////////////// + +/obj/item/reagent_containers/food/snacks/eggplantparm + name = "Eggplant Parmigiana" + desc = "The only good recipe for eggplant." + icon_state = "eggplantparm" + trash = /obj/item/trash/plate + filling_color = "#4D2F5E" + list_reagents = list("nutriment" = 6, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/soylentgreen + name = "Soylent Green" + desc = "Not made of people. Honest." //Totally people. + icon_state = "soylent_green" + trash = /obj/item/trash/waffles + filling_color = "#B8E6B5" + list_reagents = list("nutriment" = 10, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/soylentviridians + name = "Soylent Virdians" + desc = "Not made of people. Honest." //Actually honest for once. + icon_state = "soylent_yellow" + trash = /obj/item/trash/waffles + filling_color = "#E6FA61" + list_reagents = list("nutriment" = 10, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/monkeysdelight + name = "monkey's Delight" + desc = "Eeee Eee!" + icon_state = "monkeysdelight" + trash = /obj/item/trash/tray + filling_color = "#5C3C11" + bitesize = 6 + list_reagents = list("nutriment" = 10, "banana" = 5, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/dionaroast + name = "roast diona" + desc = "It's like an enormous, leathery carrot. With an eye." + icon_state = "dionaroast" + trash = /obj/item/trash/plate + filling_color = "#75754B" + list_reagents = list("plantmatter" = 4, "nutriment" = 2, "radium" = 2, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/tofurkey + name = "Tofurkey" + desc = "A fake turkey made from tofu." + icon_state = "tofurkey" + filling_color = "#FFFEE0" + bitesize = 3 + list_reagents = list("nutriment" = 12, "ether" = 3) + + +////////////////////// +// Salads // +////////////////////// + +/obj/item/reagent_containers/food/snacks/aesirsalad + name = "Aesir salad" + desc = "Probably too incredible for mortal men to fully enjoy." + icon_state = "aesirsalad" + trash = /obj/item/trash/snack_bowl + filling_color = "#468C00" + bitesize = 3 + list_reagents = list("nutriment" = 8, "omnizine" = 8, "vitamin" = 6) + +/obj/item/reagent_containers/food/snacks/herbsalad + name = "herb salad" + desc = "A tasty salad with apples on top." + icon_state = "herbsalad" + trash = /obj/item/trash/snack_bowl + filling_color = "#76B87F" + bitesize = 3 + list_reagents = list("nutriment" = 8, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/validsalad + name = "valid salad" + desc = "It's just an herb salad with meatballs and fried potato slices. Nothing suspicious about it." + icon_state = "validsalad" + trash = /obj/item/trash/snack_bowl + filling_color = "#76B87F" + bitesize = 3 + list_reagents = list("nutriment" = 8, "salglu_solution" = 5, "vitamin" = 2) + + +////////////////////// +// Donk Pockets // +////////////////////// + +/obj/item/reagent_containers/food/snacks/donkpocket + name = "Donk-pocket" + desc = "The food of choice for the seasoned traitor." + icon_state = "donkpocket" + filling_color = "#DEDEAB" + list_reagents = list("nutriment" = 4) + +/obj/item/reagent_containers/food/snacks/warmdonkpocket + name = "Warm Donk-pocket" + desc = "The food of choice for the seasoned traitor." + icon_state = "donkpocket" + filling_color = "#DEDEAB" + list_reagents = list("nutriment" = 4) + +/obj/item/reagent_containers/food/snacks/warmdonkpocket/Post_Consume(mob/living/M) + M.reagents.add_reagent("omnizine", 15) + +/obj/item/reagent_containers/food/snacks/warmdonkpocket_weak + name = "Lightly Warm Donk-pocket" + desc = "The food of choice for the seasoned traitor. This one is lukewarm." + icon_state = "donkpocket" + filling_color = "#DEDEAB" + list_reagents = list("nutriment" = 4, "weak_omnizine" = 3) + +/obj/item/reagent_containers/food/snacks/syndidonkpocket + name = "Donk-pocket" + desc = "This donk-pocket is emitting a small amount of heat." + icon_state = "donkpocket" + filling_color = "#DEDEAB" + bitesize = 100 //nom the whole thing at once. + list_reagents = list("nutriment" = 1) + +/obj/item/reagent_containers/food/snacks/syndidonkpocket/Post_Consume(mob/living/M) + M.reagents.add_reagent("omnizine", 15) + M.reagents.add_reagent("teporone", 15) + M.reagents.add_reagent("synaptizine", 15) + M.reagents.add_reagent("salglu_solution", 15) + M.reagents.add_reagent("salbutamol", 15) + M.reagents.add_reagent("methamphetamine", 15) + + +////////////////////// +// Misc // +////////////////////// + +/obj/item/reagent_containers/food/snacks/boiledslimecore + name = "Boiled Slime Core" + desc = "A boiled red thing." + icon_state = "boiledrorocore" + bitesize = 3 + list_reagents = list("slimejelly" = 5) + +/obj/item/reagent_containers/food/snacks/popcorn + name = "Popcorn" + desc = "Now let's find some cinema." + icon_state = "popcorn" + trash = /obj/item/trash/popcorn + var/unpopped = 0 + filling_color = "#FFFAD4" + bitesize = 0.1 //this snack is supposed to be eating during looooong time. And this it not dinner food! --rastaf0 + list_reagents = list("nutriment" = 2) + +/obj/item/reagent_containers/food/snacks/popcorn/New() + ..() + unpopped = rand(1,10) + +/obj/item/reagent_containers/food/snacks/popcorn/On_Consume(mob/M, mob/user) + if(prob(unpopped)) //lol ...what's the point? + to_chat(user, "You bite down on an un-popped kernel!") + unpopped = max(0, unpopped-1) + ..() + +/obj/item/reagent_containers/food/snacks/liquidfood + name = "\improper LiquidFood Ration" + desc = "A prepackaged grey slurry of all the essential nutrients for a spacefarer on the go. Should this be crunchy?" + icon_state = "liquidfood" + trash = /obj/item/trash/liquidfood + filling_color = "#A8A8A8" + bitesize = 4 + list_reagents = list("nutriment" = 20, "iron" = 3, "vitamin" = 2) diff --git a/code/modules/food_and_drinks/food/foods/pasta.dm b/code/modules/food_and_drinks/food/foods/pasta.dm new file mode 100644 index 00000000000..1b9c253ab53 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/pasta.dm @@ -0,0 +1,70 @@ + +////////////////////// +// Raw Pasta // +////////////////////// + +/obj/item/reagent_containers/food/snacks/spaghetti + name = "Spaghetti" + desc = "A bundle of raw spaghetti." + icon = 'icons/obj/food/pasta.dmi' + icon_state = "spaghetti" + filling_color = "#EDDD00" + list_reagents = list("nutriment" = 1, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/macaroni + name = "Macaroni twists" + desc = "These are little twists of raw macaroni." + icon = 'icons/obj/food/pasta.dmi' + icon_state = "macaroni" + filling_color = "#EDDD00" + list_reagents = list("nutriment" = 1, "vitamin" = 1) + + +////////////////////// +// Pasta Dishes // +////////////////////// + +/obj/item/reagent_containers/food/snacks/boiledspaghetti + name = "Boiled Spaghetti" + desc = "A plain dish of noodles, this sucks." + icon = 'icons/obj/food/pasta.dmi' + icon_state = "spaghettiboiled" + trash = /obj/item/trash/plate + filling_color = "#FCEE81" + list_reagents = list("nutriment" = 2, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/pastatomato + name = "spaghetti" + desc = "Spaghetti and crushed tomatoes. Just like your abusive father used to make!" + icon = 'icons/obj/food/pasta.dmi' + icon_state = "pastatomato" + trash = /obj/item/trash/plate + filling_color = "#DE4545" + bitesize = 4 + list_reagents = list("nutriment" = 6, "tomatojuice" = 10, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/meatballspaghetti + name = "spaghetti & Meatballs" + desc = "Now thats a nic'e meatball!" + icon = 'icons/obj/food/pasta.dmi' + icon_state = "meatballspaghetti" + trash = /obj/item/trash/plate + filling_color = "#DE4545" + list_reagents = list("nutriment" = 8, "synaptizine" = 5, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/spesslaw + name = "Spesslaw" + desc = "A lawyer's favourite." + icon = 'icons/obj/food/pasta.dmi' + icon_state = "spesslaw" + filling_color = "#DE4545" + list_reagents = list("nutriment" = 8, "synaptizine" = 10, "vitamin" = 6) + +/obj/item/reagent_containers/food/snacks/macncheese + name = "Macaroni cheese" + desc = "One of the most comforting foods in the world. Apparently." + trash = /obj/item/trash/snack_bowl + icon = 'icons/obj/food/pasta.dmi' + icon_state = "macncheese" + filling_color = "#ffe45d" + list_reagents = list("nutriment" = 5, "vitamin" = 2, "cheese" = 4) diff --git a/code/modules/food_and_drinks/food/foods/pizza.dm b/code/modules/food_and_drinks/food/foods/pizza.dm new file mode 100644 index 00000000000..c34d8943da7 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/pizza.dm @@ -0,0 +1,254 @@ + +////////////////////// +// Pizzas // +////////////////////// + +/obj/item/reagent_containers/food/snacks/sliceable/pizza + icon = 'icons/obj/food/pizza.dmi' + slices_num = 6 + filling_color = "#BAA14C" + +/obj/item/reagent_containers/food/snacks/sliceable/pizza/margherita + name = "Margherita" + desc = "The golden standard of pizzas." + icon_state = "pizzamargherita" + slice_path = /obj/item/reagent_containers/food/snacks/margheritaslice + list_reagents = list("nutriment" = 30, "tomatojuice" = 6, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/margheritaslice + name = "Margherita slice" + desc = "A slice of the classic pizza." + icon = 'icons/obj/food/pizza.dmi' + icon_state = "pizzamargheritaslice" + filling_color = "#BAA14C" + list_reagents = list("nutriment" = 5) + +/obj/item/reagent_containers/food/snacks/sliceable/pizza/meatpizza + name = "Meatpizza" + desc = "A pizza with meat topping." + icon_state = "meatpizza" + slice_path = /obj/item/reagent_containers/food/snacks/meatpizzaslice + list_reagents = list("protein" = 30, "tomatojuice" = 6, "vitamin" = 8) + +/obj/item/reagent_containers/food/snacks/meatpizzaslice + name = "Meatpizza slice" + desc = "A slice of a meaty pizza." + icon = 'icons/obj/food/pizza.dmi' + icon_state = "meatpizzaslice" + filling_color = "#BAA14C" + +/obj/item/reagent_containers/food/snacks/sliceable/pizza/mushroompizza + name = "Mushroompizza" + desc = "Very special pizza." + icon_state = "mushroompizza" + slice_path = /obj/item/reagent_containers/food/snacks/mushroompizzaslice + list_reagents = list("plantmatter" = 30, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/mushroompizzaslice + name = "Mushroompizza slice" + desc = "Maybe it is the last slice of pizza in your life." + icon = 'icons/obj/food/pizza.dmi' + icon_state = "mushroompizzaslice" + filling_color = "#BAA14C" + +/obj/item/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza + name = "Vegetable pizza" + desc = "No one of Tomato Sapiens were harmed during making this pizza." + icon_state = "vegetablepizza" + slice_path = /obj/item/reagent_containers/food/snacks/vegetablepizzaslice + list_reagents = list("plantmatter" = 25, "tomatojuice" = 6, "oculine" = 12, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/vegetablepizzaslice + name = "Vegetable pizza slice" + desc = "A slice of the most green pizza of all pizzas not containing green ingredients." + icon = 'icons/obj/food/pizza.dmi' + icon_state = "vegetablepizzaslice" + filling_color = "#BAA14C" + +/obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza + name = "Hawaiian Pizza" + desc = "Love it or hate it, this pizza divides opinions. Complete with juicy pineapple." + icon_state = "hawaiianpizza" //NEEDED + slice_path = /obj/item/reagent_containers/food/snacks/hawaiianpizzaslice + list_reagents = list("protein" = 15, "tomatojuice" = 6, "plantmatter" = 20, "pineapplejuice" = 6, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/hawaiianpizzaslice + name = "Hawaiian pizza slice" + desc = "A slice of polarising pizza." + icon = 'icons/obj/food/pizza.dmi' + icon_state = "hawaiianpizzaslice" + filling_color = "#e5b437" + +/obj/item/reagent_containers/food/snacks/sliceable/pizza/macpizza + name = "Macaroni cheese pizza" + desc = "Gastronomists have yet to classify this dish as 'pizza'." + icon_state = "macpizza" + slice_path = /obj/item/reagent_containers/food/snacks/macpizzaslice + list_reagents = list("nutriment" = 40, "vitamin" = 5) //More nutriment because carbs, but it's not any more vitaminicious + filling_color = "#ffe45d" + +/obj/item/reagent_containers/food/snacks/macpizzaslice + name = "Macaroni cheese pizza slice" + desc = "A delicious slice of pizza topped with macaroni cheese... wait, what the hell? Who would do this?!" + icon = 'icons/obj/food/pizza.dmi' + icon_state = "macpizzaslice" + filling_color = "#ffe45d" + + +////////////////////// +// Boxes // +////////////////////// + +/obj/item/pizzabox + name = "pizza box" + desc = "A box suited for pizzas." + icon = 'icons/obj/food/pizza.dmi' + icon_state = "pizzabox1" + + var/open = 0 // Is the box open? + var/ismessy = 0 // Fancy mess on the lid + var/obj/item/reagent_containers/food/snacks/sliceable/pizza/pizza // Content pizza + var/list/boxes = list() // If the boxes are stacked, they come here + var/boxtag = "" + +/obj/item/pizzabox/update_icon() + overlays = list() + + // Set appropriate description + if(open && pizza) + desc = "A box suited for pizzas. It appears to have a [pizza.name] inside." + else if(boxes.len > 0) + desc = "A pile of boxes suited for pizzas. There appears to be [boxes.len + 1] boxes in the pile." + var/obj/item/pizzabox/topbox = boxes[boxes.len] + var/toptag = topbox.boxtag + if(toptag != "") + desc = "[desc] The box on top has a tag, it reads: '[toptag]'." + else + desc = "A box suited for pizzas." + if(boxtag != "") + desc = "[desc] The box has a tag, it reads: '[boxtag]'." + + // Icon states and overlays + if(open) + if(ismessy) + icon_state = "pizzabox_messy" + else + icon_state = "pizzabox_open" + if(pizza) + var/image/pizzaimg = image("food/pizza.dmi", icon_state = pizza.icon_state) + pizzaimg.pixel_y = -3 + overlays += pizzaimg + + return + else + // Stupid code because byondcode sucks + var/doimgtag = 0 + if(boxes.len > 0) + var/obj/item/pizzabox/topbox = boxes[boxes.len] + if(topbox.boxtag != "") + doimgtag = 1 + else + if(boxtag != "") + doimgtag = 1 + if(doimgtag) + var/image/tagimg = image("food/pizza.dmi", icon_state = "pizzabox_tag") + tagimg.pixel_y = boxes.len * 3 + overlays += tagimg + icon_state = "pizzabox[boxes.len+1]" + +/obj/item/pizzabox/attack_hand(mob/user) + if(open && pizza) + user.put_in_hands(pizza) + to_chat(user, "You take the [pizza] out of the [src].") + pizza = null + update_icon() + return + + if(boxes.len > 0) + if(user.is_in_inactive_hand(src)) + ..() + return + var/obj/item/pizzabox/box = boxes[boxes.len] + boxes -= box + user.put_in_hands(box) + to_chat(user, "You remove the topmost [src] from your hand.") + box.update_icon() + update_icon() + return + ..() + +/obj/item/pizzabox/attack_self(mob/user) + if(boxes.len > 0) + return + open = !open + if(open && pizza) + ismessy = 1 + update_icon() + +/obj/item/pizzabox/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/pizzabox/)) + var/obj/item/pizzabox/box = I + if(!box.open && !open) + // Make a list of all boxes to be added + var/list/boxestoadd = list() + boxestoadd += box + for(var/obj/item/pizzabox/i in box.boxes) + boxestoadd += i + if((boxes.len+1) + boxestoadd.len <= 5) + user.drop_item() + box.loc = src + box.boxes = list() // Clear the box boxes so we don't have boxes inside boxes. - Xzibit + boxes.Add(boxestoadd) + box.update_icon() + update_icon() + to_chat(user, "You put the [box] ontop of the [src]!") + else + to_chat(user, "The stack is too high!") + else + to_chat(user, "Close the [box] first!") + return + + if(istype(I, /obj/item/reagent_containers/food/snacks/sliceable/pizza/)) // Long ass fucking object name + if(open) + user.drop_item() + I.loc = src + pizza = I + + update_icon() + + to_chat(user, "You put the [I] in the [src]!") + else + to_chat(user, "You try to push the [I] through the lid but it doesn't work!") + return + + if(istype(I, /obj/item/pen/)) + if(open) + return + var/t = input("Enter what you want to add to the tag:", "Write", null, null) as text + var/obj/item/pizzabox/boxtotagto = src + if(boxes.len > 0) + boxtotagto = boxes[boxes.len] + boxtotagto.boxtag = copytext("[boxtotagto.boxtag][t]", 1, 30) + update_icon() + return + ..() + +/obj/item/pizzabox/margherita/New() + pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/margherita(src) + boxtag = "Margherita Deluxe" + +/obj/item/pizzabox/vegetable/New() + pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza(src) + boxtag = "Gourmet Vegatable" + +/obj/item/pizzabox/mushroom/New() + pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/mushroompizza(src) + boxtag = "Mushroom Special" + +/obj/item/pizzabox/meat/New() + pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/meatpizza(src) + boxtag = "Meatlover's Supreme" + +/obj/item/pizzabox/hawaiian/New() + pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza(src) + boxtag = "Hawaiian Feast" \ No newline at end of file diff --git a/code/modules/food_and_drinks/food/foods/sandwiches.dm b/code/modules/food_and_drinks/food/foods/sandwiches.dm new file mode 100644 index 00000000000..a55a92ae3d1 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/sandwiches.dm @@ -0,0 +1,196 @@ + +////////////////////// +// Burgers // +////////////////////// + +/obj/item/reagent_containers/food/snacks/brainburger + name = "brainburger" + desc = "A strange looking burger. It looks almost sentient." + icon_state = "brainburger" + filling_color = "#F2B6EA" + bitesize = 3 + list_reagents = list("nutriment" = 6, "prions" = 10, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/ghostburger + name = "Ghost Burger" + desc = "Spooky! It doesn't look very filling." + icon_state = "ghostburger" + filling_color = "#FFF2FF" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/human + var/hname = "" + var/job = null + filling_color = "#D63C3C" + +/obj/item/reagent_containers/food/snacks/human/burger + name = "-burger" + desc = "A bloody burger." + icon_state = "hburger" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/cheeseburger + name = "cheeseburger" + desc = "The cheese adds a good flavor." + icon_state = "cheeseburger" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/monkeyburger + name = "burger" + desc = "The cornerstone of every nutritious breakfast." + icon_state = "hburger" + filling_color = "#D63C3C" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/tofuburger + name = "Tofu Burger" + desc = "What.. is that meat?" + icon_state = "tofuburger" + filling_color = "#FFFEE0" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/roburger + name = "roburger" + desc = "The lettuce is the only organic component. Beep." + icon_state = "roburger" + filling_color = "#CCCCCC" + bitesize = 3 + list_reagents = list("nutriment" = 6, "nanomachines" = 10, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/roburgerbig + name = "roburger" + desc = "This massive patty looks like poison. Beep." + icon_state = "roburger" + filling_color = "#CCCCCC" + volume = 120 + bitesize = 3 + list_reagents = list("nutriment" = 6, "nanomachines" = 70, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/xenoburger + name = "xenoburger" + desc = "Smells caustic. Tastes like heresy." + icon_state = "xburger" + filling_color = "#43DE18" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/clownburger + name = "Clown Burger" + desc = "This tastes funny..." + icon_state = "clownburger" + filling_color = "#FF00FF" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/mimeburger + name = "Mime Burger" + desc = "Its taste defies language." + icon_state = "mimeburger" + filling_color = "#FFFFFF" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/baseballburger + name = "home run baseball burger" + desc = "It's still warm. The steam coming off of it looks like baseball." + icon_state = "baseball" + filling_color = "#CD853F" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/spellburger + name = "Spell Burger" + desc = "This is absolutely Ei Nath." + icon_state = "spellburger" + filling_color = "#D505FF" + bitesize = 3 + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/bigbiteburger + name = "Big Bite Burger" + desc = "Forget the Big Mac. THIS is the future!" + icon_state = "bigbiteburger" + filling_color = "#E3D681" + bitesize = 3 + list_reagents = list("nutriment" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/superbiteburger + name = "Super Bite Burger" + desc = "This is a mountain of a burger. FOOD!" + icon_state = "superbiteburger" + filling_color = "#CCA26A" + bitesize = 7 + list_reagents = list("nutriment" = 40, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/jellyburger + name = "Jelly Burger" + desc = "Culinary delight..?" + icon_state = "jellyburger" + filling_color = "#B572AB" + bitesize = 3 + +/obj/item/reagent_containers/food/snacks/jellyburger/slime + list_reagents = list("nutriment" = 6, "slimejelly" = 5, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/jellyburger/cherry + list_reagents = list("nutriment" = 6, "cherryjelly" = 5, "vitamin" = 1) + + +////////////////////// +// Sandwiches // +////////////////////// + +/obj/item/reagent_containers/food/snacks/sandwich + name = "Sandwich" + desc = "A grand creation of meat, cheese, bread, and several leaves of lettuce! Arthur Dent would be proud." + icon_state = "sandwich" + trash = /obj/item/trash/plate + filling_color = "#D9BE29" + list_reagents = list("nutriment" = 6, "vitamin" = 1) + +/obj/item/reagent_containers/food/snacks/toastedsandwich + name = "Toasted Sandwich" + desc = "Now if you only had a pepper bar." + icon_state = "toastedsandwich" + trash = /obj/item/trash/plate + filling_color = "#D9BE29" + list_reagents = list("nutriment" = 6, "carbon" = 2) + +/obj/item/reagent_containers/food/snacks/grilledcheese + name = "Grilled Cheese Sandwich" + desc = "Goes great with Tomato soup!" + icon_state = "toastedsandwich" + trash = /obj/item/trash/plate + filling_color = "#D9BE29" + list_reagents = list("nutriment" = 7, "vitamin" = 1) //why make a regualr sandwhich when you can make grilled cheese, with this nutriment value? + +/obj/item/reagent_containers/food/snacks/jellysandwich + name = "Jelly Sandwich" + desc = "You wish you had some peanut butter to go with this..." + icon_state = "jellysandwich" + trash = /obj/item/trash/plate + filling_color = "#9E3A78" + bitesize = 3 + +/obj/item/reagent_containers/food/snacks/jellysandwich/slime + list_reagents = list("nutriment" = 2, "slimejelly" = 5, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/jellysandwich/cherry + list_reagents = list("nutriment" = 2, "cherryjelly" = 5, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/notasandwich + name = "not-a-sandwich" + desc = "Something seems to be wrong with this, you can't quite figure what. Maybe it's his moustache." + icon_state = "notasandwich" + list_reagents = list("nutriment" = 6, "vitamin" = 6) + +/obj/item/reagent_containers/food/snacks/wrap + name = "egg wrap" + desc = "The precursor to Pigs in a Blanket." + icon_state = "wrap" + list_reagents = list("nutriment" = 5) diff --git a/code/modules/food_and_drinks/food/seafood.dm b/code/modules/food_and_drinks/food/foods/seafood.dm similarity index 100% rename from code/modules/food_and_drinks/food/seafood.dm rename to code/modules/food_and_drinks/food/foods/seafood.dm diff --git a/code/modules/food_and_drinks/food/foods/side_dishes.dm b/code/modules/food_and_drinks/food/foods/side_dishes.dm new file mode 100644 index 00000000000..7b563519ca3 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/side_dishes.dm @@ -0,0 +1,105 @@ + +////////////////////// +// Raw // +////////////////////// + +/obj/item/reagent_containers/food/snacks/rawsticks + name = "raw potato sticks" + desc = "Raw fries, not very tasty." + icon = 'icons/obj/food/food_ingredients.dmi' + icon_state = "rawsticks" + list_reagents = list("plantmatter" = 3) + + +////////////////////// +// Fried // +////////////////////// + +/obj/item/reagent_containers/food/snacks/fries + name = "Space fries" + desc = "AKA: French Fries, Freedom Fries, etc." + icon_state = "fries" + trash = /obj/item/trash/plate + filling_color = "#EDDD00" + list_reagents = list("nutriment" = 4) + +/obj/item/reagent_containers/food/snacks/cheesyfries + name = "cheesy fries" + desc = "Fries. Covered in cheese. Duh." + icon_state = "cheesyfries" + trash = /obj/item/trash/plate + filling_color = "#EDDD00" + list_reagents = list("nutriment" = 6) + +/obj/item/reagent_containers/food/snacks/tatortot + name = "tator tot" + desc = "A large fried potato nugget that may or may not try to valid you." + icon_state = "tatortot" + list_reagents = list("nutriment" = 4) + filling_color = "FFD700" + +/obj/item/reagent_containers/food/snacks/onionrings + name = "onion rings" + desc = "Onion slices coated in batter." + icon_state = "onionrings" + list_reagents = list("nutriment" = 3) + filling_color = "#C0C9A0" + gender = PLURAL + +/obj/item/reagent_containers/food/snacks/carrotfries + name = "carrot fries" + desc = "Tasty fries from fresh carrots." + icon_state = "carrotfries" + trash = /obj/item/trash/plate + filling_color = "#FAA005" + list_reagents = list("plantmatter" = 3, "oculine" = 3, "vitamin" = 2) + + +////////////////////// +// Misc // +////////////////////// + +/obj/item/reagent_containers/food/snacks/beans + name = "tin of beans" + desc = "Musical fruit in a slightly less musical container." + icon_state = "beans" + list_reagents = list("nutriment" = 10, "beans" = 10, "vitamin" = 3) + +/obj/item/reagent_containers/food/snacks/mashed_potatoes //mashed taters + name = "mashed potatoes" + desc = "Some soft, creamy, and irresistible mashed potatoes." + icon_state = "mashedtaters" + trash = /obj/item/trash/plate + filling_color = "#D6D9C1" + list_reagents = list("nutriment" = 5, "gravy" = 5, "mashedpotatoes" = 10, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/stuffing + name = "Stuffing" + desc = "Moist, peppery breadcrumbs for filling the body cavities of dead birds. Dig in!" + icon_state = "stuffing" + filling_color = "#C9AC83" + list_reagents = list("nutriment" = 3) + +/obj/item/reagent_containers/food/snacks/loadedbakedpotato + name = "loaded baked potato" + desc = "Totally baked." + icon_state = "loadedbakedpotato" + filling_color = "#9C7A68" + list_reagents = list("nutriment" = 6) + +/obj/item/reagent_containers/food/snacks/boiledrice + name = "Boiled Rice" + desc = "A boring dish of boring rice." + icon_state = "boiledrice" + trash = /obj/item/trash/snack_bowl + filling_color = "#FFFBDB" + list_reagents = list("nutriment" = 5, "vitamin" = 1) + + +/obj/item/reagent_containers/food/snacks/roastparsnip + name = "roast parsnip" + desc = "Sweet and crunchy." + icon_state = "roastparsnip" + trash = /obj/item/trash/plate + list_reagents = list("nutriment" = 3, "vitamin" = 4) + filling_color = "#FF5500" diff --git a/code/modules/food_and_drinks/food/foods/soups.dm b/code/modules/food_and_drinks/food/foods/soups.dm new file mode 100644 index 00000000000..76e4d752a41 --- /dev/null +++ b/code/modules/food_and_drinks/food/foods/soups.dm @@ -0,0 +1,166 @@ + +////////////////////// +// Soups // +////////////////////// + +/obj/item/reagent_containers/food/snacks/meatballsoup + name = "Meatball soup" + desc = "You've got balls kid, BALLS!" + icon_state = "meatballsoup" + trash = /obj/item/trash/snack_bowl + filling_color = "#785210" + bitesize = 5 + list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/slimesoup + name = "slime soup" + desc = "If no water is available, you may substitute tears." + icon_state = "slimesoup" + filling_color = "#C4DBA0" + bitesize = 5 + list_reagents = list("nutriment" = 5, "slimejelly" = 5, "water" = 5, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/bloodsoup + name = "Tomato soup" + desc = "Smells like copper." + icon_state = "tomatosoup" + filling_color = "#FF0000" + bitesize = 5 + list_reagents = list("nutriment" = 2, "blood" = 10, "water" = 5, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/clownstears + name = "Clown's Tears" + desc = "Not very funny." + icon_state = "clownstears" + filling_color = "#C4FBFF" + bitesize = 5 + list_reagents = list("nutriment" = 4, "banana" = 5, "water" = 5, "vitamin" = 8) + +/obj/item/reagent_containers/food/snacks/vegetablesoup + name = "Vegetable soup" + desc = "A true vegan meal." //TODO + icon_state = "vegetablesoup" + trash = /obj/item/trash/snack_bowl + filling_color = "#AFC4B5" + bitesize = 5 + list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/nettlesoup + name = "Nettle soup" + desc = "To think, the botanist would've beat you to death with one of these." + icon_state = "nettlesoup" + trash = /obj/item/trash/snack_bowl + filling_color = "#AFC4B5" + bitesize = 5 + list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/mysterysoup + name = "mystery soup" + desc = "The mystery is, why aren't you eating it?" + icon_state = "mysterysoup" + var/extra_reagent = null + bitesize = 5 + list_reagents = list("nutriment" = 6) + +/obj/item/reagent_containers/food/snacks/mysterysoup/New() + ..() + extra_reagent = pick("capsaicin", "frostoil", "omnizine", "banana", "blood", "slimejelly", "toxin", "banana", "carbon", "oculine") + reagents.add_reagent("[extra_reagent]", 5) + +/obj/item/reagent_containers/food/snacks/wishsoup + name = "Wish Soup" + desc = "I wish this was soup." + icon_state = "wishsoup" + trash = /obj/item/trash/snack_bowl + filling_color = "#D1F4FF" + bitesize = 5 + list_reagents = list("water" = 10) + +/obj/item/reagent_containers/food/snacks/wishsoup/New() + ..() + if(prob(25)) + desc = "A wish come true!" // hue + reagents.add_reagent("nutriment", 9) + reagents.add_reagent("vitamin", 1) + +/obj/item/reagent_containers/food/snacks/tomatosoup + name = "Tomato Soup" + desc = "Drinking this feels like being a vampire! A tomato vampire..." + icon_state = "tomatosoup" + trash = /obj/item/trash/snack_bowl + filling_color = "#D92929" + bitesize = 5 + list_reagents = list("nutriment" = 5, "tomatojuice" = 10, "vitamin" = 3) + +/obj/item/reagent_containers/food/snacks/milosoup + name = "Milosoup" + desc = "The universe's best soup! Yum!!!" + icon_state = "milosoup" + trash = /obj/item/trash/snack_bowl + bitesize = 5 + list_reagents = list("nutriment" = 7, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/mushroomsoup + name = "chantrelle soup" + desc = "A delicious and hearty mushroom soup." + icon_state = "mushroomsoup" + trash = /obj/item/trash/snack_bowl + filling_color = "#E386BF" + bitesize = 5 + list_reagents = list("nutriment" = 8, "vitamin" = 4) + +/obj/item/reagent_containers/food/snacks/beetsoup + name = "beet soup" + desc = "Wait, how do you spell it again..?" + icon_state = "beetsoup" + trash = /obj/item/trash/snack_bowl + bitesize = 5 + filling_color = "#FAC9FF" + list_reagents = list("nutriment" = 7, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/beetsoup/New() + ..() + name = pick("borsch","bortsch","borstch","borsh","borshch","borscht") + + +////////////////////// +// Stews // +////////////////////// + +/obj/item/reagent_containers/food/snacks/stew + name = "Stew" + desc = "A nice and warm stew. Healthy and strong." + icon_state = "stew" + filling_color = "#9E673A" + bitesize = 7 + list_reagents = list("nutriment" = 10, "oculine" = 5, "tomatojuice" = 5, "vitamin" = 5) + +/obj/item/reagent_containers/food/snacks/stewedsoymeat + name = "Stewed Soy Meat" + desc = "Even non-vegetarians will LOVE this!" + icon_state = "stewedsoymeat" + trash = /obj/item/trash/plate + list_reagents = list("nutriment" = 8) + + +////////////////////// +// Chili // +////////////////////// + +/obj/item/reagent_containers/food/snacks/hotchili + name = "Hot Chili" + desc = "A five alarm Texan Chili!" + icon_state = "hotchili" + trash = /obj/item/trash/snack_bowl + filling_color = "#FF3C00" + bitesize = 5 + list_reagents = list("nutriment" = 5, "capsaicin" = 1, "tomatojuice" = 2, "vitamin" = 2) + +/obj/item/reagent_containers/food/snacks/coldchili + name = "Cold Chili" + desc = "This slush is barely a liquid!" + icon_state = "coldchili" + filling_color = "#2B00FF" + trash = /obj/item/trash/snack_bowl + bitesize = 5 + list_reagents = list("nutriment" = 5, "frostoil" = 1, "tomatojuice" = 2, "vitamin" = 2) diff --git a/code/modules/food_and_drinks/food/meat.dm b/code/modules/food_and_drinks/food/meat.dm deleted file mode 100644 index 7940050b35a..00000000000 --- a/code/modules/food_and_drinks/food/meat.dm +++ /dev/null @@ -1,55 +0,0 @@ -/obj/item/reagent_containers/food/snacks/meat - name = "meat" - desc = "A slab of meat" - icon_state = "meat" - health = 180 - filling_color = "#FF1C1C" - bitesize = 3 - list_reagents = list("protein" = 3) - -/obj/item/reagent_containers/food/snacks/meat/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/kitchen/knife) || istype(W, /obj/item/scalpel)) - new /obj/item/reagent_containers/food/snacks/rawcutlet(src) - new /obj/item/reagent_containers/food/snacks/rawcutlet(src) - new /obj/item/reagent_containers/food/snacks/rawcutlet(src) - to_chat(user, "You cut the meat in thin strips.") - qdel(src) - else - ..() - -/obj/item/reagent_containers/food/snacks/meat/syntiflesh - name = "synthetic meat" - desc = "A synthetic slab of flesh." - -/obj/item/reagent_containers/food/snacks/meat/human - name = "-meat" - var/subjectname = "" - var/subjectjob = null - -/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct - name = "meat product" - desc = "A slab of station reclaimed and chemically processed meat product." - -/obj/item/reagent_containers/food/snacks/meat/monkey - //same as plain meat - -/obj/item/reagent_containers/food/snacks/meat/corgi - name = "Corgi meat" - desc = "Tastes like... well you know..." - -/obj/item/reagent_containers/food/snacks/meat/pug - name = "Pug meat" - desc = "Tastes like... well you know..." - -/obj/item/reagent_containers/food/snacks/meat/ham - name = "Ham" - desc = "Taste like bacon." - list_reagents = list("protein" = 3, "porktonium" = 10) - -/obj/item/reagent_containers/food/snacks/meat/meatwheat - name = "meatwheat clump" - desc = "This doesn't look like meat, but your standards aren't that high to begin with." - list_reagents = list("nutriment" = 3, "vitamin" = 2, "blood" = 5) - filling_color = rgb(150, 0, 0) - icon_state = "meatwheat_clump" - bitesize = 4 \ No newline at end of file diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index cd94d79bd5c..4803405520a 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -99,6 +99,7 @@ U.overlays += I var/obj/item/reagent_containers/food/snacks/collected = new type + collected.name = name collected.loc = U collected.reagents.remove_any(collected.reagents.total_volume) collected.trash = null @@ -270,791 +271,6 @@ // bitesize = 3 //This is the amount each bite consumes. - - -/obj/item/reagent_containers/food/snacks/aesirsalad - name = "Aesir salad" - desc = "Probably too incredible for mortal men to fully enjoy." - icon_state = "aesirsalad" - trash = /obj/item/trash/snack_bowl - filling_color = "#468C00" - bitesize = 3 - list_reagents = list("nutriment" = 8, "omnizine" = 8, "vitamin" = 6) - -/obj/item/reagent_containers/food/snacks/chips - name = "chips" - desc = "Commander Riker's What-The-Crisps." - icon_state = "chips" - bitesize = 1 - trash = /obj/item/trash/chips - filling_color = "#E8C31E" - junkiness = 20 - list_reagents = list("nutriment" = 1, "sodiumchloride" = 1, "sugar" = 3) - -/obj/item/reagent_containers/food/snacks/cornchips - name = "corn chips" - desc = "Goes great with salsa! OLE!" - icon_state = "chips" - bitesize = 1 - trash = /obj/item/trash/chips - filling_color = "#E8C31E" - list_reagents = list("nutriment" = 3) - -/obj/item/reagent_containers/food/snacks/cookie - name = "cookie" - desc = "COOKIE!!!" - icon_state = "COOKIE!!!" - bitesize = 1 - filling_color = "#DBC94F" - list_reagents = list("nutriment" = 1) - -/obj/item/reagent_containers/food/snacks/chocolatebar - name = "Chocolate Bar" - desc = "Such sweet, fattening food." - icon_state = "chocolatebar" - filling_color = "#7D5F46" - list_reagents = list("nutriment" = 2, "sugar" = 2, "cocoa" = 2) - -/obj/item/reagent_containers/food/snacks/choc_pile //for reagent chocolate being spilled on turfs - name = "Pile of Chocolate" - desc = "A pile of pure chocolate pieces." - icon_state = "cocoa" - filling_color = "#7D5F46" - list_reagents = list("chocolate" = 5) - -/obj/item/reagent_containers/food/snacks/chocolateegg - name = "Chocolate Egg" - desc = "Such sweet, fattening food." - icon_state = "chocolateegg" - filling_color = "#7D5F46" - list_reagents = list("nutriment" = 4, "sugar" = 2, "cocoa" = 2) - -/obj/item/reagent_containers/food/snacks/donut - name = "donut" - desc = "Goes great with Robust Coffee." - icon_state = "donut1" - bitesize = 5 - list_reagents = list("nutriment" = 3, "sugar" = 2) - var/extra_reagent = null - filling_color = "#D2691E" - var/randomized_sprinkles = 1 - -/obj/item/reagent_containers/food/snacks/donut/New() - ..() - if(randomized_sprinkles && prob(30)) - icon_state = "donut2" - name = "frosted donut" - reagents.add_reagent("sprinkles", 2) - filling_color = "#FF69B4" - -/obj/item/reagent_containers/food/snacks/donut/sprinkles - name = "frosted donut" - icon_state = "donut2" - list_reagents = list("nutriment" = 3, "sugar" = 2, "spinkles" = 2) - filling_color = "#FF69B4" - randomized_sprinkles = 0 - -/obj/item/reagent_containers/food/snacks/donut/chaos - name = "chaos donut" - desc = "Like life, it never quite tastes the same." - bitesize = 10 - -/obj/item/reagent_containers/food/snacks/donut/chaos/New() - ..() - extra_reagent = pick("nutriment", "capsaicin", "frostoil", "krokodil", "plasma", "cocoa", "slimejelly", "banana", "berryjuice", "omnizine") - reagents.add_reagent("[extra_reagent]", 3) - if(prob(30)) - icon_state = "donut2" - name = "frosted chaos donut" - reagents.add_reagent("sprinkles", 2) - filling_color = "#FF69B4" - -/obj/item/reagent_containers/food/snacks/donut/jelly - name = "jelly donut" - desc = "You jelly?" - icon_state = "jdonut1" - extra_reagent = "berryjuice" - -/obj/item/reagent_containers/food/snacks/donut/jelly/New() - ..() - if(extra_reagent) - reagents.add_reagent("[extra_reagent]", 3) - if(prob(30)) - icon_state = "jdonut2" - name = "frosted jelly Donut" - reagents.add_reagent("sprinkles", 2) - filling_color = "#FF69B4" - -/obj/item/reagent_containers/food/snacks/donut/jelly/slimejelly - name = "jelly donut" - desc = "You jelly?" - icon_state = "jdonut1" - extra_reagent = "slimejelly" - -/obj/item/reagent_containers/food/snacks/donut/jelly/cherryjelly - name = "jelly donut" - desc = "You jelly?" - icon_state = "jdonut1" - extra_reagent = "cherryjelly" - -/obj/item/reagent_containers/food/snacks/egg - name = "egg" - desc = "An egg!" - icon_state = "egg" - filling_color = "#FDFFD1" - list_reagents = list("protein" = 1, "egg" = 5) - -/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom) - ..() - var/turf/T = get_turf(hit_atom) - new/obj/effect/decal/cleanable/egg_smudge(T) - if(reagents) - reagents.reaction(hit_atom, TOUCH) - qdel(src) - -/obj/item/reagent_containers/food/snacks/egg/attackby(obj/item/W, mob/user, params) - if(istype( W, /obj/item/toy/crayon )) - var/obj/item/toy/crayon/C = W - var/clr = C.colourName - - if(!(clr in list("blue","green","mime","orange","purple","rainbow","red","yellow"))) - to_chat(usr, "The egg refuses to take on this color!") - return - - to_chat(usr, "You color \the [src] [clr]") - icon_state = "egg-[clr]" - item_color = clr - else - ..() - -/obj/item/reagent_containers/food/snacks/egg/blue - icon_state = "egg-blue" - item_color = "blue" - -/obj/item/reagent_containers/food/snacks/egg/green - icon_state = "egg-green" - item_color = "green" - -/obj/item/reagent_containers/food/snacks/egg/mime - icon_state = "egg-mime" - item_color = "mime" - -/obj/item/reagent_containers/food/snacks/egg/orange - icon_state = "egg-orange" - item_color = "orange" - -/obj/item/reagent_containers/food/snacks/egg/purple - icon_state = "egg-purple" - item_color = "purple" - -/obj/item/reagent_containers/food/snacks/egg/rainbow - icon_state = "egg-rainbow" - item_color = "rainbow" - -/obj/item/reagent_containers/food/snacks/egg/red - icon_state = "egg-red" - item_color = "red" - -/obj/item/reagent_containers/food/snacks/egg/yellow - icon_state = "egg-yellow" - item_color = "yellow" - -/obj/item/reagent_containers/food/snacks/friedegg - name = "Fried egg" - desc = "A fried egg, with a touch of salt and pepper." - icon_state = "friedegg" - filling_color = "#FFDF78" - bitesize = 1 - list_reagents = list("nutriment" = 3, "egg" = 5) - -/obj/item/reagent_containers/food/snacks/boiledegg - name = "Boiled egg" - desc = "A hard boiled egg." - icon_state = "egg" - filling_color = "#FFFFFF" - list_reagents = list("nutriment" = 2, "egg" = 5, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/organ - - name = "organ" - desc = "It's good for you." - icon = 'icons/obj/surgery.dmi' - icon_state = "appendix" - filling_color = "#E00D34" - bitesize = 3 - list_reagents = list("protein" = 4, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/appendix -//yes, this is the same as meat. I might do something different in future - name = "appendix" - desc = "An appendix which looks perfectly healthy." - icon = 'icons/obj/surgery.dmi' - icon_state = "appendix" - filling_color = "#E00D34" - bitesize = 3 - list_reagents = list("protein" = 3, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/appendix/inflamed - name = "inflamed appendix" - desc = "An appendix which appears to be inflamed." - icon_state = "appendixinflamed" - filling_color = "#E00D7A" - -/obj/item/reagent_containers/food/snacks/tofu - name = "Tofu" - icon_state = "tofu" - desc = "We all love tofu." - filling_color = "#FFFEE0" - bitesize = 3 - list_reagents = list("plantmatter" = 2) - -/obj/item/reagent_containers/food/snacks/fried_tofu - name = "Fried Tofu" - icon_state = "tofu" - desc = "Proof that even vegetarians crave unhealthy foods." - filling_color = "#FFFEE0" - bitesize = 3 - list_reagents = list("plantmatter" = 3) - -/obj/item/reagent_containers/food/snacks/tofurkey - name = "Tofurkey" - desc = "A fake turkey made from tofu." - icon_state = "tofurkey" - filling_color = "#FFFEE0" - bitesize = 3 - list_reagents = list("nutriment" = 12, "ether" = 3) - -/obj/item/reagent_containers/food/snacks/stuffing - name = "Stuffing" - desc = "Moist, peppery breadcrumbs for filling the body cavities of dead birds. Dig in!" - icon_state = "stuffing" - filling_color = "#C9AC83" - list_reagents = list("nutriment" = 3) - -/obj/item/reagent_containers/food/snacks/hugemushroomslice - name = "huge mushroom slice" - desc = "A slice from a huge mushroom." - icon_state = "hugemushroomslice" - filling_color = "#E0D7C5" - bitesize = 6 - list_reagents = list("plantmatter" = 3, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/tomatomeat - name = "tomato slice" - desc = "A slice from a huge tomato." - icon_state = "tomatomeat" - filling_color = "#DB0000" - bitesize = 6 - list_reagents = list("protein" = 2) - -/obj/item/reagent_containers/food/snacks/bearmeat - name = "bear meat" - desc = "A very manly slab of meat." - icon_state = "bearmeat" - filling_color = "#DB0000" - bitesize = 3 - list_reagents = list("protein" = 12, "morphine" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/xenomeat - name = "meat" - desc = "A slab of meat." - icon_state = "xenomeat" - filling_color = "#43DE18" - bitesize = 6 - list_reagents = list("protein" = 3, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/spidermeat - name = "spider meat" - desc = "A slab of spider meat." - icon_state = "spidermeat" - bitesize = 3 - list_reagents = list("protein" = 3, "toxin" = 3, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/lizardmeat - name = "mutant lizard meat" - desc = "Seems to be a slab of meat from some mutant lizard thing?" - icon_state = "xenomeat" - filling_color = "#43DE18" - bitesize = 3 - list_reagents = list("protein" = 3, "toxin" = 3) - -/obj/item/reagent_containers/food/snacks/spiderleg - name = "spider leg" - desc = "A still twitching leg of a giant spider... you don't really want to eat this, do you?" - icon_state = "spiderleg" - list_reagents = list("protein" = 2, "toxin" = 2) - -/obj/item/reagent_containers/food/snacks/meatball - name = "Meatball" - desc = "A great meal all round." - icon_state = "meatball" - filling_color = "#DB0000" - list_reagents = list("protein" = 4, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/sausage - name = "Sausage" - desc = "A piece of mixed, long meat." - icon_state = "sausage" - filling_color = "#DB0000" - list_reagents = list("protein" = 6, "vitamin" = 1, "porktonium" = 10) - -/obj/item/reagent_containers/food/snacks/donkpocket - name = "Donk-pocket" - desc = "The food of choice for the seasoned traitor." - icon_state = "donkpocket" - filling_color = "#DEDEAB" - list_reagents = list("nutriment" = 4) - -/obj/item/reagent_containers/food/snacks/warmdonkpocket - name = "Warm Donk-pocket" - desc = "The food of choice for the seasoned traitor." - icon_state = "donkpocket" - filling_color = "#DEDEAB" - list_reagents = list("nutriment" = 4) - -/obj/item/reagent_containers/food/snacks/warmdonkpocket/Post_Consume(mob/living/M) - M.reagents.add_reagent("omnizine", 15) - -/obj/item/reagent_containers/food/snacks/warmdonkpocket_weak - name = "Lightly Warm Donk-pocket" - desc = "The food of choice for the seasoned traitor. This one is lukewarm." - icon_state = "donkpocket" - filling_color = "#DEDEAB" - list_reagents = list("nutriment" = 4, "weak_omnizine" = 3) - -/obj/item/reagent_containers/food/snacks/syndidonkpocket - name = "Donk-pocket" - desc = "This donk-pocket is emitting a small amount of heat." - icon_state = "donkpocket" - filling_color = "#DEDEAB" - bitesize = 100 //nom the whole thing at once. - list_reagents = list("nutriment" = 1) - -/obj/item/reagent_containers/food/snacks/syndidonkpocket/Post_Consume(mob/living/M) - M.reagents.add_reagent("omnizine", 15) - M.reagents.add_reagent("teporone", 15) - M.reagents.add_reagent("synaptizine", 15) - M.reagents.add_reagent("salglu_solution", 15) - M.reagents.add_reagent("salbutamol", 15) - M.reagents.add_reagent("methamphetamine", 15) - -/obj/item/reagent_containers/food/snacks/brainburger - name = "brainburger" - desc = "A strange looking burger. It looks almost sentient." - icon_state = "brainburger" - filling_color = "#F2B6EA" - bitesize = 3 - list_reagents = list("nutriment" = 6, "prions" = 10, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/ghostburger - name = "Ghost Burger" - desc = "Spooky! It doesn't look very filling." - icon_state = "ghostburger" - filling_color = "#FFF2FF" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/human - var/hname = "" - var/job = null - filling_color = "#D63C3C" - -/obj/item/reagent_containers/food/snacks/human/burger - name = "-burger" - desc = "A bloody burger." - icon_state = "hburger" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/cheeseburger - name = "cheeseburger" - desc = "The cheese adds a good flavor." - icon_state = "cheeseburger" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/monkeyburger - name = "burger" - desc = "The cornerstone of every nutritious breakfast." - icon_state = "hburger" - filling_color = "#D63C3C" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/tofuburger - name = "Tofu Burger" - desc = "What.. is that meat?" - icon_state = "tofuburger" - filling_color = "#FFFEE0" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/roburger - name = "roburger" - desc = "The lettuce is the only organic component. Beep." - icon_state = "roburger" - filling_color = "#CCCCCC" - bitesize = 3 - list_reagents = list("nutriment" = 6, "nanomachines" = 10, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/roburgerbig - name = "roburger" - desc = "This massive patty looks like poison. Beep." - icon_state = "roburger" - filling_color = "#CCCCCC" - volume = 120 - bitesize = 3 - list_reagents = list("nutriment" = 6, "nanomachines" = 70, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/xenoburger - name = "xenoburger" - desc = "Smells caustic. Tastes like heresy." - icon_state = "xburger" - filling_color = "#43DE18" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/clownburger - name = "Clown Burger" - desc = "This tastes funny..." - icon_state = "clownburger" - filling_color = "#FF00FF" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/mimeburger - name = "Mime Burger" - desc = "Its taste defies language." - icon_state = "mimeburger" - filling_color = "#FFFFFF" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/baseballburger - name = "home run baseball burger" - desc = "It's still warm. The steam coming off of it looks like baseball." - icon_state = "baseball" - filling_color = "#CD853F" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/omelette - name = "Omelette Du Fromage" - desc = "That's all you can say!" - icon_state = "omelette" - trash = /obj/item/trash/plate - filling_color = "#FFF9A8" - list_reagents = list("nutriment" = 8, "vitamin" = 1) - bitesize = 1 - -/obj/item/reagent_containers/food/snacks/muffin - name = "Muffin" - desc = "A delicious and spongy little cake." - icon_state = "muffin" - filling_color = "#E0CF9B" - list_reagents = list("nutriment" = 6) - -/obj/item/reagent_containers/food/snacks/pie - name = "Banana Cream Pie" - desc = "Just like back home, on clown planet! HONK!" - icon_state = "pie" - trash = /obj/item/trash/plate - filling_color = "#FBFFB8" - bitesize = 3 - list_reagents = list("nutriment" = 6, "banana" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/pie/throw_impact(atom/hit_atom) - ..() - new/obj/effect/decal/cleanable/pie_smudge(loc) - visible_message("[src] splats.","You hear a splat.") - qdel(src) - -/obj/item/reagent_containers/food/snacks/berryclafoutis - name = "Berry Clafoutis" - desc = "No black birds, this is a good sign." - icon_state = "berryclafoutis" - trash = /obj/item/trash/plate - bitesize = 3 - list_reagents = list("nutriment" = 10, "berryjuice" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/waffles - name = "waffles" - desc = "Mmm, waffles." - icon_state = "waffles" - trash = /obj/item/trash/waffles - filling_color = "#E6DEB5" - list_reagents = list("nutriment" = 8, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/eggplantparm - name = "Eggplant Parmigiana" - desc = "The only good recipe for eggplant." - icon_state = "eggplantparm" - trash = /obj/item/trash/plate - filling_color = "#4D2F5E" - list_reagents = list("nutriment" = 6, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/soylentgreen - name = "Soylent Green" - desc = "Not made of people. Honest." //Totally people. - icon_state = "soylent_green" - trash = /obj/item/trash/waffles - filling_color = "#B8E6B5" - list_reagents = list("nutriment" = 10, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/soylentviridians - name = "Soylent Virdians" - desc = "Not made of people. Honest." //Actually honest for once. - icon_state = "soylent_yellow" - trash = /obj/item/trash/waffles - filling_color = "#E6FA61" - list_reagents = list("nutriment" = 10, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/meatpie - name = "Meat-pie" - icon_state = "meatpie" - desc = "An old barber recipe, very delicious!" - trash = /obj/item/trash/plate - filling_color = "#948051" - bitesize = 3 - list_reagents = list("nutriment" = 10, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/tofupie - name = "Tofu-pie" - icon_state = "meatpie" - desc = "A delicious tofu pie." - trash = /obj/item/trash/plate - filling_color = "#FFFEE0" - bitesize = 3 - list_reagents = list("nutriment" = 10, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/amanita_pie - name = "amanita pie" - desc = "Sweet and tasty poison pie." - icon_state = "amanita_pie" - filling_color = "#FFCCCC" - bitesize = 4 - list_reagents = list("nutriment" = 6, "amanitin" = 3, "psilocybin" = 1, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/plump_pie - name = "plump pie" - desc = "I bet you love stuff made out of plump helmets!" - icon_state = "plump_pie" - filling_color = "#B8279B" - bitesize = 3 - list_reagents = list("nutriment" = 10, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/plump_pie/New() - ..() - if(prob(10)) - name = "exceptional plump pie" - desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump pie!" // What - reagents.add_reagent("omnizine", 5) - -/obj/item/reagent_containers/food/snacks/xemeatpie - name = "Xeno-pie" - icon_state = "xenomeatpie" - desc = "A delicious meatpie. Probably heretical." - trash = /obj/item/trash/plate - filling_color = "#43DE18" - list_reagents = list("nutriment" = 10, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/wingfangchu - name = "Wing Fang Chu" - desc = "A savory dish of alien wing wang in soy." - icon_state = "wingfangchu" - trash = /obj/item/trash/snack_bowl - filling_color = "#43DE18" - list_reagents = list("nutriment" = 6, "soysauce" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/human/kabob - name = "-kabob" - icon_state = "kabob" - desc = "A human meat, on a stick." - trash = /obj/item/stack/rods - filling_color = "#A85340" - list_reagents = list("nutriment" = 8) - -/obj/item/reagent_containers/food/snacks/monkeykabob - name = "Meat-kabob" - icon_state = "kabob" - desc = "Delicious meat, on a stick." - trash = /obj/item/stack/rods - filling_color = "#A85340" - list_reagents = list("nutriment" = 8) - -/obj/item/reagent_containers/food/snacks/tofukabob - name = "Tofu-kabob" - icon_state = "kabob" - desc = "Vegan meat, on a stick." - trash = /obj/item/stack/rods - filling_color = "#FFFEE0" - list_reagents = list("nutriment" = 8) - -/obj/item/reagent_containers/food/snacks/popcorn - name = "Popcorn" - desc = "Now let's find some cinema." - icon_state = "popcorn" - trash = /obj/item/trash/popcorn - var/unpopped = 0 - filling_color = "#FFFAD4" - bitesize = 0.1 //this snack is supposed to be eating during looooong time. And this it not dinner food! --rastaf0 - list_reagents = list("nutriment" = 2) - -/obj/item/reagent_containers/food/snacks/popcorn/New() - ..() - unpopped = rand(1,10) - -/obj/item/reagent_containers/food/snacks/popcorn/On_Consume(mob/M, mob/user) - if(prob(unpopped)) //lol ...what's the point? - to_chat(user, "You bite down on an un-popped kernel!") - unpopped = max(0, unpopped-1) - ..() - -/obj/item/reagent_containers/food/snacks/sosjerky - name = "Scaredy's Private Reserve Beef Jerky" - icon_state = "sosjerky" - desc = "Beef jerky made from the finest space cows." - trash = /obj/item/trash/sosjerky - filling_color = "#631212" - junkiness = 25 - list_reagents = list("protein" = 1, "sugar" = 3) - -/obj/item/reagent_containers/food/snacks/sosjerky/healthy - name = "homemade beef jerky" - desc = "Homemade beef jerky made from the finest space cows." - list_reagents = list("nutriment" = 3, "vitamin" = 1) - junkiness = 0 - -/obj/item/reagent_containers/food/snacks/pistachios - name = "Pistachios" - icon_state = "pistachios" - desc = "A snack of deliciously salted pistachios. A perfectly valid choice..." - trash = /obj/item/trash/pistachios - filling_color = "#BAD145" - junkiness = 20 - list_reagents = list("plantmatter" = 2, "sodiumchloride" = 1, "sugar" = 4) - -/obj/item/reagent_containers/food/snacks/no_raisin - name = "4no Raisins" - icon_state = "4no_raisins" - desc = "Best raisins in the universe. Not sure why." - trash = /obj/item/trash/raisins - filling_color = "#343834" - junkiness = 25 - list_reagents = list("plantmatter" = 2, "sugar" = 4) - -/obj/item/reagent_containers/food/snacks/no_raisin/healthy - name = "homemade raisins" - desc = "homemade raisins, the best in all of spess." - list_reagents = list("nutriment" = 3, "vitamin" = 2) - junkiness = 0 - -/obj/item/reagent_containers/food/snacks/spacetwinkie - name = "Space Twinkie" - icon_state = "space_twinkie" - desc = "Guaranteed to survive longer then you will." - filling_color = "#FFE591" - junkiness = 25 - list_reagents = list("sugar" = 4) - -/obj/item/reagent_containers/food/snacks/cheesiehonkers - name = "Cheesie Honkers" - icon_state = "cheesie_honkers" - desc = "Bite sized cheesie snacks that will honk all over your mouth." - trash = /obj/item/trash/cheesie - filling_color = "#FFA305" - junkiness = 25 - list_reagents = list("nutriment" = 1, "fake_cheese" = 2, "sugar" = 3) - -/obj/item/reagent_containers/food/snacks/chinese/chowmein - name = "chow mein" - desc = "What is in this anyways?" - icon_state = "chinese1" - junkiness = 25 - list_reagents = list("nutriment" = 1, "beans" = 3, "msg" = 4, "sugar" = 2) - -/obj/item/reagent_containers/food/snacks/chinese/sweetsourchickenball - name = "Sweet & Sour Chicken Balls" - desc = "Is this chicken cooked? The odds are better than wok paper scissors." - icon_state = "chickenball" - junkiness = 25 - list_reagents = list("nutriment" = 2, "msg" = 4, "sugar" = 2) - -/obj/item/reagent_containers/food/snacks/chinese/tao - name = "Admiral Yamamoto carp" - desc = "Tastes like chicken." - icon_state = "chinese2" - junkiness = 25 - list_reagents = list("nutriment" = 1, "protein" = 1, "msg" = 4, "sugar" = 4) - -/obj/item/reagent_containers/food/snacks/chinese/newdles - name = "chinese newdles" - desc = "Made fresh, weekly!" - icon_state = "chinese3" - junkiness = 25 - list_reagents = list("nutriment" = 1, "msg" = 4, "sugar" = 3) - -/obj/item/reagent_containers/food/snacks/chinese/rice - name = "fried rice" - desc = "A timeless classic." - icon_state = "chinese4" - junkiness = 20 - list_reagents = list("nutriment" = 1, "rice" = 3, "msg" = 4, "sugar" = 2) - -/obj/item/reagent_containers/food/snacks/syndicake - name = "Syndi-Cakes" - icon_state = "syndi_cakes" - desc = "An extremely moist snack cake that tastes just as good after being nuked." - filling_color = "#FF5D05" - trash = /obj/item/trash/syndi_cakes - bitesize = 3 - list_reagents = list("nutriment" = 4, "salglu_solution" = 5) - -/obj/item/reagent_containers/food/snacks/loadedbakedpotato - name = "Loaded Baked Potato" - desc = "Totally baked." - icon_state = "loadedbakedpotato" - filling_color = "#9C7A68" - list_reagents = list("nutriment" = 6) - -/obj/item/reagent_containers/food/snacks/fries - name = "Space Fries" - desc = "AKA: French Fries, Freedom Fries, etc." - icon_state = "fries" - trash = /obj/item/trash/plate - filling_color = "#EDDD00" - list_reagents = list("nutriment" = 4) - -/obj/item/reagent_containers/food/snacks/soydope - name = "Soy Dope" - desc = "Dope from a soy." - icon_state = "soydope" - trash = /obj/item/trash/plate - filling_color = "#C4BF76" - list_reagents = list("nutriment" = 2) - -/obj/item/reagent_containers/food/snacks/spaghetti - name = "Spaghetti" - desc = "A bundle of raw spaghetti." - icon_state = "spaghetti" - filling_color = "#EDDD00" - list_reagents = list("nutriment" = 1, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/cheesyfries - name = "Cheesy Fries" - desc = "Fries. Covered in cheese. Duh." - icon_state = "cheesyfries" - trash = /obj/item/trash/plate - filling_color = "#EDDD00" - list_reagents = list("nutriment" = 6) - -/obj/item/reagent_containers/food/snacks/fortunecookie - name = "Fortune cookie" - desc = "A true prophecy in each cookie!" - icon_state = "fortune_cookie" - filling_color = "#E8E79E" - list_reagents = list("nutriment" = 3) - /obj/item/reagent_containers/food/snacks/badrecipe name = "Burned mess" desc = "Someone should be demoted from chef for this." @@ -1068,1333 +284,7 @@ cooktype["grilled"] = 1 cooktype["deep fried"] = 1 -/obj/item/reagent_containers/food/snacks/meatsteak - name = "Meat steak" - desc = "A piece of hot spicy meat." - icon_state = "meatstake" - trash = /obj/item/trash/plate - filling_color = "#7A3D11" - bitesize = 3 - list_reagents = list("nutriment" = 5) - -/obj/item/reagent_containers/food/snacks/spacylibertyduff - name = "Spacy Liberty Duff" - desc = "Jello gelatin, from Alfred Hubbard's cookbook." - icon_state = "spacylibertyduff" - trash = /obj/item/trash/snack_bowl - filling_color = "#42B873" - bitesize = 3 - list_reagents = list("nutriment" = 6, "psilocybin" = 6) - -/obj/item/reagent_containers/food/snacks/amanitajelly - name = "Amanita Jelly" - desc = "Looks curiously toxic." - icon_state = "amanitajelly" - trash = /obj/item/trash/snack_bowl - filling_color = "#ED0758" - bitesize = 3 - list_reagents = list("nutriment" = 6, "amanitin" = 6, "psilocybin" = 3) - -/obj/item/reagent_containers/food/snacks/poppypretzel - name = "Poppy pretzel" - desc = "It's all twisted up!" - icon_state = "poppypretzel" - filling_color = "#916E36" - list_reagents = list("nutriment" = 5) - -/obj/item/reagent_containers/food/snacks/meatballsoup - name = "Meatball soup" - desc = "You've got balls kid, BALLS!" - icon_state = "meatballsoup" - trash = /obj/item/trash/snack_bowl - filling_color = "#785210" - bitesize = 5 - list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/slimesoup - name = "slime soup" - desc = "If no water is available, you may substitute tears." - icon_state = "slimesoup" - filling_color = "#C4DBA0" - bitesize = 5 - list_reagents = list("nutriment" = 5, "slimejelly" = 5, "water" = 5, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/bloodsoup - name = "Tomato soup" - desc = "Smells like copper." - icon_state = "tomatosoup" - filling_color = "#FF0000" - bitesize = 5 - list_reagents = list("nutriment" = 2, "blood" = 10, "water" = 5, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/clownstears - name = "Clown's Tears" - desc = "Not very funny." - icon_state = "clownstears" - filling_color = "#C4FBFF" - bitesize = 5 - list_reagents = list("nutriment" = 4, "banana" = 5, "water" = 5, "vitamin" = 8) - -/obj/item/reagent_containers/food/snacks/vegetablesoup - name = "Vegetable soup" - desc = "A true vegan meal." //TODO - icon_state = "vegetablesoup" - trash = /obj/item/trash/snack_bowl - filling_color = "#AFC4B5" - bitesize = 5 - list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/nettlesoup - name = "Nettle soup" - desc = "To think, the botanist would've beat you to death with one of these." - icon_state = "nettlesoup" - trash = /obj/item/trash/snack_bowl - filling_color = "#AFC4B5" - bitesize = 5 - list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/mysterysoup - name = "mystery soup" - desc = "The mystery is, why aren't you eating it?" - icon_state = "mysterysoup" - var/extra_reagent = null - bitesize = 5 - list_reagents = list("nutriment" = 6) - -/obj/item/reagent_containers/food/snacks/mysterysoup/New() - ..() - extra_reagent = pick("capsaicin", "frostoil", "omnizine", "banana", "blood", "slimejelly", "toxin", "banana", "carbon", "oculine") - reagents.add_reagent("[extra_reagent]", 5) - -/obj/item/reagent_containers/food/snacks/wishsoup - name = "Wish Soup" - desc = "I wish this was soup." - icon_state = "wishsoup" - trash = /obj/item/trash/snack_bowl - filling_color = "#D1F4FF" - bitesize = 5 - list_reagents = list("water" = 10) - -/obj/item/reagent_containers/food/snacks/wishsoup/New() - ..() - if(prob(25)) - desc = "A wish come true!" // hue - reagents.add_reagent("nutriment", 9) - reagents.add_reagent("vitamin", 1) - -/obj/item/reagent_containers/food/snacks/hotchili - name = "Hot Chili" - desc = "A five alarm Texan Chili!" - icon_state = "hotchili" - trash = /obj/item/trash/snack_bowl - filling_color = "#FF3C00" - bitesize = 5 - list_reagents = list("nutriment" = 5, "capsaicin" = 1, "tomatojuice" = 2, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/coldchili - name = "Cold Chili" - desc = "This slush is barely a liquid!" - icon_state = "coldchili" - filling_color = "#2B00FF" - trash = /obj/item/trash/snack_bowl - bitesize = 5 - list_reagents = list("nutriment" = 5, "frostoil" = 1, "tomatojuice" = 2, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/raw_bacon - name = "raw bacon" - desc = "It's fleshy and pink!" - icon_state = "raw_bacon" - list_reagents = list("nutriment" = 1, "porktonium" = 10) - -/obj/item/reagent_containers/food/snacks/bacon - name = "bacon" - desc = "It looks juicy and tastes amazing!" - icon_state = "bacon2" - list_reagents = list("nutriment" = 4, "porktonium" = 10, "msg" = 4) - -/obj/item/reagent_containers/food/snacks/telebacon - name = "Tele Bacon" - desc = "It tastes a little odd but it is still delicious." - icon_state = "bacon" - var/obj/item/radio/beacon/bacon/baconbeacon - list_reagents = list("nutriment" = 4, "porktonium" = 10) - -/obj/item/reagent_containers/food/snacks/telebacon/New() - ..() - baconbeacon = new /obj/item/radio/beacon/bacon(src) - -/obj/item/reagent_containers/food/snacks/telebacon/On_Consume(mob/M, mob/user) - if(!reagents.total_volume) - baconbeacon.loc = user - baconbeacon.digest_delay() - - -/obj/item/reagent_containers/food/snacks/monkeycube - name = "monkey cube" - desc = "Just add water!" - icon_state = "monkeycube" - bitesize = 12 - filling_color = "#ADAC7F" - var/monkey_type = "Monkey" - list_reagents = list("nutriment" = 2) - -/obj/item/reagent_containers/food/snacks/monkeycube/water_act(volume, temperature) - if(volume >= 5) - return Expand() - -/obj/item/reagent_containers/food/snacks/monkeycube/wash(mob/user, atom/source) - user.drop_item() - forceMove(get_turf(source)) - return 1 - -/obj/item/reagent_containers/food/snacks/monkeycube/proc/Expand() - if(!QDELETED(src)) - visible_message("[src] expands!") - if(fingerprintslast) - log_game("Cube ([monkey_type]) inflated, last touched by: " + fingerprintslast) - else - log_game("Cube ([monkey_type]) inflated, last touched by: NO_DATA") - var/mob/living/carbon/human/creature = new /mob/living/carbon/human(get_turf(src)) - if(fingerprintshidden.len) - creature.fingerprintshidden = fingerprintshidden.Copy() - creature.set_species(monkey_type) - qdel(src) - -/obj/item/reagent_containers/food/snacks/monkeycube/farwacube - name = "farwa cube" - monkey_type = "Farwa" - -/obj/item/reagent_containers/food/snacks/monkeycube/wolpincube - name = "wolpin cube" - monkey_type = "Wolpin" - -/obj/item/reagent_containers/food/snacks/monkeycube/stokcube - name = "stok cube" - monkey_type = "Stok" - -/obj/item/reagent_containers/food/snacks/monkeycube/neaeracube - name = "neaera cube" - monkey_type = "Neara" - - -/obj/item/reagent_containers/food/snacks/spellburger - name = "Spell Burger" - desc = "This is absolutely Ei Nath." - icon_state = "spellburger" - filling_color = "#D505FF" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/bigbiteburger - name = "Big Bite Burger" - desc = "Forget the Big Mac. THIS is the future!" - icon_state = "bigbiteburger" - filling_color = "#E3D681" - bitesize = 3 - list_reagents = list("nutriment" = 10, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/enchiladas - name = "Enchiladas" - desc = "Viva La Mexico!" - icon_state = "enchiladas" - trash = /obj/item/trash/tray - filling_color = "#A36A1F" - bitesize = 4 - list_reagents = list("nutriment" = 8, "capsaicin" = 6) - -/obj/item/reagent_containers/food/snacks/burrito - name = "Burrito" - desc = "Meat, beans, cheese, and rice wrapped up as an easy-to-hold meal." - icon_state = "burrito" - trash = /obj/item/trash/plate - filling_color = "#A36A1F" - list_reagents = list("nutriment" = 4, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/chimichanga - name = "Chimichanga" - desc = "Time to eat a chimi-f***ing-changa." - icon_state = "chimichanga" - trash = /obj/item/trash/plate - filling_color = "#A36A1F" - list_reagents = list("omnizine" = 4, "cheese" = 2) //Deadpool reference. Deal with it. - -/obj/item/reagent_containers/food/snacks/monkeysdelight - name = "monkey's Delight" - desc = "Eeee Eee!" - icon_state = "monkeysdelight" - trash = /obj/item/trash/tray - filling_color = "#5C3C11" - bitesize = 6 - list_reagents = list("nutriment" = 10, "banana" = 5, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/baguette - name = "Baguette" - desc = "Bon appetit!" - icon_state = "baguette" - filling_color = "#E3D796" - bitesize = 3 - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/sandwich - name = "Sandwich" - desc = "A grand creation of meat, cheese, bread, and several leaves of lettuce! Arthur Dent would be proud." - icon_state = "sandwich" - trash = /obj/item/trash/plate - filling_color = "#D9BE29" - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/toastedsandwich - name = "Toasted Sandwich" - desc = "Now if you only had a pepper bar." - icon_state = "toastedsandwich" - trash = /obj/item/trash/plate - filling_color = "#D9BE29" - list_reagents = list("nutriment" = 6, "carbon" = 2) - -/obj/item/reagent_containers/food/snacks/grilledcheese - name = "Grilled Cheese Sandwich" - desc = "Goes great with Tomato soup!" - icon_state = "toastedsandwich" - trash = /obj/item/trash/plate - filling_color = "#D9BE29" - list_reagents = list("nutriment" = 7, "vitamin" = 1) //why make a regualr sandwhich when you can make grilled cheese, with this nutriment value? - -/obj/item/reagent_containers/food/snacks/tomatosoup - name = "Tomato Soup" - desc = "Drinking this feels like being a vampire! A tomato vampire..." - icon_state = "tomatosoup" - trash = /obj/item/trash/snack_bowl - filling_color = "#D92929" - bitesize = 5 - list_reagents = list("nutriment" = 5, "tomatojuice" = 10, "vitamin" = 3) - -/obj/item/reagent_containers/food/snacks/rofflewaffles - name = "Roffle Waffles" - desc = "Waffles from Roffle. Co." - icon_state = "rofflewaffles" - trash = /obj/item/trash/waffles - filling_color = "#FF00F7" - bitesize = 4 - list_reagents = list("nutriment" = 8, "psilocybin" = 2, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/stew - name = "Stew" - desc = "A nice and warm stew. Healthy and strong." - icon_state = "stew" - filling_color = "#9E673A" - bitesize = 7 - list_reagents = list("nutriment" = 10, "oculine" = 5, "tomatojuice" = 5, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/jelliedtoast - name = "Jellied Toast" - desc = "A slice of bread covered with delicious jam." - icon_state = "jellytoast" - trash = /obj/item/trash/plate - filling_color = "#B572AB" - bitesize = 3 - -/obj/item/reagent_containers/food/snacks/jelliedtoast/cherry - list_reagents = list("nutriment" = 1, "cherryjelly" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/jelliedtoast/slime - list_reagents = list("nutriment" = 1, "slimejelly" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/jellyburger - name = "Jelly Burger" - desc = "Culinary delight..?" - icon_state = "jellyburger" - filling_color = "#B572AB" - bitesize = 3 - -/obj/item/reagent_containers/food/snacks/jellyburger/slime - list_reagents = list("nutriment" = 6, "slimejelly" = 5, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/jellyburger/cherry - list_reagents = list("nutriment" = 6, "cherryjelly" = 5, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/milosoup - name = "Milosoup" - desc = "The universe's best soup! Yum!!!" - icon_state = "milosoup" - trash = /obj/item/trash/snack_bowl - bitesize = 5 - list_reagents = list("nutriment" = 7, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/stewedsoymeat - name = "Stewed Soy Meat" - desc = "Even non-vegetarians will LOVE this!" - icon_state = "stewedsoymeat" - trash = /obj/item/trash/plate - list_reagents = list("nutriment" = 8) - -/obj/item/reagent_containers/food/snacks/boiledspaghetti - name = "Boiled Spaghetti" - desc = "A plain dish of noodles, this sucks." - icon_state = "spaghettiboiled" - trash = /obj/item/trash/plate - filling_color = "#FCEE81" - list_reagents = list("nutriment" = 2, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/boiledrice - name = "Boiled Rice" - desc = "A boring dish of boring rice." - icon_state = "boiledrice" - trash = /obj/item/trash/snack_bowl - filling_color = "#FFFBDB" - list_reagents = list("nutriment" = 5, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/ricepudding - name = "Rice Pudding" - desc = "Where's the Jam!" - icon_state = "rpudding" - trash = /obj/item/trash/snack_bowl - filling_color = "#FFFBDB" - list_reagents = list("nutriment" = 7, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/pastatomato - name = "spaghetti" - desc = "Spaghetti and crushed tomatoes. Just like your abusive father used to make!" - icon_state = "pastatomato" - trash = /obj/item/trash/plate - filling_color = "#DE4545" - bitesize = 4 - list_reagents = list("nutriment" = 6, "tomatojuice" = 10, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/meatballspaghetti - name = "spaghetti & Meatballs" - desc = "Now thats a nic'e meatball!" - icon_state = "meatballspaghetti" - trash = /obj/item/trash/plate - filling_color = "#DE4545" - list_reagents = list("nutriment" = 8, "synaptizine" = 5, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/spesslaw - name = "Spesslaw" - desc = "A lawyer's favourite." - icon_state = "spesslaw" - filling_color = "#DE4545" - list_reagents = list("nutriment" = 8, "synaptizine" = 10, "vitamin" = 6) - -/obj/item/reagent_containers/food/snacks/poppypretzel - name = "Poppy Pretzel" - desc = "A large soft pretzel full of POP!" - icon_state = "poppypretzel" - filling_color = "#AB7D2E" - list_reagents = list("nutriment" = 5) - -/obj/item/reagent_containers/food/snacks/carrotfries - name = "Carrot Fries" - desc = "Tasty fries from fresh carrots." - icon_state = "carrotfries" - trash = /obj/item/trash/plate - filling_color = "#FAA005" - list_reagents = list("plantmatter" = 3, "oculine" = 3, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/superbiteburger - name = "Super Bite Burger" - desc = "This is a mountain of a burger. FOOD!" - icon_state = "superbiteburger" - filling_color = "#CCA26A" - bitesize = 7 - list_reagents = list("nutriment" = 40, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/candiedapple - name = "Candied Apple" - desc = "An apple coated in sugary sweetness." - icon_state = "candiedapple" - filling_color = "#F21873" - bitesize = 3 - list_reagents = list("nutriment" = 3, "sugar" = 2) - -/obj/item/reagent_containers/food/snacks/applepie - name = "Apple Pie" - desc = "A pie containing sweet sweet love... or apple." - icon_state = "applepie" - filling_color = "#E0EDC5" - bitesize = 3 - list_reagents = list("nutriment" = 10, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/cherrypie - name = "Cherry Pie" - desc = "Taste so good, make a grown man cry." - icon_state = "cherrypie" - filling_color = "#FF525A" - bitesize = 3 - list_reagents = list("nutriment" = 10, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/twobread - name = "Two Bread" - desc = "It is very bitter and winy." - icon_state = "twobread" - filling_color = "#DBCC9A" - bitesize = 3 - list_reagents = list("nutriment" = 2, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/jellysandwich - name = "Jelly Sandwich" - desc = "You wish you had some peanut butter to go with this..." - icon_state = "jellysandwich" - trash = /obj/item/trash/plate - filling_color = "#9E3A78" - bitesize = 3 - -/obj/item/reagent_containers/food/snacks/jellysandwich/slime - list_reagents = list("nutriment" = 2, "slimejelly" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/jellysandwich/cherry - list_reagents = list("nutriment" = 2, "cherryjelly" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/boiledslimecore - name = "Boiled Slime Core" - desc = "A boiled red thing." - icon_state = "boiledrorocore" - bitesize = 3 - list_reagents = list("slimejelly" = 5) - -/obj/item/reagent_containers/food/snacks/mint - name = "mint" - desc = "it is only wafer thin." - icon_state = "mint" - bitesize = 1 - filling_color = "#F2F2F2" - list_reagents = list("minttoxin" = 1) - -/obj/item/reagent_containers/food/snacks/mushroomsoup - name = "chantrelle soup" - desc = "A delicious and hearty mushroom soup." - icon_state = "mushroomsoup" - trash = /obj/item/trash/snack_bowl - filling_color = "#E386BF" - bitesize = 5 - list_reagents = list("nutriment" = 8, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/plumphelmetbiscuit - name = "plump helmet biscuit" - desc = "This is a finely-prepared plump helmet biscuit. The ingredients are exceptionally minced plump helmet, and well-minced dwarven wheat flour." - icon_state = "phelmbiscuit" - filling_color = "#CFB4C4" - list_reagents = list("nutriment" = 5) - -/obj/item/reagent_containers/food/snacks/plumphelmetbiscuit/New() - ..() - if(prob(10)) - name = "exceptional plump helmet biscuit" - desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!" // Is this a reference? - reagents.add_reagent("omnizine", 5) - -/obj/item/reagent_containers/food/snacks/chawanmushi - name = "chawanmushi" - desc = "A legendary egg custard that makes friends out of enemies. Probably too hot for a cat to eat." - icon_state = "chawanmushi" - trash = /obj/item/trash/snack_bowl - filling_color = "#F0F2E4" - list_reagents = list("nutriment" = 5) - -/obj/item/reagent_containers/food/snacks/beetsoup - name = "beet soup" - desc = "Wait, how do you spell it again..?" - icon_state = "beetsoup" - trash = /obj/item/trash/snack_bowl - bitesize = 5 - filling_color = "#FAC9FF" - list_reagents = list("nutriment" = 7, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/beetsoup/New() - ..() - name = pick("borsch","bortsch","borstch","borsh","borshch","borscht") - -/obj/item/reagent_containers/food/snacks/herbsalad - name = "herb salad" - desc = "A tasty salad with apples on top." - icon_state = "herbsalad" - trash = /obj/item/trash/snack_bowl - filling_color = "#76B87F" - bitesize = 3 - list_reagents = list("nutriment" = 8, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/validsalad - name = "valid salad" - desc = "It's just an herb salad with meatballs and fried potato slices. Nothing suspicious about it." - icon_state = "validsalad" - trash = /obj/item/trash/snack_bowl - filling_color = "#76B87F" - bitesize = 3 - list_reagents = list("nutriment" = 8, "salglu_solution" = 5, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/appletart - name = "golden apple streusel tart" - desc = "A tasty dessert that won't make it through a metal detector." - icon_state = "gappletart" - trash = /obj/item/trash/plate - filling_color = "#FFFF00" - bitesize = 3 - list_reagents = list("nutriment" = 8, "gold" = 5, "vitamin" = 4) - -/////////////////////////////////////////////////Sliceable//////////////////////////////////////// -// All the food items that can be sliced into smaller bits like Meatbread and Cheesewheels - -// sliceable is just an organization type path, it doesn't have any additional code or variables tied to it. - -/obj/item/reagent_containers/food/snacks/sliceable/meatbread - name = "meatbread loaf" - desc = "The culinary base of every self-respecting eloquen/tg/entleman." - icon_state = "meatbread" - slice_path = /obj/item/reagent_containers/food/snacks/meatbreadslice - slices_num = 5 - filling_color = "#FF7575" - list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/meatbreadslice - name = "meatbread slice" - desc = "A slice of delicious meatbread." - icon_state = "meatbreadslice" - trash = /obj/item/trash/plate - filling_color = "#FF7575" - -/obj/item/reagent_containers/food/snacks/sliceable/xenomeatbread - name = "xenomeatbread loaf" - desc = "The culinary base of every self-respecting eloquent gentleman. Extra Heretical." - icon_state = "xenomeatbread" - slice_path = /obj/item/reagent_containers/food/snacks/xenomeatbreadslice - slices_num = 5 - filling_color = "#8AFF75" - list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/xenomeatbreadslice - name = "xenomeatbread slice" - desc = "A slice of delicious meatbread. Extra Heretical." - icon_state = "xenobreadslice" - trash = /obj/item/trash/plate - filling_color = "#8AFF75" - -/obj/item/reagent_containers/food/snacks/sliceable/spidermeatbread - name = "spider meat loaf" - desc = "Reassuringly green meatloaf made from spider meat." - icon_state = "spidermeatbread" - slice_path = /obj/item/reagent_containers/food/snacks/spidermeatbreadslice - slices_num = 5 - list_reagents = list("protein" = 20, "nutriment" = 10, "toxin" = 15, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/spidermeatbreadslice - name = "spider meat bread slice" - desc = "A slice of meatloaf made from an animal that most likely still wants you dead." - icon_state = "xenobreadslice" - trash = /obj/item/trash/plate - list_reagents = list("toxin" = 2) - -/obj/item/reagent_containers/food/snacks/sliceable/bananabread - name = "Banana-nut bread" - desc = "A heavenly and filling treat." - icon_state = "bananabread" - slice_path = /obj/item/reagent_containers/food/snacks/bananabreadslice - slices_num = 5 - filling_color = "#EDE5AD" - list_reagents = list("banana" = 20, "nutriment" = 20) - -/obj/item/reagent_containers/food/snacks/bananabreadslice - name = "Banana-nut bread slice" - desc = "A slice of delicious banana bread." - icon_state = "bananabreadslice" - trash = /obj/item/trash/plate - filling_color = "#EDE5AD" - -/obj/item/reagent_containers/food/snacks/sliceable/tofubread - name = "Tofubread" - icon_state = "Like meatbread but for vegetarians. Not guaranteed to give superpowers." - icon_state = "tofubread" - slice_path = /obj/item/reagent_containers/food/snacks/tofubreadslice - slices_num = 5 - filling_color = "#F7FFE0" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/tofubreadslice - name = "Tofubread slice" - desc = "A slice of delicious tofubread." - icon_state = "tofubreadslice" - trash = /obj/item/trash/plate - filling_color = "#F7FFE0" - -/obj/item/reagent_containers/food/snacks/sliceable/carrotcake - name = "Carrot Cake" - desc = "A favorite desert of a certain wascally wabbit. Not a lie." - icon_state = "carrotcake" - slice_path = /obj/item/reagent_containers/food/snacks/carrotcakeslice - slices_num = 5 - bitesize = 3 - filling_color = "#FFD675" - list_reagents = list("nutriment" = 20, "oculine" = 10, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/carrotcakeslice - name = "Carrot Cake slice" - desc = "Carrotty slice of Carrot Cake, carrots are good for your eyes! Also not a lie." - icon_state = "carrotcake_slice" - trash = /obj/item/trash/plate - filling_color = "#FFD675" - -/obj/item/reagent_containers/food/snacks/sliceable/braincake - name = "Brain Cake" - desc = "A squishy cake-thing." - icon_state = "braincake" - slice_path = /obj/item/reagent_containers/food/snacks/braincakeslice - slices_num = 5 - filling_color = "#E6AEDB" - bitesize = 3 - list_reagents = list("protein" = 10, "nutriment" = 10, "mannitol" = 10, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/braincakeslice - name = "Brain Cake slice" - desc = "Lemme tell you something about prions. THEY'RE DELICIOUS." - icon_state = "braincakeslice" - trash = /obj/item/trash/plate - filling_color = "#E6AEDB" - -/obj/item/reagent_containers/food/snacks/sliceable/cheesecake - name = "Cheese Cake" - desc = "DANGEROUSLY cheesy." - icon_state = "cheesecake" - slice_path = /obj/item/reagent_containers/food/snacks/cheesecakeslice - slices_num = 5 - filling_color = "#FAF7AF" - bitesize = 3 - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/cheesecakeslice - name = "Cheese Cake slice" - desc = "Slice of pure cheestisfaction." - icon_state = "cheesecake_slice" - trash = /obj/item/trash/plate - filling_color = "#FAF7AF" - -/obj/item/reagent_containers/food/snacks/sliceable/plaincake - name = "Vanilla Cake" - desc = "A plain cake, not a lie." - icon_state = "plaincake" - slice_path = /obj/item/reagent_containers/food/snacks/plaincakeslice - slices_num = 5 - bitesize = 3 - filling_color = "#F7EDD5" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/plaincakeslice - name = "Vanilla Cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "plaincake_slice" - trash = /obj/item/trash/plate - filling_color = "#F7EDD5" - -/obj/item/reagent_containers/food/snacks/sliceable/orangecake - name = "Orange Cake" - desc = "A cake with added orange." - icon_state = "orangecake" - slice_path = /obj/item/reagent_containers/food/snacks/orangecakeslice - slices_num = 5 - bitesize = 3 - filling_color = "#FADA8E" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/orangecakeslice - name = "Orange Cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "orangecake_slice" - trash = /obj/item/trash/plate - filling_color = "#FADA8E" - -/obj/item/reagent_containers/food/snacks/sliceable/limecake - name = "Lime Cake" - desc = "A cake with added lime." - icon_state = "limecake" - bitesize = 3 - slice_path = /obj/item/reagent_containers/food/snacks/limecakeslice - slices_num = 5 - filling_color = "#CBFA8E" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/limecakeslice - name = "Lime Cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "limecake_slice" - trash = /obj/item/trash/plate - filling_color = "#CBFA8E" - -/obj/item/reagent_containers/food/snacks/sliceable/lemoncake - name = "Lemon Cake" - desc = "A cake with added lemon." - icon_state = "lemoncake" - slice_path = /obj/item/reagent_containers/food/snacks/lemoncakeslice - slices_num = 5 - bitesize = 3 - filling_color = "#FAFA8E" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/lemoncakeslice - name = "Lemon Cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "lemoncake_slice" - trash = /obj/item/trash/plate - filling_color = "#FAFA8E" - -/obj/item/reagent_containers/food/snacks/sliceable/chocolatecake - name = "Chocolate Cake" - desc = "A cake with added chocolate." - icon_state = "chocolatecake" - slice_path = /obj/item/reagent_containers/food/snacks/chocolatecakeslice - slices_num = 5 - bitesize = 3 - filling_color = "#805930" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/chocolatecakeslice - name = "Chocolate Cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "chocolatecake_slice" - trash = /obj/item/trash/plate - filling_color = "#805930" - -/obj/item/reagent_containers/food/snacks/sliceable/cheesewheel - name = "Cheese wheel" - desc = "A big wheel of delicious Cheddar." - icon_state = "cheesewheel" - slice_path = /obj/item/reagent_containers/food/snacks/cheesewedge - slices_num = 5 - filling_color = "#FFF700" - list_reagents = list("nutriment" = 15, "vitamin" = 5, "cheese" = 20) - -/obj/item/reagent_containers/food/snacks/cheesewedge - name = "Cheese wedge" - desc = "A wedge of delicious Cheddar. The cheese wheel it was cut from can't have gone far." - icon_state = "cheesewedge" - filling_color = "#FFF700" - -/obj/item/reagent_containers/food/snacks/weirdcheesewedge - name = "Weird Cheese" - desc = "Some kind of... gooey, messy, gloopy thing. Similar to cheese, but only in the looser sense of the word." - icon_state = "weirdcheesewedge" - filling_color = "#00FF33" - list_reagents = list("mercury" = 5, "lsd" = 5, "ethanol" = 5, "weird_cheese" = 5) - -/obj/item/reagent_containers/food/snacks/sliceable/birthdaycake - name = "Birthday Cake" - desc = "Happy Birthday..." - icon_state = "birthdaycake" - slice_path = /obj/item/reagent_containers/food/snacks/birthdaycakeslice - slices_num = 5 - filling_color = "#FFD6D6" - bitesize = 3 - list_reagents = list("nutriment" = 20, "sprinkles" = 10, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/birthdaycakeslice - name = "Birthday Cake slice" - desc = "A slice of your birthday" - icon_state = "birthdaycakeslice" - trash = /obj/item/trash/plate - filling_color = "#FFD6D6" - -/obj/item/reagent_containers/food/snacks/sliceable/bread - name = "Bread" - icon_state = "Some plain old Earthen bread." - icon_state = "bread" - slice_path = /obj/item/reagent_containers/food/snacks/breadslice - slices_num = 6 - filling_color = "#FFE396" - list_reagents = list("nutriment" = 10) - -/obj/item/reagent_containers/food/snacks/breadslice - name = "Bread slice" - desc = "A slice of home." - icon_state = "breadslice" - trash = /obj/item/trash/plate - filling_color = "#D27332" - list_reagents = list("nutriment" = 2, "bread" = 5) - -/obj/item/reagent_containers/food/snacks/sliceable/creamcheesebread - name = "Cream Cheese Bread" - desc = "Yum yum yum!" - icon_state = "creamcheesebread" - slice_path = /obj/item/reagent_containers/food/snacks/creamcheesebreadslice - slices_num = 5 - filling_color = "#FFF896" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/creamcheesebreadslice - name = "Cream Cheese Bread slice" - desc = "A slice of yum!" - icon_state = "creamcheesebreadslice" - trash = /obj/item/trash/plate - filling_color = "#FFF896" - list_reagents = list("nutriment" = 4, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/watermelonslice - name = "Watermelon Slice" - desc = "A slice of watery goodness." - icon_state = "watermelonslice" - filling_color = "#FF3867" - -/obj/item/reagent_containers/food/snacks/pineappleslice - name = "Pineapple Slices" - desc = "Rings of pineapple." - icon_state = "pineappleslice" - filling_color = "#e5b437" - -/obj/item/reagent_containers/food/snacks/sliceable/applecake - name = "Apple Cake" - desc = "A cake centered with Apple." - icon_state = "applecake" - slice_path = /obj/item/reagent_containers/food/snacks/applecakeslice - slices_num = 5 - bitesize = 3 - filling_color = "#EBF5B8" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/applecakeslice - name = "Apple Cake slice" - desc = "A slice of heavenly cake." - icon_state = "applecakeslice" - trash = /obj/item/trash/plate - filling_color = "#EBF5B8" - -/obj/item/reagent_containers/food/snacks/sliceable/pumpkinpie - name = "Pumpkin Pie" - desc = "A delicious treat for the autumn months." - icon_state = "pumpkinpie" - slice_path = /obj/item/reagent_containers/food/snacks/pumpkinpieslice - slices_num = 5 - bitesize = 3 - filling_color = "#F5B951" - list_reagents = list("nutriment" = 20, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/pumpkinpieslice - name = "Pumpkin Pie slice" - desc = "A slice of pumpkin pie, with whipped cream on top. Perfection." - icon_state = "pumpkinpieslice" - trash = /obj/item/trash/plate - filling_color = "#F5B951" - -/obj/item/reagent_containers/food/snacks/cracker - name = "Cracker" - desc = "It's a salted cracker." - icon_state = "cracker" - bitesize = 1 - filling_color = "#F5DEB8" - list_reagents = list("nutriment" = 1) - -/obj/item/reagent_containers/food/snacks/rawcutlet - name = "raw cutlet" - desc = "A thin piece of raw meat." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "rawcutlet" - bitesize = 1 - list_reagents = list("protein" = 1) - -/obj/item/reagent_containers/food/snacks/rawcutlet/attackby(obj/item/W, mob/user, params) - if(istype(W,/obj/item/kitchen/knife)) - user.visible_message( \ - "[user] cuts the raw cutlet with the knife!", \ - "You cut the raw cutlet with your knife!" \ - ) - new /obj/item/reagent_containers/food/snacks/raw_bacon(loc) - qdel(src) - - -/////////////////////////////////////////////////PIZZA//////////////////////////////////////// - -/obj/item/reagent_containers/food/snacks/sliceable/pizza - slices_num = 6 - filling_color = "#BAA14C" - -/obj/item/reagent_containers/food/snacks/sliceable/pizza/margherita - name = "Margherita" - desc = "The golden standard of pizzas." - icon_state = "pizzamargherita" - slice_path = /obj/item/reagent_containers/food/snacks/margheritaslice - slices_num = 6 - list_reagents = list("nutriment" = 30, "tomatojuice" = 6, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/margheritaslice - name = "Margherita slice" - desc = "A slice of the classic pizza." - icon_state = "pizzamargheritaslice" - filling_color = "#BAA14C" - list_reagents = list("nutriment" = 5) - -/obj/item/reagent_containers/food/snacks/sliceable/pizza/meatpizza - name = "Meatpizza" - desc = "A pizza with meat topping." - icon_state = "meatpizza" - slice_path = /obj/item/reagent_containers/food/snacks/meatpizzaslice - slices_num = 6 - list_reagents = list("protein" = 30, "tomatojuice" = 6, "vitamin" = 8) - -/obj/item/reagent_containers/food/snacks/meatpizzaslice - name = "Meatpizza slice" - desc = "A slice of a meaty pizza." - icon_state = "meatpizzaslice" - filling_color = "#BAA14C" - -/obj/item/reagent_containers/food/snacks/sliceable/pizza/mushroompizza - name = "Mushroompizza" - desc = "Very special pizza." - icon_state = "mushroompizza" - slice_path = /obj/item/reagent_containers/food/snacks/mushroompizzaslice - slices_num = 6 - list_reagents = list("plantmatter" = 30, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/mushroompizzaslice - name = "Mushroompizza slice" - desc = "Maybe it is the last slice of pizza in your life." - icon_state = "mushroompizzaslice" - filling_color = "#BAA14C" - -/obj/item/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza - name = "Vegetable pizza" - desc = "No one of Tomato Sapiens were harmed during making this pizza." - icon_state = "vegetablepizza" - slice_path = /obj/item/reagent_containers/food/snacks/vegetablepizzaslice - slices_num = 6 - list_reagents = list("plantmatter" = 25, "tomatojuice" = 6, "oculine" = 12, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/vegetablepizzaslice - name = "Vegetable pizza slice" - desc = "A slice of the most green pizza of all pizzas not containing green ingredients." - icon_state = "vegetablepizzaslice" - filling_color = "#BAA14C" - -/obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza - name = "Hawaiian Pizza" - desc = "Love it or hate it, this pizza divides opinions. Complete with juicy pineapple." - icon_state = "hawaiianpizza" //NEEDED - slice_path = /obj/item/reagent_containers/food/snacks/hawaiianpizzaslice - slices_num = 6 - list_reagents = list("protein" = 15, "tomatojuice" = 6, "plantmatter" = 20, "pineapplejuice" = 6, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/hawaiianpizzaslice - name = "Hawaiian pizza slice" - desc = "A slice of polarising pizza." - icon_state = "hawaiianpizzaslice" - filling_color = "#e5b437" - -/obj/item/pizzabox - name = "pizza box" - desc = "A box suited for pizzas." - icon = 'icons/obj/food/food.dmi' - icon_state = "pizzabox1" - - var/open = 0 // Is the box open? - var/ismessy = 0 // Fancy mess on the lid - var/obj/item/reagent_containers/food/snacks/sliceable/pizza/pizza // Content pizza - var/list/boxes = list() // If the boxes are stacked, they come here - var/boxtag = "" - -/obj/item/pizzabox/update_icon() - - overlays = list() - - // Set appropriate description - if( open && pizza ) - desc = "A box suited for pizzas. It appears to have a [pizza.name] inside." - else if( boxes.len > 0 ) - desc = "A pile of boxes suited for pizzas. There appears to be [boxes.len + 1] boxes in the pile." - - var/obj/item/pizzabox/topbox = boxes[boxes.len] - var/toptag = topbox.boxtag - if( toptag != "" ) - desc = "[desc] The box on top has a tag, it reads: '[toptag]'." - else - desc = "A box suited for pizzas." - - if( boxtag != "" ) - desc = "[desc] The box has a tag, it reads: '[boxtag]'." - - // Icon states and overlays - if( open ) - if( ismessy ) - icon_state = "pizzabox_messy" - else - icon_state = "pizzabox_open" - - if( pizza ) - var/image/pizzaimg = image("food/food.dmi", icon_state = pizza.icon_state) - pizzaimg.pixel_y = -3 - overlays += pizzaimg - - return - else - // Stupid code because byondcode sucks - var/doimgtag = 0 - if( boxes.len > 0 ) - var/obj/item/pizzabox/topbox = boxes[boxes.len] - if( topbox.boxtag != "" ) - doimgtag = 1 - else - if( boxtag != "" ) - doimgtag = 1 - - if( doimgtag ) - var/image/tagimg = image("food/food.dmi", icon_state = "pizzabox_tag") - tagimg.pixel_y = boxes.len * 3 - overlays += tagimg - - icon_state = "pizzabox[boxes.len+1]" - -/obj/item/pizzabox/attack_hand(mob/user) - if(open && pizza) - user.put_in_hands(pizza) - to_chat(user, "You take the [pizza] out of the [src].") - pizza = null - update_icon() - return - - if(boxes.len > 0) - if(user.is_in_inactive_hand(src)) - ..() - return - - var/obj/item/pizzabox/box = boxes[boxes.len] - boxes -= box - - user.put_in_hands( box ) - to_chat(user, "You remove the topmost [src] from your hand.") - box.update_icon() - update_icon() - return - ..() - -/obj/item/pizzabox/attack_self(mob/user) - if(boxes.len > 0) - return - - open = !open - - if( open && pizza ) - ismessy = 1 - - update_icon() - -/obj/item/pizzabox/attackby( obj/item/I, mob/user, params) - if(istype(I, /obj/item/pizzabox/)) - var/obj/item/pizzabox/box = I - - if(!box.open && !open) - // Make a list of all boxes to be added - var/list/boxestoadd = list() - boxestoadd += box - for(var/obj/item/pizzabox/i in box.boxes) - boxestoadd += i - - if( (boxes.len+1) + boxestoadd.len <= 5 ) - user.drop_item() - - box.loc = src - box.boxes = list() // Clear the box boxes so we don't have boxes inside boxes. - Xzibit - boxes.Add( boxestoadd ) - - box.update_icon() - update_icon() - - to_chat(user, "You put the [box] ontop of the [src]!") - else - to_chat(user, "The stack is too high!") - else - to_chat(user, "Close the [box] first!") - - return - - if(istype(I, /obj/item/reagent_containers/food/snacks/sliceable/pizza/)) // Long ass fucking object name - - if(open) - user.drop_item() - I.loc = src - pizza = I - - update_icon() - - to_chat(user, "You put the [I] in the [src]!") - else - to_chat(user, "You try to push the [I] through the lid but it doesn't work!") - return - - if(istype(I, /obj/item/pen/)) - - if(open) - return - - var/t = input("Enter what you want to add to the tag:", "Write", null, null) as text - - var/obj/item/pizzabox/boxtotagto = src - if( boxes.len > 0 ) - boxtotagto = boxes[boxes.len] - - boxtotagto.boxtag = copytext("[boxtotagto.boxtag][t]", 1, 30) - - update_icon() - return - ..() - -/obj/item/pizzabox/margherita/New() - pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/margherita(src) - boxtag = "Margherita Deluxe" - -/obj/item/pizzabox/vegetable/New() - pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza(src) - boxtag = "Gourmet Vegatable" - -/obj/item/pizzabox/mushroom/New() - pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/mushroompizza(src) - boxtag = "Mushroom Special" - -/obj/item/pizzabox/meat/New() - pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/meatpizza(src) - boxtag = "Meatlover's Supreme" - -/obj/item/pizzabox/hawaiian/New() - pizza = new /obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza(src) - boxtag = "Hawaiian Feast" - -////////////////////////////////FOOD ADDITIONS//////////////////////////////////////////// - -/obj/item/reagent_containers/food/snacks/wrap - name = "egg wrap" - desc = "The precursor to Pigs in a Blanket." - icon_state = "wrap" - list_reagents = list("nutriment" = 5) - -/obj/item/reagent_containers/food/snacks/beans - name = "tin of beans" - desc = "Musical fruit in a slightly less musical container." - icon_state = "beans" - list_reagents = list("nutriment" = 10, "beans" = 10, "vitamin" = 3) - -/obj/item/reagent_containers/food/snacks/benedict - name = "eggs benedict" - desc = "There is only one egg on this, how rude." - icon_state = "benedict" - bitesize = 3 - list_reagents = list("nutriment" = 6, "egg" = 3, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/hotdog - name = "hotdog" - desc = "Fresh footlong ready to go down on." - icon_state = "hotdog" - bitesize = 3 - list_reagents = list("nutriment" = 6, "ketchup" = 3, "vitamin" = 3) - -/obj/item/reagent_containers/food/snacks/meatbun - name = "meat bun" - desc = "Has the potential to not be Dog." - icon_state = "meatbun" - bitesize = 6 - list_reagents = list("nutriment" = 6, "vitamin" = 2) - -/obj/item/reagent_containers/food/snacks/icecreamsandwich - name = "icecream sandwich" - desc = "Portable Ice-cream in it's own packaging." - icon_state = "icecreamsandwich" - list_reagents = list("nutriment" = 2, "ice" = 2) - -/obj/item/reagent_containers/food/snacks/notasandwich - name = "not-a-sandwich" - desc = "Something seems to be wrong with this, you can't quite figure what. Maybe it's his moustache." - icon_state = "notasandwich" - list_reagents = list("nutriment" = 6, "vitamin" = 6) - -/obj/item/reagent_containers/food/snacks/sugarcookie - name = "sugar cookie" - desc = "Just like your little sister used to make." - icon_state = "sugarcookie" - list_reagents = list("nutriment" = 3, "sugar" = 3) - -/obj/item/reagent_containers/food/snacks/friedbanana - name = "Fried Banana" - desc = "Goreng Pisang, also known as fried bananas." - icon_state = "friedbanana" - list_reagents = list("sugar" = 5, "nutriment" = 8, "cornoil" = 4) - -/obj/item/reagent_containers/food/snacks/dionaroast - name = "roast diona" - desc = "It's like an enormous, leathery carrot. With an eye." - icon_state = "dionaroast" - trash = /obj/item/trash/plate - filling_color = "#75754B" - list_reagents = list("plantmatter" = 4, "nutriment" = 2, "radium" = 2, "vitamin" = 4) - -/obj/item/reagent_containers/food/snacks/boiledspiderleg - name = "boiled spider leg" - desc = "A giant spider's leg that's still twitching after being cooked. Gross!" - icon_state = "spiderlegcooked" - trash = /obj/item/trash/plate - bitesize = 3 - list_reagents = list("nutriment" = 3, "capsaicin" = 2) - -/obj/item/reagent_containers/food/snacks/spidereggs - name = "spider eggs" - desc = "A cluster of juicy spider eggs. A great side dish for when you care not for your health." - icon_state = "spidereggs" - list_reagents = list("protein" = 2, "toxin" = 2) - -/obj/item/reagent_containers/food/snacks/spidereggsham - name = "green eggs and ham" - desc = "Would you eat them on a train? Would you eat them on a plane? Would you eat them on a state of the art corporate deathtrap floating through space?" - icon_state = "spidereggsham" - trash = /obj/item/trash/plate - bitesize = 4 - list_reagents = list("nutriment" = 6) - -/obj/item/reagent_containers/food/snacks/sliceable/turkey - name = "Turkey" - desc = "A traditional turkey served with stuffing." - icon_state = "turkey" - slice_path = /obj/item/reagent_containers/food/snacks/turkeyslice - slices_num = 6 - list_reagents = list("protein" = 24, "nutriment" = 18, "vitamin" = 5) - -/obj/item/reagent_containers/food/snacks/turkeyslice - name = "turkey serving" - desc = "A serving of some tender and delicious turkey." - icon_state = "turkeyslice" - trash = /obj/item/trash/plate - filling_color = "#B97A57" - -/obj/item/reagent_containers/food/snacks/mashed_potatoes //mashed taters - name = "mashed potatoes" - desc = "Some sot creamy, and irresistible mashed potatoes." - icon_state = "mashedtaters" - trash = /obj/item/trash/plate - filling_color = "#D6D9C1" - list_reagents = list("nutriment" = 5, "gravy" = 5, "mashedpotatoes" = 10, "vitamin" = 2) - -////////////////////////////////ICE CREAM/////////////////////////////////// -/obj/item/reagent_containers/food/snacks/icecream - name = "ice cream" - desc = "Delicious ice cream." - icon = 'icons/obj/kitchen.dmi' - icon_state = "icecream_cone" - bitesize = 3 - list_reagents = list("nutriment" = 1, "sugar" = 1) - -/obj/item/reagent_containers/food/snacks/icecream/New() - ..() - update_icon() - -/obj/item/reagent_containers/food/snacks/icecream/update_icon() - overlays.Cut() - var/image/filling = image('icons/obj/kitchen.dmi', src, "icecream_color") - filling.icon += mix_color_from_reagents(reagents.reagent_list) - overlays += filling - -/obj/item/reagent_containers/food/snacks/icecream/icecreamcone - name = "ice cream cone" - desc = "Delicious ice cream." - icon_state = "icecream_cone" - volume = 50 - bitesize = 3 - list_reagents = list("nutriment" = 3, "sugar" = 7, "ice" = 2) - -/obj/item/reagent_containers/food/snacks/icecream/icecreamcup - name = "chocolate ice cream cone" - desc = "Delicious ice cream." - icon_state = "icecream_cup" - volume = 50 - bitesize = 6 - list_reagents = list("nutriment" = 5, "chocolate" = 8, "ice" = 2) +// MISC /obj/item/reagent_containers/food/snacks/cereal name = "box of cereal" @@ -2410,131 +300,5 @@ icon_state = "deepfried_holder_icon" list_reagents = list("nutriment" = 3) -/obj/item/reagent_containers/food/snacks/dough - name = "dough" - desc = "A piece of dough." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "dough" - list_reagents = list("nutriment" = 6) -// Dough + rolling pin = flat dough -/obj/item/reagent_containers/food/snacks/dough/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/kitchen/rollingpin)) - if(isturf(loc)) - new /obj/item/reagent_containers/food/snacks/sliceable/flatdough(loc) - to_chat(user, "You flatten [src].") - qdel(src) - else - to_chat(user, "You need to put [src] on a surface to roll it out!") - else - ..() - -// slicable into 3xdoughslices -/obj/item/reagent_containers/food/snacks/sliceable/flatdough - name = "flat dough" - desc = "Some flattened dough." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "flat dough" - slice_path = /obj/item/reagent_containers/food/snacks/doughslice - slices_num = 3 - list_reagents = list("nutriment" = 6) - -/obj/item/reagent_containers/food/snacks/doughslice - name = "dough slice" - desc = "The building block of an impressive dish." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "doughslice" - list_reagents = list("nutriment" = 1) - -/obj/item/reagent_containers/food/snacks/bun - name = "bun" - desc = "The base for any self-respecting burger." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "bun" - list_reagents = list("nutriment" = 1) - -/obj/item/reagent_containers/food/snacks/taco - name = "taco" - desc = "Take a bite!" - icon_state = "taco" - bitesize = 3 - list_reagents = list("nutriment" = 7, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/cutlet - name = "cutlet" - desc = "A tasty meat slice." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "cutlet" - list_reagents = list("protein" = 2) - -/obj/item/reagent_containers/food/snacks/flatbread - name = "flatbread" - desc = "Bland but filling." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "flatbread" - list_reagents = list("nutriment" = 6, "vitamin" = 1) - -/obj/item/reagent_containers/food/snacks/rawsticks - name = "raw potato sticks" - desc = "Raw fries, not very tasty." - icon = 'icons/obj/food/food_ingredients.dmi' - icon_state = "rawsticks" - list_reagents = list("plantmatter" = 3) - -/obj/item/reagent_containers/food/snacks/ectoplasm - name = "ectoplasm" - desc = "A luminescent blob of what scientists refer to as 'ghost goo'." - icon = 'icons/obj/wizard.dmi' - icon_state = "ectoplasm" - list_reagents = list("ectoplasm" = 10) - -/obj/item/reagent_containers/food/snacks/liquidfood - name = "\improper LiquidFood Ration" - desc = "A prepackaged grey slurry of all the essential nutrients for a spacefarer on the go. Should this be crunchy?" - icon_state = "liquidfood" - trash = /obj/item/trash/liquidfood - filling_color = "#A8A8A8" - bitesize = 4 - list_reagents = list("nutriment" = 20, "iron" = 3, "vitamin" = 2) - - -/obj/item/reagent_containers/food/snacks/tastybread - name = "bread tube" - desc = "Bread in a tube. Chewy...and surprisingly tasty." - icon_state = "tastybread" - trash = /obj/item/trash/tastybread - filling_color = "#A66829" - junkiness = 20 - list_reagents = list("nutriment" = 2, "sugar" = 4) - -/obj/item/reagent_containers/food/snacks/yakiimo - name = "yaki imo" - desc = "Made with roasted sweet potatoes!" - icon_state = "yakiimo" - trash = /obj/item/trash/plate - list_reagents = list("nutriment" = 5, "vitamin" = 4) - filling_color = "#8B1105" - -/obj/item/reagent_containers/food/snacks/roastparsnip - name = "roast parsnip" - desc = "Sweet and crunchy." - icon_state = "roastparsnip" - trash = /obj/item/trash/plate - list_reagents = list("nutriment" = 3, "vitamin" = 4) - filling_color = "#FF5500" - -/obj/item/reagent_containers/food/snacks/tatortot - name = "tator tot" - desc = "A large fried potato nugget that may or may not try to valid you." - icon_state = "tatortot" - list_reagents = list("nutriment" = 4) - filling_color = "FFD700" - -/obj/item/reagent_containers/food/snacks/onionrings - name = "onion rings" - desc = "Onion slices coated in batter." - icon_state = "onionrings" - list_reagents = list("nutriment" = 3) - filling_color = "#C0C9A0" - gender = PLURAL #undef MAX_WEIGHT_CLASS \ No newline at end of file diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index b4a787ea4c8..6f6d9132fdf 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -58,7 +58,7 @@ C.emote("scream") user.changeNext_move(CLICK_CD_MELEE) C.apply_damage(25, BURN, "head") //25 fire damage and disfigurement because your face was just deep fried! - head.disfigure("burn") + head.disfigure() add_attack_logs(user, G.affecting, "Deep-fried with [src]") qdel(G) //Removes the grip so the person MIGHT have a small chance to run the fuck away and to prevent rapid dunks. return 0 diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 0c2af905a74..1e3c5602a22 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -122,7 +122,7 @@ to_chat(user, "The [src] is locked and running, wait for it to finish.") return - if(!ishuman(victim) || issmall(victim)) + if(!ishuman(victim)) to_chat(user, "This is not suitable for the [src]!") return @@ -255,12 +255,15 @@ if(occupant.reagents) occupant.reagents.trans_to(new_meat, round(occupant.reagents.total_volume/slab_count,1)) - if(occupant.get_species() == "Human") - new /obj/item/stack/sheet/animalhide/human(src) + if(ishuman(occupant)) + var/mob/living/carbon/human/H = occupant + var/skinned = H.dna.species.skinned_type + if(skinned) + new skinned(src) new /obj/effect/decal/cleanable/blood/gibs(src) if(!UserOverride) - add_attack_logs(user, occupant, "Gibbed in [src]", !!occupant.ckey) + add_attack_logs(user, occupant, "Gibbed in [src]", !!occupant.ckey ? ATKLOG_FEW : ATKLOG_ALL) if(!iscarbon(user)) occupant.LAssailant = null diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm index dfbea528d53..ad4dcb5e4d8 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm @@ -87,6 +87,10 @@ input = /obj/item/reagent_containers/food/snacks/doughslice output = /obj/item/reagent_containers/food/snacks/spaghetti +/datum/food_processor_process/macaroni + input = /obj/item/reagent_containers/food/snacks/spaghetti + output = /obj/item/reagent_containers/food/snacks/macaroni + /datum/food_processor_process/parsnip input = /obj/item/reagent_containers/food/snacks/grown/parsnip output = /obj/item/reagent_containers/food/snacks/roastparsnip diff --git a/code/modules/food_and_drinks/recipes/recipes_microwave.dm b/code/modules/food_and_drinks/recipes/recipes_microwave.dm index effbcef37ba..70169476c9d 100644 --- a/code/modules/food_and_drinks/recipes/recipes_microwave.dm +++ b/code/modules/food_and_drinks/recipes/recipes_microwave.dm @@ -396,6 +396,14 @@ ) result = /obj/item/reagent_containers/food/snacks/spesslaw +/datum/recipe/microwave/macncheese + reagents = list("water" = 5, "milk" = 5) + items = list( + /obj/item/reagent_containers/food/snacks/cheesewedge, + /obj/item/reagent_containers/food/snacks/macaroni, + ) + result = /obj/item/reagent_containers/food/snacks/macncheese + /datum/recipe/microwave/superbiteburger reagents = list("sodiumchloride" = 5, "blackpepper" = 5) items = list( diff --git a/code/modules/food_and_drinks/recipes/recipes_oven.dm b/code/modules/food_and_drinks/recipes/recipes_oven.dm index b4b636a6ee7..7dcfe199ded 100644 --- a/code/modules/food_and_drinks/recipes/recipes_oven.dm +++ b/code/modules/food_and_drinks/recipes/recipes_oven.dm @@ -180,21 +180,16 @@ result = /obj/item/reagent_containers/food/snacks/fortunecookie /datum/recipe/oven/fortunecookie/make_food(obj/container) - var/obj/item/paper/paper = locate() in container - paper.loc = null //prevent deletion + var/obj/item/paper/P = locate() in container + P.loc = null //So we don't delete the paper while cooking the cookie var/obj/item/reagent_containers/food/snacks/fortunecookie/being_cooked = ..() - paper.loc = being_cooked - being_cooked.trash = paper //so the paper is left behind as trash without special-snowflake(TM Nodrak) code ~carn + if(P.info) //If there's anything written on the paper, just move it into the fortune cookie + P.forceMove(being_cooked) //Prevents the oven deleting our paper + being_cooked.trash = P //so the paper is left behind as trash without special-snowflake(TM Nodrak) code ~carn + else + qdel(P) return being_cooked -/datum/recipe/oven/fortunecookie/check_items(obj/container) - . = ..() - if(.) - var/obj/item/paper/paper = locate() in container - if(!paper || !paper.info) - return -1 - return . - /datum/recipe/oven/pizzamargherita items = list( /obj/item/reagent_containers/food/snacks/sliceable/flatdough, @@ -264,6 +259,15 @@ ) result = /obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza +/datum/recipe/oven/macncheesepizza + items = list( + /obj/item/reagent_containers/food/snacks/sliceable/flatdough, + /obj/item/reagent_containers/food/snacks/cheesewedge, + /obj/item/reagent_containers/food/snacks/cheesewedge, + /obj/item/reagent_containers/food/snacks/macncheese, + ) + result = /obj/item/reagent_containers/food/snacks/sliceable/pizza/macpizza + /datum/recipe/oven/amanita_pie items = list( /obj/item/reagent_containers/food/snacks/sliceable/flatdough, diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm index 58cec86dc1c..7acd3efc961 100644 --- a/code/modules/hydroponics/beekeeping/beebox.dm +++ b/code/modules/hydroponics/beekeeping/beebox.dm @@ -23,7 +23,7 @@ return 1 /mob/living/carbon/human/bee_friendly() - if(get_species() == "Diona") //bees pollinate plants, duh. + if(isdiona(src)) //bees pollinate plants, duh. return 1 if((wear_suit && (wear_suit.flags & THICKMATERIAL)) && (head && (head.flags & THICKMATERIAL))) return 1 @@ -179,7 +179,7 @@ visible_message("The [qb] refuses to settle down. Maybe it's something to do with its reagent?") if(queen_bee) - visible_message("[user] sets [qb] down inside the apiary, making it their new home.") + visible_message("[user] sets [qb] down inside the apiary, making it [user.p_their()] new home.") var/relocated = 0 for(var/b in bees) var/mob/living/simple_animal/hostile/poison/bees/worker/B = b diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm index 36065efa298..6874038a7bf 100644 --- a/code/modules/hydroponics/grown/banana.dm +++ b/code/modules/hydroponics/grown/banana.dm @@ -25,7 +25,7 @@ bitesize = 5 /obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user) - user.visible_message("[user] is aiming the [src.name] at themself! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is aiming the [name] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide.") playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1) sleep(25) if(!user) @@ -34,7 +34,7 @@ sleep(25) if(!user) return (OXYLOSS) - user.visible_message("[user] laughs so hard they begin to suffocate!") + user.visible_message("[user] laughs so hard [user.p_they()] begin[user.p_s()] to suffocate!") return (OXYLOSS) /obj/item/grown/bananapeel @@ -49,7 +49,7 @@ throw_range = 7 /obj/item/grown/bananapeel/suicide_act(mob/user) - user.visible_message("[user] is deliberately slipping on the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is deliberately slipping on the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.") playsound(loc, 'sound/misc/slip.ogg', 50, 1, -1) return (BRUTELOSS) diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm index 157a2813b8f..86bc8082661 100644 --- a/code/modules/hydroponics/grown/citrus.dm +++ b/code/modules/hydroponics/grown/citrus.dm @@ -109,7 +109,7 @@ var/area/A = get_area(user) user.visible_message("[user] primes the [src]!", "You prime the [src]!") var/message = "[ADMIN_LOOKUPFLW(user)] primed a combustible lemon for detonation at [A] [ADMIN_COORDJMP(user)]" - bombers += message + investigate_log("[key_name(user)] primed a combustible lemon for detonation at [A] [COORD(user)].", INVESTIGATE_BOMB) message_admins(message) log_game("[key_name(user)] primed a combustible lemon for detonation at [A] [COORD(user)].") if(iscarbon(user)) diff --git a/code/modules/hydroponics/grown/kudzu.dm b/code/modules/hydroponics/grown/kudzu.dm index 0169e3bb5d9..09c16544396 100644 --- a/code/modules/hydroponics/grown/kudzu.dm +++ b/code/modules/hydroponics/grown/kudzu.dm @@ -22,7 +22,7 @@ return S /obj/item/seeds/kudzu/suicide_act(mob/user) - user.visible_message("[user] swallows the pack of kudzu seeds! It looks like \he's trying to commit suicide..") + user.visible_message("[user] swallows the pack of kudzu seeds! It looks like [user.p_theyre()] trying to commit suicide..") plant(user) return (BRUTELOSS) diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm index c65c9dcf618..8bbe4a4e240 100644 --- a/code/modules/hydroponics/grown/nettle.dm +++ b/code/modules/hydroponics/grown/nettle.dm @@ -44,7 +44,7 @@ attack_verb = list("stung") /obj/item/grown/nettle/suicide_act(mob/user) - user.visible_message("[user] is eating some of the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is eating some of the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.") return (BRUTELOSS|TOXLOSS) /obj/item/grown/nettle/pickup(mob/living/user) diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm index 7bb064f752e..6b2da2c29ae 100644 --- a/code/modules/hydroponics/hydroitemdefines.dm +++ b/code/modules/hydroponics/hydroitemdefines.dm @@ -33,7 +33,7 @@ reagents.add_reagent("atrazine", 100) /obj/item/reagent_containers/spray/weedspray/suicide_act(mob/user) - user.visible_message("[user] is huffing the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is huffing the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.") return (TOXLOSS) /obj/item/reagent_containers/spray/pestspray // -- Skie @@ -55,7 +55,7 @@ reagents.add_reagent("pestkiller", 100) /obj/item/reagent_containers/spray/pestspray/suicide_act(mob/user) - user.visible_message("[user] is huffing the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is huffing the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.") return (TOXLOSS) /obj/item/cultivator @@ -89,7 +89,7 @@ sharp = 1 /obj/item/hatchet/suicide_act(mob/user) - user.visible_message("[user] is chopping at \himself with the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is chopping at [user.p_them()]self with the [name]! It looks like [user.p_theyre()] trying to commit suicide.") playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) return (BRUTELOSS) @@ -119,7 +119,7 @@ var/swiping = FALSE /obj/item/scythe/suicide_act(mob/user) - user.visible_message("[user] is beheading \himself with the [src.name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is beheading [user.p_them()]self with the [name]! It looks like [user.p_theyre()] trying to commit suicide.") if(ishuman(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/external/affecting = H.get_organ("head") diff --git a/code/modules/karma/karma.dm b/code/modules/karma/karma.dm index e9265c15b4a..1f18edfae22 100644 --- a/code/modules/karma/karma.dm +++ b/code/modules/karma/karma.dm @@ -371,29 +371,30 @@ You've gained [totalkarma] total karma in your time here.
    "} return /client/proc/karmarefund(var/type,var/name,var/cost) - if(name == "Tajaran Ambassador") - cost = 30 - else if(name == "Unathi Ambassador") - cost = 30 - else if(name == "Skrell Ambassador") - cost = 30 - else if(name == "Diona Ambassador") - cost = 30 - else if(name == "Kidan Ambassador") - cost = 30 - else if(name == "Slime People Ambassador") - cost = 30 - else if(name == "Grey Ambassador") - cost = 30 - else if(name == "Vox Ambassador") - cost = 30 - else if(name == "Customs Officer") - cost = 30 - else if(name == "Nanotrasen Recruiter") - cost = 10 - else - to_chat(usr, "That job is not refundable.") - return + switch(name) + if("Tajaran Ambassador") + cost = 30 + if("Unathi Ambassador") + cost = 30 + if("Skrell Ambassador") + cost = 30 + if("Diona Ambassador") + cost = 30 + if("Kidan Ambassador") + cost = 30 + if("Slime People Ambassador") + cost = 30 + if("Grey Ambassador") + cost = 30 + if("Vox Ambassador") + cost = 30 + if("Customs Officer") + cost = 30 + if("Nanotrasen Recruiter") + cost = 10 + else + to_chat(usr, "That job is not refundable.") + return var/DBQuery/query = dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[usr.ckey]'") query.Execute() @@ -408,12 +409,13 @@ You've gained [totalkarma] total karma in your time here.
    "} if(dbckey) var/list/typelist = list() - if(type == "job") - typelist = splittext(dbjob,",") - else if(type == "species") - typelist = splittext(dbspecies,",") - else - to_chat(usr, "Type [type] is not a valid column.") + switch(type) + if("job") + typelist = splittext(dbjob,",") + if("species") + typelist = splittext(dbspecies,",") + else + to_chat(usr, "Type [type] is not a valid column.") if(name in typelist) typelist -= name diff --git a/code/modules/library/computers/checkout.dm b/code/modules/library/computers/checkout.dm index 0f0774aa1f4..fdcfee0e87a 100644 --- a/code/modules/library/computers/checkout.dm +++ b/code/modules/library/computers/checkout.dm @@ -49,7 +49,7 @@ if(src.arcanecheckout) new /obj/item/tome(src.loc) to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a dusty old tome sitting on the desk. You don't really remember printing it.") - user.visible_message("[user] stares at the blank screen for a few moments, his expression frozen in fear. When he finally awakens from it, he looks a lot older.", 2) + user.visible_message("[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.", 2) src.arcanecheckout = 0 if(1) // Inventory diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 8df5d593b9b..a856e3f822f 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -228,7 +228,7 @@ src.name = newtitle src.title = newtitle if("Contents") - var/content = strip_html(input(usr, "Write your book's contents (HTML NOT allowed):"), MAX_BOOK_MESSAGE_LEN) as message|null + var/content = strip_html(input(usr, "Write your book's contents (HTML NOT allowed):") as message|null, MAX_BOOK_MESSAGE_LEN) if(!content) to_chat(usr, "The content is invalid.") return 1 diff --git a/code/modules/martial_arts/brawling.dm b/code/modules/martial_arts/brawling.dm index 9f9fa5236b2..b326e9f8b33 100644 --- a/code/modules/martial_arts/brawling.dm +++ b/code/modules/martial_arts/brawling.dm @@ -11,11 +11,11 @@ /datum/martial_art/boxing/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) var/atk_verb = pick("left hook","right hook","straight punch") - var/damage = rand(5, 8) + A.species.punchdamagelow + var/damage = rand(5, 8) + A.dna.species.punchdamagelow if(!damage) playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") @@ -62,7 +62,7 @@ /datum/martial_art/drunk_brawling/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) add_attack_logs(A, D, "Melee attacked with [src]") - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) var/atk_verb = pick("jab","uppercut","overhand punch","drunken right hook","drunken left hook") diff --git a/code/modules/martial_arts/krav_maga.dm b/code/modules/martial_arts/krav_maga.dm index d17d1b30495..9e889bdce7a 100644 --- a/code/modules/martial_arts/krav_maga.dm +++ b/code/modules/martial_arts/krav_maga.dm @@ -109,7 +109,6 @@ datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/livi if(check_streak(A,D)) return 1 add_attack_logs(A, D, "Melee attacked with [src]") - A.do_attack_animation(D) var/picked_hit_type = pick("punches", "kicks") var/bonus_damage = 10 if(D.weakened || D.resting || D.lying) @@ -117,8 +116,10 @@ datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/livi picked_hit_type = "stomps on" D.apply_damage(bonus_damage, BRUTE) if(picked_hit_type == "kicks" || picked_hit_type == "stomps") + A.do_attack_animation(D, ATTACK_EFFECT_KICK) playsound(get_turf(D), 'sound/effects/hit_kick.ogg', 50, 1, -1) else + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) playsound(get_turf(D), 'sound/effects/hit_punch.ogg', 50, 1, -1) D.visible_message("[A] [picked_hit_type] [D]!", \ "[A] [picked_hit_type] you!") diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm index 3e1be19b0de..bff0cf0d2e4 100644 --- a/code/modules/martial_arts/martial.dm +++ b/code/modules/martial_arts/martial.dm @@ -33,14 +33,19 @@ /datum/martial_art/proc/basic_hit(var/mob/living/carbon/human/A,var/mob/living/carbon/human/D) - A.do_attack_animation(D) - var/damage = rand(A.species.punchdamagelow, A.species.punchdamagehigh) - var/datum/unarmed_attack/attack = A.species.unarmed + var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh) + var/datum/unarmed_attack/attack = A.dna.species.unarmed var/atk_verb = "[pick(attack.attack_verb)]" if(D.lying) atk_verb = "kick" + switch(atk_verb) + if("kick") + A.do_attack_animation(D, ATTACK_EFFECT_KICK) + else + A.do_attack_animation(D, attack.animation_type) + if(!damage) playsound(D.loc, attack.miss_sound, 25, 1, -1) D.visible_message("[A] has attempted to [atk_verb] [D]!") @@ -55,9 +60,9 @@ D.apply_damage(damage, BRUTE, affecting, armor_block) - add_attack_logs(A, D, "Melee attacked with martial-art [src]", admin_notify = (damage > 0) ? TRUE : FALSE) + add_attack_logs(A, D, "Melee attacked with martial-art [src]", (damage > 0) ? null : ATKLOG_ALL) - if((D.stat != DEAD) && damage >= A.species.punchstunthreshold) + if((D.stat != DEAD) && damage >= A.dna.species.punchstunthreshold) D.visible_message("[A] has weakened [D]!!", \ "[A] has weakened [D]!") D.apply_effect(4, WEAKEN, armor_block) @@ -205,7 +210,7 @@ return ..() var/mob/living/carbon/C = target if(C.stat) - to_chat(user, "It would be dishonorable to attack a foe while they cannot retaliate.") + to_chat(user, "It would be dishonorable to attack a foe while [C.p_they()] cannot retaliate.") return switch(user.a_intent) if(INTENT_DISARM) @@ -231,7 +236,7 @@ if(H.staminaloss && !H.sleeping) var/total_health = (H.health - H.staminaloss) if(total_health <= config.health_threshold_crit && !H.stat) - H.visible_message("[user] delivers a heavy hit to [H]'s head, knocking them out cold!", \ + H.visible_message("[user] delivers a heavy hit to [H]'s head, knocking [H.p_them()] out cold!", \ "[user] knocks you unconscious!") H.SetSleeping(30) H.adjustBrainLoss(25) diff --git a/code/modules/martial_arts/mimejutsu.dm b/code/modules/martial_arts/mimejutsu.dm index 4d8edbf7236..e8aa7a53d03 100644 --- a/code/modules/martial_arts/mimejutsu.dm +++ b/code/modules/martial_arts/mimejutsu.dm @@ -23,7 +23,7 @@ /datum/martial_art/mimejutsu/proc/mimeChuck(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!D.stat && !D.stunned && !D.weakened) - var/damage = rand(5, 8) + A.species.punchdamagelow + var/damage = rand(5, 8) + A.dna.species.punchdamagelow if(!damage) playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) D.visible_message("[A] swings invisible nunchcuks at [D]..and misses?") @@ -55,8 +55,8 @@ /datum/martial_art/mimejutsu/proc/mimePalm(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!D.stat && !D.stunned && !D.weakened) - D.visible_message("[A] has barely touched [D] with their palm!", \ - "[A] hovers their palm over your face!") + D.visible_message("[A] has barely touched [D] with [A.p_their()] palm!", \ + "[A] hovers [A.p_their()] palm over your face!") var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) D.throw_at(throw_target, 200, 4,A) diff --git a/code/modules/martial_arts/plasma_fist.dm b/code/modules/martial_arts/plasma_fist.dm index d2e047dc08d..5aed9b8e9e1 100644 --- a/code/modules/martial_arts/plasma_fist.dm +++ b/code/modules/martial_arts/plasma_fist.dm @@ -46,7 +46,7 @@ return /datum/martial_art/plasma_fist/proc/Plasma(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) A.say("PLASMA FIST!") D.visible_message("[A] has hit [D] with THE PLASMA FIST TECHNIQUE!", \ diff --git a/code/modules/martial_arts/sleeping_carp.dm b/code/modules/martial_arts/sleeping_carp.dm index 45f4948bc14..a6cd25d50c0 100644 --- a/code/modules/martial_arts/sleeping_carp.dm +++ b/code/modules/martial_arts/sleeping_carp.dm @@ -36,7 +36,7 @@ /datum/martial_art/the_sleeping_carp/proc/wristWrench(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!D.stat && !D.stunned && !D.weakened) - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) D.visible_message("[A] grabs [D]'s wrist and wrenches it sideways!", \ "[A] grabs your wrist and violently wrenches it to the side!") playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) @@ -51,7 +51,7 @@ /datum/martial_art/the_sleeping_carp/proc/backKick(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(A.dir == D.dir && !D.stat && !D.weakened) - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_KICK) D.visible_message("[A] kicks [D] in the back!", \ "[A] kicks you in the back, making you stumble and fall!") step_to(D,get_step(D,D.dir),1) @@ -64,7 +64,7 @@ /datum/martial_art/the_sleeping_carp/proc/kneeStomach(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!D.stat && !D.weakened) - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_KICK) D.visible_message("[A] knees [D] in the stomach!", \ "[A] winds you with a knee in the stomach!") D.audible_message("[D] gags!") @@ -78,7 +78,7 @@ /datum/martial_art/the_sleeping_carp/proc/headKick(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!D.stat && !D.weakened) - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_KICK) D.visible_message("[A] kicks [D] in the head!", \ "[A] kicks you in the jaw!") D.apply_damage(20, BRUTE, "head") @@ -92,9 +92,9 @@ /datum/martial_art/the_sleeping_carp/proc/elbowDrop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(D.weakened || D.resting || D.stat) - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) D.visible_message("[A] elbow drops [D]!", \ - "[A] piledrives you with their elbow!") + "[A] piledrives you with [A.p_their()] elbow!") if(D.stat) D.death() //FINISH HIM! D.apply_damage(50, BRUTE, "chest") @@ -117,7 +117,7 @@ add_to_streak("H",D) if(check_streak(A,D)) return 1 - A.do_attack_animation(D) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams") D.visible_message("[A] [atk_verb] [D]!", \ "[A] [atk_verb] you!") diff --git a/code/modules/mining/coins.dm b/code/modules/mining/coins.dm index 9f4f7629c7e..4d94793a5e9 100644 --- a/code/modules/mining/coins.dm +++ b/code/modules/mining/coins.dm @@ -106,7 +106,7 @@ return if(CC.use(1)) - overlays += image('icons/obj/items.dmi',"coin_string_overlay") + overlays += image('icons/obj/economy.dmi',"coin_string_overlay") string_attached = 1 to_chat(user, "You attach a string to the coin.") else diff --git a/code/modules/mining/lavaland/loot/ashdragon_loot.dm b/code/modules/mining/lavaland/loot/ashdragon_loot.dm index fba4725e5f0..d88ec709dce 100644 --- a/code/modules/mining/lavaland/loot/ashdragon_loot.dm +++ b/code/modules/mining/lavaland/loot/ashdragon_loot.dm @@ -52,7 +52,7 @@ return to_chat(user, "You call out for aid, attempting to summon spirits to your side.") - notify_ghosts("[user] is raising their [src], calling for your help!", enter_link="(Click to help)", source = user, action = NOTIFY_FOLLOW) + notify_ghosts("[user] is raising [user.p_their()] [src], calling for your help!", enter_link="(Click to help)", source = user, action = NOTIFY_FOLLOW) summon_cooldown = world.time + 600 @@ -116,7 +116,7 @@ switch(random) if(1) to_chat(user, "Your flesh begins to melt! Miraculously, you seem fine otherwise.") - H.set_species("Skeleton") + H.set_species(/datum/species/skeleton) if(2) to_chat(user, "Power courses through you! You can now shift your form at will.") if(user.mind) diff --git a/code/modules/mining/lavaland/loot/bubblegum_loot.dm b/code/modules/mining/lavaland/loot/bubblegum_loot.dm index 03ee7eb0a8d..613239b58a9 100644 --- a/code/modules/mining/lavaland/loot/bubblegum_loot.dm +++ b/code/modules/mining/lavaland/loot/bubblegum_loot.dm @@ -75,7 +75,7 @@ for(var/mob/living/carbon/human/H in player_list) if(H == L) continue - to_chat(H, "You have an overwhelming desire to kill [L]. They have been marked red! Go kill them!") + to_chat(H, "You have an overwhelming desire to kill [L]. [L.p_they(TRUE)] [L.p_have()] been marked red! Go kill [L.p_them()]!") H.put_in_hands(new /obj/item/kitchen/knife/butcher(H)) qdel(src) \ No newline at end of file diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm index ddf1255cca0..59d3a715f32 100644 --- a/code/modules/mining/lavaland/loot/colossus_loot.dm +++ b/code/modules/mining/lavaland/loot/colossus_loot.dm @@ -289,7 +289,7 @@ if(ishuman(i)) var/mob/living/carbon/human/H = i if(H.stat == DEAD) - H.set_species("Shadow") + H.set_species(/datum/species/shadow) H.revive() H.disabilities |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal H.grab_ghost(force = TRUE) diff --git a/code/modules/mining/lavaland/loot/hierophant_loot.dm b/code/modules/mining/lavaland/loot/hierophant_loot.dm index 62d72d4a0a9..1d66d59d316 100644 --- a/code/modules/mining/lavaland/loot/hierophant_loot.dm +++ b/code/modules/mining/lavaland/loot/hierophant_loot.dm @@ -57,7 +57,7 @@ return if(!rune) if(isturf(user.loc)) - user.visible_message("[user] holds [src] carefully in front of them, moving it in a strange pattern...", \ + user.visible_message("[user] holds [src] carefully in front of [user.p_them()], moving it in a strange pattern...", \ "You start creating a hierophant rune to teleport to...") timer = world.time + 51 if(do_after(user, 50, target = user)) @@ -67,7 +67,7 @@ var/obj/effect/hierophant/H = new/obj/effect/hierophant(T) rune = H user.update_action_buttons_icon() - user.visible_message("[user] creates a strange rune beneath them!", \ + user.visible_message("[user] creates a strange rune beneath [user.p_them()]!", \ "You create a hierophant rune, which you can teleport yourself and any allies to at any time!\n\ You can remove the rune to place a new one by striking it with the staff.") else diff --git a/code/modules/mining/lavaland/loot/legion_loot.dm b/code/modules/mining/lavaland/loot/legion_loot.dm index 210710db4d9..f11d6162f55 100644 --- a/code/modules/mining/lavaland/loot/legion_loot.dm +++ b/code/modules/mining/lavaland/loot/legion_loot.dm @@ -5,7 +5,6 @@ item_state = "staffofstorms" icon = 'icons/obj/guns/magic.dmi' slot_flags = SLOT_BACK - item_state = "staffofstorms" w_class = WEIGHT_CLASS_BULKY force = 25 damtype = BURN @@ -19,34 +18,36 @@ return var/area/user_area = get_area(user) + var/turf/user_turf = get_turf(user) + if(!user_area || !user_turf) + to_chat(user, "Something is preventing you from using the staff here.") + return var/datum/weather/A - var/z_level_name = space_manager.levels_by_name[user.z] - for(var/V in weather_master.existing_weather) + for(var/V in SSweather.processing) var/datum/weather/W = V - if(W.target_z == z_level_name && W.area_type == user_area.type) + if((user_turf.z in W.impacted_z_levels) && W.area_type == user_area.type) A = W break - if(A) + if(A) if(A.stage != END_STAGE) if(A.stage == WIND_DOWN_STAGE) to_chat(user, "The storm is already ending! It would be a waste to use the staff now.") return user.visible_message("[user] holds [src] skywards as an orange beam travels into the sky!", \ "You hold [src] skyward, dispelling the storm!") - playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) + playsound(user, 'sound/magic/staff_change.ogg', 200, 0) A.wind_down() return else - A = new storm_type + A = new storm_type(list(user_turf.z)) A.name = "staff storm" A.area_type = user_area.type - A.target_z = z_level_name A.telegraph_duration = 100 A.end_duration = 100 user.visible_message("[user] holds [src] skywards as red lightning crackles into the sky!", \ "You hold [src] skyward, calling down a terrible storm!") - playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) + playsound(user, 'sound/magic/staff_change.ogg', 200, 0) A.telegraph() storm_cooldown = world.time + 200 diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm index 9c6ea675ba3..a80c2ae6c18 100644 --- a/code/modules/mining/lavaland/loot/tendril_loot.dm +++ b/code/modules/mining/lavaland/loot/tendril_loot.dm @@ -105,13 +105,13 @@ to_chat(M, "This item is currently non-functional.") /*if(ishuman(M) && M.stat != DEAD) var/mob/living/carbon/human/H = M - if(H.species.name != "Human" || reac_volume < 5) // implying xenohumans are holy + if(!ishumanbasic(H) || reac_volume < 5) // implying xenohumans are holy if(method == INGEST && show_message) to_chat(H, "You feel nothing but a terrible aftertaste.") return ..() to_chat(H, "A terrible pain travels down your back as wings burst out!") - H.set_species("Angel") + H.set_species(/datum/species/angel) playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1, -1) H.adjustBruteLoss(20) H.emote("scream") @@ -355,7 +355,7 @@ if(cooldown < world.time) feedback_add_details("immortality_talisman","U") // usage cooldown = world.time + 600 - user.visible_message("[user] vanishes from reality, leaving a a hole in their place!") + user.visible_message("[user] vanishes from reality, leaving a a hole in [user.p_their()] place!") var/obj/effect/immortality_talisman/Z = new(get_turf(src.loc)) Z.name = "hole in reality" Z.desc = "It's shaped an awful lot like [user.name]." diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 1ef887c2527..c4487d61948 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -341,20 +341,28 @@ //Pod turfs and objects //Window +/obj/structure/window/shuttle/survival_pod + name = "pod window" + icon = 'icons/obj/smooth_structures/pod_window.dmi' + icon_state = "smooth" + dir = FULLTILE_WINDOW_DIR + max_integrity = 100 + fulltile = TRUE + reinf = TRUE + heat_resistance = 1600 + armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100) + smooth = SMOOTH_MORE + canSmoothWith = list(/turf/simulated/wall/mineral/titanium/survival, /obj/machinery/door/airlock/survival_pod, /obj/structure/window/shuttle/survival_pod) + explosion_block = 3 + level = 3 + glass_type = /obj/item/stack/sheet/titaniumglass + glass_amount = 2 + /obj/structure/window/reinforced/survival_pod name = "pod window" icon = 'icons/obj/lavaland/survival_pod.dmi' icon_state = "pwindow" -// This override can be removed whenever we get rid of the stupid fucking `dir = 9` = full tile!!!! shit -/obj/structure/window/reinforced/survival_pod/CanPass(atom/movable/mover, turf/target, height=0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) - return !density - else - return 1 - //Floors /turf/simulated/floor/pod name = "pod floor" @@ -515,7 +523,7 @@ icon_state = "fan_tiny" buildstackamount = 2 -/obj/structure/fans/New(loc) +/obj/structure/fans/Initialize(loc) ..() air_update_turf(1) diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index 711d4cea992..57be913c699 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -70,7 +70,7 @@ if(speaker == src) to_chat(src, "You cannot hear yourself speak!") else - to_chat(src, "[speaker_name][alt_name] talks but you cannot hear them.") + to_chat(src, "[speaker_name][alt_name] talks but you cannot hear [speaker.p_them()].") else if(language) to_chat(src, "[speaker_name][alt_name] [track][language.format_message(message, verb)]") diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index dc2e8ee7106..1a6f29a6dd0 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -226,7 +226,14 @@ "SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA") /datum/language/vox/get_random_name() - return ..(FEMALE,1,6) + var/sounds = rand(2, 8) + var/i = 0 + var/newname = "" + + while(i <= sounds) + i++ + newname += pick(vox_name_syllables) + return capitalize(newname) /datum/language/diona name = "Rootspeak" @@ -240,8 +247,8 @@ syllables = list("hs","zt","kr","st","sh") /datum/language/diona/get_random_name() - var/new_name = "[pick(list("To Sleep Beneath","Wind Over","Embrace of","Dreams of","Witnessing","To Walk Beneath","Approaching the"))]" - new_name += " [pick(list("the Void","the Sky","Encroaching Night","Planetsong","Starsong","the Wandering Star","the Empty Day","Daybreak","Nightfall","the Rain"))]" + var/new_name = "[pick(list("To Sleep Beneath", "Wind Over", "Embrace of", "Dreams of", "Witnessing", "To Walk Beneath", "Approaching the", "Glimmer of", "The Ripple of", "Colors of", "The Still of", "Silence of", "Gentle Breeze of", "Glistening Waters under", "Child of", "Blessed Plant-ling of", "Grass-Walker of", "Element of", "Spawn of"))]" + new_name += " [pick(list("the Void", "the Sky", "Encroaching Night", "Planetsong", "Starsong", "the Wandering Star", "the Empty Day", "Daybreak", "Nightfall", "the Rain", "the Stars", "the Waves", "Dusk", "Night", "the Wind", "the Summer Wind", "the Blazing Sun", "the Scorching Sun", "Eternal Fields", "the Soothing Plains", "the Undying Fiona", "Mother Nature's Bousum"))]" return new_name /datum/language/trinary @@ -310,12 +317,7 @@ to_chat(speaker,"You can't communicate while unable to move your hands to your head!") return FALSE - var/their = "their" - if(speaker.gender == "female") - their = "her" - if(speaker.gender == "male") - their = "his" - speaker.visible_message("[speaker] touches [their] fingers to [their] temple.") //If placed in grey/broadcast, it will happen regardless of the success of the action. + speaker.visible_message("[speaker] touches [speaker.p_their()] fingers to [speaker.p_their()] temple.") //If placed in grey/broadcast, it will happen regardless of the success of the action. return TRUE @@ -512,8 +514,10 @@ ..(speaker,message,speaker.real_name) /datum/language/abductor/check_special_condition(mob/living/carbon/human/other, mob/living/carbon/human/speaker) - if(other.mind && other.mind.abductor) - if(other.mind.abductor.team == speaker.mind.abductor.team) + if(isabductor(other) && isabductor(speaker)) + var/datum/species/abductor/A = speaker.dna.species + var/datum/species/abductor/A2 = other.dna.species + if(A.team == A2.team) return TRUE return FALSE @@ -558,7 +562,7 @@ if(!message) return - + log_say("(ROBOT) [message]", speaker) var/message_start = "[name], [speaker.name]" var/message_body = "[speaker.say_quote(message)],\"[message]\"
    " diff --git a/code/modules/mob/living/autohiss.dm b/code/modules/mob/living/autohiss.dm index da19b6a35b2..df1bde34306 100644 --- a/code/modules/mob/living/autohiss.dm +++ b/code/modules/mob/living/autohiss.dm @@ -4,7 +4,7 @@ /mob/living/carbon/human/handle_autohiss(message, datum/language/L) if(!client || client.prefs.autohiss_mode == AUTOHISS_OFF) // no need to process if there's no client or they have autohiss off return message - return species.handle_autohiss(message, L, client.prefs.autohiss_mode) + return dna.species.handle_autohiss(message, L, client.prefs.autohiss_mode) /client/verb/toggle_autohiss() set name = "Toggle Auto-Accent" diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index e706b89ca85..8f74fbce413 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -1,7 +1,3 @@ -#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point -#define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point -#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point - /mob/living/carbon/alien name = "alien" voice_name = "alien" @@ -229,10 +225,6 @@ Des: Removes all infected images from the alien. /mob/living/carbon/alien/can_use_vents() return -#undef HEAT_DAMAGE_LEVEL_1 -#undef HEAT_DAMAGE_LEVEL_2 -#undef HEAT_DAMAGE_LEVEL_3 - /mob/living/carbon/alien/handle_footstep(turf/T) if(..()) if(T.footstep_sounds["xeno"]) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 22954451834..72bf30ceedf 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -29,13 +29,13 @@ In all, this is a lot like the monkey code. /N else if(health > 0) - M.do_attack_animation(src) + M.do_attack_animation(src, ATTACK_EFFECT_BITE) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) var/damage = 1 visible_message("[M.name] bites [src]!", \ "[M.name] bites [src]!") adjustBruteLoss(damage) - add_attack_logs(M, src, "Alien attack", FALSE) + add_attack_logs(M, src, "Alien attack", ATKLOG_ALL) updatehealth() else to_chat(M, "[name] is too injured for that.") @@ -52,8 +52,10 @@ In all, this is a lot like the monkey code. /N help_shake_act(M) if(INTENT_GRAB) grabbedby(M) - if(INTENT_HARM, INTENT_DISARM) - M.do_attack_animation(src) + if(INTENT_HARM) + M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) + if(INTENT_DISARM) + M.do_attack_animation(src, ATTACK_EFFECT_DISARM) return 1 return 0 diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index a2527317eec..7f23be77774 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -161,7 +161,7 @@ Doesn't work on other aliens/AI.*/ stomach_contents.Remove(M) M.loc = loc //Paralyse(10) - src.visible_message("[src] hurls out the contents of their stomach!") + src.visible_message("[src] hurls out the contents of [p_their()] stomach!") return /mob/living/carbon/proc/getPlasma() diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm index 0056bb709a5..3fa08702605 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -1,16 +1,25 @@ +/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + ..(user, TRUE) + adjustBruteLoss(15) + var/hitverb = "punched" + if(mob_size < MOB_SIZE_LARGE) + Paralyse(1) + spawn(0) + step_away(src, user, 15) + sleep(1) + step_away(src, user, 15) + hitverb = "slammed" + playsound(loc, "punch", 25, 1, -1) + visible_message("[user] has [hitverb] [src]!", "[user] has [hitverb] [src]!") + return TRUE + /mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M) if(..()) switch(M.a_intent) if(INTENT_HARM) var/damage = rand(1, 9) if(prob(90)) - if(HULK in M.mutations)//HULK SMASH - damage = 15 - spawn(0) - Paralyse(1) - step_away(src, M, 15) - sleep(3) - step_away(src, M, 15) playsound(loc, "punch", 25, 1, -1) visible_message("[M] has punched [src]!", \ "[M] has punched [src]!") @@ -43,3 +52,8 @@ else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) visible_message("[M] has attempted to disarm [src]!") + +/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y) + if(!no_effect && !visual_effect_icon) + visual_effect_icon = ATTACK_EFFECT_CLAW + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm index f1bcfc0eeaf..44287493718 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -3,7 +3,7 @@ #define X_SUIT_LAYER 2 #define X_L_HAND_LAYER 3 #define X_R_HAND_LAYER 4 -#define TARGETED_LAYER 5 +#define X_TARGETED_LAYER 5 #define X_FIRE_LAYER 6 #define X_TOTAL_LAYERS 6 ///////////////////////////////// @@ -161,6 +161,6 @@ #undef X_SUIT_LAYER #undef X_L_HAND_LAYER #undef X_R_HAND_LAYER -#undef TARGETED_LAYER +#undef X_TARGETED_LAYER #undef X_FIRE_LAYER #undef X_TOTAL_LAYERS diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm index fc7fa22510b..919eecee8d8 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm @@ -2,13 +2,6 @@ if(..()) var/damage = rand(1, 9) if(prob(90)) - if(HULK in M.mutations) - damage += 5 - spawn(0) - Paralyse(1) - step_away(src, M, 15) - sleep(3) - step_away(src, M, 15) playsound(loc, "punch", 25, 1, -1) add_attack_logs(M, src, "Melee attacked with fists") visible_message("[M] has kicked [src]!", \ @@ -22,3 +15,20 @@ playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) visible_message("[M] has attempted to kick [src]!", \ "[M] has attempted to kick [src]!") + + +/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + ..(user, TRUE) + adjustBruteLoss(5 + rand(1, 9)) + spawn(0) + Paralyse(1) + step_away(src, user, 15) + sleep(3) + step_away(src, user, 15) + return TRUE + +/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y) + if(!no_effect && !visual_effect_icon) + visual_effect_icon = ATTACK_EFFECT_BITE + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index ae03f103e86..e09340872b9 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -96,7 +96,7 @@ if(ticker && ticker.mode) ticker.mode.xenos += new_xeno.mind new_xeno.mind.name = new_xeno.name - new_xeno.mind.assigned_role = "MODE" + new_xeno.mind.assigned_role = SPECIAL_ROLE_XENOMORPH new_xeno.mind.special_role = SPECIAL_ROLE_XENOMORPH new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100)//To get the player's attention diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 99d5c795eb5..9d50d8bf2ea 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -16,6 +16,9 @@ var/obj/mecha/mecha = null//This does not appear to be used outside of reference in mecha.dm. // I'm using this for mechs giving MMIs HUDs now + var/obj/item/radio/radio = null // For use with the radio MMI upgrade + var/datum/action/generic/configure_mmi_radio/radio_action = null + /obj/item/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob, params) if(istype(O, /obj/item/organ/internal/brain/crystal )) to_chat(user, " This brain is too malformed to be able to use with the [src].") @@ -29,34 +32,70 @@ to_chat(user, "Somehow, this MMI still has a brain in it. Report this to the bug tracker.") log_runtime(EXCEPTION("[user] tried to stick a [O] into [src] in [get_area(src)], but the held brain variable wasn't cleared"), src) return - for(var/mob/V in viewers(src, null)) - V.show_message("[user] sticks \a [O] into \the [src].") - brainmob = B.brainmob - B.brainmob = null - brainmob.loc = src - brainmob.container = src - brainmob.stat = CONSCIOUS - respawnable_list -= brainmob - dead_mob_list -= brainmob//Update dem lists - living_mob_list += brainmob + if(user.drop_item()) + B.forceMove(src) + visible_message("[user] sticks \a [O] into \the [src].") + brainmob = B.brainmob + B.brainmob = null + brainmob.loc = src + brainmob.container = src + brainmob.stat = CONSCIOUS + respawnable_list -= brainmob + dead_mob_list -= brainmob//Update dem lists + living_mob_list += brainmob - user.drop_item() - B.forceMove(src) - held_brain = B - if(istype(O,/obj/item/organ/internal/brain/xeno)) // kept the type check, as it still does other weird stuff - name = "Man-Machine Interface: Alien - [brainmob.real_name]" - icon = 'icons/mob/alien.dmi' - icon_state = "AlienMMI" - alien = 1 + held_brain = B + if(istype(O,/obj/item/organ/internal/brain/xeno)) // kept the type check, as it still does other weird stuff + name = "Man-Machine Interface: Alien - [brainmob.real_name]" + icon = 'icons/mob/alien.dmi' + become_occupied("AlienMMI") + alien = 1 + else + name = "Man-Machine Interface: [brainmob.real_name]" + icon = B.mmi_icon + become_occupied("[B.mmi_icon_state]") + alien = 0 + + if(radio_action) + radio_action.UpdateButtonIcon() + feedback_inc("cyborg_mmis_filled",1) else - name = "Man-Machine Interface: [brainmob.real_name]" - icon = B.mmi_icon - icon_state = "[B.mmi_icon_state]" - alien = 0 - feedback_inc("cyborg_mmis_filled",1) + to_chat(user, "You can't drop [B]!") return + if(istype(O, /obj/item/mmi_radio_upgrade)) + if(radio) + to_chat(user, "[src] already has a radio installed.") + else + user.visible_message("[user] begins to install the [O] into [src]...", \ + "You start to install the [O] into [src]...") + if(do_after(user, 20, target=src)) + if(user.drop_item()) + user.visible_message("[user] installs [O] in [src].", \ + "You install [O] in [src].") + if(brainmob) + to_chat(brainmob, "MMI radio capability installed.") + install_radio() + qdel(O) + else + to_chat(user, "You can't drop [O]!") + return + + // Maybe later add encryption key support, but that's a pain in the neck atm + if(isscrewdriver(O)) + if(radio) + user.visible_message("[user] begins to uninstall the radio from [src]...", \ + "You start to uninstall the radio from [src]...") + if(do_after(user, 40 * O.toolspeed, target = src)) + uninstall_radio() + new /obj/item/mmi_radio_upgrade(get_turf(src)) + user.visible_message("[user] uninstalls the radio from [src].", \ + "You uninstall the radio from [src].") + else + to_chat(user, "There is no radio in [src]!") + return + if(brainmob) O.attack(brainmob, user)//Oh noooeeeee // Brainmobs can take damage, but they can't actually die. Maybe should fix. @@ -82,10 +121,10 @@ brainmob.dna = H.dna.Clone() brainmob.container = src - if(!istype(H.species) || isnull(H.species.return_organ("brain"))) // Diona/buggy people + if(!istype(H.dna.species) || isnull(H.dna.species.return_organ("brain"))) // Diona/buggy people held_brain = new(src) else // We have a species, and it has a brain - var/brain_path = H.species.return_organ("brain") + var/brain_path = H.dna.species.return_organ("brain") if(!ispath(brain_path, /obj/item/organ/internal/brain)) brain_path = /obj/item/organ/internal/brain held_brain = new brain_path(src) // Slime people will keep their slimy brains this way @@ -93,8 +132,7 @@ held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]" name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_full" - return + become_occupied("mmi_full") //I made this proc as a way to have a brainmob be transferred to any created brain, and to solve the //problem i was having with alien/nonalien brain drops. @@ -116,31 +154,54 @@ held_brain.forceMove(dropspot) held_brain = null +/obj/item/mmi/proc/become_occupied(var/new_icon) + icon_state = new_icon + if(radio) + radio_action.ApplyIcon() -/obj/item/mmi/radio_enabled - name = "Radio-enabled Man-Machine Interface" - desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity. This one comes with a built-in radio." - origin_tech = "biotech=2;programming=3;engineering=2;magnets=2" +/obj/item/mmi/examine(mob/user) + . = ..() + if(radio) + to_chat(user, "A radio is installed on [src].") - var/obj/item/radio/radio = null//Let's give it a radio. +/obj/item/mmi/proc/install_radio() + radio = new(src) + radio.broadcasting = TRUE + radio_action = new(radio, src) + if(brainmob && brainmob.loc == src) + radio_action.Grant(brainmob) -/obj/item/mmi/radio_enabled/New() - ..() - radio = new(src)//Spawns a radio inside the MMI. - radio.broadcasting = 1//So it's broadcasting from the start. +/obj/item/mmi/proc/uninstall_radio() + QDEL_NULL(radio) + QDEL_NULL(radio_action) -/obj/item/mmi/radio_enabled/verb/Toggle_Listening() - set name = "Toggle Listening" - set desc = "Toggle listening channel on or off." - set category = "MMI" - set src = usr.loc - set popup_menu = 0 +/datum/action/generic/configure_mmi_radio + name = "Configure MMI Radio" + desc = "Configure the radio installed in your MMI." + check_flags = AB_CHECK_CONSCIOUS + procname = "ui_interact" + var/obj/item/mmi = null - if(brainmob.stat) - to_chat(brainmob, "Can't do that while incapacitated or dead.") +/datum/action/generic/configure_mmi_radio/New(var/Target, var/obj/item/mmi/M) + . = ..() + mmi = M - radio.listening = radio.listening==1 ? 0 : 1 - to_chat(brainmob, "Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast.") +/datum/action/generic/configure_mmi_radio/Destroy() + mmi = null + return ..() + +/datum/action/generic/configure_mmi_radio/ApplyIcon(obj/screen/movable/action_button/current_button) + // A copy/paste of the item action icon code + current_button.overlays.Cut() + if(target) + var/obj/item/I = mmi + var/old_layer = I.layer + var/old_plane = I.plane + I.layer = 21 + I.plane = HUD_PLANE + current_button.overlays += I + I.layer = old_layer + I.plane = old_plane /obj/item/mmi/emp_act(severity) if(!brainmob) @@ -168,8 +229,22 @@ borg.mmi = null QDEL_NULL(brainmob) QDEL_NULL(held_brain) + QDEL_NULL(radio) + QDEL_NULL(radio_action) return ..() +// These two procs are important for when an MMI pilots a mech +// (Brainmob "enters/leaves" the MMI when piloting) +// Also neatly handles basically every case where a brain +// is inserted or removed from an MMI +/obj/item/mmi/Entered(atom/movable/A) + if(radio && istype(A, /mob/living/carbon/brain)) + radio_action.Grant(A) + +/obj/item/mmi/Exited(atom/movable/A) + if(radio && istype(A, /mob/living/carbon/brain)) + radio_action.Remove(A) + /obj/item/mmi/syndie name = "Syndicate Man-Machine Interface" desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores." @@ -190,10 +265,25 @@ forceMove(holder) holder.stored_mmi = src holder.update_from_mmi() - if(istype(src, /obj/item/mmi/posibrain)) - holder.robotize() if(brainmob && brainmob.mind) brainmob.mind.transfer_to(H) holder.insert(H) return 1 + +// As a synthetic, the only limit on visibility is view range +/obj/item/mmi/contents_nano_distance(var/src_object, var/mob/living/user) + if((src_object in view(src)) && get_dist(src_object, src) <= user.client.view) + return STATUS_INTERACTIVE // interactive (green visibility) + return user.shared_living_nano_distance(src_object) + +// For now the only thing that is helped by this is radio access +// Later a more intricate system for MMI UI interaction can be established +/obj/item/mmi/contents_nano_interact(var/src_object, var/mob/living/user) + if(!istype(user, /mob/living/carbon/brain)) + log_runtime(EXCEPTION("Somehow a non-brain mob is inside an MMI!"), user) + return ..() + var/mob/living/carbon/brain/BM = user + if(BM.container == src && src_object == radio) + return STATUS_INTERACTIVE + return ..() diff --git a/code/modules/mob/living/carbon/brain/MMI_radio.dm b/code/modules/mob/living/carbon/brain/MMI_radio.dm new file mode 100644 index 00000000000..6eeaa44a42c --- /dev/null +++ b/code/modules/mob/living/carbon/brain/MMI_radio.dm @@ -0,0 +1,5 @@ +/obj/item/mmi_radio_upgrade + name = "MMI radio upgrade" + desc = "Enables radio capability on MMIs when either installed directly on the MMI, or through a cyborg's chassis." + icon = 'icons/obj/module.dmi' + icon_state = "cyborg_upgrade1" diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm index 82e062246b6..c64318d804b 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/carbon/brain/brain.dm @@ -84,12 +84,12 @@ I'm using this for Stat to give it a more nifty interface to work with if(container) var/obj/item/mmi/M = container if(istype(M) && M.held_brain) - return M.held_brain.dna.get_species_name() + return M.held_brain.dna.species.name else return "Artificial Life" if(istype(loc, /obj/item/organ/internal/brain)) var/obj/item/organ/internal/brain/B = loc - return B.dna.get_species_name() + return B.dna.species.name /mob/living/carbon/brain/Stat() ..() diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 2abc612f758..0a8f6fb3b83 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -14,7 +14,8 @@ organ_tag = "brain" parent_organ = "head" slot = "brain" - vital = 1 + vital = TRUE + hidden_pain = TRUE //the brain has no pain receptors, and brain damage is meant to be a stealthy damage type. var/mmi_icon = 'icons/obj/assemblies.dmi' var/mmi_icon_state = "mmi_full" diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm deleted file mode 100644 index f5e575dccaf..00000000000 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ /dev/null @@ -1,205 +0,0 @@ -/obj/item/mmi/posibrain - name = "positronic brain" - desc = "A cube of shining metal, four inches to a side and covered in shallow grooves." - icon = 'icons/obj/assemblies.dmi' - icon_state = "posibrain" - w_class = WEIGHT_CLASS_NORMAL - origin_tech = "biotech=3;programming=3;plasmatech=2" - - var/searching = 0 - var/askDelay = 10 * 60 * 1 - //var/mob/living/carbon/brain/brainmob = null - var/list/ghost_volunteers[0] - req_access = list(access_robotics) - mecha = null//This does not appear to be used outside of reference in mecha.dm. - var/silenced = 0 //if set to 1, they can't talk. - var/next_ping_at = 0 - -/obj/item/mmi/posibrain/examine(mob/user) - if(..(user, 1)) - to_chat(user, "Its speaker is turned [silenced ? "off" : "on"].") - -/obj/item/mmi/posibrain/attack_self(mob/user) - if(brainmob && !brainmob.key && searching == 0) - //Start the process of searching for a new user. - to_chat(user, "You carefully locate the manual activation switch and start the positronic brain's boot process.") - icon_state = "posibrain-searching" - ghost_volunteers.Cut() - searching = 1 - request_player() - spawn(600) - if(ghost_volunteers.len) - var/mob/dead/observer/O - while(!istype(O) && ghost_volunteers.len) - O = pick_n_take(ghost_volunteers) - if(istype(O) && check_observer(O)) - transfer_personality(O) - reset_search() - else - silenced = !silenced - to_chat(user, "You toggle the speaker [silenced ? "off" : "on"].") - if(brainmob && brainmob.key) - to_chat(brainmob, "Your internal speaker has been toggled [silenced ? "off" : "on"].") - -/obj/item/mmi/posibrain/proc/request_player() - for(var/mob/dead/observer/O in player_list) - if(check_observer(O)) - to_chat(O, "\A [src] has been activated. (Teleport | Sign Up)") - -/obj/item/mmi/posibrain/proc/check_observer(var/mob/dead/observer/O) - if(cannotPossess(O)) - return 0 - if(jobban_isbanned(O, "Cyborg") || jobban_isbanned(O,"nonhumandept")) - return 0 - if(!O.can_reenter_corpse) - return 0 - if(O.client) - return 1 - return 0 - -/obj/item/mmi/posibrain/proc/question(var/client/C) - spawn(0) - if(!C) return - var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round") - if(!C || brainmob.key || 0 == searching) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located. - if(response == "Yes") - transfer_personality(C.mob) - else if(response == "Never for this round") - C.prefs.be_special -= ROLE_POSIBRAIN - -// This should not ever happen, but let's be safe -/obj/item/mmi/posibrain/dropbrain(var/turf/dropspot) - log_runtime(EXCEPTION("[src] at [loc] attempted to drop brain without a contained brain."), src) - return - -/obj/item/mmi/posibrain/transfer_identity(var/mob/living/carbon/H) - name = "positronic brain ([H])" - if(isnull(brainmob.dna)) - brainmob.dna = H.dna.Clone() - brainmob.name = brainmob.dna.real_name - brainmob.real_name = brainmob.name - brainmob.timeofhostdeath = H.timeofdeath - brainmob.stat = CONSCIOUS - if(brainmob.mind) - brainmob.mind.assigned_role = "Positronic Brain" - if(H.mind) - H.mind.transfer_to(brainmob) - to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a metal cube.") - icon_state = "posibrain-occupied" - return - -/obj/item/mmi/posibrain/proc/transfer_personality(var/mob/candidate) - src.searching = 0 - src.brainmob.key = candidate.key - src.name = "positronic brain ([src.brainmob.name])" - - to_chat(src.brainmob, "You are a positronic brain, brought into existence on [station_name()].") - to_chat(src.brainmob, "As a synthetic intelligence, you answer to all crewmembers, as well as the AI.") - to_chat(src.brainmob, "Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.") - src.brainmob.mind.assigned_role = "Positronic Brain" - - var/turf/T = get_turf_or_move(src.loc) - for(var/mob/M in viewers(T)) - M.show_message("The positronic brain chimes quietly.") - icon_state = "posibrain-occupied" - -/obj/item/mmi/posibrain/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer. - if(src.brainmob && src.brainmob.key) return - - src.searching = 0 - icon_state = "posibrain" - - var/turf/T = get_turf_or_move(src.loc) - for(var/mob/M in viewers(T)) - M.show_message("The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?") - -/obj/item/mmi/posibrain/Topic(href,href_list) - if("signup" in href_list) - var/mob/dead/observer/O = locate(href_list["signup"]) - if(!O) return - volunteer(O) - -/obj/item/mmi/posibrain/proc/volunteer(var/mob/dead/observer/O) - if(!searching) - to_chat(O, "Not looking for a ghost, yet.") - return - if(!istype(O)) - to_chat(O, "Error.") - return - if(O in ghost_volunteers) - to_chat(O, "Removed from registration list.") - ghost_volunteers.Remove(O) - return - if(!check_observer(O)) - to_chat(O, "You cannot be \a [src].") - return - if(cannotPossess(O)) - to_chat(O, "Upon using the antagHUD you forfeited the ability to join the round.") - return - if(jobban_isbanned(O, "Cyborg") || jobban_isbanned(O,"nonhumandept")) - to_chat(O, "You are job banned from this role.") - return - to_chat(O., "You've been added to the list of ghosts that may become this [src]. Click again to unvolunteer.") - ghost_volunteers.Add(O) - - -/obj/item/mmi/posibrain/examine(mob/user) - to_chat(user, "*---------*") - if(!..(user)) - to_chat(user, "*---------*") - return - - var/msg = "" - - if(src.brainmob && src.brainmob.key) - switch(src.brainmob.stat) - if(CONSCIOUS) - if(!src.brainmob.client) msg += "It appears to be in stand-by mode.\n" //afk - if(UNCONSCIOUS) msg += "It doesn't seem to be responsive.\n" - if(DEAD) msg += "It appears to be completely inactive.\n" - else - msg += "It appears to be completely inactive.\n" - msg += "*---------*" - to_chat(user, msg) - -/obj/item/mmi/posibrain/emp_act(severity) - if(!src.brainmob) - return - else - switch(severity) - if(1) - src.brainmob.emp_damage += rand(20,30) - if(2) - src.brainmob.emp_damage += rand(10,20) - if(3) - src.brainmob.emp_damage += rand(0,10) - ..() - -/obj/item/mmi/posibrain/New() - src.brainmob = new(src) - src.brainmob.name = "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]" - src.brainmob.real_name = src.brainmob.name - src.brainmob.loc = src - src.brainmob.container = src - src.brainmob.stat = 0 - src.brainmob.SetSilence(0) - dead_mob_list -= src.brainmob - - ..() - -/obj/item/mmi/posibrain/attack_ghost(var/mob/dead/observer/O) - if(searching) - volunteer(O) - return - if(brainmob && brainmob.key) - return // No point pinging a posibrain with a player already inside - if(check_observer(O) && (world.time >= next_ping_at)) - next_ping_at = world.time + (20 SECONDS) - playsound(get_turf(src), 'sound/items/posiping.ogg', 80, 0) - var/turf/T = get_turf_or_move(src.loc) - for(var/mob/M in viewers(T)) - M.show_message("The positronic brain pings softly.") - -/obj/item/mmi/posibrain/ipc - desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. The speaker switch is set to 'off'." - silenced = 1 diff --git a/code/modules/mob/living/carbon/brain/robotic_brain.dm b/code/modules/mob/living/carbon/brain/robotic_brain.dm new file mode 100644 index 00000000000..ea83ab90206 --- /dev/null +++ b/code/modules/mob/living/carbon/brain/robotic_brain.dm @@ -0,0 +1,231 @@ +/obj/item/mmi/robotic_brain + name = "robotic brain" + desc = "An advanced circuit, capable of housing a non-sentient synthetic intelligence." + icon = 'icons/obj/module.dmi' + icon_state = "boris_blank" + var/blank_icon = "boris_blank" + var/searching_icon = "boris_recharging" + var/occupied_icon = "boris" + w_class = WEIGHT_CLASS_NORMAL + origin_tech = "biotech=3;programming=3;plasmatech=2" + + var/searching = FALSE + var/askDelay = 10 * 60 * 1 + //var/mob/living/carbon/brain/brainmob = null + var/list/ghost_volunteers[0] + req_access = list(access_robotics) + mecha = null//This does not appear to be used outside of reference in mecha.dm. + var/silenced = FALSE //if TRUE, they can't talk. + var/next_ping_at = 0 + var/requires_master = TRUE + var/mob/living/carbon/human/imprinted_master = null + var/ejected_flavor_text = "circuit" + +/obj/item/mmi/robotic_brain/Destroy() + imprinted_master = null + return ..() + +/obj/item/mmi/robotic_brain/attack_self(mob/user) + if(requires_master && !imprinted_master) + to_chat(user, "You press your thumb on [src] and imprint your user information.") + imprinted_master = user + return + if(brainmob && !brainmob.key && !searching) + //Start the process of searching for a new user. + to_chat(user, "You carefully locate the manual activation switch and start [src]'s boot process.") + icon_state = searching_icon + ghost_volunteers.Cut() + searching = TRUE + request_player() + spawn(600) + if(ghost_volunteers.len) + var/mob/dead/observer/O + while(!istype(O) && ghost_volunteers.len) + O = pick_n_take(ghost_volunteers) + if(istype(O) && check_observer(O)) + transfer_personality(O) + reset_search() + else + silenced = !silenced + to_chat(user, "You toggle the speaker [silenced ? "off" : "on"].") + if(brainmob && brainmob.key) + to_chat(brainmob, "Your internal speaker has been toggled [silenced ? "off" : "on"].") + +/obj/item/mmi/robotic_brain/proc/request_player() + for(var/mob/dead/observer/O in player_list) + if(check_observer(O)) + to_chat(O, "\A [src] has been activated. (Teleport | Sign Up)") + +/obj/item/mmi/robotic_brain/proc/check_observer(mob/dead/observer/O) + if(cannotPossess(O)) + return FALSE + if(jobban_isbanned(O, "Cyborg") || jobban_isbanned(O,"nonhumandept")) + return FALSE + if(!O.can_reenter_corpse) + return FALSE + if(O.client) + return TRUE + return FALSE + +/obj/item/mmi/robotic_brain/proc/question(client/C) + spawn(0) + if(!C) + return + var/response = alert(C, "Someone is requesting a personality for a [src]. Would you like to play as one?", "[src] request", "Yes", "No", "Never for this round") + if(!C || brainmob.key || !searching) + return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located. + if(response == "Yes") + transfer_personality(C.mob) + else if(response == "Never for this round") + C.prefs.be_special -= ROLE_POSIBRAIN + +// This should not ever happen, but let's be safe +/obj/item/mmi/robotic_brain/dropbrain(turf/dropspot) + log_runtime(EXCEPTION("[src] at [loc] attempted to drop brain without a contained brain."), src) + +/obj/item/mmi/robotic_brain/transfer_identity(mob/living/carbon/H) + name = "[src] ([H])" + if(isnull(brainmob.dna)) + brainmob.dna = H.dna.Clone() + brainmob.name = brainmob.dna.real_name + brainmob.real_name = brainmob.name + brainmob.timeofhostdeath = H.timeofdeath + brainmob.stat = CONSCIOUS + if(brainmob.mind) + brainmob.mind.assigned_role = "Positronic Brain" + if(H.mind) + H.mind.transfer_to(brainmob) + to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a [ejected_flavor_text].") + become_occupied(occupied_icon) + if(radio) + radio_action.ApplyIcon() + +/obj/item/mmi/robotic_brain/attempt_become_organ(obj/item/organ/external/parent, mob/living/carbon/human/H) + if(..()) + if(imprinted_master) + to_chat(H, "You are permanently imprinted to [imprinted_master], obey [imprinted_master]'s every order and assist [imprinted_master.p_them()] in completing [imprinted_master.p_their()] goals at any cost.") + + +/obj/item/mmi/robotic_brain/proc/transfer_personality(mob/candidate) + searching = FALSE + brainmob.key = candidate.key + name = "[src] ([brainmob.name])" + + to_chat(brainmob, "You are a [src], brought into existence on [station_name()].") + to_chat(brainmob, "As a non-sentient synthetic intelligence, you answer to [imprinted_master], unless otherwise placed inside of a lawed synthetic structure or mech.") + to_chat(brainmob, "Remember, the purpose of your existence is to serve [imprinted_master]'s every word, unless lawed or placed into a mech in the future.") + brainmob.mind.assigned_role = "Positronic Brain" + + visible_message("[src] chimes quietly.") + become_occupied(occupied_icon) + + +/obj/item/mmi/robotic_brain/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer. + if(brainmob && brainmob.key) + return + + searching = FALSE + icon_state = blank_icon + + visible_message("[src] buzzes quietly as the light fades out. Perhaps you could try again?") + +/obj/item/mmi/robotic_brain/Topic(href, href_list) + if("signup" in href_list) + var/mob/dead/observer/O = locate(href_list["signup"]) + if(!O) + return + volunteer(O) + +/obj/item/mmi/robotic_brain/proc/volunteer(mob/dead/observer/O) + if(!searching) + to_chat(O, "Not looking for a ghost, yet.") + return + if(!istype(O)) + to_chat(O, "Error.") + return + if(O in ghost_volunteers) + to_chat(O, "Removed from registration list.") + ghost_volunteers.Remove(O) + return + if(!check_observer(O)) + to_chat(O, "You cannot be \a [src].") + return + if(cannotPossess(O)) + to_chat(O, "Upon using the antagHUD you forfeited the ability to join the round.") + return + if(jobban_isbanned(O, "Cyborg") || jobban_isbanned(O,"nonhumandept")) + to_chat(O, "You are job banned from this role.") + return + to_chat(O., "You've been added to the list of ghosts that may become this [src]. Click again to unvolunteer.") + ghost_volunteers.Add(O) + + +/obj/item/mmi/robotic_brain/examine(mob/user) + to_chat(user, "Its speaker is turned [silenced ? "off" : "on"].") + to_chat(user, "*---------*") + . = ..() + if(!.) + to_chat(user, "*---------*") + return + + var/list/msg = list("") + + if(brainmob && brainmob.key) + switch(brainmob.stat) + if(CONSCIOUS) + if(!brainmob.client) + msg += "It appears to be in stand-by mode.\n" //afk + if(UNCONSCIOUS) + msg += "It doesn't seem to be responsive.\n" + if(DEAD) + msg += "It appears to be completely inactive.\n" + else + msg += "It appears to be completely inactive.\n" + msg += "*---------*" + to_chat(user, msg.Join("")) + +/obj/item/mmi/robotic_brain/emp_act(severity) + if(!brainmob) + return + switch(severity) + if(1) + brainmob.emp_damage += rand(20, 30) + if(2) + brainmob.emp_damage += rand(10, 20) + if(3) + brainmob.emp_damage += rand(0, 10) + ..() + +/obj/item/mmi/robotic_brain/New() + brainmob = new(src) + brainmob.name = "[pick(list("PBU", "HIU", "SINA", "ARMA", "OSI"))]-[rand(100, 999)]" + brainmob.real_name = brainmob.name + brainmob.forceMove(src) + brainmob.container = src + brainmob.stat = CONSCIOUS + brainmob.SetSilence(0) + dead_mob_list -= brainmob + ..() + +/obj/item/mmi/robotic_brain/attack_ghost(mob/dead/observer/O) + if(searching) + volunteer(O) + return + if(brainmob && brainmob.key) + return // No point pinging a posibrain with a player already inside + if(check_observer(O) && (world.time >= next_ping_at)) + next_ping_at = world.time + (20 SECONDS) + playsound(get_turf(src), 'sound/items/posiping.ogg', 80, 0) + visible_message("[src] pings softly.") + +/obj/item/mmi/robotic_brain/positronic + name = "positronic brain" + icon = 'icons/obj/assemblies.dmi' + icon_state = "posibrain" + blank_icon = "posibrain" + searching_icon = "posibrain-searching" + occupied_icon = "posibrain-occupied" + desc = "A cube of shining metal, four inches to a side and covered in shallow grooves." + silenced = TRUE + requires_master = FALSE + ejected_flavor_text = "metal cube" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm index e8e2dd00c45..907a2e4862d 100644 --- a/code/modules/mob/living/carbon/brain/say.dm +++ b/code/modules/mob/living/carbon/brain/say.dm @@ -2,7 +2,7 @@ /mob/living/carbon/brain/say(var/message, var/datum/language/speaking = null) if(!can_speak(warning = TRUE)) return - + if(prob(emp_damage * 4)) if(prob(10)) //10% chance to drop the message entirely return @@ -10,21 +10,21 @@ message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher ..(message) - + /mob/living/carbon/brain/whisper(message as text) if(!can_speak(warning = TRUE)) return ..() - + /mob/living/carbon/brain/can_speak(var/warning = FALSE) . = ..() if(!istype(container, /obj/item/mmi)) . = FALSE - else if(istype(container, /obj/item/mmi/posibrain)) - var/obj/item/mmi/posibrain/P = container - if(P && P.silenced) + else if(istype(container, /obj/item/mmi/robotic_brain)) + var/obj/item/mmi/robotic_brain/R = container + if(R && R.silenced) if(warning) to_chat(usr, "You cannot speak, as your internal speaker is turned off.") . = FALSE @@ -41,12 +41,10 @@ if(metalgear.radio) radio_worked = metalgear.radio.talk_into(src, message, message_mode, verb, speaking) - else if(!radio_worked && istype(c, /obj/item/mmi/radio_enabled)) - var/obj/item/mmi/radio_enabled/R = c - if(R.radio) - radio_worked = R.radio.talk_into(src, message, message_mode, verb, speaking) + else if(!radio_worked && c.radio) + radio_worked = c.radio.talk_into(src, message, message_mode, verb, speaking) return radio_worked if("whisper") whisper_say(message, speaking, alt_name) return 1 - else return 0 \ No newline at end of file + else return 0 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index a1e4b555412..4b00bf832c8 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -201,7 +201,7 @@ swap_hand() /mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) - add_attack_logs(M, src, "Shaked", admin_notify = FALSE) + add_attack_logs(M, src, "Shaked", ATKLOG_ALL) if(health >= config.health_threshold_crit) if(src == M && ishuman(src)) var/mob/living/carbon/human/H = src @@ -256,14 +256,9 @@ H.play_xylophone() else if(player_logged) - M.visible_message("[M] shakes [src], but they do not respond. Probably suffering from SSD.", \ - "You shake [src], but they are unresponsive. Probably suffering from SSD.") + M.visible_message("[M] shakes [src], but [p_they()] [p_do()] not respond. Probably suffering from SSD.", \ + "You shake [src], but [p_theyre()] unresponsive. Probably suffering from SSD.") if(lying) // /vg/: For hugs. This is how update_icon figgers it out, anyway. - N3X15 - var/t_him = "it" - if(gender == MALE) - t_him = "him" - else if(gender == FEMALE) - t_him = "her" if(ishuman(src)) var/mob/living/carbon/human/H = src if(H.w_uniform) @@ -277,8 +272,8 @@ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) if(!player_logged) M.visible_message( \ - "[M] shakes [src] trying to wake [t_him] up!",\ - "You shake [src] trying to wake [t_him] up!",\ + "[M] shakes [src] trying to wake [p_them()] up!",\ + "You shake [src] trying to wake [p_them()] up!",\ ) // BEGIN HUGCODE - N3X else @@ -347,7 +342,7 @@ AdjustEyeBlurry(damage * rand(3, 6)) if(E.damage > (E.min_bruised_damage + E.min_broken_damage) / 2) - if(!(E.status & ORGAN_ROBOT)) + if(!E.is_robotic()) to_chat(src, "Your eyes start to burn badly!") else //snowflake conditions piss me off for the record to_chat(src, "The flash blinds you!") @@ -387,7 +382,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, if(!ventcrawler) if(ishuman(src)) var/mob/living/carbon/human/H = src - ventcrawlerlocal = H.species.ventcrawler + ventcrawlerlocal = H.dna.species.ventcrawler if(!ventcrawlerlocal) return @@ -745,7 +740,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, if(restrained()) changeNext_move(CLICK_CD_BREAKOUT) last_special = world.time + CLICK_CD_BREAKOUT - visible_message("[src] attempts to unbuckle themself!", \ + visible_message("[src] attempts to unbuckle [p_them()]self!", \ "You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)") if(do_after(src, 600, 0, target = src)) if(!buckled) @@ -762,11 +757,11 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, Weaken(3, 1, 1) //We dont check for CANWEAKEN, I don't care how immune to weakening you are, if you're rolling on the ground, you're busy. update_canmove() spin(32,2) - visible_message("[src] rolls on the floor, trying to put themselves out!", \ + visible_message("[src] rolls on the floor, trying to put [p_them()]self out!", \ "You stop, drop, and roll!") sleep(30) if(fire_stacks <= 0) - visible_message("[src] has successfully extinguished themselves!", \ + visible_message("[src] has successfully extinguished [p_them()]self!", \ "You extinguish yourself.") ExtinguishMob() @@ -1020,7 +1015,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, return 1 /mob/living/carbon/proc/forceFedAttackLog(var/obj/item/reagent_containers/food/toEat, mob/user) - add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagentlist(toEat)]") + add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagentlist(toEat)]", ATKLOG_FEW) if(!iscarbon(user)) LAssailant = null else diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 80b871e7996..d19051692ca 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -3,20 +3,9 @@ AC.flags = flags AC.ui_interact(user, state = state) -/mob/living/carbon/human/proc/change_species(var/new_species) - if(!new_species || species == new_species || !(new_species in all_species)) - return - - set_species(new_species, null, 1) - reset_hair() - if(species.bodyflags & HAS_MARKINGS) - reset_markings() - - return 1 - /mob/living/carbon/human/proc/change_gender(var/new_gender, var/update_dna = 1) var/obj/item/organ/external/head/H = bodyparts_by_name["head"] - if(gender == new_gender || (gender == PLURAL && species.has_gender)) + if(gender == new_gender || (gender == PLURAL && dna.species.has_gender)) return gender = new_gender @@ -129,7 +118,7 @@ /mob/living/carbon/human/proc/change_alt_head(var/alternate_head) var/obj/item/organ/external/head/H = get_organ("head") - if(!H || H.alt_head == alternate_head || (H.status & ORGAN_ROBOT) || (!(species.bodyflags & HAS_ALT_HEADS) && alternate_head != "None") || !(alternate_head in alt_heads_list)) + if(!H || H.alt_head == alternate_head || H.is_robotic() || (!(dna.species.bodyflags & HAS_ALT_HEADS) && alternate_head != "None") || !(alternate_head in alt_heads_list)) return H.alt_head = alternate_head @@ -296,7 +285,7 @@ /mob/living/carbon/human/proc/change_skin_color(var/colour = "#000000") - if(colour == skin_colour || !(species.bodyflags & HAS_SKIN_COLOR)) + if(colour == skin_colour || !(dna.species.bodyflags & HAS_SKIN_COLOR)) return skin_colour = colour @@ -306,7 +295,7 @@ return 1 /mob/living/carbon/human/proc/change_skin_tone(var/tone) - if(s_tone == tone || !((species.bodyflags & HAS_SKIN_TONE) || (species.bodyflags & HAS_ICON_SKIN_TONE))) + if(s_tone == tone || !((dna.species.bodyflags & HAS_SKIN_TONE) || (dna.species.bodyflags & HAS_ICON_SKIN_TONE))) return s_tone = tone @@ -321,8 +310,8 @@ /mob/living/carbon/human/proc/generate_valid_species(var/check_whitelist = 1, var/list/whitelist = list(), var/list/blacklist = list()) var/list/valid_species = new() - for(var/current_species_name in all_species) - var/datum/species/current_species = all_species[current_species_name] + for(var/current_species_name in GLOB.all_species) + var/datum/species/current_species = GLOB.all_species[current_species_name] if(check_whitelist && config.usealienwhitelist && !check_rights(R_ADMIN, 0, src)) //If we're using the whitelist, make sure to check it! if(whitelist.len && !(current_species_name in whitelist)) @@ -350,16 +339,16 @@ continue if((H.gender == MALE && S.gender == FEMALE) || (H.gender == FEMALE && S.gender == MALE)) continue - if(H.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... + if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = all_robolimbs[H.model] - if((H.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. + if((H.dna.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. else if(!robohead.is_monitor && ("Human" in S.species_allowed)) /*If the hairstyle is not native to the user's species and they're using a head with an ipc-style screen, don't let them access it. But if the user has a robotic humanoid head and the hairstyle can fit humans, let them use it as a wig. */ valid_hairstyles += hairstyle else //If the user is not a species who can have robotic heads, use the default handling. - if(H.species.name in S.species_allowed) //If the user's head is of a species the hairstyle allows, add it to the list. + if(H.dna.species.name in S.species_allowed) //If the user's head is of a species the hairstyle allows, add it to the list. valid_hairstyles += hairstyle return valid_hairstyles @@ -378,17 +367,17 @@ continue if((H.gender == MALE && S.gender == FEMALE) || (H.gender == FEMALE && S.gender == MALE)) continue - if(H.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... + if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = all_robolimbs[H.model] - if(H.species.name in S.species_allowed) //If this is a facial hair style native to the user's species... - if((H.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a facial hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. + if(H.dna.species.name in S.species_allowed) //If this is a facial hair style native to the user's species... + if((H.dna.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a facial hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hairstyles if they do. else if(!robohead.is_monitor && ("Human" in S.species_allowed)) /*If the facial hairstyle is not native to the user's species and they're using a head with an ipc-style screen, don't let them access it. But if the user has a robotic humanoid head and the facial hairstyle can fit humans, let them use it as a wig. */ valid_facial_hairstyles += facialhairstyle else //If the user is not a species who can have robotic heads, use the default handling. - if(H.species.name in S.species_allowed) //If the user's head is of a species the facial hair style allows, add it to the list. + if(H.dna.species.name in S.species_allowed) //If the user's head is of a species the facial hair style allows, add it to the list. valid_facial_hairstyles += facialhairstyle return valid_facial_hairstyles @@ -402,7 +391,7 @@ for(var/head_accessory in head_accessory_styles_list) var/datum/sprite_accessory/S = head_accessory_styles_list[head_accessory] - if(!(H.species.name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. + if(!(H.dna.species.name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. continue valid_head_accessories += head_accessory @@ -421,7 +410,7 @@ continue if(S.marking_location != location) //If the marking isn't for the location we desire, skip. continue - if(!(species.name in S.species_allowed)) //If the user is not of a species the marking style allows, skip it. Otherwise, add it to the list. + if(!(dna.species.name in S.species_allowed)) //If the user is not of a species the marking style allows, skip it. Otherwise, add it to the list. continue if(location == "tail") if(!body_accessory) @@ -432,7 +421,7 @@ continue if(location == "head") var/datum/sprite_accessory/body_markings/head/M = marking_styles_list[S.name] - if(H.species.bodyflags & ALL_RPARTS)//If the user is a species that can have a robotic head... + if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species that can have a robotic head... var/datum/robolimb/robohead = all_robolimbs[H.model] if(!(S.models_allowed && (robohead.company in S.models_allowed))) //Make sure they don't get markings incompatible with their head. continue @@ -456,7 +445,7 @@ if(!istype(A)) valid_body_accessories["None"] = "None" //The only null entry should be the "None" option. continue - if(species.name in A.allowed_species) //If the user is not of a species the body accessory style allows, skip it. Otherwise, add it to the list. + if(dna.species.name in A.allowed_species) //If the user is not of a species the body accessory style allows, skip it. Otherwise, add it to the list. valid_body_accessories += B return valid_body_accessories @@ -469,7 +458,7 @@ valid_alt_heads["None"] = alt_heads_list["None"] //The only null entry should be the "None" option, and there should always be a "None" option. for(var/alternate_head in alt_heads_list) var/datum/sprite_accessory/alt_heads/head = alt_heads_list[alternate_head] - if(!(H.species.name in head.species_allowed)) + if(!(H.dna.species.name in head.species_allowed)) continue valid_alt_heads += alternate_head diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 84b4608b233..bdca496d256 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -62,7 +62,7 @@ animation.master = src flick("dust-h", animation) - new species.remains_type(get_turf(src)) + new dna.species.remains_type(get_turf(src)) spawn(15) if(animation) qdel(animation) @@ -103,8 +103,8 @@ set_heartattack(FALSE) //Handle species-specific deaths. - if(species) - species.handle_death(src) + if(dna.species) + dna.species.handle_death(src) callHook("death", list(src, gibbed)) @@ -139,9 +139,11 @@ /mob/living/carbon/human/proc/makeSkeleton() var/obj/item/organ/external/head/H = get_organ("head") - if(SKELETON in src.mutations) return + if(SKELETON in src.mutations) + return if(istype(H)) + H.disfigured = TRUE if(H.f_style) H.f_style = initial(H.f_style) if(H.h_style) @@ -159,16 +161,17 @@ mutations.Add(SKELETON) mutations.Add(NOCLONE) - status_flags |= DISFIGURED update_body(0) update_mutantrace() return /mob/living/carbon/human/proc/ChangeToHusk() var/obj/item/organ/external/head/H = bodyparts_by_name["head"] - if(HUSK in mutations) return + if(HUSK in mutations) + return if(istype(H)) + H.disfigured = TRUE //makes them unknown without fucking up other stuff like admintools if(H.f_style) H.f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE if(H.h_style) @@ -177,7 +180,6 @@ update_hair(0) mutations.Add(HUSK) - status_flags |= DISFIGURED //makes them unknown without fucking up other stuff like admintools update_body(0) update_mutantrace() return diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index e9ae44bf433..c1eb8641820 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -29,34 +29,42 @@ switch(act) //Cooldown-inducing emotes if("ping", "pings", "buzz", "buzzes", "beep", "beeps", "yes", "no", "buzz2") - if(species.name == "Machine") //Only Machines can beep, ping, and buzz, yes, no, and make a silly sad trombone noise. + var/found_machine_head = FALSE + if(ismachine(src)) //Only Machines can beep, ping, and buzz, yes, no, and make a silly sad trombone noise. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm - else //Everyone else fails, skip the emote attempt - return + found_machine_head = TRUE + else + var/obj/item/organ/external/head/H = get_organ("head") // If you have a robotic head, you can make beep-boop noises + if(H && H.is_robotic()) + on_CD = handle_emote_CD() + found_machine_head = TRUE + + if(!found_machine_head) //Everyone else fails, skip the emote attempt + return //Everyone else fails, skip the emote attempt if("drone","drones","hum","hums","rumble","rumbles") - if(get_species() == "Drask") //Only Drask can make whale noises + if(isdrask(src)) //Only Drask can make whale noises on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm else return if("howl", "howls") - if(get_species() == "Vulpkanin") //Only Vulpkanin can howl + if(isvulpkanin(src)) //Only Vulpkanin can howl on_CD = handle_emote_CD(100) else return if("growl", "growls") - if(get_species() == "Vulpkanin") //Only Vulpkanin can growl + if(isvulpkanin(src)) //Only Vulpkanin can growl on_CD = handle_emote_CD() else return if("squish", "squishes") var/found_slime_bodypart = 0 - if(get_species() == "Slime People") //Only Slime People can squish + if(isslimeperson(src)) //Only Slime People can squish on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' found_slime_bodypart = 1 else for(var/obj/item/organ/external/L in bodyparts) // if your limbs are squishy you can squish too! - if(L.dna.species in list("Slime People")) + if(istype(L.dna.species, /datum/species/slime)) on_CD = handle_emote_CD() found_slime_bodypart = 1 break @@ -65,31 +73,31 @@ return if("clack", "clacks") - if(get_species() == "Kidan") //Only Kidan can clack and rightfully so. + if(iskidan(src)) //Only Kidan can clack and rightfully so. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' else //Everyone else fails, skip the emote attempt return if("click", "clicks") - if(get_species() == "Kidan") //Only Kidan can click and rightfully so. + if(iskidan(src)) //Only Kidan can click and rightfully so. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' else //Everyone else fails, skip the emote attempt return if("creaks", "creak") - if(get_species() == "Diona") //Only Dionas can Creaks. + if(isdiona(src)) //Only Dionas can Creaks. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' else //Everyone else fails, skip the emote attempt return if("hiss", "hisses") - if(get_species() == "Unathi") //Only Unathi can hiss. + if(isunathi(src)) //Only Unathi can hiss. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' else //Everyone else fails, skip the emote attempt return if("quill", "quills") - if(get_species() == "Vox") //Only Vox can rustle their quills. + if(isvox(src)) //Only Vox can rustle their quills. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' else //Everyone else fails, skip the emote attempt return @@ -173,14 +181,14 @@ if("clack", "clacks") var/M = handle_emote_param(param) - message = "[src] clacks their mandibles[M ? " at [M]" : ""]." + message = "[src] clacks [p_their()] mandibles[M ? " at [M]" : ""]." playsound(loc, 'sound/effects/Kidanclack.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound. m_type = 2 if("click", "clicks") var/M = handle_emote_param(param) - message = "[src] clicks their mandibles[M ? " at [M]" : ""]." + message = "[src] clicks [p_their()] mandibles[M ? " at [M]" : ""]." playsound(loc, 'sound/effects/Kidanclack2.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound. m_type = 2 @@ -201,7 +209,7 @@ if("quill", "quills") var/M = handle_emote_param(param) - message = "[src] rustles their quills[M ? " at [M]" : ""]." + message = "[src] rustles [p_their()] quills[M ? " at [M]" : ""]." playsound(loc, 'sound/effects/voxrustle.ogg', 50, 0) //Credit to sound-ideas (freesfx.co.uk) for the sound. m_type = 2 @@ -222,12 +230,12 @@ if("wag", "wags") if(body_accessory) if(body_accessory.try_restrictions(src)) - message = "[src] starts wagging \his tail." + message = "[src] starts wagging [p_their()] tail." start_tail_wagging(1) - else if(species.bodyflags & TAIL_WAGGING) + else if(dna.species.bodyflags & TAIL_WAGGING) if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) - message = "[src] starts wagging \his tail." + message = "[src] starts wagging [p_their()] tail." start_tail_wagging(1) else return @@ -236,8 +244,8 @@ m_type = 1 if("swag", "swags") - if(species.bodyflags & TAIL_WAGGING || body_accessory) - message = "[src] stops wagging \his tail." + if(dna.species.bodyflags & TAIL_WAGGING || body_accessory) + message = "[src] stops wagging [p_their()] tail." stop_tail_wagging(1) else return @@ -282,7 +290,7 @@ if("choke", "chokes") if(miming) - message = "[src] clutches \his throat desperately!" + message = "[src] clutches [p_their()] throat desperately!" m_type = 1 else if(!muzzled) @@ -294,7 +302,7 @@ if("burp", "burps") if(miming) - message = "[src] opens their mouth rather obnoxiously." + message = "[src] opens [p_their()] mouth rather obnoxiously." m_type = 1 else if(!muzzled) @@ -330,7 +338,7 @@ if("flap", "flaps") if(!restrained()) - message = "[src] flaps \his wings." + message = "[src] flaps [p_their()] wings." m_type = 2 if(miming) m_type = 1 @@ -382,7 +390,7 @@ if("aflap", "aflaps") if(!restrained()) - message = "[src] flaps \his wings ANGRILY!" + message = "[src] flaps [p_their()] wings ANGRILY!" m_type = 2 if(miming) m_type = 1 @@ -431,11 +439,11 @@ message = "[src] coughs!" m_type = 2 if(gender == FEMALE) - if(species.female_cough_sounds) - playsound(src, pick(species.female_cough_sounds), 120) + if(dna.species.female_cough_sounds) + playsound(src, pick(dna.species.female_cough_sounds), 120) else - if(species.male_cough_sounds) - playsound(src, pick(species.male_cough_sounds), 120) + if(dna.species.male_cough_sounds) + playsound(src, pick(dna.species.male_cough_sounds), 120) else message = "[src] makes a strong noise." m_type = 2 @@ -479,7 +487,7 @@ m_type = 2 if("deathgasp", "deathgasps") - message = "[src] [species.death_message]" + message = "[src] [replacetext(dna.species.death_message, "their", p_their())]" m_type = 1 if("giggle", "giggles") @@ -527,7 +535,7 @@ message = "[src] cries." m_type = 2 else - message = "[src] makes a weak noise. \He frowns." + message = "[src] makes a weak noise. [p_they(TRUE)] frown[p_s()]." m_type = 2 if("sigh", "sighs") @@ -605,7 +613,7 @@ message = "[src] takes a drag from a cigarette and blows \"[M]\" out in smoke." m_type = 1 else - message = "[src] says, \"[M], please. They had a family.\" [name] takes a drag from a cigarette and blows their name out in smoke." + message = "[src] says, \"[M], please. They had a family.\" [name] takes a drag from a cigarette and blows [p_their()] name out in smoke." m_type = 2 if("point", "points") @@ -631,7 +639,7 @@ if("shake", "shakes") var/M = handle_emote_param(param, 1) //Check to see if the param is valid (mob with the param name is in view) but exclude ourselves. - message = "[src] shakes \his head[M ? " at [M]" : ""]." + message = "[src] shakes [p_their()] head[M ? " at [M]" : ""]." m_type = 1 if("shrug", "shrugs") @@ -676,9 +684,9 @@ if(!muzzled) message = "[src] sneezes." if(gender == FEMALE) - playsound(src, species.female_sneeze_sound, 70) + playsound(src, dna.species.female_sneeze_sound, 70) else - playsound(src, species.male_sneeze_sound, 70) + playsound(src, dna.species.male_sneeze_sound, 70) m_type = 2 else message = "[src] makes a strange noise." @@ -742,7 +750,7 @@ if(M) message = "[src] hugs [M]." else - message = "[src] hugs \himself." + message = "[src] hugs [p_them()]self." if("handshake") m_type = 1 @@ -753,7 +761,7 @@ if(M.canmove && !M.r_hand && !M.restrained()) message = "[src] shakes hands with [M]." else - message = "[src] holds out \his hand to [M]." + message = "[src] holds out [p_their()] hand to [M]." if("dap", "daps") m_type = 1 @@ -763,7 +771,7 @@ if(M) message = "[src] gives daps to [M]." else - message = "[src] sadly can't find anybody to give daps to, and daps \himself. Shameful." + message = "[src] sadly can't find anybody to give daps to, and daps [p_them()]self. Shameful." if("slap", "slaps") m_type = 1 @@ -773,7 +781,7 @@ if(M) message = "[src] slaps [M] across the face. Ouch!" else - message = "[src] slaps \himself!" + message = "[src] slaps [p_them()]self!" adjustFireLoss(4) playsound(loc, 'sound/effects/snap.ogg', 50, 1) @@ -784,12 +792,12 @@ m_type = 1 else if(!muzzled) - message = "[src] [species.scream_verb][M ? " at [M]" : ""]!" + message = "[src] [dna.species.scream_verb][M ? " at [M]" : ""]!" m_type = 2 if(gender == FEMALE) - playsound(loc, "[species.female_scream_sound]", 80, 1, frequency = get_age_pitch()) + playsound(loc, "[dna.species.female_scream_sound]", 80, 1, frequency = get_age_pitch()) else - playsound(loc, "[species.male_scream_sound]", 80, 1, frequency = get_age_pitch()) //default to male screams if no gender is present. + playsound(loc, "[dna.species.male_scream_sound]", 80, 1, frequency = get_age_pitch()) //default to male screams if no gender is present. else message = "[src] makes a very loud noise[M ? " at [M]" : ""]." @@ -814,10 +822,10 @@ var/M = handle_emote_param(param) - message = "[src] snaps \his fingers[M ? " at [M]" : ""]." + message = "[src] snaps [p_their()] fingers[M ? " at [M]" : ""]." playsound(loc, 'sound/effects/fingersnap.ogg', 50, 1, -3) else - message = "[src] snaps \his fingers right off!" + message = "[src] snaps [p_their()] fingers right off!" playsound(loc, 'sound/effects/snap.ogg', 50, 1) // Needed for M_TOXIC_FART @@ -826,34 +834,34 @@ return // playsound(loc, 'sound/effects/fart.ogg', 50, 1, -3) //Admins still vote no to fun if(locate(/obj/item/storage/bible) in get_turf(src)) - to_chat(viewers(src), "[src] farts on the Bible!") - var/image/cross = image('icons/obj/storage.dmi',"bible") - var/adminbfmessage = "\blue [bicon(cross)] Bible Fart: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src)]) (CA) (SMITE):" + to_chat(viewers(src), "[src] farts on the Bible!") + var/image/cross = image('icons/obj/storage.dmi', "bible") + var/adminbfmessage = "[bicon(cross)] Bible Fart: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src)]) (CA) (SMITE):" for(var/client/X in admins) - if(check_rights(R_EVENT,0,X.mob)) + if(check_rights(R_EVENT, 0, X.mob)) to_chat(X, adminbfmessage) else if(TOXIC_FARTS in mutations) - message = "[src] unleashes a [pick("horrible","terrible","foul","disgusting","awful")] fart." + message = "[src] unleashes a [pick("horrible", "terrible", "foul", "disgusting", "awful")] fart." else if(SUPER_FART in mutations) - message = "[src] unleashes a [pick("loud","deafening")] fart." - newtonian_move(dir) + message = "[src] unleashes a [pick("loud", "deafening")] fart." else - message = "[src] [pick("passes wind","farts")]." + message = "[src] [pick("passes wind", "farts")]." m_type = 2 var/turf/location = get_turf(src) - var/aoe_range=2 // Default // Process toxic farts first. if(TOXIC_FARTS in mutations) - for(var/mob/M in range(location,aoe_range)) - if(M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT)) + for(var/mob/living/carbon/C in range(location, 2)) + if(C.internal != null && C.wear_mask && (C.wear_mask.flags & AIRTIGHT)) continue - // Now, we don't have this: - //new /obj/effects/fart_cloud(T,L) - if(M == src) + if(C == src) continue - M.reagents.add_reagent("jenkem", 1) + C.reagents.add_reagent("jenkem", 1) + + // Farting as a form of locomotion in space + if(SUPER_FART in mutations) + newtonian_move(dir) if("hem") message = "[src] hems." @@ -890,9 +898,7 @@ + " shiver(s), shrug(s), sigh(s), signal(s)-#1-10,slap(s)-(none)/mob, smile(s),snap(s), sneeze(s), sniff(s), snore(s), stare(s)-(none)/mob, swag(s), tremble(s), twitch(es), twitch(es)_s," \ + " wag(s), wave(s), whimper(s), wink(s), yawn(s), quill(s)" - switch(species.name) - if("Machine") - emotelist += "\nMachine specific emotes :- beep(s)-(none)/mob, buzz(es)-none/mob, no-(none)/mob, ping(s)-(none)/mob, yes-(none)/mob, buzz2-(none)/mob" + switch(dna.species.name) if("Drask") emotelist += "\nDrask specific emotes :- drone(s)-(none)/mob, hum(s)-(none)/mob, rumble(s)-(none)/mob" if("Kidan") @@ -906,11 +912,18 @@ if("Diona") emotelist += "\nDiona specific emotes :- creak(s)" - if (species.name == "Slime People") + if(ismachine(src)) + emotelist += "\nMachine specific emotes :- beep(s)-(none)/mob, buzz(es)-none/mob, no-(none)/mob, ping(s)-(none)/mob, yes-(none)/mob, buzz2-(none)/mob" + else + var/obj/item/organ/external/head/H = get_organ("head") // If you have a robotic head, you can make beep-boop noises + if(H && H.is_robotic()) + emotelist += "\nRobotic head specific emotes :- beep(s)-(none)/mob, buzz(es)-none/mob, no-(none)/mob, ping(s)-(none)/mob, yes-(none)/mob, buzz2-(none)/mob" + + if(isslimeperson(src)) emotelist += "\nSlime people specific emotes :- squish(es)-(none)/mob" else for(var/obj/item/organ/external/L in bodyparts) // if your limbs are squishy you can squish too! - if(L.dna.species in list("Slime People")) + if(istype(L.dna.species, /datum/species/slime)) emotelist += "\nSlime people body part specific emotes :- squish(es)-(none)/mob" break @@ -941,7 +954,7 @@ set desc = "Sets a description which will be shown when someone examines you." set category = "IC" - pose = sanitize(copytext(input(usr, "This is [src]. \He is...", "Pose", null) as text, 1, MAX_MESSAGE_LEN)) + pose = sanitize(copytext(input(usr, "This is [src]. [p_they(TRUE)] [p_are()]...", "Pose", null) as text, 1, MAX_MESSAGE_LEN)) /mob/living/carbon/human/verb/set_flavor() set name = "Set Flavour Text" diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index c15f30f94bd..a39d2843501 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -23,51 +23,18 @@ if(wear_mask) skipface |= wear_mask.flags_inv & HIDEFACE - - // crappy hacks because you can't do \his[src] etc. I'm sorry this proc is so unreadable, blame the text macros :< - var/t_He = "It" //capitalised for use at the start of each line. - var/t_his = "its" - var/t_him = "it" - var/t_has = "has" - var/t_is = "is" - var/msg = "*---------*\nThis is " - if((skipjumpsuit && skipface)) //big suits/masks/helmets make it hard to tell their gender - t_He = "They" - t_his = "their" - t_him = "them" - t_has = "have" - t_is = "are" - else - if(icon) - msg += "[bicon(icon(icon, dir=SOUTH))] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated - switch(gender) - if(MALE) - t_He = "He" - t_his = "his" - t_him = "him" - if(FEMALE) - t_He = "She" - t_his = "her" - t_him = "her" - if(PLURAL) - t_He = "They" - t_his = "their" - t_him = "them" - t_has = "have" - t_is = "are" - + if(!(skipjumpsuit && skipface) && icon) //big suits/masks/helmets make it hard to tell their gender + msg += "[bicon(icon(icon, dir=SOUTH))] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated msg += "[name]" - var/list/nospecies = list("Abductor", "Shadowling", "Neara", "Monkey", "Stok", "Farwa", "Wolpin") //species that won't show their race no matter what - - var/displayed_species = get_species() + var/displayed_species = dna.species.name for(var/obj/item/clothing/C in src) //Disguise checks if(C == src.head || C == src.wear_suit || C == src.wear_mask || C == src.w_uniform || C == src.belt || C == src.back) if(C.species_disguise) displayed_species = C.species_disguise - if(skipjumpsuit && skipface || (displayed_species in nospecies)) //either obscured or on the nospecies list + if(skipjumpsuit && skipface || (NO_EXAMINE in dna.species.species_traits)) //either obscured or on the nospecies list msg += "!\n" //omit the species when examining else if(displayed_species == "Slime People") //snowflakey because Slime People are defined as a plural msg += ", a slime person!\n" @@ -86,129 +53,129 @@ tie_msg += " with [english_accessory_list(U)]" if(w_uniform.blood_DNA) - msg += "[t_He] [t_is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [w_uniform.blood_color != "#030303" ? "blood-stained":"oil-stained"] [w_uniform.name][tie_msg]!\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [w_uniform.blood_color != "#030303" ? "blood-stained":"oil-stained"] [w_uniform.name][tie_msg]!\n" else - msg += "[t_He] [t_is] wearing [bicon(w_uniform)] \a [w_uniform][tie_msg].\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(w_uniform)] \a [w_uniform][tie_msg].\n" //head if(head && !(head.flags & ABSTRACT)) if(head.blood_DNA) - msg += "[t_He] [t_is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [head.blood_color != "#030303" ? "blood-stained":"oil-stained"] [head.name] on [t_his] head!\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [head.blood_color != "#030303" ? "blood-stained":"oil-stained"] [head.name] on [p_their()] head!\n" else - msg += "[t_He] [t_is] wearing [bicon(head)] \a [head] on [t_his] head.\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(head)] \a [head] on [p_their()] head.\n" //suit/armour if(wear_suit && !(wear_suit.flags & ABSTRACT)) if(wear_suit.blood_DNA) - msg += "[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_suit.name]!\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_suit.name]!\n" else - msg += "[t_He] [t_is] wearing [bicon(wear_suit)] \a [wear_suit].\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(wear_suit)] \a [wear_suit].\n" //suit/armour storage if(s_store && !skipsuitstorage) if(s_store.blood_DNA) - msg += "[t_He] [t_is] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [s_store.blood_color != "#030303" ? "blood-stained":"oil-stained"] [s_store.name] on [t_his] [wear_suit.name]!\n" + msg += "[p_they(TRUE)] [p_are()] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [s_store.blood_color != "#030303" ? "blood-stained":"oil-stained"] [s_store.name] on [p_their()] [wear_suit.name]!\n" else - msg += "[t_He] [t_is] carrying [bicon(s_store)] \a [s_store] on [t_his] [wear_suit.name].\n" + msg += "[p_they(TRUE)] [p_are()] carrying [bicon(s_store)] \a [s_store] on [p_their()] [wear_suit.name].\n" //back if(back && !(back.flags & ABSTRACT)) if(back.blood_DNA) - msg += "[t_He] [t_has] [bicon(back)] [back.gender==PLURAL?"some":"a"] [back.blood_color != "#030303" ? "blood-stained":"oil-stained"] [back] on [t_his] back.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(back)] [back.gender==PLURAL?"some":"a"] [back.blood_color != "#030303" ? "blood-stained":"oil-stained"] [back] on [p_their()] back.\n" else - msg += "[t_He] [t_has] [bicon(back)] \a [back] on [t_his] back.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(back)] \a [back] on [p_their()] back.\n" //left hand if(l_hand && !(l_hand.flags & ABSTRACT)) if(l_hand.blood_DNA) - msg += "[t_He] [t_is] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [l_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [l_hand.name] in [t_his] left hand!\n" + msg += "[p_they(TRUE)] [p_are()] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [l_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [l_hand.name] in [p_their()] left hand!\n" else - msg += "[t_He] [t_is] holding [bicon(l_hand)] \a [l_hand] in [t_his] left hand.\n" + msg += "[p_they(TRUE)] [p_are()] holding [bicon(l_hand)] \a [l_hand] in [p_their()] left hand.\n" //right hand if(r_hand && !(r_hand.flags & ABSTRACT)) if(r_hand.blood_DNA) - msg += "[t_He] [t_is] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [r_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [r_hand.name] in [t_his] right hand!\n" + msg += "[p_they(TRUE)] [p_are()] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [r_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [r_hand.name] in [p_their()] right hand!\n" else - msg += "[t_He] [t_is] holding [bicon(r_hand)] \a [r_hand] in [t_his] right hand.\n" + msg += "[p_they(TRUE)] [p_are()] holding [bicon(r_hand)] \a [r_hand] in [p_their()] right hand.\n" //gloves if(gloves && !skipgloves && !(gloves.flags & ABSTRACT)) if(gloves.blood_DNA) - msg += "[t_He] [t_has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [gloves.blood_color != "#030303" ? "blood-stained":"oil-stained"] [gloves.name] on [t_his] hands!\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [gloves.blood_color != "#030303" ? "blood-stained":"oil-stained"] [gloves.name] on [p_their()] hands!\n" else - msg += "[t_He] [t_has] [bicon(gloves)] \a [gloves] on [t_his] hands.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(gloves)] \a [gloves] on [p_their()] hands.\n" else if(blood_DNA) - msg += "[t_He] [t_has] [hand_blood_color != "#030303" ? "blood-stained":"oil-stained"] hands!\n" + msg += "[p_they(TRUE)] [p_have()] [hand_blood_color != "#030303" ? "blood-stained":"oil-stained"] hands!\n" //handcuffed? if(handcuffed) if(istype(handcuffed, /obj/item/restraints/handcuffs/cable/zipties)) - msg += "[t_He] [t_is] [bicon(handcuffed)] restrained with zipties!\n" + msg += "[p_they(TRUE)] [p_are()] [bicon(handcuffed)] restrained with zipties!\n" else if(istype(handcuffed, /obj/item/restraints/handcuffs/cable)) - msg += "[t_He] [t_is] [bicon(handcuffed)] restrained with cable!\n" + msg += "[p_they(TRUE)] [p_are()] [bicon(handcuffed)] restrained with cable!\n" else - msg += "[t_He] [t_is] [bicon(handcuffed)] handcuffed!\n" + msg += "[p_they(TRUE)] [p_are()] [bicon(handcuffed)] handcuffed!\n" //belt if(belt) if(belt.blood_DNA) - msg += "[t_He] [t_has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [belt.blood_color != "#030303" ? "blood-stained":"oil-stained"] [belt.name] about [t_his] waist!\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [belt.blood_color != "#030303" ? "blood-stained":"oil-stained"] [belt.name] about [p_their()] waist!\n" else - msg += "[t_He] [t_has] [bicon(belt)] \a [belt] about [t_his] waist.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(belt)] \a [belt] about [p_their()] waist.\n" //shoes if(shoes && !skipshoes && !(shoes.flags & ABSTRACT)) if(shoes.blood_DNA) - msg += "[t_He] [t_is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [shoes.blood_color != "#030303" ? "blood-stained":"oil-stained"] [shoes.name] on [t_his] feet!\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [shoes.blood_color != "#030303" ? "blood-stained":"oil-stained"] [shoes.name] on [p_their()] feet!\n" else - msg += "[t_He] [t_is] wearing [bicon(shoes)] \a [shoes] on [t_his] feet.\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(shoes)] \a [shoes] on [p_their()] feet.\n" else if(blood_DNA) - msg += "[t_He] [t_has] [feet_blood_color != "#030303" ? "blood-stained":"oil-stained"] feet!\n" + msg += "[p_they(TRUE)] [p_have()] [feet_blood_color != "#030303" ? "blood-stained":"oil-stained"] feet!\n" //mask if(wear_mask && !skipmask && !(wear_mask.flags & ABSTRACT)) if(wear_mask.blood_DNA) - msg += "[t_He] [t_has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_mask.name] on [t_his] face!\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_mask.name] on [p_their()] face!\n" else - msg += "[t_He] [t_has] [bicon(wear_mask)] \a [wear_mask] on [t_his] face.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(wear_mask)] \a [wear_mask] on [p_their()] face.\n" //eyes if(glasses && !skipeyes && !(glasses.flags & ABSTRACT)) if(glasses.blood_DNA) - msg += "[t_He] [t_has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [glasses.blood_color != "#030303" ? "blood-stained":"oil-stained"] [glasses] covering [t_his] eyes!\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [glasses.blood_color != "#030303" ? "blood-stained":"oil-stained"] [glasses] covering [p_their()] eyes!\n" else - msg += "[t_He] [t_has] [bicon(glasses)] \a [glasses] covering [t_his] eyes.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(glasses)] \a [glasses] covering [p_their()] eyes.\n" //left ear if(l_ear && !skipears) - msg += "[t_He] [t_has] [bicon(l_ear)] \a [l_ear] on [t_his] left ear.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(l_ear)] \a [l_ear] on [p_their()] left ear.\n" //right ear if(r_ear && !skipears) - msg += "[t_He] [t_has] [bicon(r_ear)] \a [r_ear] on [t_his] right ear.\n" + msg += "[p_they(TRUE)] [p_have()] [bicon(r_ear)] \a [r_ear] on [p_their()] right ear.\n" //ID if(wear_id) - msg += "[t_He] [t_is] wearing [bicon(wear_id)] \a [wear_id].\n" + msg += "[p_they(TRUE)] [p_are()] wearing [bicon(wear_id)] \a [wear_id].\n" //Jitters switch(jitteriness) if(300 to INFINITY) - msg += "[t_He] [t_is] convulsing violently!\n" + msg += "[p_they(TRUE)] [p_are()] convulsing violently!\n" if(200 to 300) - msg += "[t_He] [t_is] extremely jittery.\n" + msg += "[p_they(TRUE)] [p_are()] extremely jittery.\n" if(100 to 200) - msg += "[t_He] [t_is] twitching ever so slightly.\n" + msg += "[p_they(TRUE)] [p_are()] twitching ever so slightly.\n" var/appears_dead = FALSE if(stat == DEAD || (status_flags & FAKEDEATH)) appears_dead = TRUE if(suiciding) - msg += "[t_He] appears to have committed suicide... there is no hope of recovery.\n" - msg += "[t_He] [t_is] limp and unresponsive; there are no signs of life" + msg += "[p_they(TRUE)] appear[p_s()] to have committed suicide... there is no hope of recovery.\n" + msg += "[p_they(TRUE)] [p_are()] limp and unresponsive; there are no signs of life" if(get_int_organ(/obj/item/organ/internal/brain)) if(!key) var/foundghost = FALSE @@ -220,35 +187,35 @@ foundghost = FALSE break if(!foundghost) - msg += " and [t_his] soul has departed" + msg += " and [p_their()] soul has departed" msg += "...\n" if(!get_int_organ(/obj/item/organ/internal/brain)) - msg += "It appears that [t_his] brain is missing...\n" + msg += "It appears that [p_their()] brain is missing...\n" msg += "" var/list/wound_flavor_text = list() var/list/is_destroyed = list() - for(var/organ_tag in species.has_limbs) + for(var/organ_tag in dna.species.has_limbs) - var/list/organ_data = species.has_limbs[organ_tag] + var/list/organ_data = dna.species.has_limbs[organ_tag] var/organ_descriptor = organ_data["descriptor"] is_destroyed["[organ_data["descriptor"]]"] = 1 var/obj/item/organ/external/E = bodyparts_by_name[organ_tag] if(!E) - wound_flavor_text["[organ_tag]"] = "[t_He] [t_is] missing [t_his] [organ_descriptor].\n" + wound_flavor_text["[organ_tag]"] = "[p_they(TRUE)] [p_are()] missing [p_their()] [organ_descriptor].\n" else if(!isSynthetic()) - if(E.status & ORGAN_ROBOT) - wound_flavor_text["[E.limb_name]"] = "[t_He] [t_has] a robotic [E.name]!\n" + if(E.is_robotic()) + wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a robotic [E.name]!\n" else if(E.status & ORGAN_SPLINTED) - wound_flavor_text["[E.limb_name]"] = "[t_He] [t_has] a splint on [t_his] [E.name]!\n" + wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a splint on [p_their()] [E.name]!\n" for(var/obj/item/I in E.embedded_objects) - msg += "[t_He] [t_has] \a [bicon(I)] [I] embedded in [t_his] [E.name]!\n" + msg += "[p_they(TRUE)] [p_have()] \a [bicon(I)] [I] embedded in [p_their()] [E.name]!\n" //Handles the text strings being added to the actual description. //If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext. @@ -280,101 +247,101 @@ if(temp) var/brute_message = !isSynthetic() ? "bruising" : "denting" if(temp < 30) - msg += "[t_He] [t_has] minor [brute_message ].\n" + msg += "[p_they(TRUE)] [p_have()] minor [brute_message ].\n" else - msg += "[t_He] [t_has] severe [brute_message ]!\n" + msg += "[p_they(TRUE)] [p_have()] severe [brute_message ]!\n" temp = getFireLoss() if(temp) if(temp < 30) - msg += "[t_He] [t_has] minor burns.\n" + msg += "[p_they(TRUE)] [p_have()] minor burns.\n" else - msg += "[t_He] [t_has] severe burns!\n" + msg += "[p_they(TRUE)] [p_have()] severe burns!\n" temp = getCloneLoss() if(temp) if(temp < 30) - msg += "[t_He] [t_has] minor cellular damage.\n" + msg += "[p_they(TRUE)] [p_have()] minor cellular damage.\n" else - msg += "[t_He] [t_has] severe cellular damage.\n" + msg += "[p_they(TRUE)] [p_have()] severe cellular damage.\n" if(fire_stacks > 0) - msg += "[t_He] [t_is] covered in something flammable.\n" + msg += "[p_they(TRUE)] [p_are()] covered in something flammable.\n" if(fire_stacks < 0) - msg += "[t_He] looks a little soaked.\n" + msg += "[p_they(TRUE)] looks a little soaked.\n" switch(wetlevel) if(1) - msg += "[t_He] looks a bit damp.\n" + msg += "[p_they(TRUE)] looks a bit damp.\n" if(2) - msg += "[t_He] looks a little bit wet.\n" + msg += "[p_they(TRUE)] looks a little bit wet.\n" if(3) - msg += "[t_He] looks wet.\n" + msg += "[p_they(TRUE)] looks wet.\n" if(4) - msg += "[t_He] looks very wet.\n" + msg += "[p_they(TRUE)] looks very wet.\n" if(5) - msg += "[t_He] looks absolutely soaked.\n" + msg += "[p_they(TRUE)] looks absolutely soaked.\n" if(nutrition < NUTRITION_LEVEL_STARVING - 50) - msg += "[t_He] [t_is] severely malnourished.\n" + msg += "[p_they(TRUE)] [p_are()] severely malnourished.\n" else if(nutrition >= NUTRITION_LEVEL_FAT) if(user.nutrition < NUTRITION_LEVEL_STARVING - 50) - msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" + msg += "[p_they(TRUE)] [p_are()] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" else - msg += "[t_He] [t_is] quite chubby.\n" + msg += "[p_they(TRUE)] [p_are()] quite chubby.\n" if(blood_volume < BLOOD_VOLUME_SAFE) - msg += "[t_He] [t_has] pale skin.\n" + msg += "[p_they(TRUE)] [p_have()] pale skin.\n" if(bleedsuppress) - msg += "[t_He] [t_is] bandaged with something.\n" + msg += "[p_they(TRUE)] [p_are()] bandaged with something.\n" else if(bleed_rate) if(reagents.has_reagent("heparin")) - msg += "[t_He] [t_is] bleeding uncontrollably!\n" + msg += "[p_they(TRUE)] [p_are()] bleeding uncontrollably!\n" else - msg += "[t_He] [t_is] bleeding!\n" + msg += "[p_they(TRUE)] [p_are()] bleeding!\n" if(reagents.has_reagent("teslium")) - msg += "[t_He] is emitting a gentle blue glow!\n" + msg += "[p_they(TRUE)] [p_are()] emitting a gentle blue glow!\n" msg += "" if(!appears_dead) if(stat == UNCONSCIOUS) - msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" + msg += "[p_they(TRUE)] [p_are()]n't responding to anything around [p_them()] and seems to be asleep.\n" else if(getBrainLoss() >= 60) - msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" + msg += "[p_they(TRUE)] [p_have()] a stupid expression on [p_their()] face.\n" if(get_int_organ(/obj/item/organ/internal/brain)) if(istype(src, /mob/living/carbon/human/interactive)) var/mob/living/carbon/human/interactive/auto = src if(auto.showexaminetext) - msg += "[t_He] [t_is] appears to be some sort of sick automaton, [t_his] eyes are glazed over and [t_his] mouth is slightly agape.\n" + msg += "[p_they(TRUE)] [p_are()] appears to be some sort of sick automaton, [p_their()] eyes are glazed over and [p_their()] mouth is slightly agape.\n" if(auto.debugexamine) var/dodebug = auto.doing2string(auto.doing) var/interestdebug = auto.interest2string(auto.interest) - msg += "[t_He] [t_is] appears to be [interestdebug] and [dodebug].\n" - else if(species.show_ssd) + msg += "[p_they(TRUE)] [p_are()] appears to be [interestdebug] and [dodebug].\n" + else if(dna.species.show_ssd) if(!key) - msg += "[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely.\n" + msg += "[p_they(TRUE)] [p_are()] totally catatonic. The stresses of life in deep-space must have been too much for [p_them()]. Any recovery is unlikely.\n" else if(!client) - msg += "[t_He] [t_has] suddenly fallen asleep, suffering from Space Sleep Disorder. [t_He] may wake up soon.\n" + msg += "[p_they(TRUE)] [p_have()] suddenly fallen asleep, suffering from Space Sleep Disorder. [p_they(TRUE)] may wake up soon.\n" if(digitalcamo) - msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n" + msg += "[p_they(TRUE)] [p_are()] moving [p_their()] body in an unnatural and blatantly inhuman manner.\n" if(!(skipface || ( wear_mask && ( wear_mask.flags_inv & HIDEFACE || wear_mask.flags_cover & MASKCOVERSMOUTH) ) ) && is_thrall(src) && in_range(user,src)) msg += "Their features seem unnaturally tight and drawn.\n" if(decaylevel == 1) - msg += "[t_He] [t_is] starting to smell.\n" + msg += "[p_they(TRUE)] [p_are()] starting to smell.\n" if(decaylevel == 2) - msg += "[t_He] [t_is] bloated and smells disgusting.\n" + msg += "[p_they(TRUE)] [p_are()] bloated and smells disgusting.\n" if(decaylevel == 3) - msg += "[t_He] [t_is] rotting and blackened, the skin sloughing off. The smell is indescribably foul.\n" + msg += "[p_they(TRUE)] [p_are()] rotting and blackened, the skin sloughing off. The smell is indescribably foul.\n" if(decaylevel == 4) - msg += "[t_He] [t_is] mostly dessicated now, with only bones remaining of what used to be a person.\n" + msg += "[p_they(TRUE)] [p_are()] mostly dessicated now, with only bones remaining of what used to be a person.\n" if(hasHUD(user,"security")) var/perpname = "wot" @@ -429,7 +396,7 @@ if(pose) if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) pose = addtext(pose,".") //Makes sure all emotes end with a period. - msg += "\n[t_He] is [pose]" + msg += "\n[p_they(TRUE)] [p_are()] [pose]" to_chat(user, msg) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index e0f90aacdd0..3f36b8b6d55 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -4,10 +4,6 @@ voice_name = "unknown" icon = 'icons/mob/human.dmi' icon_state = "body_m_s" - - //why are these here and not in human_defines.dm - //var/list/hud_list[10] - var/datum/species/species //Contains icon generation and language information, set during New(). var/obj/item/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. /mob/living/carbon/human/New(loc) @@ -15,21 +11,17 @@ log_runtime(EXCEPTION("human/New called with more than 1 argument (REPORT THIS ENTIRE RUNTIME TO A CODER)")) . = ..() -/mob/living/carbon/human/Initialize(mapload, new_species = null) +/mob/living/carbon/human/Initialize(mapload, datum/species/new_species = /datum/species/human) if(!dna) dna = new /datum/dna(null) // Species name is handled by set_species() - if(!species) - if(new_species) - set_species(new_species, 1, delay_icon_update = 1) - else - set_species(delay_icon_update = 1) + set_species(new_species, 1, delay_icon_update = 1, skip_same_check = TRUE) ..() - if(species) - real_name = species.get_random_name(gender) + if(dna.species) + real_name = dna.species.get_random_name(gender) name = real_name if(mind) mind.name = real_name @@ -74,79 +66,92 @@ status_flags = GODMODE|CANPUSH /mob/living/carbon/human/skrell/Initialize(mapload) - ..(mapload, "Skrell") + ..(mapload, /datum/species/skrell) /mob/living/carbon/human/tajaran/Initialize(mapload) - ..(mapload, "Tajaran") + ..(mapload, /datum/species/tajaran) /mob/living/carbon/human/vulpkanin/Initialize(mapload) - ..(mapload, "Vulpkanin") + ..(mapload, /datum/species/vulpkanin) /mob/living/carbon/human/unathi/Initialize(mapload) - ..(mapload, "Unathi") + ..(mapload, /datum/species/unathi) /mob/living/carbon/human/vox/Initialize(mapload) - ..(mapload, "Vox") + ..(mapload, /datum/species/vox) /mob/living/carbon/human/voxarmalis/Initialize(mapload) - ..(mapload, "Vox Armalis") + ..(mapload, /datum/species/vox/armalis) /mob/living/carbon/human/skeleton/Initialize(mapload) - ..(mapload, "Skeleton") + ..(mapload, /datum/species/skeleton) /mob/living/carbon/human/kidan/Initialize(mapload) - ..(mapload, "Kidan") + ..(mapload, /datum/species/kidan) /mob/living/carbon/human/plasma/Initialize(mapload) - ..(mapload, "Plasmaman") + ..(mapload, /datum/species/plasmaman) /mob/living/carbon/human/slime/Initialize(mapload) - ..(mapload, "Slime People") + ..(mapload, /datum/species/slime) /mob/living/carbon/human/grey/Initialize(mapload) - ..(mapload, "Grey") + ..(mapload, /datum/species/grey) /mob/living/carbon/human/abductor/Initialize(mapload) - ..(mapload, "Abductor") - -/mob/living/carbon/human/human/Initialize(mapload) - ..(mapload, "Human") + ..(mapload, /datum/species/abductor) /mob/living/carbon/human/diona/Initialize(mapload) - ..(mapload, "Diona") + ..(mapload, /datum/species/diona) /mob/living/carbon/human/machine/Initialize(mapload) - ..(mapload, "Machine") + ..(mapload, /datum/species/machine) + +/mob/living/carbon/human/machine/created + name = "Integrated Robotic Chassis" + +/mob/living/carbon/human/machine/created/Initialize(mapload) + ..() + rename_character(null, "Integrated Robotic Chassis ([rand(1, 9999)])") + update_dna() + for(var/obj/item/organ/external/E in bodyparts) + if(istype(E, /obj/item/organ/external/chest) || istype(E, /obj/item/organ/external/groin)) + continue + qdel(E) + for(var/obj/item/organ/O in internal_organs) + qdel(O) + regenerate_icons() + death() /mob/living/carbon/human/shadow/Initialize(mapload) - ..(mapload, "Shadow") + ..(mapload, /datum/species/shadow) /mob/living/carbon/human/golem/Initialize(mapload) - ..(mapload, "Golem") + ..(mapload, /datum/species/golem) /mob/living/carbon/human/wryn/Initialize(mapload) - ..(mapload, "Wryn") + ..(mapload, /datum/species/wryn) /mob/living/carbon/human/nucleation/Initialize(mapload) - ..(mapload, "Nucleation") + ..(mapload, /datum/species/nucleation) /mob/living/carbon/human/drask/Initialize(mapload) - ..(mapload, "Drask") + ..(mapload, /datum/species/drask) /mob/living/carbon/human/monkey/Initialize(mapload) - ..(mapload, "Monkey") + ..(mapload, /datum/species/monkey) /mob/living/carbon/human/farwa/Initialize(mapload) - ..(mapload, "Farwa") + ..(mapload, /datum/species/monkey/tajaran) /mob/living/carbon/human/wolpin/Initialize(mapload) - ..(mapload, "Wolpin") + ..(mapload, /datum/species/monkey/vulpkanin) /mob/living/carbon/human/neara/Initialize(mapload) - ..(mapload, "Neara") + ..(mapload, /datum/species/monkey/skrell) /mob/living/carbon/human/stok/Initialize(mapload) - ..(mapload, "Stok") + ..(mapload, /datum/species/monkey/unathi) /mob/living/carbon/human/Stat() ..() @@ -306,7 +311,7 @@ if(!prob(martial_art.deflection_chance)) return ..() if(!src.lying && !(HULK in mutations)) //But only if they're not lying down, and hulks can't do it - visible_message("[src] deflects the projectile; they can't be hit with ranged weapons!", "You deflect the projectile!") + visible_message("[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!", "You deflect the projectile!") return 0 ..() @@ -513,7 +518,7 @@ //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() var/obj/item/organ/external/head = get_organ("head") - if( !head || head.disfigured || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible + if(!head || head.disfigured || cloneloss > 50 || !real_name || (HUSK in mutations)) //disfigured. use id-name if possible return "Unknown" return real_name @@ -550,7 +555,7 @@ grant_death_vision() return - species.update_sight(src) + dna.species.update_sight(src) //Removed the horrible safety parameter. It was only being used by ninja code anyways. //Now checks siemens_coefficient of the affected area by default @@ -580,8 +585,8 @@ if(gloves) var/obj/item/clothing/gloves/G = gloves gloves_siemens_coeff = G.siemens_coefficient - if(species) - species_siemens_coeff = species.siemens_coeff + if(dna.species) + species_siemens_coeff = dna.species.siemens_coeff siemens_coeff = gloves_siemens_coeff * species_siemens_coeff if(undergoing_cardiac_arrest()) if(shock_damage * siemens_coeff >= 1 && prob(25)) @@ -608,7 +613,7 @@ if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore return var/time_taken = I.embedded_unsafe_removal_time*I.w_class - usr.visible_message("[usr] attempts to remove [I] from their [L.name].","You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)") + usr.visible_message("[usr] attempts to remove [I] from [usr.p_their()] [L.name].","You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)") if(do_after(usr, time_taken, needhand = 1, target = src)) if(!I || !L || I.loc != src || !(I in L.embedded_objects)) return @@ -617,7 +622,7 @@ I.forceMove(get_turf(src)) usr.put_in_hands(I) usr.emote("scream") - usr.visible_message("[usr] successfully rips [I] out of their [L.name]!","You successfully remove [I] from your [L.name].") + usr.visible_message("[usr] successfully rips [I] out of [usr.p_their()] [L.name]!","You successfully remove [I] from your [L.name].") if(!has_embedded_objects()) clear_alert("embeddedobject") return @@ -651,12 +656,12 @@ unEquip(pocket_item) if(thief_mode) usr.put_in_hands(pocket_item) - add_attack_logs(usr, src, "Stripped of [pocket_item]", isLivingSSD(src)) + add_attack_logs(usr, src, "Stripped of [pocket_item]", isLivingSSD(src) ? null : ATKLOG_ALL) else if(place_item) usr.unEquip(place_item) equip_to_slot_if_possible(place_item, pocket_id, 0, 1) - add_attack_logs(usr, src, "Equipped with [pocket_item]", isLivingSSD(src)) + add_attack_logs(usr, src, "Equipped with [pocket_item]", isLivingSSD(src) ? null : ATKLOG_ALL) // Update strip window if(usr.machine == src && in_range(src, usr)) @@ -665,7 +670,7 @@ // Display a warning if the user mocks up if they don't have pickpocket gloves. if(!thief_mode) to_chat(src, "You feel your [pocket_side] pocket being fumbled with!") - add_attack_logs(usr, src, "Attempted strip of [pocket_item]", isLivingSSD(src)) + add_attack_logs(usr, src, "Attempted strip of [pocket_item]", isLivingSSD(src) ? null : ATKLOG_ALL) if(href_list["set_sensor"]) if(istype(w_uniform, /obj/item/clothing/under)) @@ -680,7 +685,7 @@ "You have dislodged everything from [src]'s headpocket!") var/obj/item/organ/internal/headpocket/C = get_int_organ(/obj/item/organ/internal/headpocket) C.empty_contents() - add_attack_logs(usr, src, "Stripped of headpocket items", isLivingSSD(src)) + add_attack_logs(usr, src, "Stripped of headpocket items", isLivingSSD(src) ? null : ATKLOG_ALL) if(href_list["strip_accessory"]) if(istype(w_uniform, /obj/item/clothing/under)) @@ -1032,18 +1037,10 @@ /mob/living/carbon/human/proc/check_dna() dna.check_integrity(src) - return - -/mob/living/carbon/human/get_species() - - if(!species) - set_species() - - return species.name /mob/living/carbon/human/proc/play_xylophone() if(!src.xylophone) - visible_message("[src] begins playing his ribcage like a xylophone. It's quite spooky.","You begin to play a spooky refrain on your ribcage.","You hear a spooky xylophone melody.") + visible_message("[src] begins playing [p_their()] ribcage like a xylophone. It's quite spooky.","You begin to play a spooky refrain on your ribcage.","You hear a spooky xylophone melody.") var/song = pick('sound/effects/xylophone1.ogg','sound/effects/xylophone2.ogg','sound/effects/xylophone3.ogg') playsound(loc, song, 50, 1, -1) xylophone = 1 @@ -1064,8 +1061,8 @@ var/fail_msg if(!affecting) . = 0 - fail_msg = "They are missing that limb." - else if(affecting.status & ORGAN_ROBOT) + fail_msg = "[p_they(TRUE)] [p_are()] missing that limb." + else if(affecting.is_robotic()) . = 0 fail_msg = "That limb is robotic." else @@ -1078,7 +1075,7 @@ . = 0 if(!. && error_msg && user) if(!fail_msg) - fail_msg = "There is no exposed flesh or thin material [target_zone == "head" ? "on their head" : "on their body"] to inject into." + fail_msg = "There is no exposed flesh or thin material [target_zone == "head" ? "on [p_their()] head" : "on [p_their()] body"] to inject into." to_chat(user, "[fail_msg]") /mob/living/carbon/human/proc/check_obscured_slots() @@ -1114,8 +1111,10 @@ return 1 /mob/living/carbon/human/proc/get_visible_gender() - if(wear_suit && wear_suit.flags_inv & HIDEJUMPSUIT && ((head && head.flags_inv & HIDEMASK) || wear_mask)) - return NEUTER + var/list/obscured = check_obscured_slots() + var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE)) + if((slot_w_uniform in obscured) && skipface) + return PLURAL return gender /mob/living/carbon/human/proc/increase_germ_level(n) @@ -1138,9 +1137,9 @@ //Replacing lost limbs with the species default. var/mob/living/carbon/human/temp_holder - for(var/limb_type in H.species.has_limbs) + for(var/limb_type in H.dna.species.has_limbs) if(!(limb_type in H.bodyparts_by_name)) - var/list/organ_data = H.species.has_limbs[limb_type] + var/list/organ_data = H.dna.species.has_limbs[limb_type] var/limb_path = organ_data["path"] var/obj/item/organ/external/O = new limb_path(temp_holder) if(H.get_limb_by_name(O.name)) //Check to see if the user already has an limb with the same name as the 'missing limb'. If they do, skip regrowth. @@ -1153,8 +1152,8 @@ //Replacing lost organs with the species default. temp_holder = new /mob/living/carbon/human() - for(var/index in H.species.has_organ) - var/organ = H.species.has_organ[index] + for(var/index in H.dna.species.has_organ) + var/organ = H.dna.species.has_organ[index] if(!(organ in types_of_int_organs)) //If the mob is missing this particular organ... var/obj/item/organ/internal/I = new organ(temp_holder) //Create the organ inside our holder so we can check it before implantation. if(H.get_organ_slot(I.slot)) //Check to see if the user already has an organ in the slot the 'missing organ' belongs to. If they do, skip implantation. @@ -1171,7 +1170,7 @@ surgeries.Cut() //End all surgeries. update_revive() - if(species.name != "Skeleton" && (SKELETON in mutations)) + if(!isskeleton(src) && (SKELETON in mutations)) mutations.Remove(SKELETON) if(NOCLONE in mutations) mutations.Remove(NOCLONE) @@ -1201,7 +1200,7 @@ return 0 if(!L.is_bruised()) - src.custom_pain("You feel a stabbing pain in your chest!", 1) + custom_pain("You feel a stabbing pain in your chest!") L.damage = L.min_bruised_damage //returns 1 if made bloody, returns 0 otherwise @@ -1234,7 +1233,7 @@ ..() /mob/living/carbon/human/generate_name() - name = species.makeName(gender,src) + name = dna.species.get_random_name(gender) real_name = name if(dna) dna.real_name = name @@ -1252,10 +1251,10 @@ if(usr == src) self = 1 if(!self) - usr.visible_message("[usr] kneels down, puts \his hand on [src]'s wrist and begins counting their pulse.",\ + usr.visible_message("[usr] kneels down, puts [usr.p_their()] hand on [src]'s wrist and begins counting [p_their()] pulse.",\ "You begin counting [src]'s pulse") else - usr.visible_message("[usr] begins counting their pulse.",\ + usr.visible_message("[usr] begins counting [p_their()] pulse.",\ "You begin counting your pulse.") if(src.pulse) @@ -1273,88 +1272,90 @@ else to_chat(usr, "[self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)].") -/mob/living/carbon/human/proc/set_species(var/new_species, var/default_colour, var/delay_icon_update = 0) - var/datum/species/oldspecies = species - var/datum/species/NS = all_species[new_species] - if(!dna) - if(!new_species) - new_species = "Human" - else - if(!new_species) - new_species = dna.species - else - dna.species = new_species - - if(species) - if(species.name && species.name == new_species) +/mob/living/carbon/human/proc/set_species(datum/species/new_species, default_colour, delay_icon_update = FALSE, skip_same_check = FALSE) + if(!skip_same_check) + if(dna.species.name == initial(new_species.name)) return - - if(species.language) - remove_language(species.language) - - if(species.default_language) - remove_language(species.default_language) - - if(gender == PLURAL && NS.has_gender) - change_gender(pick(MALE,FEMALE)) - species.handle_pre_change(src) - - species = all_species[new_species] + var/datum/species/oldspecies = dna.species if(oldspecies) + if(oldspecies.language) + remove_language(oldspecies.language) + + if(oldspecies.default_language) + remove_language(oldspecies.default_language) + + if(gender == PLURAL && oldspecies.has_gender) + change_gender(pick(MALE, FEMALE)) + if(oldspecies.default_genes.len) - oldspecies.handle_dna(src,1) // Remove any genes that belong to the old species + oldspecies.handle_dna(src, TRUE) // Remove any genes that belong to the old species - tail = species.tail + oldspecies.on_species_loss(src) - maxHealth = species.total_health + dna.species = new new_species() - if(species.language) - add_language(species.language) + tail = dna.species.tail - if(species.default_language) - add_language(species.default_language) + maxHealth = dna.species.total_health - hunger_drain = species.hunger_drain - digestion_ratio = species.digestion_ratio + if(dna.species.language) + add_language(dna.species.language) - if(species.base_color && default_colour) + if(dna.species.default_language) + add_language(dna.species.default_language) + + hunger_drain = dna.species.hunger_drain + digestion_ratio = dna.species.digestion_ratio + + if(dna.species.base_color && default_colour) //Apply colour. - skin_colour = species.base_color + skin_colour = dna.species.base_color else skin_colour = "#000000" - if(!(species.bodyflags & HAS_SKIN_TONE)) + if(!(dna.species.bodyflags & HAS_SKIN_TONE)) s_tone = 0 - species.create_organs(src) + var/list/thing_to_check = list(slot_wear_mask, slot_head, slot_shoes, slot_gloves, slot_l_ear, slot_r_ear, slot_glasses, slot_l_hand, slot_r_hand) + var/list/kept_items[0] + + for(var/thing in thing_to_check) + var/obj/item/I = get_item_by_slot(thing) + if(I) + kept_items[I] = thing + + dna.species.create_organs(src) + + for(var/thing in kept_items) + equip_to_slot_or_del(thing, kept_items[thing]) //Handle default hair/head accessories for created mobs. var/obj/item/organ/external/head/H = get_organ("head") - if(species.default_hair) - H.h_style = species.default_hair + if(dna.species.default_hair) + H.h_style = dna.species.default_hair else H.h_style = "Bald" - if(species.default_fhair) - H.f_style = species.default_fhair + if(dna.species.default_fhair) + H.f_style = dna.species.default_fhair else H.f_style = "Shaved" - if(species.default_headacc) - H.ha_style = species.default_headacc + if(dna.species.default_headacc) + H.ha_style = dna.species.default_headacc else H.ha_style = "None" - if(species.default_hair_colour) + if(dna.species.default_hair_colour) //Apply colour. - H.hair_colour = species.default_hair_colour + H.hair_colour = dna.species.default_hair_colour else H.hair_colour = "#000000" - if(species.default_fhair_colour) - H.facial_colour = species.default_fhair_colour + if(dna.species.default_fhair_colour) + H.facial_colour = dna.species.default_fhair_colour else H.facial_colour = "#000000" - if(species.default_headacc_colour) - H.headacc_colour = species.default_headacc_colour + if(dna.species.default_headacc_colour) + H.headacc_colour = dna.species.default_headacc_colour else H.headacc_colour = "#000000" @@ -1362,43 +1363,39 @@ m_colours = DEFAULT_MARKING_COLOURS //Defaults colour to #00000 for all markings. body_accessory = null - if(!dna) - dna = new /datum/dna(null) - dna.species = species.name - dna.real_name = real_name + dna.real_name = real_name - species.handle_post_spawn(src) + dna.species.on_species_gain(src) - see_in_dark = species.get_resultant_darksight(src) + see_in_dark = dna.species.get_resultant_darksight(src) if(see_in_dark > 2) see_invisible = SEE_INVISIBLE_LEVEL_ONE else see_invisible = SEE_INVISIBLE_LIVING - species.handle_dna(src) //Give them whatever special dna business they got. + dna.species.handle_dna(src) //Give them whatever special dna business they got. update_client_colour(0) - spawn(0) - overlays.Cut() - update_mutantrace(1) - regenerate_icons() - if(!delay_icon_update) UpdateAppearance() - if(species) - return 1 + overlays.Cut() + update_mutantrace(1) + regenerate_icons() + + if(dna.species) + return TRUE else - return 0 + return FALSE /mob/living/carbon/human/get_default_language() if(default_language) return default_language - if(!species) + if(!dna.species) return null - return species.default_language ? all_languages[species.default_language] : null + return dna.species.default_language ? all_languages[dna.species.default_language] : null /mob/living/carbon/human/proc/bloody_doodle() set category = "IC" @@ -1450,127 +1447,11 @@ W.message = message W.add_fingerprint(src) -// Allows IPC's to change their monitor display -/mob/living/carbon/human/proc/change_monitor() - set category = "IC" - set name = "Change Monitor/Optical Display" - set desc = "Change the display on your monitor or the colour of your optics." - - if(incapacitated()) - to_chat(src, "You cannot change your monitor or optical display in your current state.") - return - - var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ) //If the rock'em-sock'em robot's head came off during a fight, they shouldn't be able to change their screen/optics. - to_chat(src, "Where's your head at? Can't change your monitor/display without one.") - return - - if(species.bodyflags & ALL_RPARTS) //If they can have a fully cybernetic body... - var/datum/robolimb/robohead = all_robolimbs[head_organ.model] - if(!head_organ) - return - if(!robohead.is_monitor) //If they've got a prosthetic head and it isn't a monitor, they've no screen to adjust. Instead, let them change the colour of their optics! - var/optic_colour = input(src, "Select optic colour", m_colours["head"]) as color|null - if(incapacitated()) - to_chat(src, "You were interrupted while changing the colour of your optics.") - return - if(optic_colour) - change_markings(optic_colour, "head") - - else if(robohead.is_monitor) //Means that the character's head is a monitor (has a screen). Time to customize. - var/list/hair = list() - for(var/i in hair_styles_public_list) - var/datum/sprite_accessory/hair/tmp_hair = hair_styles_public_list[i] - if((head_organ.species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. - hair += i - - var/new_style = input(src, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair - if(incapacitated()) - to_chat(src, "You were interrupted while changing your monitor display.") - return - if(new_style) - change_hair(new_style) - -//Putting a couple of procs here that I don't know where else to dump. -//Mostly going to be used for Vox and Vox Armalis, but other human mobs might like them (for adminbuse). -/mob/living/carbon/human/proc/leap() - set category = "Abilities" - set name = "Leap" - set desc = "Leap at a target and grab them aggressively." - - if(last_special > world.time) - return - - if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) - to_chat(src, "You cannot leap in your current state.") - return - - var/list/choices = list() - for(var/mob/living/M in view(6,src)) - if(!istype(M,/mob/living/silicon)) - choices += M - choices -= src - - var/mob/living/T = input(src,"Who do you wish to leap at?") as null|anything in choices - - if(!T || !src || src.stat) return - - if(get_dist(get_turf(T), get_turf(src)) > 6) return - - if(last_special > world.time) - return - - if(!canmove) - to_chat(src, "You cannot leap in your current state.") - return - - last_special = world.time + 75 - status_flags |= LEAPING - - src.visible_message("\The [src] leaps at [T]!") - src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1, src) - playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1) - - sleep(5) - - if(status_flags & LEAPING) status_flags &= ~LEAPING - - if(!src.Adjacent(T)) - to_chat(src, "You miss!") - return - - T.Weaken(5) - - //Only official raider vox get the grab and no self-prone." - if(src.mind && src.mind.special_role != "Vox Raider") - src.Weaken(5) - return - - var/use_hand = "left" - if(l_hand) - if(r_hand) - to_chat(src, "You need to have one hand free to grab someone.") - return - else - use_hand = "right" - - src.visible_message("\The [src] seizes [T] aggressively!") - - var/obj/item/grab/G = new(src,T) - if(use_hand == "left") - l_hand = G - else - r_hand = G - - G.state = GRAB_AGGRESSIVE - G.icon_state = "grabbed1" - G.synch() - /mob/living/carbon/human/proc/get_eyecon() var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) var/obj/item/organ/internal/cyberimp/eyes/eye_implant = get_int_organ(/obj/item/organ/internal/cyberimp/eyes) - if(istype(species) && species.eyes) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes) + if(istype(dna.species) && dna.species.eyes) + var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', dna.species.eyes) if(eye_implant) //Eye implants override native DNA eye colo(u)r eyes_icon = eye_implant.generate_icon() else if(eyes) @@ -1601,43 +1482,6 @@ Eyes need to have significantly high darksight to shine unless the mob has the X return TRUE -/mob/living/carbon/human/proc/gut() - set category = "Abilities" - set name = "Gut" - set desc = "While grabbing someone aggressively, rip their guts out or tear them apart." - - if(last_special > world.time) - return - - if(!canmove) - to_chat(src, "You cannot do that in your current state.") - return - - var/obj/item/grab/G = locate() in src - if(!G || !istype(G)) - to_chat(src, "You are not grabbing anyone.") - return - - if(G.state < GRAB_AGGRESSIVE) - to_chat(src, "You must have an aggressive grab to gut your prey!") - return - - last_special = world.time + 50 - - visible_message("\The [src] rips viciously at \the [G.affecting]'s body with its claws!") - - if(istype(G.affecting,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = G.affecting - H.apply_damage(50,BRUTE) - if(H.stat == 2) - H.gib() - else - var/mob/living/M = G.affecting - if(!istype(M)) return //wut - M.apply_damage(50,BRUTE) - if(M.stat == 2) - M.gib() - /mob/living/carbon/human/assess_threat(var/mob/living/simple_animal/bot/secbot/judgebot, var/lasercolor) if(judgebot.emagged == 2) return 10 //Everyone is a criminal! @@ -1746,7 +1590,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X to_chat(src, "Remove your mask first!") return 0 if((H.head && (H.head.flags_cover & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags_cover & MASKCOVERSMOUTH) && !H.wear_mask.mask_adjusted)) - to_chat(src, "Remove their mask first!") + to_chat(src, "Remove [H.p_their()] mask first!") return 0 visible_message("[src] is trying to perform CPR on [H.name]!", \ "You try to perform CPR on [H.name]!") @@ -1760,7 +1604,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X to_chat(H, "You feel a breath of fresh air enter your lungs. It feels good.") to_chat(src, "Repeat at least every 7 seconds.") - add_attack_logs(src, H, "CPRed", FALSE) + add_attack_logs(src, H, "CPRed", ATKLOG_ALL) return 1 else to_chat(src, "You need to stay still while performing CPR!") @@ -1776,7 +1620,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X /mob/living/carbon/human/IsAdvancedToolUser() - if(species.has_fine_manipulation) + if(dna.species.has_fine_manipulation) return 1 return 0 @@ -1811,7 +1655,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X return 1 /mob/living/carbon/human/can_eat(flags = 255) - return species && (species.dietflags & flags) + return dna.species && (dna.species.dietflags & flags) /mob/living/carbon/human/selfFeed(var/obj/item/reagent_containers/food/toEat, fullness) if(!check_has_mouth()) @@ -1821,14 +1665,14 @@ Eyes need to have significantly high darksight to shine unless the mob has the X /mob/living/carbon/human/forceFed(var/obj/item/reagent_containers/food/toEat, mob/user, fullness) if(!check_has_mouth()) - if(!((istype(toEat, /obj/item/reagent_containers/food/drinks) && (get_species() == "Machine")))) + if(!((istype(toEat, /obj/item/reagent_containers/food/drinks) && (ismachine(src))))) to_chat(user, "Where do you intend to put \the [toEat]? \The [src] doesn't have a mouth!") return 0 return ..() /mob/living/carbon/human/selfDrink(var/obj/item/reagent_containers/food/drinks/toDrink) if(!check_has_mouth()) - if(!get_species() == "Machine") + if(!ismachine(src)) to_chat(src, "Where do you intend to put \the [src]? You don't have a mouth!") return 0 else @@ -1872,7 +1716,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X . |= A.GetAccess() /mob/living/carbon/human/is_mechanical() - return ..() || (species.bodyflags & ALL_RPARTS) != 0 + return ..() || (dna.species.bodyflags & ALL_RPARTS) != 0 /mob/living/carbon/human/can_use_guns(var/obj/item/gun/G) . = ..() @@ -1881,7 +1725,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X if(HULK in mutations) to_chat(src, "Your meaty finger is much too large for the trigger guard!") return 0 - if(NOGUNS in species.species_traits) + if(NOGUNS in dna.species.species_traits) to_chat(src, "Your fingers don't fit in the trigger guard!") return 0 @@ -1948,7 +1792,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X dna.deserialize(data["dna"]) real_name = dna.real_name name = real_name - set_species(dna.species) + set_species(dna.species.type, skip_same_check = TRUE) age = data["age"] undershirt = data["ushirt"] underwear = data["uwear"] @@ -2010,8 +1854,8 @@ Eyes need to have significantly high darksight to shine unless the mob has the X . += "---" /mob/living/carbon/human/get_taste_sensitivity() - if(species) - return species.taste_sensitivity + if(dna.species) + return dna.species.taste_sensitivity else return 1 diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index c216badda93..80c128ee07f 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -17,7 +17,7 @@ //TODO: fix husking if(((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD) ChangeToHusk() - if(species.can_revive_by_healing) + if(dna.species.can_revive_by_healing) var/obj/item/organ/internal/brain/B = get_int_organ(/obj/item/organ/internal/brain) if(B) if((health >= (config.health_threshold_dead + config.health_threshold_crit) * 0.5) && stat == DEAD && getBrainLoss()<120) @@ -32,11 +32,11 @@ if(status_flags & GODMODE) return 0 //godmode - if(species && species.has_organ["brain"]) + if(dna.species && dna.species.has_organ["brain"]) var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain) if(sponge) - if(species) - amount = amount * species.brain_mod + if(dna.species) + amount = amount * dna.species.brain_mod sponge.receive_damage(amount, 1) brainloss = sponge.damage else @@ -48,11 +48,11 @@ if(status_flags & GODMODE) return 0 //godmode - if(species && species.has_organ["brain"]) + if(dna.species && dna.species.has_organ["brain"]) var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain) if(sponge) - if(species) - amount = amount * species.brain_mod + if(dna.species) + amount = amount * dna.species.brain_mod sponge.damage = min(max(amount, 0), (maxHealth*2)) brainloss = sponge.damage else @@ -64,7 +64,7 @@ if(status_flags & GODMODE) return 0 //godmode - if(species && species.has_organ["brain"]) + if(dna.species && dna.species.has_organ["brain"]) var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain) if(sponge) brainloss = min(sponge.damage,maxHealth*2) @@ -89,24 +89,24 @@ /mob/living/carbon/human/adjustBruteLoss(amount, damage_source) - if(species) - amount = amount * species.brute_mod + if(dna.species) + amount = amount * dna.species.brute_mod if(amount > 0) take_overall_damage(amount, 0, used_weapon = damage_source) else heal_overall_damage(-amount, 0) /mob/living/carbon/human/adjustFireLoss(amount, damage_source) - if(species) - amount = amount * species.burn_mod + if(dna.species) + amount = amount * dna.species.burn_mod if(amount > 0) take_overall_damage(0, amount, used_weapon = damage_source) else heal_overall_damage(0, -amount) /mob/living/carbon/human/proc/adjustBruteLossByPart(amount, organ_name, obj/damage_source = null) - if(species) - amount = amount * species.brute_mod + if(dna.species) + amount = amount * dna.species.brute_mod if(organ_name in bodyparts_by_name) var/obj/item/organ/external/O = get_organ(organ_name) @@ -115,12 +115,12 @@ O.receive_damage(amount, 0, sharp=is_sharp(damage_source), used_weapon=damage_source) else //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. - O.heal_damage(-amount, 0, internal=0, robo_repair=(O.status & ORGAN_ROBOT)) + O.heal_damage(-amount, 0, internal = 0, robo_repair = O.is_robotic()) /mob/living/carbon/human/proc/adjustFireLossByPart(amount, organ_name, obj/damage_source = null) - if(species) - amount = amount * species.burn_mod + if(dna.species) + amount = amount * dna.species.burn_mod if(organ_name in bodyparts_by_name) var/obj/item/organ/external/O = get_organ(organ_name) @@ -129,7 +129,7 @@ O.receive_damage(0, amount, sharp=is_sharp(damage_source), used_weapon=damage_source) else //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. - O.heal_damage(0, -amount, internal=0, robo_repair=(O.status & ORGAN_ROBOT)) + O.heal_damage(0, -amount, internal = 0, robo_repair = O.is_robotic()) /mob/living/carbon/human/Paralyse(amount) @@ -139,8 +139,8 @@ ..() /mob/living/carbon/human/adjustCloneLoss(amount) - if(species) - amount = amount * species.clone_mod + if(dna.species) + amount = amount * dna.species.clone_mod ..() var/heal_prob = max(0, 80 - getCloneLoss()) @@ -149,7 +149,7 @@ if(prob(mut_prob)) var/list/obj/item/organ/external/candidates = list() //TYPECASTED LISTS ARE NOT A FUCKING THING WHAT THE FUCK for(var/obj/item/organ/external/O in bodyparts) - if(O.status & ORGAN_ROBOT) + if(O.is_robotic()) continue if(!(O.status & ORGAN_MUTATED)) candidates |= O @@ -179,23 +179,23 @@ // Defined here solely to take species flags into account without having to recast at mob/living level. /mob/living/carbon/human/adjustOxyLoss(amount) - if(species) - amount = amount * species.oxy_mod + if(dna.species) + amount = amount * dna.species.oxy_mod ..() /mob/living/carbon/human/setOxyLoss(amount) - if(species) - amount = amount * species.oxy_mod + if(dna.species) + amount = amount * dna.species.oxy_mod ..() /mob/living/carbon/human/adjustToxLoss(amount) - if(species) - amount = amount * species.tox_mod + if(dna.species) + amount = amount * dna.species.tox_mod ..() /mob/living/carbon/human/setToxLoss(amount) - if(species) - amount = amount * species.tox_mod + if(dna.species) + amount = amount * dna.species.tox_mod ..() //////////////////////////////////////////// @@ -205,9 +205,9 @@ var/list/obj/item/organ/external/parts = list() for(var/obj/item/organ/external/O in bodyparts) if((brute && O.brute_dam) || (burn && O.burn_dam)) - if(!(flags & AFFECT_ROBOTIC_ORGAN) && O.status & ORGAN_ROBOT) + if(!(flags & AFFECT_ROBOTIC_ORGAN) && O.is_robotic()) continue - if(!(flags & AFFECT_ORGANIC_ORGAN) && !(O.status & ORGAN_ROBOT)) + if(!(flags & AFFECT_ORGANIC_ORGAN) && !O.is_robotic()) continue parts += O return parts @@ -352,8 +352,8 @@ This function restores all organs. switch(damagetype) if(BRUTE) damageoverlaytemp = 20 - if(species) - damage = damage * species.brute_mod + if(dna.species) + damage = damage * dna.species.brute_mod if(organ.receive_damage(damage, 0, sharp, used_weapon)) UpdateDamageIcon() @@ -372,13 +372,12 @@ This function restores all organs. dmgIcon.pixel_y = (!lying) ? rand(-11,9) : rand(-10,1) flick_overlay(dmgIcon, attack_bubble_recipients, 9) - receiving_damage() if(BURN) damageoverlaytemp = 20 - if(species) - damage = damage * species.burn_mod + if(dna.species) + damage = damage * dna.species.burn_mod if(organ.receive_damage(0, damage, sharp, used_weapon)) UpdateDamageIcon() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index c45154e4931..6c2bb844155 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -165,7 +165,7 @@ emp_act /mob/living/carbon/human/emag_act(user as mob, var/obj/item/organ/external/affecting) if(!istype(affecting)) return - if(!(affecting.status & ORGAN_ROBOT)) + if(!affecting.is_robotic()) to_chat(user, "That limb isn't robotic.") return if(affecting.sabotaged) @@ -348,12 +348,24 @@ emp_act if(penetrated_dam) SS.create_breaches(damtype, penetrated_dam) +/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + var/hulk_verb = pick("smash", "pummel") + if(check_shields(user, 15, "the [hulk_verb]ing")) + return + ..(user, TRUE) + playsound(loc, user.dna.species.unarmed.attack_sound, 25, 1, -1) + var/message = "[user] has [hulk_verb]ed [src]!" + visible_message("[message]", "[message]") + adjustBruteLoss(15) + return TRUE + /mob/living/carbon/human/attack_hand(mob/user) if(..()) //to allow surgery to return properly. return if(ishuman(user)) var/mob/living/carbon/human/H = user - species.spec_attack_hand(H, src) + dna.species.spec_attack_hand(H, src) /mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L) if(..()) //successful larva bite. @@ -482,7 +494,7 @@ emp_act /mob/living/carbon/human/water_act(volume, temperature, source) ..() - species.water_act(src,volume,temperature,source) + dna.species.water_act(src,volume,temperature,source) /mob/living/carbon/human/is_eyes_covered(check_glasses = TRUE, check_head = TRUE, check_mask = TRUE) if(check_glasses && glasses && (glasses.flags_cover & GLASSESCOVERSEYES)) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index a7fcc6874a2..96693a0d086 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -1,7 +1,7 @@ var/global/default_martial_art = new/datum/martial_art /mob/living/carbon/human - hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,NATIONS_HUD) + hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,NATIONS_HUD,GLAND_HUD) //Marking colour and style var/list/m_colours = DEFAULT_MARKING_COLOURS //All colours set to #000000. diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index a835133f4d0..71a5f0396a1 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -2,7 +2,7 @@ . = 0 . += ..() . += config.human_delay - . += species.movement_delay(src) + . += dna.species.movement_delay(src) /mob/living/carbon/human/Process_Spacemove(movement_dir = 0) @@ -39,12 +39,12 @@ if(!lying && !buckled && !throwing) for(var/obj/item/organ/external/splinted in splinted_limbs) splinted.update_splints() - + if(!has_gravity(loc)) return - + var/obj/item/clothing/shoes/S = shoes - + //Bloody footprints var/turf/T = get_turf(src) var/obj/item/organ/external/l_foot = get_organ("l_foot") @@ -119,7 +119,7 @@ if(step_count % 3) //this basically says, every three moves make a noise return 0 //1st - none, 1%3==1, 2nd - none, 2%3==2, 3rd - noise, 3%3==0 - if(species.silent_steps) + if(dna.species.silent_steps) return 0 //species is silent playsound(T, S, volume, 1, range) diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 428fafeb71e..5dcae16b87a 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -20,7 +20,7 @@ //Moving around with fractured ribs won't do you any good if(E.is_broken() && E.internal_organs && E.internal_organs.len && prob(15)) var/obj/item/organ/internal/I = pick(E.internal_organs) - custom_pain("You feel broken bones moving in your [E.name]!", 1) + custom_pain("You feel broken bones moving in your [E.name]!") I.receive_damage(rand(3,5)) //handle_stance() @@ -62,7 +62,7 @@ // standing is poor if(stance_damage >= 8) if(!(lying || resting)) - if(!(NO_PAIN in species.species_traits)) + if(!(NO_PAIN in dna.species.species_traits)) emote("scream") custom_emote(1, "collapses!") Weaken(5) //can't emote while weakened, apparently. @@ -90,7 +90,7 @@ continue var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ") - custom_emote(1, "[(NO_PAIN in species.species_traits) ? "" : emote_scream ]drops what they were holding in their [E.name]!") + custom_emote(1, "[(NO_PAIN in dna.species.species_traits) ? "" : emote_scream ]drops what [p_they()] [p_were()] holding in [p_their()] [E.name]!") else if(E.is_malfunctioning()) @@ -105,7 +105,7 @@ if(!unEquip(r_hand)) continue - custom_emote(1, "drops what they were holding, their [E.name] malfunctioning!") + custom_emote(1, "drops what [p_they()] [p_were()] holding, [p_their()] [E.name] malfunctioning!") var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(5, 0, src) @@ -178,7 +178,7 @@ I use this to standardize shadowling dethrall code /mob/living/carbon/human/has_organic_damage() var/odmg = 0 for(var/obj/item/organ/external/O in bodyparts) - if(O.status & ORGAN_ROBOT) + if(O.is_robotic()) odmg += O.brute_dam odmg += O.burn_dam return (health < (100 - odmg)) diff --git a/code/modules/mob/living/carbon/human/interactive/functions.dm b/code/modules/mob/living/carbon/human/interactive/functions.dm index eae754b5283..8e8c2c80013 100644 --- a/code/modules/mob/living/carbon/human/interactive/functions.dm +++ b/code/modules/mob/living/carbon/human/interactive/functions.dm @@ -87,11 +87,11 @@ if(inactivity_period <= 0) inactivity_period = 9999 // technically infinite if(do_after(src, 60, target = traitorTarget)) - custom_emote(1, "A fire bursts from [src]'s eyes, igniting white hot and consuming their body in a flaming explosion!") + custom_emote(1, "A fire bursts from [src]'s eyes, igniting white hot and consuming [p_their()] body in a flaming explosion!") explosion(src, 6, 6, 6) else inactivity_period = 0 - custom_emote(1, "[src]'s chest closes, hiding their insides.") + custom_emote(1, "[src]'s chest closes, hiding [p_their()] insides.") if(SNPC_PSYCHO) var/choice = pick(typesof(/obj/item/grenade/chem_grenade) - /obj/item/grenade/chem_grenade) @@ -469,7 +469,7 @@ if(!Adjacent(SF)) tryWalk(get_turf(SF)) else - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")], grabbing various foodstuffs from [SF] and sticking them in it's mouth!") + custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")], grabbing various foodstuffs from [SF] and sticking them in its mouth!") for(var/obj/item/A in SF.contents) if(prob(smartness/2)) var/count = SF.item_quants[A.name] @@ -631,7 +631,7 @@ TARGET = newSnack newSnack.reagents.remove_any((newSnack.reagents.total_volume/2)-1) newSnack.name = "Synthetic [newSnack.name]" - custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as they vomit [newSnack] from their mouth!") + custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as [p_they()] vomit[p_s()] [newSnack] from [p_their()] mouth!") catch(var/exception/e) log_runtime(e, src, "Caught in SNPC cooking module") doing &= ~SNPC_SPECIAL diff --git a/code/modules/mob/living/carbon/human/interactive/interactive.dm b/code/modules/mob/living/carbon/human/interactive/interactive.dm index a93fd9e8635..763a5ef15be 100644 --- a/code/modules/mob/living/carbon/human/interactive/interactive.dm +++ b/code/modules/mob/living/carbon/human/interactive/interactive.dm @@ -128,7 +128,7 @@ //this is here because this has no client/prefs/brain whatever. age = rand(AGE_MIN, AGE_MAX) change_gender(pick("male", "female")) - rename_character(real_name, species.get_random_name(gender)) + rename_character(real_name, dna.species.get_random_name(gender)) //job handling myjob = new default_job() job = myjob.title @@ -208,9 +208,9 @@ var/datum/dna/toDoppel = chosen.dna T.real_name = toDoppel.real_name - T.set_species(chosen.species.name) - T.body_accessory = chosen.body_accessory + T.set_species(chosen.dna.species.type) T.dna = toDoppel.Clone() + T.body_accessory = chosen.body_accessory T.UpdateAppearance() domutcheck(T) @@ -245,7 +245,7 @@ MYID.age = age MYID.registered_name = real_name MYID.photo = get_id_photo(src) - MYID.access = Path_ID.access // Automatons have strange powers... strange indeed + MYID.access = Path_ID.access.Copy() // Automatons have strange powers... strange indeed RPID = new(src) RPID.name = "[real_name]'s ID Card ([alt_title])" @@ -257,7 +257,10 @@ RPID.photo = get_id_photo(src) RPID.access = myjob.get_access() - equip_to_slot_or_del(MYID, slot_wear_id) + if(wear_id) + qdel(wear_id) + if(!equip_to_slot_or_del(MYID, slot_wear_id)) + create_attack_log("Deleted ID due to slot contention") if(wear_pda) MYPDA = wear_pda else @@ -403,8 +406,12 @@ if(!hud_used) hud_used = new /datum/hud/human(src) -/mob/living/carbon/human/interactive/New(var/new_loc, var/new_species = null) +/mob/living/carbon/human/interactive/Initialize() ..() + return INITIALIZE_HINT_LATELOAD + +/mob/living/carbon/human/interactive/LateInitialize() + . = ..() snpc_list += src create_mob_hud() @@ -427,6 +434,7 @@ /mob/living/carbon/human/interactive/Destroy() hear_radio_list -= src snpc_list -= src + npc_master.removeBot(src) return ..() /mob/living/carbon/human/interactive/proc/retalTarget(mob/living/target) diff --git a/code/modules/mob/living/carbon/human/interactive/prefabs.dm b/code/modules/mob/living/carbon/human/interactive/prefabs.dm index 6553bb26b70..cee716b66ec 100644 --- a/code/modules/mob/living/carbon/human/interactive/prefabs.dm +++ b/code/modules/mob/living/carbon/human/interactive/prefabs.dm @@ -1,18 +1,18 @@ -/mob/living/carbon/human/interactive/angry/New() +/mob/living/carbon/human/interactive/angry/Initialize(mapload) TRAITS |= TRAIT_ROBUST TRAITS |= TRAIT_MEAN faction += "bot_angry" - ..() + return ..() -/mob/living/carbon/human/interactive/friendly/New() +/mob/living/carbon/human/interactive/friendly/Initialize(mapload) TRAITS |= TRAIT_FRIENDLY TRAITS |= TRAIT_UNROBUST faction += "bot_friendly" faction += "neutral" functions -= "combat" - ..() + return ..() -/mob/living/carbon/human/interactive/greytide/New() +/mob/living/carbon/human/interactive/greytide/Initialize(mapload) TRAITS |= TRAIT_ROBUST TRAITS |= TRAIT_MEAN TRAITS |= TRAIT_THIEVING @@ -21,4 +21,4 @@ targetInterestShift = 2 // likewise faction += "bot_grey" graytide = 1 - ..() \ No newline at end of file + return ..() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 882501c49f2..50848851646 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -419,7 +419,7 @@ ..(what, who, where, silent = is_silent) /mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0) - switch(species.handle_can_equip(I, slot, disable_warning, src)) + 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 diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 00de7814170..d577a02e2c4 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -15,10 +15,10 @@ handle_heartbeat() handle_heartattack() handle_drunk() - species.handle_life(src) + dna.species.handle_life(src) if(!client) - species.handle_npc(src) + dna.species.handle_npc(src) if(stat != DEAD) //Stuff jammed in your limbs hurts @@ -150,7 +150,7 @@ AdjustSilence(2) if(getBrainLoss() >= 120 && stat != 2) //they died from stupidity--literally. -Fox - visible_message("[src] goes limp, their facial expression utterly blank.") + visible_message("[src] goes limp, [p_their()] facial expression utterly blank.") death() /mob/living/carbon/human/handle_mutations_and_radiation() @@ -178,7 +178,7 @@ if(gene_stability < GENETIC_DAMAGE_STAGE_3) gib() - if(!(RADIMMUNE in species.species_traits)) + if(!(RADIMMUNE in dna.species.species_traits)) if(radiation) radiation = Clamp(radiation, 0, 200) @@ -238,7 +238,7 @@ chest.add_autopsy_data("Radiation Poisoning", autopsy_damage) /mob/living/carbon/human/breathe() - if(!species.breathe(src)) + if(!dna.species.breathe(src)) ..() /mob/living/carbon/human/check_breath(datum/gas_mixture/breath) @@ -253,8 +253,8 @@ failed_last_breath = TRUE - if(species) - var/datum/species/S = species + if(dna.species) + var/datum/species/S = dna.species if(S.breathid == "o2") throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy) @@ -332,39 +332,39 @@ bodytemperature += min((1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX) // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. - if(bodytemperature > species.heat_level_1) + if(bodytemperature > dna.species.heat_level_1) //Body temperature is too hot. if(status_flags & GODMODE) return 1 //godmode - var/mult = species.heatmod + var/mult = dna.species.heatmod - if(bodytemperature >= species.heat_level_1 && bodytemperature <= species.heat_level_2) + if(bodytemperature >= dna.species.heat_level_1 && bodytemperature <= dna.species.heat_level_2) throw_alert("temp", /obj/screen/alert/hot, 1) take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature") - if(bodytemperature > species.heat_level_2 && bodytemperature <= species.heat_level_3) + if(bodytemperature > dna.species.heat_level_2 && bodytemperature <= dna.species.heat_level_3) throw_alert("temp", /obj/screen/alert/hot, 2) take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature") - if(bodytemperature > species.heat_level_3 && bodytemperature < INFINITY) + if(bodytemperature > dna.species.heat_level_3 && bodytemperature < INFINITY) throw_alert("temp", /obj/screen/alert/hot, 3) if(on_fire) take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_3, used_weapon = "Fire") else take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature") - else if(bodytemperature < species.cold_level_1) + else if(bodytemperature < dna.species.cold_level_1) if(status_flags & GODMODE) return 1 if(stat == DEAD) return 1 if(!istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) - var/mult = species.coldmod - if(bodytemperature >= species.cold_level_2 && bodytemperature <= species.cold_level_1) + var/mult = dna.species.coldmod + if(bodytemperature >= dna.species.cold_level_2 && bodytemperature <= dna.species.cold_level_1) throw_alert("temp", /obj/screen/alert/cold, 1) take_overall_damage(burn=mult*COLD_DAMAGE_LEVEL_1, used_weapon = "Low Body Temperature") - if(bodytemperature >= species.cold_level_3 && bodytemperature < species.cold_level_2) + if(bodytemperature >= dna.species.cold_level_3 && bodytemperature < dna.species.cold_level_2) throw_alert("temp", /obj/screen/alert/cold, 2) take_overall_damage(burn=mult*COLD_DAMAGE_LEVEL_2, used_weapon = "Low Body Temperature") - if(bodytemperature > -INFINITY && bodytemperature < species.cold_level_3) + if(bodytemperature > -INFINITY && bodytemperature < dna.species.cold_level_3) throw_alert("temp", /obj/screen/alert/cold, 3) take_overall_damage(burn=mult*COLD_DAMAGE_LEVEL_3, used_weapon = "Low Body Temperature") else @@ -379,18 +379,18 @@ var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. if(status_flags & GODMODE) return 1 //godmode - if(adjusted_pressure >= species.hazard_high_pressure) + if(adjusted_pressure >= dna.species.hazard_high_pressure) if(!(HEATRES in mutations)) - var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) + var/pressure_damage = min( ( (adjusted_pressure / dna.species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure") throw_alert("pressure", /obj/screen/alert/highpressure, 2) else clear_alert("pressure") - else if(adjusted_pressure >= species.warning_high_pressure) + else if(adjusted_pressure >= dna.species.warning_high_pressure) throw_alert("pressure", /obj/screen/alert/highpressure, 1) - else if(adjusted_pressure >= species.warning_low_pressure) + else if(adjusted_pressure >= dna.species.warning_low_pressure) clear_alert("pressure") - else if(adjusted_pressure >= species.hazard_low_pressure) + else if(adjusted_pressure >= dna.species.hazard_low_pressure) throw_alert("pressure", /obj/screen/alert/lowpressure, 1) else if(COLDRES in mutations) @@ -430,13 +430,13 @@ //END FIRE CODE /mob/living/carbon/human/proc/stabilize_temperature_from_calories() - var/body_temperature_difference = species.body_temperature - bodytemperature + var/body_temperature_difference = dna.species.body_temperature - bodytemperature - if(bodytemperature <= species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects. + if(bodytemperature <= dna.species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects. bodytemperature += max((body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM) - if(bodytemperature >= species.cold_level_1 && bodytemperature <= species.heat_level_1) + if(bodytemperature >= dna.species.cold_level_1 && bodytemperature <= dna.species.heat_level_1) bodytemperature += body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR - if(bodytemperature >= species.heat_level_1) //360.15 is 310.15 + 50, the temperature where you start to feel effects. + if(bodytemperature >= dna.species.heat_level_1) //360.15 is 310.15 + 50, the temperature where you start to feel effects. //We totally need a sweat system cause it totally makes sense...~ bodytemperature += min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers @@ -588,7 +588,7 @@ return 0 //godmode //The fucking FAT mutation is the greatest shit ever. It makes everyone so hot and bothered. - if(CAN_BE_FAT in species.species_traits) + if(CAN_BE_FAT in dna.species.species_traits) if(FAT in mutations) if(overeatduration < 100) becomeSlim() @@ -652,7 +652,7 @@ AdjustDizzy(-3) AdjustJitter(-3) - if(NO_INTORGANS in species.species_traits) + if(NO_INTORGANS in dna.species.species_traits) return handle_trace_chems() @@ -766,10 +766,10 @@ //Vision //god knows why this is here var/obj/item/organ/vision - if(species.vision_organ) - vision = get_int_organ(species.vision_organ) + if(dna.species.vision_organ) + vision = get_int_organ(dna.species.vision_organ) - if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means. + if(!dna.species.vision_organ) // Presumably if a species has no vision organs, they see via some other means. SetEyeBlind(0) blinded = 0 SetEyeBlurry(0) @@ -832,7 +832,8 @@ /mob/living/carbon/human/handle_vision() if(machine) - if(!machine.check_eye(src)) reset_perspective(null) + if(!machine.check_eye(src)) + reset_perspective(null) else var/isRemoteObserve = 0 if((REMOTE_VIEW in mutations) && remoteview_target) @@ -859,10 +860,10 @@ remoteview_target = null reset_perspective(null) - species.handle_vision(src) + dna.species.handle_vision(src) /mob/living/carbon/human/handle_hud_icons() - species.handle_hud_icons(src) + dna.species.handle_hud_icons(src) /mob/living/carbon/human/handle_random_events() // Puke if toxloss is too high @@ -906,7 +907,7 @@ if(times_fired % 5 == 1) return pulse //update pulse every 5 life ticks (~1 tick/sec, depending on server load) - if(NO_BLOOD in species.species_traits) + if(NO_BLOOD in dna.species.species_traits) return PULSE_NONE //No blood, no pulse. if(stat == DEAD) @@ -976,7 +977,7 @@ var/obj/item/clothing/mask/M = H.wear_mask if(M && (M.flags_cover & MASKCOVERSMOUTH)) return - if(NO_BREATHE in H.species.species_traits) + if(NO_BREATHE in H.dna.species.species_traits) return //no puking if you can't smell! // Humans can lack a mind datum, y'know if(H.mind && (H.mind.assigned_role == "Detective" || H.mind.assigned_role == "Coroner")) @@ -992,7 +993,7 @@ if(!H) //H.status will runtime if there is no H (obviously) return - if(H.status & ORGAN_ROBOT) //Handle robotic hearts specially with a wuuuubb. This also applies to machine-people. + if(H.is_robotic()) //Handle robotic hearts specially with a wuuuubb. This also applies to machine-people. if(shock_stage >= 10 || istype(get_turf(src), /turf/space)) //PULSE_THREADY - maximum value for pulse, currently it 5. //High pulse value corresponds to a fast rate of heartbeat. @@ -1019,10 +1020,7 @@ if(heartbeat >= rate) heartbeat = 0 - if(H.status & ORGAN_ASSISTED) - src << sound('sound/effects/pacemakebeat.ogg',0,0,CHANNEL_HEARTBEAT,50) - else - src << sound('sound/effects/singlebeat.ogg',0,0,CHANNEL_HEARTBEAT,50) + src << sound('sound/effects/singlebeat.ogg',0,0,CHANNEL_HEARTBEAT,50) else heartbeat++ @@ -1056,9 +1054,9 @@ /mob/living/carbon/human/proc/can_heartattack() - if(NO_BLOOD in species.species_traits) + if(NO_BLOOD in dna.species.species_traits) return FALSE - if(NO_INTORGANS in species.species_traits) + if(NO_INTORGANS in dna.species.species_traits) return FALSE return TRUE diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index d4b160509ea..e16c67a56d0 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -1,7 +1,7 @@ /mob/living/carbon/human/Login() ..() - if(species && species.ventcrawler) + if(dna.species && dna.species.ventcrawler) to_chat(src, "You can ventcrawl! Use alt+click on vents to quickly travel about the station.") update_pipe_vision() return diff --git a/code/modules/mob/living/carbon/human/npcs.dm b/code/modules/mob/living/carbon/human/npcs.dm index b66a0ee52ba..c21c1990cbe 100644 --- a/code/modules/mob/living/carbon/human/npcs.dm +++ b/code/modules/mob/living/carbon/human/npcs.dm @@ -5,9 +5,8 @@ item_color = "punpun" species_restricted = list("Monkey") -/mob/living/carbon/human/monkey/punpun/New() +/mob/living/carbon/human/monkey/punpun/Initialize(mapload) ..() - spawn(1) - name = "Pun Pun" - real_name = name - equip_to_slot(new /obj/item/clothing/under/punpun(src), slot_w_uniform) \ No newline at end of file + name = "Pun Pun" + real_name = name + equip_to_slot(new /obj/item/clothing/under/punpun(src), slot_w_uniform) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 7657a3be3be..7d408ce9199 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -42,7 +42,7 @@ if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak. return 1 - if(species.can_understand(other)) + if(dna.species.can_understand(other)) return 1 //These only pertain to common. Languages are handled by mob/say_understands() @@ -87,7 +87,7 @@ /mob/living/carbon/human/IsVocal() // how do species that don't breathe talk? magic, that's what. - var/breathes = (!(NO_BREATHE in species.species_traits)) + var/breathes = (!(NO_BREATHE in dna.species.species_traits)) var/obj/item/organ/internal/L = get_organ_slot("lungs") if((breathes && !L) || breathes && L && (L.status & ORGAN_DEAD)) return FALSE @@ -219,8 +219,8 @@ /mob/living/carbon/human/handle_speech_sound() var/list/returns[2] - if(species.speech_sounds && prob(species.speech_chance)) - returns[1] = sound(pick(species.speech_sounds)) + if(dna.species.speech_sounds && prob(dna.species.speech_chance)) + returns[1] = sound(pick(dna.species.speech_sounds)) returns[2] = 50 return returns diff --git a/code/modules/mob/living/carbon/human/shock.dm b/code/modules/mob/living/carbon/human/shock.dm index 05042a226d6..e2d5dd79cec 100644 --- a/code/modules/mob/living/carbon/human/shock.dm +++ b/code/modules/mob/living/carbon/human/shock.dm @@ -23,7 +23,7 @@ /mob/living/carbon/human/proc/handle_shock() if(status_flags & GODMODE) //godmode return - if(NO_PAIN in species.species_traits) + if(NO_PAIN in dna.species.species_traits) return updateshock() @@ -43,7 +43,7 @@ if(shock_stage >= 30) if(shock_stage == 30) - custom_emote(1,"is having trouble keeping their eyes open.") + custom_emote(1,"is having trouble keeping [p_their()] eyes open.") EyeBlurry(2) Stuttering(5) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/_species.dm similarity index 88% rename from code/modules/mob/living/carbon/human/species/species.dm rename to code/modules/mob/living/carbon/human/species/_species.dm index 50f969cae45..c11d84451f9 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -1,11 +1,6 @@ -/* - Datum-based species. Should make for much cleaner and easier to maintain mutantrace code. -*/ - /datum/species var/name // Species name. var/name_plural // Pluralized name (since "[name]s" is not always valid) - var/path // Species path var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. @@ -18,10 +13,10 @@ var/blurb = "A completely nondescript species." // A brief lore summary for use in the chargen screen. var/butt_sprite = "human" - var/primitive_form // Lesser form, if any (ie. monkey for humans) - var/greater_form // Greater form, if any, ie. human for monkeys. + var/datum/species/primitive_form = null // Lesser form, if any (ie. monkey for humans) + var/datum/species/greater_form = null // Greater form, if any, ie. human for monkeys. var/tail // Name of tail image in species effects icon file. - var/unarmed //For empty hand harm-intent attack + var/datum/unarmed_attack/unarmed //For empty hand harm-intent attack var/unarmed_type = /datum/unarmed_attack var/slowdown = 0 // Passive movement speed malus (or boost, if negative) var/silent_steps = 0 // Stops step noises @@ -80,11 +75,10 @@ var/clothing_flags = 0 // Underwear and socks. var/exotic_blood + var/skinned_type var/bodyflags = 0 var/dietflags = 0 // Make sure you set this, otherwise it won't be able to digest a lot of foods - var/list/abilities = list() // For species-derived or admin-given powers - var/blood_color = "#A10808" //Red. var/flesh_color = "#FFC896" //Pink. var/single_gib_type = /obj/effect/decal/cleanable/blood/gibs @@ -94,10 +88,13 @@ //Used in icon caching. var/race_key = 0 var/icon/icon_template + var/is_small var/show_ssd = 1 var/can_revive_by_healing // Determines whether or not this species can be revived by simply healing them var/has_gender = TRUE + var/blacklisted = FALSE + var/dangerous_existence = FALSE //Death vars. var/death_message = "seizes up and falls limp, their eyes dead and lifeless..." @@ -154,9 +151,7 @@ "l_hand" = list("path" = /obj/item/organ/external/hand), "r_hand" = list("path" = /obj/item/organ/external/hand/right), "l_foot" = list("path" = /obj/item/organ/external/foot), - "r_foot" = list("path" = /obj/item/organ/external/foot/right) - ) - var/list/proc/species_abilities = list() + "r_foot" = list("path" = /obj/item/organ/external/foot/right)) /datum/species/New() //If the species has eyes, they are the default vision organ @@ -165,11 +160,11 @@ unarmed = new unarmed_type() -/datum/species/proc/get_random_name(var/gender) +/datum/species/proc/get_random_name(gender) var/datum/language/species_language = all_languages[language] return species_language.get_random_name(gender) -/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. +/datum/species/proc/create_organs(mob/living/carbon/human/H) //Handles creation of mob organs. QDEL_LIST(H.internal_organs) QDEL_LIST(H.bodyparts) @@ -262,27 +257,14 @@ . -= 2 return . -/datum/species/proc/handle_post_spawn(var/mob/living/carbon/C) //Handles anything not already covered by basic species assignment. - grant_abilities(C) +/datum/species/proc/on_species_gain(mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. return -/datum/species/proc/updatespeciescolor(var/mob/living/carbon/human/H) //Handles changing icobase for species that have multiple skin colors. - return - -/datum/species/proc/grant_abilities(var/mob/living/carbon/human/H) - for(var/proc/ability in species_abilities) - H.verbs += ability - return - -/datum/species/proc/handle_pre_change(var/mob/living/carbon/human/H) - if(H.butcher_results)//clear it out so we don't butcher a actual human. +/datum/species/proc/on_species_loss(mob/living/carbon/human/H) + if(H.butcher_results) //clear it out so we don't butcher a actual human. H.butcher_results = null - remove_abilities(H) - return -/datum/species/proc/remove_abilities(var/mob/living/carbon/human/H) - for(var/proc/ability in species_abilities) - H.verbs -= ability +/datum/species/proc/updatespeciescolor(mob/living/carbon/human/H) //Handles changing icobase for species that have multiple skin colors. return // Do species-specific reagent handling here @@ -294,47 +276,42 @@ if(R.id == exotic_blood) H.blood_volume = min(H.blood_volume + round(R.volume, 0.1), BLOOD_VOLUME_NORMAL) H.reagents.del_reagent(R.id) - return 0 - return 1 + return FALSE + return TRUE // For special snowflake species effects // (Slime People changing color based on the reagents they consume) -/datum/species/proc/handle_life(var/mob/living/carbon/human/H) +/datum/species/proc/handle_life(mob/living/carbon/human/H) if((NO_BREATHE in species_traits) || (BREATHLESS in H.mutations)) H.setOxyLoss(0) H.SetLoseBreath(0) -/datum/species/proc/handle_dna(var/mob/living/carbon/C, var/remove) //Handles DNA mutations, as that doesn't work at init. Make sure you call genemutcheck on any blocks changed here +/datum/species/proc/handle_dna(mob/living/carbon/human/H, remove) //Handles DNA mutations, as that doesn't work at init. Make sure you call genemutcheck on any blocks changed here return -// Used for species-specific names (Vox, etc) -/datum/species/proc/makeName(var/gender,var/mob/living/carbon/human/H=null) - if(gender==FEMALE) return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) - else return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) - -/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). +/datum/species/proc/handle_death(mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). return /datum/species/proc/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) if(attacker_style && attacker_style.help_act(user, target))//adminfu only... - return 1 + return TRUE if(target.health >= config.health_threshold_crit) target.help_shake_act(user) - return 1 + return TRUE else user.do_cpr(target) /datum/species/proc/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) if(attacker_style && attacker_style.grab_act(user, target)) - return 1 + return TRUE else target.grabbedby(user) - return 1 + return TRUE /datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) //Vampire code if(user.mind && user.mind.vampire && (user.mind in ticker.mode.vampires) && !user.mind.vampire.draining && user.zone_sel && user.zone_sel.selecting == "head" && target != user) - if((NO_BLOOD in target.species.species_traits) || target.species.exotic_blood || !target.blood_volume) + if((NO_BLOOD in target.dna.species.species_traits) || target.dna.species.exotic_blood || !target.blood_volume) to_chat(user, "They have no blood!") return if(target.mind && target.mind.vampire && (target.mind in ticker.mode.vampires)) @@ -352,38 +329,35 @@ return //end vampire codes if(attacker_style && attacker_style.harm_act(user, target)) - return 1 + return TRUE else - var/datum/unarmed_attack/attack = user.species.unarmed + var/datum/unarmed_attack/attack = user.dna.species.unarmed - user.do_attack_animation(target) - add_attack_logs(user, target, "Melee attacked with fists", admin_notify = target.ckey ? TRUE : FALSE) + user.do_attack_animation(target, attack.animation_type) + add_attack_logs(user, target, "Melee attacked with fists", target.ckey ? null : ATKLOG_ALL) if(!iscarbon(user)) target.LAssailant = null else target.LAssailant = user - var/damage = rand(user.species.punchdamagelow, user.species.punchdamagehigh) + var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh) damage += attack.damage if(!damage) playsound(target.loc, attack.miss_sound, 25, 1, -1) target.visible_message("[user] tried to [pick(attack.attack_verb)] [target]!") - return 0 + return FALSE var/obj/item/organ/external/affecting = target.get_organ(ran_zone(user.zone_sel.selecting)) var/armor_block = target.run_armor_check(affecting, "melee") - if(HULK in user.mutations) - target.adjustBruteLoss(15) - playsound(target.loc, attack.attack_sound, 25, 1, -1) target.visible_message("[user] [pick(attack.attack_verb)]ed [target]!") target.apply_damage(damage, BRUTE, affecting, armor_block, sharp = attack.sharp) //moving this back here means Armalis are going to knock you down 70% of the time, but they're pure adminbus anyway. - if((target.stat != DEAD) && damage >= user.species.punchstunthreshold) + if((target.stat != DEAD) && damage >= user.dna.species.punchstunthreshold) target.visible_message("[user] has weakened [target]!", \ "[user] has weakened [target]!") target.apply_effect(4, WEAKEN, armor_block) @@ -393,10 +367,10 @@ /datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) if(attacker_style && attacker_style.disarm_act(user, target)) - return 1 + return TRUE else - add_attack_logs(user, target, "Disarmed", admin_notify = FALSE) - user.do_attack_animation(target) + add_attack_logs(user, target, "Disarmed", ATKLOG_ALL) + user.do_attack_animation(target, ATTACK_EFFECT_DISARM) if(target.w_uniform) target.w_uniform.add_fingerprint(user) var/obj/item/organ/external/affecting = target.get_organ(ran_zone(user.zone_sel.selecting)) @@ -405,7 +379,7 @@ target.apply_effect(2, WEAKEN, target.run_armor_check(affecting, "melee")) playsound(target.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) target.visible_message("[user] has pushed [target]!") - add_attack_logs(user, target, "Pushed over", admin_notify = FALSE) + add_attack_logs(user, target, "Pushed over", ATKLOG_ALL) if(!iscarbon(user)) target.LAssailant = null else @@ -466,7 +440,7 @@ if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(0, M.name, attack_type = UNARMED_ATTACK)) add_attack_logs(M, H, "Melee attacked with fists (miss/block)") H.visible_message("[M] attempted to touch [H]!") - return 0 + return FALSE switch(M.a_intent) if(INTENT_HELP) @@ -490,27 +464,22 @@ /datum/species/proc/after_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE) return -/datum/species/proc/can_understand(var/mob/other) +/datum/species/proc/can_understand(mob/other) return // Called in life() when the mob has no client. -/datum/species/proc/handle_npc(var/mob/living/carbon/human/H) +/datum/species/proc/handle_npc(mob/living/carbon/human/H) return //Species unarmed attacks /datum/unarmed_attack - var/attack_verb = list("attack") // Empty hand hurt intent verb. + var/attack_verb = list("punch") // Empty hand hurt intent verb. var/damage = 0 // How much flat bonus damage an attack will do. This is a *bonus* guaranteed damage amount on top of the random damage attacks do. var/attack_sound = "punch" var/miss_sound = 'sound/weapons/punchmiss.ogg' - var/sharp = 0 - -/datum/unarmed_attack/punch - attack_verb = list("punch") - -/datum/unarmed_attack/punch/weak - attack_verb = list("flail") + var/sharp = FALSE + var/animation_type = ATTACK_EFFECT_PUNCH /datum/unarmed_attack/diona attack_verb = list("lash", "bludgeon") @@ -519,14 +488,21 @@ attack_verb = list("scratch", "claw") attack_sound = 'sound/weapons/slice.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' - sharp = 1 + sharp = TRUE + animation_type = ATTACK_EFFECT_CLAW + +/datum/unarmed_attack/bite + attack_verb = list("chomp") + attack_sound = 'sound/weapons/bite.ogg' + sharp = TRUE + animation_type = ATTACK_EFFECT_BITE /datum/unarmed_attack/claws/armalis attack_verb = list("slash", "claw") damage = 6 /datum/species/proc/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user) - return 0 + return FALSE /datum/species/proc/handle_vision(mob/living/carbon/human/H) // Right now this just handles blind, blurry, and similar states @@ -632,7 +608,7 @@ Returns the path corresponding to the corresponding organ It'll return null if the organ doesn't correspond, so include null checks when using this! */ //Fethas Todo:Do i need to redo this? -/datum/species/proc/return_organ(var/organ_slot) +/datum/species/proc/return_organ(organ_slot) if(!(organ_slot in has_organ)) return null return has_organ[organ_slot] @@ -731,3 +707,14 @@ It'll return null if the organ doesn't correspond, so include null checks when u /datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source) if(abs(temperature - M.bodytemperature) > 10) //If our water and mob temperature varies by more than 10K, cool or/ heat them appropriately M.bodytemperature = (temperature + M.bodytemperature) * 0.5 //Approximation for gradual heating or cooling + +/proc/get_random_species(species_name = FALSE) // Returns a random non black-listed or hazardous species, either as a string or datum + var/static/list/random_species = list() + if(!random_species.len) + for(var/thing in subtypesof(/datum/species)) + var/datum/species/S = thing + if(!initial(S.dangerous_existence) && !initial(S.blacklisted)) + random_species += initial(S.name) + var/picked_species = pick(random_species) + var/datum/species/selected_species = GLOB.all_species[picked_species] + return species_name ? picked_species : selected_species.type \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/abductor.dm b/code/modules/mob/living/carbon/human/species/abductor.dm index 3e1bb968c81..f51870d9e00 100644 --- a/code/modules/mob/living/carbon/human/species/abductor.dm +++ b/code/modules/mob/living/carbon/human/species/abductor.dm @@ -3,10 +3,8 @@ name_plural = "Abductors" icobase = 'icons/mob/human_races/r_abductor.dmi' deform = 'icons/mob/human_races/r_abductor.dmi' - path = /mob/living/carbon/human/abductor language = "Abductor Mindlink" default_language = "Abductor Mindlink" - unarmed_type = /datum/unarmed_attack/punch eyes = "blank_eyes" has_organ = list( "heart" = /obj/item/organ/internal/heart, @@ -17,7 +15,7 @@ "eyes" = /obj/item/organ/internal/eyes/abductor //3 darksight. ) - species_traits = list(NO_BLOOD, NO_BREATHE, VIRUSIMMUNE, NOGUNS) + species_traits = list(NO_BLOOD, NO_BREATHE, VIRUSIMMUNE, NOGUNS, NO_EXAMINE) oxy_mod = 0 @@ -28,14 +26,21 @@ female_scream_sound = 'sound/goonstation/voice/male_scream.ogg' female_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') female_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' //Abductors always scream like guys + var/team = 1 + var/scientist = FALSE // vars to not pollute spieces list with castes /datum/species/abductor/can_understand(mob/other) //Abductors can understand everyone, but they can only speak over their mindlink to another team-member - return 1 + return TRUE -/datum/species/abductor/handle_post_spawn(mob/living/carbon/human/H) +/datum/species/abductor/on_species_gain(mob/living/carbon/human/H) + ..() H.gender = NEUTER - if(H.mind) - H.mind.abductor = new /datum/abductor H.languages.Cut() //Under no condition should you be able to speak any language H.add_language("Abductor Mindlink") //other than over the abductor's own mindlink - return ..() + var/datum/atom_hud/abductor_hud = huds[DATA_HUD_ABDUCTOR] + abductor_hud.add_hud_to(H) + +/datum/species/abductor/on_species_loss(mob/living/carbon/human/H) + ..() + var/datum/atom_hud/abductor_hud = huds[DATA_HUD_ABDUCTOR] + abductor_hud.remove_hud_from(H) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/diona.dm b/code/modules/mob/living/carbon/human/species/diona.dm new file mode 100644 index 00000000000..6f53be4d3c8 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/diona.dm @@ -0,0 +1,113 @@ +/datum/species/diona + name = "Diona" + name_plural = "Dionaea" + icobase = 'icons/mob/human_races/r_diona.dmi' + deform = 'icons/mob/human_races/r_def_plant.dmi' + language = "Rootspeak" + speech_sounds = list('sound/voice/dionatalk1.ogg') //Credit https://www.youtube.com/watch?v=ufnvlRjsOTI [0:13 - 0:16] + speech_chance = 20 + unarmed_type = /datum/unarmed_attack/diona + //primitive_form = "Nymph" + slowdown = 5 + remains_type = /obj/effect/decal/cleanable/ash + + + warning_low_pressure = 50 + hazard_low_pressure = -1 + + cold_level_1 = 50 + cold_level_2 = -1 + cold_level_3 = -1 + + heat_level_1 = 300 + heat_level_2 = 340 + heat_level_3 = 400 + + blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \ + species hailing from Epsilon Ursae Minoris. Each 'diona' is a cluster of numerous cat-sized organisms called nymphs; \ + there is no effective upper limit to the number that can fuse in gestalt, and reports exist of the Epsilon Ursae \ + Minoris primary being ringed with a cloud of singing space-station-sized entities.

    The Dionaea coexist peacefully with \ + all known species, especially the Skrell. Their communal mind makes them slow to react, and they have difficulty understanding \ + even the simplest concepts of other minds. Their alien physiology allows them survive happily off a diet of nothing but light, \ + water and other radiation." + + species_traits = list(NO_BREATHE, RADIMMUNE, IS_PLANT, NO_BLOOD, NO_PAIN) + clothing_flags = HAS_SOCKS + default_hair_colour = "#000000" + dietflags = 0 //Diona regenerate nutrition in light and water, no diet necessary + taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE + skinned_type = /obj/item/stack/sheet/wood + + oxy_mod = 0 + + body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not + blood_color = "#004400" + flesh_color = "#907E4A" + butt_sprite = "diona" + + reagent_tag = PROCESS_ORG + + has_organ = list( + "nutrient channel" = /obj/item/organ/internal/liver/diona, + "neural strata" = /obj/item/organ/internal/heart/diona, + "receptor node" = /obj/item/organ/internal/eyes/diona, //Default darksight of 2. + "gas bladder" = /obj/item/organ/internal/brain/diona, + "polyp segment" = /obj/item/organ/internal/kidneys/diona, + "anchoring ligament" = /obj/item/organ/internal/appendix/diona + ) + + vision_organ = /obj/item/organ/internal/eyes/diona + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest/diona), + "groin" = list("path" = /obj/item/organ/external/groin/diona), + "head" = list("path" = /obj/item/organ/external/head/diona), + "l_arm" = list("path" = /obj/item/organ/external/arm/diona), + "r_arm" = list("path" = /obj/item/organ/external/arm/right/diona), + "l_leg" = list("path" = /obj/item/organ/external/leg/diona), + "r_leg" = list("path" = /obj/item/organ/external/leg/right/diona), + "l_hand" = list("path" = /obj/item/organ/external/hand/diona), + "r_hand" = list("path" = /obj/item/organ/external/hand/right/diona), + "l_foot" = list("path" = /obj/item/organ/external/foot/diona), + "r_foot" = list("path" = /obj/item/organ/external/foot/right/diona) + ) + + suicide_messages = list( + "is losing branches!", + "pulls out a secret stash of herbicide and takes a hearty swig!", + "is pulling themselves apart!") + +/datum/species/diona/can_understand(mob/other) + if(istype(other, /mob/living/simple_animal/diona)) + return 1 + return 0 + +/datum/species/diona/on_species_gain(mob/living/carbon/human/H) + ..() + H.gender = NEUTER + +/datum/species/diona/handle_life(mob/living/carbon/human/H) + H.radiation = Clamp(H.radiation, 0, 100) //We have to clamp this first, then decrease it, or there's a few edge cases of massive heals if we clamp and decrease at the same time. + var/rads = H.radiation / 25 + H.radiation = max(H.radiation-rads, 0) + H.nutrition = min(H.nutrition+rads, NUTRITION_LEVEL_WELL_FED+10) + H.adjustBruteLoss(-(rads)) + H.adjustToxLoss(-(rads)) + + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(H.loc)) //else, there's considered to be no light + var/turf/T = H.loc + light_amount = min(T.get_lumcount() * 10, 5) //hardcapped so it's not abused by having a ton of flashlights + H.nutrition = min(H.nutrition+light_amount, NUTRITION_LEVEL_WELL_FED+10) + + if(light_amount > 0) + H.clear_alert("nolight") + else + H.throw_alert("nolight", /obj/screen/alert/nolight) + + if((light_amount >= 5) && !H.suiciding) //if there's enough light, heal + + H.adjustBruteLoss(-(light_amount/2)) + H.adjustFireLoss(-(light_amount/4)) + if(H.nutrition < NUTRITION_LEVEL_STARVING+50) + H.take_overall_damage(10,0) + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/drask.dm b/code/modules/mob/living/carbon/human/species/drask.dm new file mode 100644 index 00000000000..7914c4e7d70 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/drask.dm @@ -0,0 +1,62 @@ +/datum/species/drask + name = "Drask" + name_plural = "Drask" + icobase = 'icons/mob/human_races/r_drask.dmi' + deform = 'icons/mob/human_races/r_drask.dmi' + language = "Orluum" + eyes = "drask_eyes_s" + + speech_sounds = list('sound/voice/DraskTalk.ogg') + speech_chance = 20 + male_scream_sound = 'sound/voice/DraskTalk2.ogg' + female_scream_sound = 'sound/voice/DraskTalk2.ogg' + male_cough_sounds = 'sound/voice/DraskCough.ogg' + female_cough_sounds = 'sound/voice/DraskCough.ogg' + male_sneeze_sound = 'sound/voice/DraskSneeze.ogg' + female_sneeze_sound = 'sound/voice/DraskSneeze.ogg' + + burn_mod = 2 + //exotic_blood = "cryoxadone" + body_temperature = 273 + + blurb = "Hailing from Hoorlm, planet outside what is usually considered a habitable \ + orbit, the Drask evolved to live in extreme cold. Their strange bodies seem \ + to operate better the colder their surroundings are, and can regenerate rapidly \ + when breathing supercooled gas.

    On their homeworld, the Drask live long lives \ + in their labyrinthine settlements, carved out beneath Hoorlm's icy surface, where the air \ + is of breathable density." + + suicide_messages = list( + "is self-warming with friction!", + "is jamming fingers through their big eyes!", + "is sucking in warm air!", + "is holding their breath!") + + species_traits = list(LIPS, IS_WHITELISTED) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT + bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS + dietflags = DIET_OMNI + + cold_level_1 = -1 //Default 260 - Lower is better + cold_level_2 = -1 //Default 200 + cold_level_3 = -1 //Default 120 + coldmod = -1 + + heat_level_1 = 300 //Default 360 - Higher is better + heat_level_2 = 340 //Default 400 + heat_level_3 = 400 //Default 460 + heatmod = 2 + + flesh_color = "#a3d4eb" + reagent_tag = PROCESS_ORG + base_color = "#a3d4eb" + blood_color = "#a3d4eb" + butt_sprite = "drask" + + has_organ = list( + "heart" = /obj/item/organ/internal/heart/drask, + "lungs" = /obj/item/organ/internal/lungs/drask, + "metabolic strainer" = /obj/item/organ/internal/liver/drask, + "eyes" = /obj/item/organ/internal/eyes/drask, //5 darksight. + "brain" = /obj/item/organ/internal/brain/drask + ) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index c289ba3a19e..c3fa38611b5 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -5,7 +5,6 @@ icobase = 'icons/mob/human_races/r_golem.dmi' deform = 'icons/mob/human_races/r_golem.dmi' - default_language = "Galactic Common" species_traits = list(NO_BREATHE, NO_BLOOD, RADIMMUNE, VIRUSIMMUNE, NOGUNS) oxy_mod = 0 @@ -13,7 +12,6 @@ dietflags = DIET_OMNI //golems can eat anything because they are magic or something reagent_tag = PROCESS_ORG - unarmed_type = /datum/unarmed_attack/punch punchdamagelow = 5 punchdamagehigh = 14 punchstunthreshold = 11 //about 40% chance to stun @@ -44,7 +42,8 @@ "is crumbling into dust!", "is smashing their body apart!") -/datum/species/golem/handle_post_spawn(var/mob/living/carbon/human/H) +/datum/species/golem/on_species_gain(mob/living/carbon/human/H) + ..() if(H.mind) H.mind.assigned_role = "Golem" H.mind.special_role = SPECIAL_ROLE_GOLEM @@ -55,7 +54,6 @@ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/golem(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/golem(H), slot_wear_mask) H.equip_to_slot_or_del(new /obj/item/clothing/gloves/golem(H), slot_gloves) - ..() ////////Adamantine Golem stuff I dunno where else to put it diff --git a/code/modules/mob/living/carbon/human/species/grey.dm b/code/modules/mob/living/carbon/human/species/grey.dm new file mode 100644 index 00000000000..e8cb6b13083 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/grey.dm @@ -0,0 +1,51 @@ +/datum/species/grey + name = "Grey" + name_plural = "Greys" + icobase = 'icons/mob/human_races/r_grey.dmi' + deform = 'icons/mob/human_races/r_def_grey.dmi' + language = "Psionic Communication" + eyes = "grey_eyes_s" + butt_sprite = "grey" + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/grey, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain/grey, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes/grey //5 darksight. + ) + + brute_mod = 1.25 //greys are fragile + + default_genes = list(REMOTE_TALK) + + + species_traits = list(LIPS, IS_WHITELISTED, CAN_BE_FAT) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_BODY_MARKINGS + dietflags = DIET_HERB + reagent_tag = PROCESS_ORG + blood_color = "#A200FF" + +/datum/species/grey/handle_dna(mob/living/carbon/human/H, remove) + ..() + H.dna.SetSEState(REMOTETALKBLOCK, !remove, 1) + genemutcheck(H, REMOTETALKBLOCK, null, MUTCHK_FORCED) + +/datum/species/grey/water_act(mob/living/carbon/human/H, volume, temperature, source) + ..() + H.take_organ_damage(5, min(volume, 20)) + H.emote("scream") + +/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H) + var/speech_pref = H.client.prefs.speciesprefs + if(speech_pref) + H.mind.speech_span = "wingdings" + +/datum/species/grey/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) + if(R.id == "sacid") + H.reagents.del_reagent(R.id) + return 0 + return ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/human.dm b/code/modules/mob/living/carbon/human/species/human.dm new file mode 100644 index 00000000000..2a161ab9318 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/human.dm @@ -0,0 +1,20 @@ +/datum/species/human + name = "Human" + name_plural = "Humans" + icobase = 'icons/mob/human_races/r_human.dmi' + deform = 'icons/mob/human_races/r_def_human.dmi' + primitive_form = /datum/species/monkey + language = "Sol Common" + species_traits = list(LIPS, CAN_BE_FAT) + skinned_type = /obj/item/stack/sheet/animalhide/human + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS + dietflags = DIET_OMNI + blurb = "Humanity originated in the Sol system, and over the last five centuries has spread \ + colonies across a wide swathe of space. They hold a wide range of forms and creeds.

    \ + While the central Sol government maintains control of its far-flung people, powerful corporate \ + interests, rampant cyber and bio-augmentation and secretive factions make life on most human \ + worlds tumultous at best." + + reagent_tag = PROCESS_ORG + //Has standard darksight of 2. \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/kidan.dm b/code/modules/mob/living/carbon/human/species/kidan.dm new file mode 100644 index 00000000000..583e098054b --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/kidan.dm @@ -0,0 +1,41 @@ +/datum/species/kidan + name = "Kidan" + name_plural = "Kidan" + icobase = 'icons/mob/human_races/r_kidan.dmi' + deform = 'icons/mob/human_races/r_def_kidan.dmi' + language = "Chittin" + unarmed_type = /datum/unarmed_attack/claws + + brute_mod = 0.8 + + species_traits = list(IS_WHITELISTED) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_HEAD_ACCESSORY | HAS_HEAD_MARKINGS | HAS_BODY_MARKINGS + eyes = "kidan_eyes_s" + dietflags = DIET_HERB + blood_color = "#FB9800" + reagent_tag = PROCESS_ORG + //Default styles for created mobs. + default_headacc = "Normal Antennae" + butt_sprite = "kidan" + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/kidan, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. + "lantern" = /obj/item/organ/internal/lantern + ) + + allowed_consumed_mobs = list(/mob/living/simple_animal/diona) + + suicide_messages = list( + "is attempting to bite their antenna off!", + "is jamming their claws into their eye sockets!", + "is twisting their own neck!", + "is cracking their exoskeleton!", + "is stabbing themselves with their mandibles!", + "is holding their breath!") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/machine.dm b/code/modules/mob/living/carbon/human/species/machine.dm new file mode 100644 index 00000000000..fa3e4e321a9 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/machine.dm @@ -0,0 +1,135 @@ +/datum/species/machine + name = "Machine" + name_plural = "Machines" + + blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \ + robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \ + to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \ + generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \ + inhuman in outlook and perspective." + + icobase = 'icons/mob/human_races/r_machine.dmi' + deform = 'icons/mob/human_races/r_machine.dmi' + language = "Trinary" + remains_type = /obj/effect/decal/remains/robot + skinned_type = /obj/item/stack/sheet/metal // Let's grind up IPCs for station resources! + + eyes = "blank_eyes" + brute_mod = 2.5 // 100% * 2.5 * 0.6 (robolimbs) ~= 150% + burn_mod = 2.5 // So they take 50% extra damage from brute/burn overall. + tox_mod = 0 + clone_mod = 0 + oxy_mod = 0 + death_message = "gives one shrill beep before falling limp, their monitor flashing blue before completely shutting off..." + + species_traits = list(IS_WHITELISTED, NO_BREATHE, NO_SCAN, NO_BLOOD, NO_PAIN, NO_DNA, RADIMMUNE, VIRUSIMMUNE, NOTRANSSTING) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_SKIN_COLOR | HAS_HEAD_MARKINGS | HAS_HEAD_ACCESSORY | ALL_RPARTS + dietflags = 0 //IPCs can't eat, so no diet + taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE + blood_color = "#1F181F" + flesh_color = "#AAAAAA" + //Default styles for created mobs. + default_hair = "Blue IPC Screen" + can_revive_by_healing = 1 + has_gender = FALSE + reagent_tag = PROCESS_SYN + male_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' + female_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' + male_cough_sounds = list('sound/effects/mob_effects/m_machine_cougha.ogg','sound/effects/mob_effects/m_machine_coughb.ogg', 'sound/effects/mob_effects/m_machine_coughc.ogg') + female_cough_sounds = list('sound/effects/mob_effects/f_machine_cougha.ogg','sound/effects/mob_effects/f_machine_coughb.ogg') + male_sneeze_sound = 'sound/effects/mob_effects/machine_sneeze.ogg' + female_sneeze_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg' + butt_sprite = "machine" + + has_organ = list( + "brain" = /obj/item/organ/internal/brain/mmi_holder/posibrain, + "cell" = /obj/item/organ/internal/cell, + "optics" = /obj/item/organ/internal/eyes/optical_sensor, //Default darksight of 2. + "charger" = /obj/item/organ/internal/cyberimp/arm/power_cord + ) + + vision_organ = /obj/item/organ/internal/eyes/optical_sensor + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest/ipc), + "groin" = list("path" = /obj/item/organ/external/groin/ipc), + "head" = list("path" = /obj/item/organ/external/head/ipc), + "l_arm" = list("path" = /obj/item/organ/external/arm/ipc), + "r_arm" = list("path" = /obj/item/organ/external/arm/right/ipc), + "l_leg" = list("path" = /obj/item/organ/external/leg/ipc), + "r_leg" = list("path" = /obj/item/organ/external/leg/right/ipc), + "l_hand" = list("path" = /obj/item/organ/external/hand/ipc), + "r_hand" = list("path" = /obj/item/organ/external/hand/right/ipc), + "l_foot" = list("path" = /obj/item/organ/external/foot/ipc), + "r_foot" = list("path" = /obj/item/organ/external/foot/right/ipc) + ) + + suicide_messages = list( + "is powering down!", + "is smashing their own monitor!", + "is twisting their own neck!", + "is downloading extra RAM!", + "is frying their own circuits!", + "is blocking their ventilation port!") + + var/datum/action/innate/change_monitor/monitor + +/datum/species/machine/on_species_gain(mob/living/carbon/human/H) + ..() + monitor = new() + monitor.Grant(H) + +/datum/species/machine/on_species_loss(mob/living/carbon/human/H) + ..() + if(monitor) + monitor.Remove(H) + +/datum/species/machine/handle_death(mob/living/carbon/human/H) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!head_organ) + return + head_organ.h_style = "Bald" + head_organ.f_style = "Shaved" + spawn(100) + if(H && head_organ) + H.update_hair() + H.update_fhair() + +// Allows IPC's to change their monitor display +/datum/action/innate/change_monitor + name = "Change Monitor" + check_flags = AB_CHECK_CONSCIOUS + button_icon_state = "scan_mode" + +/datum/action/innate/change_monitor/Activate() + var/mob/living/carbon/human/H = owner + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + + if(!head_organ) //If the rock'em-sock'em robot's head came off during a fight, they shouldn't be able to change their screen/optics. + to_chat(H, "Where's your head at? Can't change your monitor/display without one.") + return + + var/datum/robolimb/robohead = all_robolimbs[head_organ.model] + if(!head_organ) + return + if(!robohead.is_monitor) //If they've got a prosthetic head and it isn't a monitor, they've no screen to adjust. Instead, let them change the colour of their optics! + var/optic_colour = input(H, "Select optic colour", H.m_colours["head"]) as color|null + if(H.incapacitated()) + to_chat(H, "You were interrupted while changing the colour of your optics.") + return + if(optic_colour) + H.change_markings(optic_colour, "head") + + else if(robohead.is_monitor) //Means that the character's head is a monitor (has a screen). Time to customize. + var/list/hair = list() + for(var/i in hair_styles_public_list) + var/datum/sprite_accessory/hair/tmp_hair = hair_styles_public_list[i] + if((head_organ.dna.species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. + hair += i + + var/new_style = input(H, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair + if(H.incapacitated()) + to_chat(src, "You were interrupted while changing your monitor display.") + return + if(new_style) + H.change_hair(new_style) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index 07d3215126e..5e926a23870 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -8,10 +8,11 @@ damage_overlays = 'icons/mob/human_races/masks/dam_monkey.dmi' damage_mask = 'icons/mob/human_races/masks/dam_mask_monkey.dmi' blood_mask = 'icons/mob/human_races/masks/blood_monkey.dmi' - path = /mob/living/carbon/human/monkey language = null default_language = "Chimpanzee" - greater_form = "Human" + species_traits = list(NO_EXAMINE) + skinned_type = /obj/item/stack/sheet/animalhide/monkey + greater_form = /datum/species/human is_small = 1 has_fine_manipulation = 0 ventcrawler = 1 @@ -28,14 +29,13 @@ reagent_tag = PROCESS_ORG //Has standard darksight of 2. - //unarmed_types = list(/datum/unarmed_attack/bite, /datum/unarmed_attack/claws) - //inherent_verbs = list(/mob/living/proc/ventcrawl) + unarmed_type = /datum/unarmed_attack/bite total_health = 75 brute_mod = 1.5 burn_mod = 1.5 -/datum/species/monkey/handle_npc(var/mob/living/carbon/human/H) +/datum/species/monkey/handle_npc(mob/living/carbon/human/H) if(H.stat != CONSCIOUS) return if(prob(33) && H.canmove && isturf(H.loc) && !H.pulledby) //won't move if being pulled @@ -46,16 +46,17 @@ /datum/species/monkey/get_random_name() return "[lowertext(name)] ([rand(100,999)])" -/datum/species/monkey/handle_post_spawn(var/mob/living/carbon/human/H) +/datum/species/monkey/on_species_gain(mob/living/carbon/human/H) + ..() H.real_name = "[lowertext(name)] ([rand(100,999)])" H.name = H.real_name H.butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/monkey = 5) +/datum/species/monkey/handle_dna(mob/living/carbon/human/H, remove) ..() - -/datum/species/monkey/handle_dna(var/mob/living/carbon/human/H) - H.dna.SetSEState(MONKEYBLOCK,1) - genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED) + if(!remove) + H.dna.SetSEState(MONKEYBLOCK, TRUE) + genemutcheck(H, MONKEYBLOCK, null, MUTCHK_FORCED) /datum/species/monkey/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user) switch(slot) @@ -100,7 +101,7 @@ icobase = 'icons/mob/human_races/monkeys/r_farwa.dmi' deform = 'icons/mob/human_races/monkeys/r_farwa.dmi' - greater_form = "Tajaran" + greater_form = /datum/species/tajaran default_language = "Farwa" flesh_color = "#AFA59E" base_color = "#000000" @@ -124,7 +125,7 @@ icobase = 'icons/mob/human_races/monkeys/r_wolpin.dmi' deform = 'icons/mob/human_races/monkeys/r_wolpin.dmi' - greater_form = "Vulpkanin" + greater_form = /datum/species/vulpkanin default_language = "Wolpin" flesh_color = "#966464" base_color = "#000000" @@ -148,7 +149,7 @@ icobase = 'icons/mob/human_races/monkeys/r_neara.dmi' deform = 'icons/mob/human_races/monkeys/r_neara.dmi' - greater_form = "Skrell" + greater_form = /datum/species/skrell default_language = "Neara" flesh_color = "#8CD7A3" blood_color = "#1D2CBF" @@ -163,7 +164,7 @@ deform = 'icons/mob/human_races/monkeys/r_stok.dmi' tail = "stoktail" - greater_form = "Unathi" + greater_form = /datum/species/unathi default_language = "Stok" flesh_color = "#34AF10" base_color = "#000000" diff --git a/code/modules/mob/living/carbon/human/species/nucleation.dm b/code/modules/mob/living/carbon/human/species/nucleation.dm new file mode 100644 index 00000000000..21d8a5c0012 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/nucleation.dm @@ -0,0 +1,41 @@ +/datum/species/nucleation + name = "Nucleation" + name_plural = "Nucleations" + icobase = 'icons/mob/human_races/r_nucleation.dmi' + blacklisted = TRUE + blurb = "A sub-race of unfortunates who have been exposed to too much supermatter radiation. As a result, \ + supermatter crystal clusters have begun to grow across their bodies. Research to find a cure for this ailment \ + has been slow, and so this is a common fate for veteran engineers. The supermatter crystals produce oxygen, \ + negating the need for the individual to breathe. Their massive change in biology, however, renders most medicines \ + obselete. Ionizing radiation seems to cause resonance in some of their crystals, which seems to encourage regeneration \ + and produces a calming effect on the individual. Nucleations are highly stigmatized, and are treated much in the same \ + way as lepers were back on Earth." + language = "Sol Common" + burn_mod = 4 // holy shite, poor guys wont survive half a second cooking smores + brute_mod = 2 // damn, double wham, double dam + oxy_mod = 0 + species_traits = list(LIPS, IS_WHITELISTED, NO_BREATHE, NO_BLOOD, NO_PAIN, NO_SCAN, RADIMMUNE) + dietflags = DIET_OMNI //still human at their core, so they maintain their eating habits and diet + + //Default styles for created mobs. + default_hair = "Nucleation Crystals" + + reagent_tag = PROCESS_ORG + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "crystallized brain" = /obj/item/organ/internal/brain/crystal, + "eyes" = /obj/item/organ/internal/eyes/luminescent_crystal, //Standard darksight of 2. + "strange crystal" = /obj/item/organ/internal/nucleation/strange_crystal + ) + vision_organ = /obj/item/organ/internal/eyes/luminescent_crystal + +/datum/species/nucleation/on_species_gain(mob/living/carbon/human/H) + ..() + H.light_color = "#1C1C00" + H.set_light(2) + +/datum/species/nucleation/handle_death(mob/living/carbon/human/H) + var/turf/T = get_turf(H) + H.visible_message("[H]'s body explodes, leaving behind a pile of microscopic crystals!") + explosion(T, 0, 0, 2, 2) // Create a small explosion burst upon death + qdel(H) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm index 620d49254f3..b49dd88d8e6 100644 --- a/code/modules/mob/living/carbon/human/species/plasmaman.dm +++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm @@ -3,10 +3,11 @@ name_plural = "Plasmamen" icobase = 'icons/mob/human_races/r_plasmaman_sb.dmi' deform = 'icons/mob/human_races/r_plasmaman_pb.dmi' // TODO: Need deform. + dangerous_existence = TRUE //So so much //language = "Clatter" - unarmed_type = /datum/unarmed_attack/punch species_traits = list(IS_WHITELISTED, NO_BLOOD, NOTRANSSTING) + skinned_type = /obj/item/stack/sheet/mineral/plasma // We're low on plasma, R&D! *eyes plasmaman co-worker intently* dietflags = DIET_OMNI reagent_tag = PROCESS_ORG @@ -162,7 +163,7 @@ H.internal = H.get_item_by_slot(tank_slot) H.update_action_buttons_icon() -/datum/species/plasmaman/handle_life(var/mob/living/carbon/human/H) +/datum/species/plasmaman/handle_life(mob/living/carbon/human/H) if(!istype(H.wear_suit, /obj/item/clothing/suit/space/eva/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/eva/plasmaman)) var/datum/gas_mixture/environment = H.loc.return_air() if(environment && environment.oxygen && environment.oxygen >= OXYCONCEN_PLASMEN_IGNITION) //Plasmamen so long as there's enough oxygen (0.5 moles, same as it takes to burn gaseous plasma). @@ -178,7 +179,7 @@ H.update_fire() ..() -/datum/species/plasmaman/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R) +/datum/species/plasmaman/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) if(R.id == "plasma") H.adjustBruteLoss(-0.5*REAGENTS_EFFECT_MULTIPLIER) H.adjustFireLoss(-0.5*REAGENTS_EFFECT_MULTIPLIER) diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index 7480d7e3a66..df1ecd61484 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -4,8 +4,8 @@ icobase = 'icons/mob/human_races/r_shadow.dmi' deform = 'icons/mob/human_races/r_shadow.dmi' + dangerous_existence = TRUE - default_language = "Galactic Common" unarmed_type = /datum/unarmed_attack/claws ignored_by = list(/mob/living/simple_animal/hostile/faithless) @@ -29,7 +29,7 @@ "is twisting their own neck!", "is staring into the closest light source!") - var/grant_vision_toggle = 1 + var/grant_vision_toggle = TRUE var/datum/action/innate/shadow/darkvision/vision_toggle /datum/action/innate/shadow/darkvision //Darkvision toggle so shadowpeople can actually see where darkness is @@ -47,19 +47,19 @@ H.vision_type = null to_chat(H, "You adjust your vision to recognize the shadows.") -/datum/species/shadow/grant_abilities(var/mob/living/carbon/human/H) - . = ..() +/datum/species/shadow/on_species_gain(mob/living/carbon/human/H) + ..() if(grant_vision_toggle) vision_toggle = new vision_toggle.Grant(H) -/datum/species/shadow/remove_abilities(var/mob/living/carbon/human/H) - . = ..() +/datum/species/shadow/on_species_loss(mob/living/carbon/human/H) + ..() if(grant_vision_toggle && vision_toggle) H.vision_type = null vision_toggle.Remove(H) -/datum/species/shadow/handle_life(var/mob/living/carbon/human/H) +/datum/species/shadow/handle_life(mob/living/carbon/human/H) var/light_amount = 0 if(isturf(H.loc)) var/turf/T = H.loc diff --git a/code/modules/mob/living/carbon/human/species/shadowling.dm b/code/modules/mob/living/carbon/human/species/shadowling.dm new file mode 100644 index 00000000000..1ce7b5cd0e0 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/shadowling.dm @@ -0,0 +1,86 @@ +/datum/species/shadow/ling + //Normal shadowpeople but with enhanced effects + name = "Shadowling" + + icobase = 'icons/mob/human_races/r_shadowling.dmi' + deform = 'icons/mob/human_races/r_shadowling.dmi' + blacklisted = TRUE + + blood_color = "#555555" + flesh_color = "#222222" + + species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE, NOGUNS, NO_EXAMINE) //Can't use guns due to muzzle flash + burn_mod = 1.5 //1.5x burn damage, 2x is excessive + oxy_mod = 0 + heatmod = 1.5 + + silent_steps = 1 + grant_vision_toggle = 0 + + has_organ = list( + "brain" = /obj/item/organ/internal/brain, + "eyes" = /obj/item/organ/internal/eyes) + +/datum/species/shadow/ling/handle_life(mob/living/carbon/human/H) + if(!H.weakeyes) + H.weakeyes = 1 //Makes them more vulnerable to flashes and flashbangs + var/light_amount = 0 + H.nutrition = NUTRITION_LEVEL_WELL_FED //i aint never get hongry + if(isturf(H.loc)) + var/turf/T = H.loc + light_amount = T.get_lumcount() * 10 + if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move) //Can survive in very small light levels. Also doesn't take damage while incorporeal, for shadow walk purposes + H.throw_alert("lightexposure", /obj/screen/alert/lightexposure) + H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN) + if(H.stat != DEAD) + to_chat(H, "The light burns you!")//Message spam to say "GET THE FUCK OUT" + H << 'sound/weapons/sear.ogg' + else if(light_amount < LIGHT_HEAL_THRESHOLD) + H.clear_alert("lightexposure") + var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes) + if(istype(E)) + E.receive_damage(-1) + H.heal_overall_damage(5, 5) + H.adjustToxLoss(-5) + H.adjustBrainLoss(-25) //Shad O. Ling gibbers, "CAN U BE MY THRALL?!!" + H.AdjustEyeBlurry(-1) + H.CureNearsighted() + H.CureBlind() + H.adjustCloneLoss(-1) + H.SetWeakened(0) + H.SetStunned(0) + ..() + + +/datum/species/shadow/ling/lesser //Empowered thralls. Obvious, but powerful + name = "Lesser Shadowling" + + icobase = 'icons/mob/human_races/r_lshadowling.dmi' + deform = 'icons/mob/human_races/r_lshadowling.dmi' + + blood_color = "#CCCCCC" + flesh_color = "#AAAAAA" + + species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE, NO_EXAMINE) + burn_mod = 1.1 + oxy_mod = 0 + heatmod = 1.1 + +/datum/species/shadow/ling/lesser/handle_life(mob/living/carbon/human/H) + if(!H.weakeyes) + H.weakeyes = 1 //Makes them more vulnerable to flashes and flashbangs + var/light_amount = 0 + H.nutrition = NUTRITION_LEVEL_WELL_FED //i aint never get hongry + if(isturf(H.loc)) + var/turf/T = H.loc + light_amount = T.get_lumcount() * 10 + if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move) + H.throw_alert("lightexposure", /obj/screen/alert/lightexposure) + H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN/2) + else if(light_amount < LIGHT_HEAL_THRESHOLD) + H.clear_alert("lightexposure") + H.heal_overall_damage(2,2) + H.adjustToxLoss(-5) + H.adjustBrainLoss(-25) + H.adjustCloneLoss(-1) + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/skeleton.dm b/code/modules/mob/living/carbon/human/species/skeleton.dm index d207dc20703..6a2b74fb671 100644 --- a/code/modules/mob/living/carbon/human/species/skeleton.dm +++ b/code/modules/mob/living/carbon/human/species/skeleton.dm @@ -6,14 +6,12 @@ icobase = 'icons/mob/human_races/r_skeleton.dmi' deform = 'icons/mob/human_races/r_skeleton.dmi' - path = /mob/living/carbon/human/skeleton - default_language = "Galactic Common" - unarmed_type = /datum/unarmed_attack/punch blood_color = "#FFFFFF" flesh_color = "#E6E6C6" species_traits = list(NO_BREATHE, NO_BLOOD, RADIMMUNE, VIRUSIMMUNE) + skinned_type = /obj/item/stack/sheet/bone oxy_mod = 0 @@ -41,7 +39,7 @@ "brain" = /obj/item/organ/internal/brain/golem, ) //Has default darksight of 2. -/datum/species/skeleton/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R) +/datum/species/skeleton/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) // Crazylemon is still silly if(R.id == "milk") H.heal_overall_damage(4,4) diff --git a/code/modules/mob/living/carbon/human/species/skrell.dm b/code/modules/mob/living/carbon/human/species/skrell.dm new file mode 100644 index 00000000000..a7c24cd338c --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/skrell.dm @@ -0,0 +1,46 @@ +/datum/species/skrell + name = "Skrell" + name_plural = "Skrell" + icobase = 'icons/mob/human_races/r_skrell.dmi' + deform = 'icons/mob/human_races/r_def_skrell.dmi' + language = "Skrellian" + primitive_form = /datum/species/monkey/skrell + + blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \ + the royals' or 'Light of the Crown'.

    Skrell are a highly advanced and logical race who live under the rule \ + of the Qerr'Katish, a caste within their society which keeps the empire of the Skrell running smoothly. Skrell are \ + herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \ + the secrets of their empire to their allies." + + species_traits = list(LIPS) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_SKIN_COLOR | HAS_BODY_MARKINGS + dietflags = DIET_HERB + taste_sensitivity = TASTE_SENSITIVITY_DULL + flesh_color = "#8CD7A3" + blood_color = "#1D2CBF" + base_color = "#38b661" //RGB: 56, 182, 97. + default_hair_colour = "#38b661" + eyes = "skrell_eyes_s" + //Default styles for created mobs. + default_hair = "Skrell Male Tentacles" + reagent_tag = PROCESS_ORG + butt_sprite = "skrell" + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/skrell, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. + "headpocket" = /obj/item/organ/internal/headpocket + ) + + suicide_messages = list( + "is attempting to bite their tongue off!", + "is jamming their thumbs into their eye sockets!", + "is twisting their own neck!", + "makes like a fish and suffocates!", + "is strangling themselves with their own tendrils!") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/slime.dm b/code/modules/mob/living/carbon/human/species/slime.dm new file mode 100644 index 00000000000..583835b7358 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/slime.dm @@ -0,0 +1,180 @@ +#define SLIMEPERSON_COLOR_SHIFT_TRIGGER 0.1 +#define SLIMEPERSON_ICON_UPDATE_PERIOD 200 // 20 seconds +#define SLIMEPERSON_BLOOD_SCALING_FACTOR 5 // Used to adjust how much of an effect the blood has on the rate of color change. Higher is slower. + +#define SLIMEPERSON_HUNGERCOST 50 +#define SLIMEPERSON_MINHUNGER 250 +#define SLIMEPERSON_REGROWTHDELAY 450 // 45 seconds + +/datum/species/slime + name = "Slime People" + name_plural = "Slime People" + language = "Bubblish" + icobase = 'icons/mob/human_races/r_slime.dmi' + deform = 'icons/mob/human_races/r_slime.dmi' + remains_type = /obj/effect/decal/remains/slime + + // More sensitive to the cold + cold_level_1 = 280 + cold_level_2 = 240 + cold_level_3 = 200 + coldmod = 3 + + oxy_mod = 0 + brain_mod = 2.5 + + male_cough_sounds = list('sound/effects/slime_squish.ogg') + female_cough_sounds = list('sound/effects/slime_squish.ogg') + + species_traits = list(LIPS, IS_WHITELISTED, NO_BREATHE, NO_INTORGANS, NO_SCAN) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_SKIN_COLOR | NO_EYES + dietflags = DIET_CARN + reagent_tag = PROCESS_ORG + + blood_color = "#0064C8" + exotic_blood = "water" + blood_damage_type = TOX + + butt_sprite = "slime" + //Has default darksight of 2. + + has_organ = list( + "brain" = /obj/item/organ/internal/brain/slime + ) + + suicide_messages = list( + "is melting into a puddle!", + "is ripping out their own core!", + "is turning a dull, brown color and melting into a puddle!") + + var/reagent_skin_coloring = FALSE + var/datum/action/innate/regrow/grow + var/datum/action/innate/slimecolor/recolor + +/datum/species/slime/on_species_gain(mob/living/carbon/human/H) + ..() + grow = new() + grow.Grant(H) + recolor = new() + recolor.Grant(H) + +/datum/species/slime/on_species_loss(mob/living/carbon/human/H) + ..() + if(grow) + grow.Remove(H) + if(recolor) + recolor.Remove(H) + +/datum/species/slime/handle_life(mob/living/carbon/human/H) + // Slowly shifting to the color of the reagents + if(reagent_skin_coloring && H.reagents.total_volume > SLIMEPERSON_COLOR_SHIFT_TRIGGER) + var/blood_amount = H.blood_volume + var/r_color = mix_color_from_reagents(H.reagents.reagent_list) + var/new_body_color = BlendRGB(r_color, H.skin_colour, (blood_amount*SLIMEPERSON_BLOOD_SCALING_FACTOR)/((blood_amount*SLIMEPERSON_BLOOD_SCALING_FACTOR)+(H.reagents.total_volume))) + H.skin_colour = new_body_color + if(world.time % SLIMEPERSON_ICON_UPDATE_PERIOD > SLIMEPERSON_ICON_UPDATE_PERIOD - 20) // The 20 is because this gets called every 2 seconds, from the mob controller + for(var/organname in H.bodyparts_by_name) + var/obj/item/organ/external/E = H.bodyparts_by_name[organname] + if(istype(E) && E.dna && istype(E.dna.species, /datum/species/slime)) + E.sync_colour_to_human(H) + H.update_hair(0) + H.update_body() + ..() + +/datum/action/innate/slimecolor + name = "Toggle Recolor" + check_flags = AB_CHECK_CONSCIOUS + icon_icon = 'icons/effects/effects.dmi' + button_icon_state = "greenglow" + +/datum/action/innate/slimecolor/Activate() + var/mob/living/carbon/human/H = owner + var/datum/species/slime/S = H.dna.species + if(S.reagent_skin_coloring) + S.reagent_skin_coloring = FALSE + to_chat(H, "You adjust your internal chemistry to filter out pigments from things you consume.") + else + S.reagent_skin_coloring = TRUE + to_chat(H, "You adjust your internal chemistry to permit pigments in chemicals you consume to tint you.") + +/datum/action/innate/regrow + name = "Regrow limbs" + check_flags = AB_CHECK_CONSCIOUS + icon_icon = 'icons/effects/effects.dmi' + button_icon_state = "greenglow" + +/datum/action/innate/regrow/Activate() + var/mob/living/carbon/human/H = owner + if(H.nutrition < SLIMEPERSON_MINHUNGER) + to_chat(H, "You're too hungry to regenerate a limb!") + return + + var/list/missing_limbs = list() + for(var/l in H.bodyparts_by_name) + var/obj/item/organ/external/E = H.bodyparts_by_name[l] + if(!istype(E)) + var/list/limblist = H.dna.species.has_limbs[l] + var/obj/item/organ/external/limb = limblist["path"] + var/parent_organ = initial(limb.parent_organ) + var/obj/item/organ/external/parentLimb = H.bodyparts_by_name[parent_organ] + if(!istype(parentLimb)) + continue + missing_limbs[initial(limb.name)] = l + + if(!missing_limbs.len) + to_chat(H, "You're not missing any limbs!") + return + + var/limb_select = input(H, "Choose a limb to regrow", "Limb Regrowth") as null|anything in missing_limbs + var/chosen_limb = missing_limbs[limb_select] + + H.visible_message("[H] begins to hold still and concentrate on [H.p_their()] missing [limb_select]...", "You begin to focus on regrowing your missing [limb_select]... (This will take [round(SLIMEPERSON_REGROWTHDELAY/10)] seconds, and you must hold still.)") + if(do_after(H, SLIMEPERSON_REGROWTHDELAY, needhand = 0, target = H)) + if(H.incapacitated()) + to_chat(H, "You cannot regenerate missing limbs in your current state.") + return + + if(H.nutrition < SLIMEPERSON_MINHUNGER) + to_chat(H, "You're too hungry to regenerate a limb!") + return + + var/obj/item/organ/external/O = H.bodyparts_by_name[chosen_limb] + + var/stored_brute = 0 + var/stored_burn = 0 + if(istype(O)) + to_chat(H, "You distribute the damaged tissue around your body, out of the way of your new pseudopod!") + var/obj/item/organ/external/doomedStump = O + stored_brute = doomedStump.brute_dam + stored_burn = doomedStump.burn_dam + qdel(O) + + var/limb_list = H.dna.species.has_limbs[chosen_limb] + var/obj/item/organ/external/limb_path = limb_list["path"] + // Parent check + var/obj/item/organ/external/potential_parent = H.bodyparts_by_name[initial(limb_path.parent_organ)] + if(!istype(potential_parent)) + to_chat(H, "You've lost the organ that you've been growing your new part on!") + return // No rayman for you + // Grah this line will leave a "not used" warning, in spite of the fact that the new() proc WILL do the thing. + // Bothersome. + var/obj/item/organ/external/new_limb = new limb_path(H) + new_limb.open = 0 // This is just so that the compiler won't think that new_limb is unused, because the compiler is horribly stupid. + H.adjustBruteLoss(stored_brute) + H.adjustFireLoss(stored_burn) + H.update_body() + H.updatehealth() + H.UpdateDamageIcon() + H.nutrition -= SLIMEPERSON_HUNGERCOST + H.visible_message("[H] finishes regrowing [H.p_their()] missing [new_limb]!", "You finish regrowing your [limb_select]") + else + to_chat(H, "You need to hold still in order to regrow a limb!") + +#undef SLIMEPERSON_COLOR_SHIFT_TRIGGER +#undef SLIMEPERSON_ICON_UPDATE_PERIOD +#undef SLIMEPERSON_BLOOD_SCALING_FACTOR + +#undef SLIMEPERSON_HUNGERCOST +#undef SLIMEPERSON_MINHUNGER +#undef SLIMEPERSON_REGROWTHDELAY \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm deleted file mode 100644 index 05e989afa50..00000000000 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ /dev/null @@ -1,1074 +0,0 @@ -/datum/species/human - name = "Human" - name_plural = "Humans" - icobase = 'icons/mob/human_races/r_human.dmi' - deform = 'icons/mob/human_races/r_def_human.dmi' - primitive_form = "Monkey" - path = /mob/living/carbon/human/human - language = "Sol Common" - species_traits = list(LIPS, CAN_BE_FAT) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS - dietflags = DIET_OMNI - unarmed_type = /datum/unarmed_attack/punch - blurb = "Humanity originated in the Sol system, and over the last five centuries has spread \ - colonies across a wide swathe of space. They hold a wide range of forms and creeds.

    \ - While the central Sol government maintains control of its far-flung people, powerful corporate \ - interests, rampant cyber and bio-augmentation and secretive factions make life on most human \ - worlds tumultous at best." - - reagent_tag = PROCESS_ORG - //Has standard darksight of 2. - -/datum/species/unathi - name = "Unathi" - name_plural = "Unathi" - icobase = 'icons/mob/human_races/r_lizard.dmi' - deform = 'icons/mob/human_races/r_def_lizard.dmi' - path = /mob/living/carbon/human/unathi - default_language = "Galactic Common" - language = "Sinta'unathi" - tail = "sogtail" - unarmed_type = /datum/unarmed_attack/claws - primitive_form = "Stok" - - blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \ - Uuosa-Eso system, which roughly translates to 'burning mother'.

    Coming from a harsh, radioactive \ - desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \ - else, frequently even their own lives. They prefer warmer temperatures than most species and \ - their native tongue is a heavy hissing laungage called Sinta'Unathi." - - species_traits = list(LIPS) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_BODY_MARKINGS | HAS_HEAD_MARKINGS | HAS_SKIN_COLOR | HAS_ALT_HEADS | TAIL_WAGGING - dietflags = DIET_CARN - - cold_level_1 = 280 //Default 260 - Lower is better - cold_level_2 = 220 //Default 200 - cold_level_3 = 140 //Default 120 - - heat_level_1 = 380 //Default 360 - Higher is better - heat_level_2 = 420 //Default 400 - heat_level_3 = 480 //Default 460 - - flesh_color = "#34AF10" - reagent_tag = PROCESS_ORG - base_color = "#066000" - //Default styles for created mobs. - default_headacc = "Simple" - default_headacc_colour = "#404040" - butt_sprite = "unathi" - brute_mod = 1.05 - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/unathi, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/unathi //3 darksight. - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, - /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!") - - var/datum/action/innate/tail_lash/lash = new() - - -/datum/species/unathi/handle_post_spawn(var/mob/living/carbon/human/H) - lash.Grant(H) - ..() - -/datum/action/innate/tail_lash - name = "Tail lash" - icon_icon = 'icons/effects/effects.dmi' - button_icon_state = "tail" - -/datum/action/innate/tail_lash/Activate() - var/mob/living/carbon/human/user = owner - if(!user.restrained() || !user.buckled) - to_chat(user, "You need freedom of movement to tail lash!") - return - if(user.getStaminaLoss() >= 50) - to_chat(user, "Rest before tail lashing again!") - return - for(var/mob/living/carbon/human/C in orange(1)) - var/obj/item/organ/external/E = C.get_organ(pick("l_leg", "r_leg", "l_foot", "r_foot", "groin")) - if(E) - user.changeNext_move(CLICK_CD_MELEE) - user.visible_message("[src] smacks [C] in [E] with their tail! ", "You hit [C] in [E] with your tail!") - user.adjustStaminaLoss(15) - C.apply_damage(5, BRUTE, E) - user.spin(20, 1) - playsound(user.loc, 'sound/weapons/slash.ogg', 50, 0) - - - -/datum/species/unathi/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/tajaran - name = "Tajaran" - name_plural = "Tajaran" - icobase = 'icons/mob/human_races/r_tajaran.dmi' - deform = 'icons/mob/human_races/r_def_tajaran.dmi' - path = /mob/living/carbon/human/tajaran - default_language = "Galactic Common" - language = "Siik'tajr" - tail = "tajtail" - unarmed_type = /datum/unarmed_attack/claws - - blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \ - S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \ - influenced heavily by their long history of Slavemaster rule. They have a structured, clan-influenced way \ - of family and politics. They prefer colder environments, and speak a variety of languages, mostly Siik'Maas, \ - using unique inflections their mouths form." - - cold_level_1 = 240 - cold_level_2 = 180 - cold_level_3 = 100 - - heat_level_1 = 340 - heat_level_2 = 380 - heat_level_3 = 440 - - primitive_form = "Farwa" - - species_traits = list(LIPS, CAN_BE_FAT) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_HEAD_MARKINGS | HAS_BODY_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING - dietflags = DIET_OMNI - taste_sensitivity = TASTE_SENSITIVITY_SHARP - reagent_tag = PROCESS_ORG - flesh_color = "#AFA59E" - base_color = "#424242" - butt_sprite = "tajaran" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/tajaran, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) - unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, - /mob/living/simple_animal/tribble) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!") - -/datum/species/tajaran/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/vulpkanin - name = "Vulpkanin" - name_plural = "Vulpkanin" - icobase = 'icons/mob/human_races/r_vulpkanin.dmi' - deform = 'icons/mob/human_races/r_vulpkanin.dmi' - path = /mob/living/carbon/human/vulpkanin - default_language = "Galactic Common" - language = "Canilunzt" - primitive_form = "Wolpin" - tail = "vulptail" - unarmed_type = /datum/unarmed_attack/claws - - blurb = "Vulpkanin are a species of sharp-witted canine-pideds residing on the planet Altam just barely within the \ - dual-star Vazzend system. Their politically de-centralized society and independent natures have led them to become a species and \ - culture both feared and respected for their scientific breakthroughs. Discovery, loyalty, and utilitarianism dominates their lifestyles \ - to the degree it can cause conflict with more rigorous and strict authorities. They speak a guttural language known as 'Canilunzt' \ - which has a heavy emphasis on utilizing tail positioning and ear twitches to communicate intent." - - species_traits = list(LIPS) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR - dietflags = DIET_OMNI - hunger_drain = 0.11 - taste_sensitivity = TASTE_SENSITIVITY_SHARP - reagent_tag = PROCESS_ORG - flesh_color = "#966464" - base_color = "#CF4D2F" - butt_sprite = "vulp" - - scream_verb = "yelps" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/vulpkanin, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) - unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, - /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!") - -/datum/species/vulpkanin/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/skrell - name = "Skrell" - name_plural = "Skrell" - icobase = 'icons/mob/human_races/r_skrell.dmi' - deform = 'icons/mob/human_races/r_def_skrell.dmi' - path = /mob/living/carbon/human/skrell - default_language = "Galactic Common" - language = "Skrellian" - primitive_form = "Neara" - unarmed_type = /datum/unarmed_attack/punch - - blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \ - the royals' or 'Light of the Crown'.

    Skrell are a highly advanced and logical race who live under the rule \ - of the Qerr'Katish, a caste within their society which keeps the empire of the Skrell running smoothly. Skrell are \ - herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \ - the secrets of their empire to their allies." - - species_traits = list(LIPS) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | HAS_BODY_MARKINGS - dietflags = DIET_HERB - taste_sensitivity = TASTE_SENSITIVITY_DULL - flesh_color = "#8CD7A3" - blood_color = "#1D2CBF" - base_color = "#38b661" //RGB: 56, 182, 97. - default_hair_colour = "#38b661" - eyes = "skrell_eyes_s" - //Default styles for created mobs. - default_hair = "Skrell Male Tentacles" - reagent_tag = PROCESS_ORG - butt_sprite = "skrell" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/skrell, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "headpocket" = /obj/item/organ/internal/headpocket - ) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their thumbs into their eye sockets!", - "is twisting their own neck!", - "makes like a fish and suffocates!", - "is strangling themselves with their own tendrils!") - -/datum/species/vox - name = "Vox" - name_plural = "Vox" - icobase = 'icons/mob/human_races/vox/r_vox.dmi' - deform = 'icons/mob/human_races/vox/r_def_vox.dmi' - path = /mob/living/carbon/human/vox - - default_language = "Galactic Common" - language = "Vox-pidgin" - tail = "voxtail" - speech_sounds = list('sound/voice/shriek1.ogg') - speech_chance = 20 - unarmed_type = /datum/unarmed_attack/claws //I dont think it will hurt to give vox claws too. - - blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \ - scavenging vermin who prey on isolated stations, ships or planets to keep their own ancient arkships \ - alive. They are four to five feet tall, reptillian, beaked, tailed and quilled; human crews often \ - refer to them as 'shitbirds' for their violent and offensive nature, as well as their horrible \ - smell.

    Most humans will never meet a Vox raider, instead learning of this insular species through \ - dealing with their traders and merchants; those that do rarely enjoy the experience." - - brute_mod = 1.2 //20% more brute damage. Fragile bird bones. - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - breathid = "n2" - - eyes = "vox_eyes_s" - - species_traits = list(NO_SCAN, IS_WHITELISTED, NOTRANSSTING) - clothing_flags = HAS_SOCKS - dietflags = DIET_OMNI - bodyflags = HAS_ICON_SKIN_TONE | HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED | HAS_BODY_MARKINGS | HAS_TAIL_MARKINGS - - blood_color = "#2299FC" - flesh_color = "#808D11" - //Default styles for created mobs. - default_hair = "Short Vox Quills" - default_hair_colour = "#614f19" //R: 97, G: 79, B: 25 - butt_sprite = "vox" - - reagent_tag = PROCESS_ORG - scream_verb = "shrieks" - male_scream_sound = 'sound/voice/shriek1.ogg' - female_scream_sound = 'sound/voice/shriek1.ogg' - male_cough_sounds = list('sound/voice/shriekcough.ogg') - female_cough_sounds = list('sound/voice/shriekcough.ogg') - male_sneeze_sound = 'sound/voice/shrieksneeze.ogg' - female_sneeze_sound = 'sound/voice/shrieksneeze.ogg' - - icon_skin_tones = list( - 1 = "Default Green", - 2 = "Dark Green", - 3 = "Brown", - 4 = "Grey", - 5 = "Emerald", - 6 = "Azure" - ) - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs/vox, - "liver" = /obj/item/organ/internal/liver/vox, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used - ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!", - "is deeply inhaling oxygen!") - -/datum/species/vox/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/vox/makeName(var/gender,var/mob/living/carbon/human/H=null) - var/sounds = rand(2,8) - var/i = 0 - var/newname = "" - - while(i<=sounds) - i++ - newname += pick(vox_name_syllables) - return capitalize(newname) - -/datum/species/vox/after_equip_job(datum/job/J, mob/living/carbon/human/H) - if(!H.mind || !H.mind.assigned_role || H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime") - H.unEquip(H.wear_mask) - H.unEquip(H.l_hand) - - H.equip_or_collect(new /obj/item/clothing/mask/breath/vox(H), slot_wear_mask) - var/tank_pref = H.client && H.client.prefs ? H.client.prefs.speciesprefs : null - if(tank_pref)//Diseasel, here you go - H.equip_or_collect(new /obj/item/tank/nitrogen(H), slot_l_hand) - else - H.equip_or_collect(new /obj/item/tank/emergency_oxygen/vox(H), slot_l_hand) - to_chat(H, "You are now running on nitrogen internals from the [H.l_hand] in your hand. Your species finds oxygen toxic, so you must breathe nitrogen only.") - H.internal = H.l_hand - H.update_action_buttons_icon() - -/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) - updatespeciescolor(H) - H.update_icons() - //H.verbs += /mob/living/carbon/human/proc/leap - ..() - -/datum/species/vox/updatespeciescolor(var/mob/living/carbon/human/H, var/owner_sensitive = 1) //Handling species-specific skin-tones for the Vox race. - if(H.species.bodyflags & HAS_ICON_SKIN_TONE) //Making sure we don't break Armalis. - var/new_icobase = 'icons/mob/human_races/vox/r_vox.dmi' //Default Green Vox. - var/new_deform = 'icons/mob/human_races/vox/r_def_vox.dmi' //Default Green Vox. - switch(H.s_tone) - if(6) //Azure Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi' - H.tail = "voxtail_azu" - if(5) //Emerald Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi' - H.tail = "voxtail_emrl" - if(4) //Grey Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxgry.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi' - H.tail = "voxtail_gry" - if(3) //Brown Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi' - H.tail = "voxtail_brn" - if(2) //Dark Green Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxdgrn.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxdgrn.dmi' - H.tail = "voxtail_dgrn" - else //Default Green Vox. - H.tail = "voxtail" //Ensures they get an appropriately coloured tail depending on the skin-tone. - - H.change_icobase(new_icobase, new_deform, owner_sensitive) //Update the icobase/deform of all our organs, but make sure we don't mess with frankenstein limbs in doing so. - H.update_dna() - -/datum/species/vox/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R) - if(R.id == "oxygen") //Armalis are above such petty things. - H.adjustToxLoss(1*REAGENTS_EFFECT_MULTIPLIER) //Same as plasma. - H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM) - return 0 //Handling reagent removal on our own. - - return ..() - -/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H) - H.verbs += /mob/living/carbon/human/proc/leap - H.verbs += /mob/living/carbon/human/proc/gut - ..() - -/datum/species/vox/armalis - name = "Vox Armalis" - name_plural = "Vox Armalis" - icobase = 'icons/mob/human_races/r_armalis.dmi' - deform = 'icons/mob/human_races/r_armalis.dmi' - path = /mob/living/carbon/human/voxarmalis - unarmed_type = /datum/unarmed_attack/claws/armalis - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - heat_level_1 = 2000 - heat_level_2 = 3000 - heat_level_3 = 4000 - - brute_mod = 0.2 - burn_mod = 0.2 - - eyes = "blank_eyes" - - species_traits = list(NO_SCAN, NO_BLOOD, NO_PAIN, IS_WHITELISTED) - bodyflags = HAS_TAIL - dietflags = DIET_OMNI //should inherit this from vox, this is here just in case - - blood_color = "#2299FC" - flesh_color = "#808D11" - - reagent_tag = PROCESS_ORG - - tail = "armalis_tail" - icon_template = 'icons/mob/human_races/r_armalis.dmi' - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs/vox, - "liver" = /obj/item/organ/internal/liver, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used - ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!", - "is huffing oxygen!") - -/datum/species/vox/armalis/handle_reagents() //Skip the Vox oxygen reagent toxicity. Armalis are above such things. - return 1 - -/datum/species/kidan - name = "Kidan" - name_plural = "Kidan" - icobase = 'icons/mob/human_races/r_kidan.dmi' - deform = 'icons/mob/human_races/r_def_kidan.dmi' - path = /mob/living/carbon/human/kidan - default_language = "Galactic Common" - language = "Chittin" - unarmed_type = /datum/unarmed_attack/claws - - brute_mod = 0.8 - - species_traits = list(IS_WHITELISTED) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_HEAD_ACCESSORY | HAS_HEAD_MARKINGS | HAS_BODY_MARKINGS - eyes = "kidan_eyes_s" - dietflags = DIET_HERB - blood_color = "#FB9800" - reagent_tag = PROCESS_ORG - //Default styles for created mobs. - default_headacc = "Normal Antennae" - butt_sprite = "kidan" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/kidan, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "lantern" = /obj/item/organ/internal/lantern - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/diona) - - suicide_messages = list( - "is attempting to bite their antenna off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is cracking their exoskeleton!", - "is stabbing themselves with their mandibles!", - "is holding their breath!") - -/datum/species/slime - name = "Slime People" - name_plural = "Slime People" - default_language = "Galactic Common" - language = "Bubblish" - icobase = 'icons/mob/human_races/r_slime.dmi' - deform = 'icons/mob/human_races/r_slime.dmi' - path = /mob/living/carbon/human/slime - unarmed_type = /datum/unarmed_attack/punch - remains_type = /obj/effect/decal/remains/slime - - // More sensitive to the cold - cold_level_1 = 280 - cold_level_2 = 240 - cold_level_3 = 200 - coldmod = 3 - - oxy_mod = 0 - brain_mod = 2.5 - - male_cough_sounds = list('sound/effects/slime_squish.ogg') - female_cough_sounds = list('sound/effects/slime_squish.ogg') - - species_traits = list(LIPS, IS_WHITELISTED, NO_BREATHE, NO_INTORGANS, NO_SCAN) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | NO_EYES - dietflags = DIET_CARN - reagent_tag = PROCESS_ORG - - blood_color = "#0064C8" - exotic_blood = "water" - blood_damage_type = TOX - - butt_sprite = "slime" - //Has default darksight of 2. - - has_organ = list( - "brain" = /obj/item/organ/internal/brain/slime - ) - - suicide_messages = list( - "is melting into a puddle!", - "is ripping out their own core!", - "is turning a dull, brown color and melting into a puddle!") - - var/list/mob/living/carbon/human/recolor_list = list() - - var/datum/action/innate/regrow/grow = new() - - species_abilities = list( - /mob/living/carbon/human/verb/toggle_recolor_verb, - /mob/living/carbon/human/proc/regrow_limbs - ) - -/datum/species/slime/handle_post_spawn(var/mob/living/carbon/human/H) - grow.Grant(H) - ..() - -/datum/action/innate/regrow - name = "Regrow limbs" - icon_icon = 'icons/effects/effects.dmi' - button_icon_state = "greenglow" - -/datum/action/innate/regrow/Activate() - var/mob/living/carbon/human/user = owner - user.regrow_limbs() - - -/datum/species/slime/handle_life(var/mob/living/carbon/human/H) -//This is allegedly for code "style". Like a plaid sweater? -#define SLIMEPERSON_COLOR_SHIFT_TRIGGER 0.1 -#define SLIMEPERSON_ICON_UPDATE_PERIOD 200 // 20 seconds -#define SLIMEPERSON_BLOOD_SCALING_FACTOR 5 // Used to adjust how much of an effect the blood has on the rate of color change. Higher is slower. - // Slowly shifting to the color of the reagents - if((H in recolor_list) && H.reagents.total_volume > SLIMEPERSON_COLOR_SHIFT_TRIGGER) - var/blood_amount = H.blood_volume - var/r_color = mix_color_from_reagents(H.reagents.reagent_list) - var/new_body_color = BlendRGB(r_color, H.skin_colour, (blood_amount*SLIMEPERSON_BLOOD_SCALING_FACTOR)/((blood_amount*SLIMEPERSON_BLOOD_SCALING_FACTOR)+(H.reagents.total_volume))) - H.skin_colour = new_body_color - if(world.time % SLIMEPERSON_ICON_UPDATE_PERIOD > SLIMEPERSON_ICON_UPDATE_PERIOD - 20) // The 20 is because this gets called every 2 seconds, from the mob controller - for(var/organname in H.bodyparts_by_name) - var/obj/item/organ/external/E = H.bodyparts_by_name[organname] - if(istype(E) && E.dna.species == "Slime People") - E.sync_colour_to_human(H) - H.update_hair(0) - H.update_body() - ..() - -#undef SLIMEPERSON_COLOR_SHIFT_TRIGGER -#undef SLIMEPERSON_ICON_UPDATE_PERIOD -#undef SLIMEPERSON_BLOOD_SCALING_FACTOR - -/mob/living/carbon/human/proc/toggle_recolor(var/silent = 0) - var/datum/species/slime/S = all_species[get_species()] - if(!istype(S)) - if(!silent) - to_chat(src, "You're not a slime person!") - return - - if(src in S.recolor_list) - S.recolor_list -= src - if(!silent) - to_chat(src, "You adjust your internal chemistry to filter out pigments from things you consume.") - else - S.recolor_list += src - if(!silent) - to_chat(src, "You adjust your internal chemistry to permit pigments in chemicals you consume to tint you.") - -/mob/living/carbon/human/verb/toggle_recolor_verb() - set category = "IC" - set name = "Toggle Reagent Recoloring" - set desc = "While active, you'll slowly adjust your body's color to that of the reagents inside of you, moderated by how much blood you have." - - toggle_recolor() - - -/mob/living/carbon/human/proc/regrow_limbs() - set category = "IC" - set name = "Regrow Limbs" - set desc = "Regrow one of your missing limbs at the cost of a large amount of hunger" - -#define SLIMEPERSON_HUNGERCOST 50 -#define SLIMEPERSON_MINHUNGER 250 -#define SLIMEPERSON_REGROWTHDELAY 450 // 45 seconds - - if(stat || paralysis || stunned) - to_chat(src, "You cannot regenerate missing limbs in your current state.") - return - - if(nutrition < SLIMEPERSON_MINHUNGER) - to_chat(src, "You're too hungry to regenerate a limb!") - return - - var/list/missing_limbs = list() - for(var/l in bodyparts_by_name) - var/obj/item/organ/external/E = bodyparts_by_name[l] - if(!istype(E)) - var/list/limblist = species.has_limbs[l] - var/obj/item/organ/external/limb = limblist["path"] - var/parent_organ = initial(limb.parent_organ) - var/obj/item/organ/external/parentLimb = bodyparts_by_name[parent_organ] - if(!istype(parentLimb)) - continue - missing_limbs[initial(limb.name)] = l - - if(!missing_limbs.len) - to_chat(src, "You're not missing any limbs!") - return - - var/limb_select = input(src, "Choose a limb to regrow", "Limb Regrowth") as null|anything in missing_limbs - var/chosen_limb = missing_limbs[limb_select] - - visible_message("[src] begins to hold still and concentrate on their missing [limb_select]...", "You begin to focus on regrowing your missing [limb_select]... (This will take [round(SLIMEPERSON_REGROWTHDELAY/10)] seconds, and you must hold still.)") - if(do_after(src, SLIMEPERSON_REGROWTHDELAY, needhand=0, target = src)) - if(stat || paralysis || stunned) - to_chat(src, "You cannot regenerate missing limbs in your current state.") - return - - if(nutrition < SLIMEPERSON_MINHUNGER) - to_chat(src, "You're too hungry to regenerate a limb!") - return - - var/obj/item/organ/external/O = bodyparts_by_name[chosen_limb] - - var/stored_brute = 0 - var/stored_burn = 0 - if(istype(O)) - to_chat(src, "You distribute the damaged tissue around your body, out of the way of your new pseudopod!") - var/obj/item/organ/external/doomedStump = O - stored_brute = doomedStump.brute_dam - stored_burn = doomedStump.burn_dam - qdel(O) - - var/limb_list = species.has_limbs[chosen_limb] - var/obj/item/organ/external/limb_path = limb_list["path"] - // Parent check - var/obj/item/organ/external/potential_parent = bodyparts_by_name[initial(limb_path.parent_organ)] - if(!istype(potential_parent)) - to_chat(src, "You've lost the organ that you've been growing your new part on!") - return // No rayman for you - // Grah this line will leave a "not used" warning, in spite of the fact that the new() proc WILL do the thing. - // Bothersome. - var/obj/item/organ/external/new_limb = new limb_path(src) - new_limb.open = 0 // This is just so that the compiler won't think that new_limb is unused, because the compiler is horribly stupid. - adjustBruteLoss(stored_brute) - adjustFireLoss(stored_burn) - update_body() - updatehealth() - UpdateDamageIcon() - nutrition -= SLIMEPERSON_HUNGERCOST - visible_message("[src] finishes regrowing their missing [new_limb]!", "You finish regrowing your [limb_select]") - else - to_chat(src, "You need to hold still in order to regrow a limb!") - return - -#undef SLIMEPERSON_HUNGERCOST -#undef SLIMEPERSON_MINHUNGER -#undef SLIMEPERSON_REGROWTHDELAY - -/datum/species/slime/handle_pre_change(var/mob/living/carbon/human/H) - ..() - if(H in recolor_list) - H.toggle_recolor(silent = 1) - -/datum/species/grey - name = "Grey" - name_plural = "Greys" - icobase = 'icons/mob/human_races/r_grey.dmi' - deform = 'icons/mob/human_races/r_def_grey.dmi' - default_language = "Galactic Common" - language = "Psionic Communication" - unarmed_type = /datum/unarmed_attack/punch - eyes = "grey_eyes_s" - butt_sprite = "grey" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/grey, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain/grey, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/grey //5 darksight. - ) - - brute_mod = 1.25 //greys are fragile - - default_genes = list(REMOTE_TALK) - - - species_traits = list(LIPS, IS_WHITELISTED, CAN_BE_FAT) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_BODY_MARKINGS - dietflags = DIET_HERB - reagent_tag = PROCESS_ORG - blood_color = "#A200FF" - -/datum/species/grey/handle_dna(var/mob/living/carbon/C, var/remove) - if(!remove) - C.dna.SetSEState(REMOTETALKBLOCK,1,1) - genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED) - else - C.dna.SetSEState(REMOTETALKBLOCK,0,1) - genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED) - ..() - -/datum/species/grey/water_act(var/mob/living/carbon/C, volume, temperature, source) - ..() - C.take_organ_damage(5,min(volume,20)) - C.emote("scream") - -/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H) - var/speech_pref = H.client.prefs.speciesprefs - if(speech_pref) - H.mind.speech_span = "wingdings" - -/datum/species/grey/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) - if(R.id == "sacid") - H.reagents.del_reagent(R.id) - return 0 - return ..() - -/datum/species/diona - name = "Diona" - name_plural = "Dionaea" - icobase = 'icons/mob/human_races/r_diona.dmi' - deform = 'icons/mob/human_races/r_def_plant.dmi' - path = /mob/living/carbon/human/diona - default_language = "Galactic Common" - language = "Rootspeak" - speech_sounds = list('sound/voice/dionatalk1.ogg') //Credit https://www.youtube.com/watch?v=ufnvlRjsOTI [0:13 - 0:16] - speech_chance = 20 - unarmed_type = /datum/unarmed_attack/diona - //primitive_form = "Nymph" - slowdown = 5 - remains_type = /obj/effect/decal/cleanable/ash - - - warning_low_pressure = 50 - hazard_low_pressure = -1 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 300 - heat_level_2 = 340 - heat_level_3 = 400 - - blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \ - species hailing from Epsilon Ursae Minoris. Each 'diona' is a cluster of numerous cat-sized organisms called nymphs; \ - there is no effective upper limit to the number that can fuse in gestalt, and reports exist of the Epsilon Ursae \ - Minoris primary being ringed with a cloud of singing space-station-sized entities.

    The Dionaea coexist peacefully with \ - all known species, especially the Skrell. Their communal mind makes them slow to react, and they have difficulty understanding \ - even the simplest concepts of other minds. Their alien physiology allows them survive happily off a diet of nothing but light, \ - water and other radiation." - - species_traits = list(NO_BREATHE, RADIMMUNE, IS_PLANT, NO_BLOOD, NO_PAIN) - clothing_flags = HAS_SOCKS - default_hair_colour = "#000000" - dietflags = 0 //Diona regenerate nutrition in light and water, no diet necessary - taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE - - oxy_mod = 0 - - body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not - blood_color = "#004400" - flesh_color = "#907E4A" - butt_sprite = "diona" - - reagent_tag = PROCESS_ORG - - has_organ = list( - "nutrient channel" = /obj/item/organ/internal/liver/diona, - "neural strata" = /obj/item/organ/internal/heart/diona, - "receptor node" = /obj/item/organ/internal/eyes/diona, //Default darksight of 2. - "gas bladder" = /obj/item/organ/internal/brain/diona, - "polyp segment" = /obj/item/organ/internal/kidneys/diona, - "anchoring ligament" = /obj/item/organ/internal/appendix/diona - ) - - vision_organ = /obj/item/organ/internal/eyes/diona - has_limbs = list( - "chest" = list("path" = /obj/item/organ/external/chest/diona), - "groin" = list("path" = /obj/item/organ/external/groin/diona), - "head" = list("path" = /obj/item/organ/external/head/diona), - "l_arm" = list("path" = /obj/item/organ/external/arm/diona), - "r_arm" = list("path" = /obj/item/organ/external/arm/right/diona), - "l_leg" = list("path" = /obj/item/organ/external/leg/diona), - "r_leg" = list("path" = /obj/item/organ/external/leg/right/diona), - "l_hand" = list("path" = /obj/item/organ/external/hand/diona), - "r_hand" = list("path" = /obj/item/organ/external/hand/right/diona), - "l_foot" = list("path" = /obj/item/organ/external/foot/diona), - "r_foot" = list("path" = /obj/item/organ/external/foot/right/diona) - ) - - suicide_messages = list( - "is losing branches!", - "pulls out a secret stash of herbicide and takes a hearty swig!", - "is pulling themselves apart!") - -/datum/species/diona/can_understand(var/mob/other) - if(istype(other, /mob/living/simple_animal/diona)) - return 1 - return 0 - -/datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H) - H.gender = NEUTER - - return ..() - -/datum/species/diona/handle_life(var/mob/living/carbon/human/H) - H.radiation = Clamp(H.radiation, 0, 100) //We have to clamp this first, then decrease it, or there's a few edge cases of massive heals if we clamp and decrease at the same time. - var/rads = H.radiation / 25 - H.radiation = max(H.radiation-rads, 0) - H.nutrition = min(H.nutrition+rads, NUTRITION_LEVEL_WELL_FED+10) - H.adjustBruteLoss(-(rads)) - H.adjustToxLoss(-(rads)) - - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(H.loc)) //else, there's considered to be no light - var/turf/T = H.loc - light_amount = min(T.get_lumcount() * 10, 5) //hardcapped so it's not abused by having a ton of flashlights - H.nutrition = min(H.nutrition+light_amount, NUTRITION_LEVEL_WELL_FED+10) - - if(light_amount > 0) - H.clear_alert("nolight") - else - H.throw_alert("nolight", /obj/screen/alert/nolight) - - if((light_amount >= 5) && !H.suiciding) //if there's enough light, heal - - H.adjustBruteLoss(-(light_amount/2)) - H.adjustFireLoss(-(light_amount/4)) - if(H.nutrition < NUTRITION_LEVEL_STARVING+50) - H.take_overall_damage(10,0) - ..() - -/datum/species/machine - name = "Machine" - name_plural = "Machines" - - blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \ - robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \ - to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \ - generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \ - inhuman in outlook and perspective." - - icobase = 'icons/mob/human_races/r_machine.dmi' - deform = 'icons/mob/human_races/r_machine.dmi' - path = /mob/living/carbon/human/machine - default_language = "Galactic Common" - language = "Trinary" - unarmed_type = /datum/unarmed_attack/punch - remains_type = /obj/effect/decal/remains/robot - - eyes = "blank_eyes" - brute_mod = 2.5 // 100% * 2.5 * 0.6 (robolimbs) ~= 150% - burn_mod = 2.5 // So they take 50% extra damage from brute/burn overall. - tox_mod = 0 - clone_mod = 0 - oxy_mod = 0 - death_message = "gives one shrill beep before falling limp, their monitor flashing blue before completely shutting off..." - - species_traits = list(IS_WHITELISTED, NO_BREATHE, NO_SCAN, NO_BLOOD, NO_PAIN, NO_DNA, RADIMMUNE, VIRUSIMMUNE, NOTRANSSTING) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | HAS_HEAD_MARKINGS | HAS_HEAD_ACCESSORY | ALL_RPARTS - dietflags = 0 //IPCs can't eat, so no diet - taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE - blood_color = "#1F181F" - flesh_color = "#AAAAAA" - //Default styles for created mobs. - default_hair = "Blue IPC Screen" - can_revive_by_healing = 1 - has_gender = FALSE - reagent_tag = PROCESS_SYN - male_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' - female_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' - male_cough_sounds = list('sound/effects/mob_effects/m_machine_cougha.ogg','sound/effects/mob_effects/m_machine_coughb.ogg', 'sound/effects/mob_effects/m_machine_coughc.ogg') - female_cough_sounds = list('sound/effects/mob_effects/f_machine_cougha.ogg','sound/effects/mob_effects/f_machine_coughb.ogg') - male_sneeze_sound = 'sound/effects/mob_effects/machine_sneeze.ogg' - female_sneeze_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg' - butt_sprite = "machine" - - has_organ = list( - "brain" = /obj/item/organ/internal/brain/mmi_holder/posibrain, - "cell" = /obj/item/organ/internal/cell, - "optics" = /obj/item/organ/internal/eyes/optical_sensor, //Default darksight of 2. - "charger" = /obj/item/organ/internal/cyberimp/arm/power_cord - ) - - vision_organ = /obj/item/organ/internal/eyes/optical_sensor - has_limbs = list( - "chest" = list("path" = /obj/item/organ/external/chest/ipc), - "groin" = list("path" = /obj/item/organ/external/groin/ipc), - "head" = list("path" = /obj/item/organ/external/head/ipc), - "l_arm" = list("path" = /obj/item/organ/external/arm/ipc), - "r_arm" = list("path" = /obj/item/organ/external/arm/right/ipc), - "l_leg" = list("path" = /obj/item/organ/external/leg/ipc), - "r_leg" = list("path" = /obj/item/organ/external/leg/right/ipc), - "l_hand" = list("path" = /obj/item/organ/external/hand/ipc), - "r_hand" = list("path" = /obj/item/organ/external/hand/right/ipc), - "l_foot" = list("path" = /obj/item/organ/external/foot/ipc), - "r_foot" = list("path" = /obj/item/organ/external/foot/right/ipc) - ) - - suicide_messages = list( - "is powering down!", - "is smashing their own monitor!", - "is twisting their own neck!", - "is downloading extra RAM!", - "is frying their own circuits!", - "is blocking their ventilation port!") - - species_abilities = list( - /mob/living/carbon/human/proc/change_monitor - ) - -/datum/species/machine/handle_death(var/mob/living/carbon/human/H) - var/obj/item/organ/external/head/head_organ = H.get_organ("head") - if(!head_organ) - return - head_organ.h_style = "Bald" - head_organ.f_style = "Shaved" - spawn(100) - if(H) - H.update_hair() - H.update_fhair() - -/datum/species/drask - name = "Drask" - name_plural = "Drask" - icobase = 'icons/mob/human_races/r_drask.dmi' - deform = 'icons/mob/human_races/r_drask.dmi' - path = /mob/living/carbon/human/drask - default_language = "Galactic Common" - language = "Orluum" - unarmed_type = /datum/unarmed_attack/punch - eyes = "drask_eyes_s" - - speech_sounds = list('sound/voice/DraskTalk.ogg') - speech_chance = 20 - male_scream_sound = 'sound/voice/DraskTalk2.ogg' - female_scream_sound = 'sound/voice/DraskTalk2.ogg' - male_cough_sounds = 'sound/voice/DraskCough.ogg' - female_cough_sounds = 'sound/voice/DraskCough.ogg' - male_sneeze_sound = 'sound/voice/DraskSneeze.ogg' - female_sneeze_sound = 'sound/voice/DraskSneeze.ogg' - - burn_mod = 2 - //exotic_blood = "cryoxadone" - body_temperature = 273 - - blurb = "Hailing from Hoorlm, planet outside what is usually considered a habitable \ - orbit, the Drask evolved to live in extreme cold. Their strange bodies seem \ - to operate better the colder their surroundings are, and can regenerate rapidly \ - when breathing supercooled gas.

    On their homeworld, the Drask live long lives \ - in their labyrinthine settlements, carved out beneath Hoorlm's icy surface, where the air \ - is of breathable density." - - suicide_messages = list( - "is self-warming with friction!", - "is jamming fingers through their big eyes!", - "is sucking in warm air!", - "is holding their breath!") - - species_traits = list(LIPS, IS_WHITELISTED) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT - bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS - dietflags = DIET_OMNI - - cold_level_1 = -1 //Default 260 - Lower is better - cold_level_2 = -1 //Default 200 - cold_level_3 = -1 //Default 120 - coldmod = -1 - - heat_level_1 = 300 //Default 360 - Higher is better - heat_level_2 = 340 //Default 400 - heat_level_3 = 400 //Default 460 - heatmod = 2 - - flesh_color = "#a3d4eb" - reagent_tag = PROCESS_ORG - base_color = "#a3d4eb" - blood_color = "#a3d4eb" - butt_sprite = "drask" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart/drask, - "lungs" = /obj/item/organ/internal/lungs/drask, - "metabolic strainer" = /obj/item/organ/internal/liver/drask, - "eyes" = /obj/item/organ/internal/eyes/drask, //5 darksight. - "brain" = /obj/item/organ/internal/brain/drask - ) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/tajaran.dm b/code/modules/mob/living/carbon/human/species/tajaran.dm new file mode 100644 index 00000000000..d4cdaf95944 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/tajaran.dm @@ -0,0 +1,58 @@ +/datum/species/tajaran + name = "Tajaran" + name_plural = "Tajaran" + icobase = 'icons/mob/human_races/r_tajaran.dmi' + deform = 'icons/mob/human_races/r_def_tajaran.dmi' + language = "Siik'tajr" + tail = "tajtail" + skinned_type = /obj/item/stack/sheet/fur + unarmed_type = /datum/unarmed_attack/claws + + blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \ + S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \ + influenced heavily by their long history of Slavemaster rule. They have a structured, clan-influenced way \ + of family and politics. They prefer colder environments, and speak a variety of languages, mostly Siik'Maas, \ + using unique inflections their mouths form." + + cold_level_1 = 240 + cold_level_2 = 180 + cold_level_3 = 100 + + heat_level_1 = 340 + heat_level_2 = 380 + heat_level_3 = 440 + + primitive_form = /datum/species/monkey/tajaran + + species_traits = list(LIPS, CAN_BE_FAT) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_HEAD_MARKINGS | HAS_BODY_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING + dietflags = DIET_OMNI + taste_sensitivity = TASTE_SENSITIVITY_SHARP + reagent_tag = PROCESS_ORG + flesh_color = "#AFA59E" + base_color = "#424242" + butt_sprite = "tajaran" + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/tajaran, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) + unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ + ) + + allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, + /mob/living/simple_animal/tribble) + + suicide_messages = list( + "is attempting to bite their tongue off!", + "is jamming their claws into their eye sockets!", + "is twisting their own neck!", + "is holding their breath!") + +/datum/species/tajaran/handle_death(mob/living/carbon/human/H) + H.stop_tail_wagging(1) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/unathi.dm b/code/modules/mob/living/carbon/human/species/unathi.dm new file mode 100644 index 00000000000..bcad7d9342e --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/unathi.dm @@ -0,0 +1,108 @@ +/datum/species/unathi + name = "Unathi" + name_plural = "Unathi" + icobase = 'icons/mob/human_races/r_lizard.dmi' + deform = 'icons/mob/human_races/r_def_lizard.dmi' + language = "Sinta'unathi" + tail = "sogtail" + skinned_type = /obj/item/stack/sheet/animalhide/lizard + unarmed_type = /datum/unarmed_attack/claws + primitive_form = /datum/species/monkey/unathi + + blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \ + Uuosa-Eso system, which roughly translates to 'burning mother'.

    Coming from a harsh, radioactive \ + desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \ + else, frequently even their own lives. They prefer warmer temperatures than most species and \ + their native tongue is a heavy hissing laungage called Sinta'Unathi." + + species_traits = list(LIPS) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_BODY_MARKINGS | HAS_HEAD_MARKINGS | HAS_SKIN_COLOR | HAS_ALT_HEADS | TAIL_WAGGING + dietflags = DIET_CARN + + cold_level_1 = 280 //Default 260 - Lower is better + cold_level_2 = 220 //Default 200 + cold_level_3 = 140 //Default 120 + + heat_level_1 = 380 //Default 360 - Higher is better + heat_level_2 = 420 //Default 400 + heat_level_3 = 480 //Default 460 + + flesh_color = "#34AF10" + reagent_tag = PROCESS_ORG + base_color = "#066000" + //Default styles for created mobs. + default_headacc = "Simple" + default_headacc_colour = "#404040" + butt_sprite = "unathi" + brute_mod = 1.05 + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/unathi, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes/unathi //3 darksight. + ) + + allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, + /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) + + suicide_messages = list( + "is attempting to bite their tongue off!", + "is jamming their claws into their eye sockets!", + "is twisting their own neck!", + "is holding their breath!") + + var/datum/action/innate/tail_lash/lash + + +/datum/species/unathi/on_species_gain(mob/living/carbon/human/H) + ..() + lash = new + lash.Grant(H) + +/datum/species/unathi/on_species_loss(mob/living/carbon/human/H) + ..() + if(lash) + lash.Remove(H) + +/datum/action/innate/tail_lash + name = "Tail lash" + icon_icon = 'icons/effects/effects.dmi' + button_icon_state = "tail" + check_flags = AB_CHECK_LYING | AB_CHECK_CONSCIOUS | AB_CHECK_STUNNED + +/datum/action/innate/tail_lash/Activate() + var/mob/living/carbon/human/user = owner + if((user.restrained() && user.pulledby) || user.buckled) + to_chat(user, "You need freedom of movement to tail lash!") + return + if(user.getStaminaLoss() >= 50) + to_chat(user, "Rest before tail lashing again!") + return + for(var/mob/living/carbon/human/C in orange(1)) + var/obj/item/organ/external/E = C.get_organ(pick("l_leg", "r_leg", "l_foot", "r_foot", "groin")) + if(E) + user.changeNext_move(CLICK_CD_MELEE) + user.visible_message("[user] smacks [C] in [E] with their tail! ", "You hit [C] in [E] with your tail!") + user.adjustStaminaLoss(15) + C.apply_damage(5, BRUTE, E) + user.spin(20, 1) + playsound(user.loc, 'sound/weapons/slash.ogg', 50, 0) + add_attack_logs(user, C, "tail whipped") + if(user.restrained()) + if(prob(50)) + user.Weaken(5) + user.visible_message("[user] loses [user.p_their()] balance!", "You lose your balance!") + return + if(user.getStaminaLoss() >= 60) //Bit higher as you don't need to start, just would need to keep going with the tail lash. + to_chat(user, "You run out of momentum!") + return + + + +/datum/species/unathi/handle_death(mob/living/carbon/human/H) + H.stop_tail_wagging(1) diff --git a/code/modules/mob/living/carbon/human/species/vox.dm b/code/modules/mob/living/carbon/human/species/vox.dm new file mode 100644 index 00000000000..1bc0b8b3b9e --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/vox.dm @@ -0,0 +1,197 @@ +/datum/species/vox + name = "Vox" + name_plural = "Vox" + icobase = 'icons/mob/human_races/vox/r_vox.dmi' + deform = 'icons/mob/human_races/vox/r_def_vox.dmi' + dangerous_existence = TRUE + language = "Vox-pidgin" + tail = "voxtail" + speech_sounds = list('sound/voice/shriek1.ogg') + speech_chance = 20 + unarmed_type = /datum/unarmed_attack/claws //I dont think it will hurt to give vox claws too. + + blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \ + scavenging vermin who prey on isolated stations, ships or planets to keep their own ancient arkships \ + alive. They are four to five feet tall, reptillian, beaked, tailed and quilled; human crews often \ + refer to them as 'shitbirds' for their violent and offensive nature, as well as their horrible \ + smell.

    Most humans will never meet a Vox raider, instead learning of this insular species through \ + dealing with their traders and merchants; those that do rarely enjoy the experience." + + brute_mod = 1.2 //20% more brute damage. Fragile bird bones. + + warning_low_pressure = 50 + hazard_low_pressure = 0 + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + breathid = "n2" + + eyes = "vox_eyes_s" + + species_traits = list(NO_SCAN, IS_WHITELISTED, NOTRANSSTING) + clothing_flags = HAS_SOCKS + dietflags = DIET_OMNI + bodyflags = HAS_ICON_SKIN_TONE | HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED | HAS_BODY_MARKINGS | HAS_TAIL_MARKINGS + + blood_color = "#2299FC" + flesh_color = "#808D11" + //Default styles for created mobs. + default_hair = "Short Vox Quills" + default_hair_colour = "#614f19" //R: 97, G: 79, B: 25 + butt_sprite = "vox" + + reagent_tag = PROCESS_ORG + scream_verb = "shrieks" + male_scream_sound = 'sound/voice/shriek1.ogg' + female_scream_sound = 'sound/voice/shriek1.ogg' + male_cough_sounds = list('sound/voice/shriekcough.ogg') + female_cough_sounds = list('sound/voice/shriekcough.ogg') + male_sneeze_sound = 'sound/voice/shrieksneeze.ogg' + female_sneeze_sound = 'sound/voice/shrieksneeze.ogg' + + icon_skin_tones = list( + 1 = "Default Green", + 2 = "Dark Green", + 3 = "Brown", + 4 = "Grey", + 5 = "Emerald", + 6 = "Azure" + ) + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs/vox, + "liver" = /obj/item/organ/internal/liver/vox, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. + "stack" = /obj/item/organ/internal/stack //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used + ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. + + suicide_messages = list( + "is attempting to bite their tongue off!", + "is jamming their claws into their eye sockets!", + "is twisting their own neck!", + "is holding their breath!", + "is deeply inhaling oxygen!") + +/datum/species/vox/handle_death(mob/living/carbon/human/H) + H.stop_tail_wagging(1) + +/datum/species/vox/after_equip_job(datum/job/J, mob/living/carbon/human/H) + if(!H.mind || !H.mind.assigned_role || H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime") + H.unEquip(H.wear_mask) + H.unEquip(H.l_hand) + + H.equip_or_collect(new /obj/item/clothing/mask/breath/vox(H), slot_wear_mask) + var/tank_pref = H.client && H.client.prefs ? H.client.prefs.speciesprefs : null + if(tank_pref)//Diseasel, here you go + H.equip_or_collect(new /obj/item/tank/nitrogen(H), slot_l_hand) + else + H.equip_or_collect(new /obj/item/tank/emergency_oxygen/vox(H), slot_l_hand) + to_chat(H, "You are now running on nitrogen internals from the [H.l_hand] in your hand. Your species finds oxygen toxic, so you must breathe nitrogen only.") + H.internal = H.l_hand + H.update_action_buttons_icon() + +/datum/species/vox/on_species_gain(mob/living/carbon/human/H) + ..() + updatespeciescolor(H) + H.update_icons() + +/datum/species/vox/updatespeciescolor(mob/living/carbon/human/H, owner_sensitive = 1) //Handling species-specific skin-tones for the Vox race. + if(H.dna.species.bodyflags & HAS_ICON_SKIN_TONE) //Making sure we don't break Armalis. + var/new_icobase = 'icons/mob/human_races/vox/r_vox.dmi' //Default Green Vox. + var/new_deform = 'icons/mob/human_races/vox/r_def_vox.dmi' //Default Green Vox. + switch(H.s_tone) + if(6) //Azure Vox. + new_icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' + new_deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi' + H.tail = "voxtail_azu" + if(5) //Emerald Vox. + new_icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi' + new_deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi' + H.tail = "voxtail_emrl" + if(4) //Grey Vox. + new_icobase = 'icons/mob/human_races/vox/r_voxgry.dmi' + new_deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi' + H.tail = "voxtail_gry" + if(3) //Brown Vox. + new_icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi' + new_deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi' + H.tail = "voxtail_brn" + if(2) //Dark Green Vox. + new_icobase = 'icons/mob/human_races/vox/r_voxdgrn.dmi' + new_deform = 'icons/mob/human_races/vox/r_def_voxdgrn.dmi' + H.tail = "voxtail_dgrn" + else //Default Green Vox. + H.tail = "voxtail" //Ensures they get an appropriately coloured tail depending on the skin-tone. + + H.change_icobase(new_icobase, new_deform, owner_sensitive) //Update the icobase/deform of all our organs, but make sure we don't mess with frankenstein limbs in doing so. + H.update_dna() + +/datum/species/vox/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) + if(R.id == "oxygen") //Armalis are above such petty things. + H.adjustToxLoss(1*REAGENTS_EFFECT_MULTIPLIER) //Same as plasma. + H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM) + return FALSE //Handling reagent removal on our own. + + return ..() + +/datum/species/vox/armalis + name = "Vox Armalis" + name_plural = "Vox Armalis" + icobase = 'icons/mob/human_races/r_armalis.dmi' + deform = 'icons/mob/human_races/r_armalis.dmi' + unarmed_type = /datum/unarmed_attack/claws/armalis + blacklisted = TRUE + + warning_low_pressure = 50 + hazard_low_pressure = 0 + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + heat_level_1 = 2000 + heat_level_2 = 3000 + heat_level_3 = 4000 + + brute_mod = 0.2 + burn_mod = 0.2 + + eyes = "blank_eyes" + + species_traits = list(NO_SCAN, NO_BLOOD, NO_PAIN, IS_WHITELISTED) + bodyflags = HAS_TAIL + dietflags = DIET_OMNI //should inherit this from vox, this is here just in case + + blood_color = "#2299FC" + flesh_color = "#808D11" + + reagent_tag = PROCESS_ORG + + tail = "armalis_tail" + icon_template = 'icons/mob/human_races/r_armalis.dmi' + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs/vox, + "liver" = /obj/item/organ/internal/liver, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. + "stack" = /obj/item/organ/internal/stack //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used + ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. + + suicide_messages = list( + "is attempting to bite their tongue off!", + "is jamming their claws into their eye sockets!", + "is twisting their own neck!", + "is holding their breath!", + "is huffing oxygen!") + +/datum/species/vox/armalis/handle_reagents() //Skip the Vox oxygen reagent toxicity. Armalis are above such things. + return TRUE \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/vulpkanin.dm b/code/modules/mob/living/carbon/human/species/vulpkanin.dm new file mode 100644 index 00000000000..3e6ebc1d41d --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/vulpkanin.dm @@ -0,0 +1,52 @@ +/datum/species/vulpkanin + name = "Vulpkanin" + name_plural = "Vulpkanin" + icobase = 'icons/mob/human_races/r_vulpkanin.dmi' + deform = 'icons/mob/human_races/r_vulpkanin.dmi' + language = "Canilunzt" + primitive_form = /datum/species/monkey/vulpkanin + tail = "vulptail" + skinned_type = /obj/item/stack/sheet/fur + unarmed_type = /datum/unarmed_attack/claws + + blurb = "Vulpkanin are a species of sharp-witted canine-pideds residing on the planet Altam just barely within the \ + dual-star Vazzend system. Their politically de-centralized society and independent natures have led them to become a species and \ + culture both feared and respected for their scientific breakthroughs. Discovery, loyalty, and utilitarianism dominates their lifestyles \ + to the degree it can cause conflict with more rigorous and strict authorities. They speak a guttural language known as 'Canilunzt' \ + which has a heavy emphasis on utilizing tail positioning and ear twitches to communicate intent." + + species_traits = list(LIPS) + clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS + bodyflags = HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR + dietflags = DIET_OMNI + hunger_drain = 0.11 + taste_sensitivity = TASTE_SENSITIVITY_SHARP + reagent_tag = PROCESS_ORG + flesh_color = "#966464" + base_color = "#CF4D2F" + butt_sprite = "vulp" + + scream_verb = "yelps" + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/vulpkanin, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) + unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ + ) + + allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, + /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) + + suicide_messages = list( + "is attempting to bite their tongue off!", + "is jamming their claws into their eye sockets!", + "is twisting their own neck!", + "is holding their breath!") + +/datum/species/vulpkanin/handle_death(mob/living/carbon/human/H) + H.stop_tail_wagging(1) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/wryn.dm similarity index 58% rename from code/modules/mob/living/carbon/human/species/apollo.dm rename to code/modules/mob/living/carbon/human/species/wryn.dm index 6c37da34395..219be4111b3 100644 --- a/code/modules/mob/living/carbon/human/species/apollo.dm +++ b/code/modules/mob/living/carbon/human/species/wryn.dm @@ -3,12 +3,11 @@ name_plural = "Wryn" icobase = 'icons/mob/human_races/r_wryn.dmi' deform = 'icons/mob/human_races/r_wryn.dmi' + blacklisted = TRUE language = "Wryn Hivemind" tail = "wryntail" - unarmed_type = /datum/unarmed_attack/punch/weak punchdamagelow = 0 punchdamagehigh = 1 - //primitive = /mob/living/carbon/monkey/wryn slowdown = 1 warning_low_pressure = -300 hazard_low_pressure = 1 @@ -50,11 +49,11 @@ default_hair = "Antennae" -/datum/species/wryn/handle_death(var/mob/living/carbon/human/H) +/datum/species/wryn/handle_death(mob/living/carbon/human/H) for(var/mob/living/carbon/C in living_mob_list) if(C.get_int_organ(/obj/item/organ/internal/wryn/hivenode)) to_chat(C, "Your antennae tingle as you are overcome with pain...") - to_chat(C, "It feels like part of you has died.") + to_chat(C, "It feels like part of you has died.") // This is bullshit /datum/species/wryn/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) if(target.handcuffed && target.get_int_organ(/obj/item/organ/internal/wryn/hivenode)) @@ -76,47 +75,4 @@ add_attack_logs(user, target, "Antennae removed") return 0 else - ..() - -/datum/species/nucleation - name = "Nucleation" - name_plural = "Nucleations" - icobase = 'icons/mob/human_races/r_nucleation.dmi' - unarmed_type = /datum/unarmed_attack/punch - blurb = "A sub-race of unfortunates who have been exposed to too much supermatter radiation. As a result, \ - supermatter crystal clusters have begun to grow across their bodies. Research to find a cure for this ailment \ - has been slow, and so this is a common fate for veteran engineers. The supermatter crystals produce oxygen, \ - negating the need for the individual to breathe. Their massive change in biology, however, renders most medicines \ - obselete. Ionizing radiation seems to cause resonance in some of their crystals, which seems to encourage regeneration \ - and produces a calming effect on the individual. Nucleations are highly stigmatized, and are treated much in the same \ - way as lepers were back on Earth." - language = "Sol Common" - burn_mod = 4 // holy shite, poor guys wont survive half a second cooking smores - brute_mod = 2 // damn, double wham, double dam - oxy_mod = 0 - species_traits = list(LIPS, IS_WHITELISTED, NO_BREATHE, NO_BLOOD, NO_PAIN, NO_SCAN, RADIMMUNE) - dietflags = DIET_OMNI //still human at their core, so they maintain their eating habits and diet - - //Default styles for created mobs. - default_hair = "Nucleation Crystals" - - reagent_tag = PROCESS_ORG - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "crystallized brain" = /obj/item/organ/internal/brain/crystal, - "eyes" = /obj/item/organ/internal/eyes/luminescent_crystal, //Standard darksight of 2. - "strange crystal" = /obj/item/organ/internal/nucleation/strange_crystal - ) - vision_organ = /obj/item/organ/internal/eyes/luminescent_crystal - -/datum/species/nucleation/handle_post_spawn(var/mob/living/carbon/human/H) - H.light_color = "#1C1C00" - H.set_light(2) - return ..() - -/datum/species/nucleation/handle_death(var/mob/living/carbon/human/H) - var/turf/T = get_turf(H) - H.visible_message("[H]'s body explodes, leaving behind a pile of microscopic crystals!") - explosion(T, 0, 0, 2, 2) // Create a small explosion burst upon death -// new /obj/item/shard/supermatter( T ) - qdel(H) \ No newline at end of file + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm index 5f74f202603..e7a65129017 100644 --- a/code/modules/mob/living/carbon/human/status_procs.dm +++ b/code/modules/mob/living/carbon/human/status_procs.dm @@ -1,19 +1,19 @@ /mob/living/carbon/human/SetStunned(amount, updating = 1, force = 0) - if(species) - amount = amount * species.stun_mod + if(dna.species) + amount = amount * dna.species.stun_mod ..() /mob/living/carbon/human/SetWeakened(amount, updating = 1, force = 0) - if(species) - amount = amount * species.stun_mod + if(dna.species) + amount = amount * dna.species.stun_mod ..() /mob/living/carbon/human/SetParalysis(amount, updating = 1, force = 0) - if(species) - amount = amount * species.stun_mod + if(dna.species) + amount = amount * dna.species.stun_mod ..() /mob/living/carbon/human/SetSleeping(amount, updating = 1, no_alert = FALSE) - if(species) - amount = amount * species.stun_mod + if(dna.species) + amount = amount * dna.species.stun_mod ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index ec7592d4d3f..450b7a6c1a4 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -185,7 +185,7 @@ var/global/list/damage_icon_parts = list() previous_damage_appearance = damage_appearance - var/icon/standing = new /icon(species.damage_overlays, "00") + var/icon/standing = new /icon(dna.species.damage_overlays, "00") var/image/standing_image = new /image("icon" = standing) @@ -194,18 +194,18 @@ var/global/list/damage_icon_parts = list() O.update_icon() if(O.damage_state == "00") continue var/icon/DI - var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.name]" + var/cache_index = "[O.damage_state]/[O.icon_name]/[dna.species.blood_color]/[dna.species.name]" if(damage_icon_parts[cache_index] == null) - DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human - DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels - DI.Blend(species.blood_color, ICON_MULTIPLY) + DI = new /icon(dna.species.damage_overlays, O.damage_state) // the damage icon for whole human + DI.Blend(new /icon(dna.species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels + DI.Blend(dna.species.blood_color, ICON_MULTIPLY) damage_icon_parts[cache_index] = DI else DI = damage_icon_parts[cache_index] standing_image.overlays += DI - overlays_standing[DAMAGE_LAYER] = standing_image + overlays_standing[H_DAMAGE_LAYER] = standing_image if(update_icons) update_icons() @@ -220,15 +220,15 @@ var/global/list/damage_icon_parts = list() var/hulk = (HULK in mutations) var/skeleton = (SKELETON in mutations) - if(species && species.bodyflags & HAS_ICON_SKIN_TONE) - species.updatespeciescolor(src) + if(dna.species && dna.species.bodyflags & HAS_ICON_SKIN_TONE) + dna.species.updatespeciescolor(src) //CACHING: Generate an index key from visible bodyparts. //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. //Create a new, blank icon for our mob to use. if(stand_icon) qdel(stand_icon) - stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") + stand_icon = new(dna.species.icon_template ? dna.species.icon_template : 'icons/mob/human.dmi',"blank") var/icon_key = "" var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) @@ -237,11 +237,11 @@ var/global/list/damage_icon_parts = list() else icon_key += "#000000" - for(var/organ_tag in species.has_limbs) + for(var/organ_tag in dna.species.has_limbs) var/obj/item/organ/external/part = bodyparts_by_name[organ_tag] if(isnull(part)) icon_key += "0" - else if(part.status & ORGAN_ROBOT) + else if(part.is_robotic()) icon_key += "2[part.model ? "-[part.model]": ""]" else if(part.status & ORGAN_DEAD) icon_key += "3" @@ -249,7 +249,8 @@ var/global/list/damage_icon_parts = list() icon_key += "1" if(part) - icon_key += "[part.species.race_key]" + var/datum/species/S = GLOB.all_species[part.dna.species.name] //This has to reference the species datums from round start, since they're global and unchanging + icon_key += "[S.race_key]" icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" if(part.s_col) @@ -307,7 +308,7 @@ var/global/list/damage_icon_parts = list() //END CACHED ICON GENERATION. stand_icon.Blend(base_icon,ICON_OVERLAY) - if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && species.bodyflags & TAIL_OVERLAPPED) // If the user's species is flagged to have a tail that needs to be overlapped by limbs... (having a non-tail body accessory like the snake body will override this) + if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the user's species is flagged to have a tail that needs to be overlapped by limbs... (having a non-tail body accessory like the snake body will override this) overlays_standing[LIMBS_LAYER] = image(stand_icon) // Diverts limbs to their own layer so they can overlay things (i.e. tails). else overlays_standing[LIMBS_LAYER] = null // So we don't get the old species' sprite splatted on top of the new one's @@ -316,18 +317,18 @@ var/global/list/damage_icon_parts = list() overlays_standing[UNDERWEAR_LAYER] = null var/icon/underwear_standing = new/icon('icons/mob/underwear.dmi',"nude") - if(underwear && species.clothing_flags & HAS_UNDERWEAR) + if(underwear && dna.species.clothing_flags & HAS_UNDERWEAR) var/datum/sprite_accessory/underwear/U = underwear_list[underwear] if(U) underwear_standing.Blend(new /icon(U.icon, "uw_[U.icon_state]_s"), ICON_OVERLAY) - if(undershirt && species.clothing_flags & HAS_UNDERSHIRT) + if(undershirt && dna.species.clothing_flags & HAS_UNDERSHIRT) var/datum/sprite_accessory/undershirt/U2 = undershirt_list[undershirt] if(U2) underwear_standing.Blend(new /icon(U2.icon, "us_[U2.icon_state]_s"), ICON_OVERLAY) - if(socks && species.clothing_flags & HAS_SOCKS) + if(socks && dna.species.clothing_flags & HAS_SOCKS) var/datum/sprite_accessory/socks/U3 = socks_list[socks] if(U3) underwear_standing.Blend(new /icon(U3.icon, "sk_[U3.icon_state]_s"), ICON_OVERLAY) @@ -339,7 +340,7 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() - if(lip_style && (LIPS in species.species_traits)) + if(lip_style && (LIPS in dna.species.species_traits)) var/icon/lips = icon("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[lip_style]_s") lips.Blend(lip_color, ICON_ADD) @@ -369,7 +370,7 @@ var/global/list/damage_icon_parts = list() if(chest_organ && m_styles["body"]) var/body_marking = m_styles["body"] var/datum/sprite_accessory/body_marking_style = marking_styles_list[body_marking] - if(body_marking_style && body_marking_style.species_allowed && (species.name in body_marking_style.species_allowed)) + if(body_marking_style && body_marking_style.species_allowed && (dna.species.name in body_marking_style.species_allowed)) var/icon/b_marking_s = new/icon("icon" = body_marking_style.icon, "icon_state" = "[body_marking_style.icon_state]_s") if(body_marking_style.do_colouration) b_marking_s.Blend(m_colours["body"], ICON_ADD) @@ -379,7 +380,7 @@ var/global/list/damage_icon_parts = list() if(head_organ && m_styles["head"]) //If the head is destroyed, forget the head markings. This prevents floating optical markings on decapitated IPCs, for example. var/head_marking = m_styles["head"] var/datum/sprite_accessory/head_marking_style = marking_styles_list[head_marking] - if(head_marking_style && head_marking_style.species_allowed && (head_organ.species.name in head_marking_style.species_allowed)) + if(head_marking_style && head_marking_style.species_allowed && (head_organ.dna.species.name in head_marking_style.species_allowed)) var/icon/h_marking_s = new/icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") if(head_marking_style.do_colouration) h_marking_s.Blend(m_colours["head"], ICON_ADD) @@ -407,10 +408,10 @@ var/global/list/damage_icon_parts = list() //base icons var/icon/head_accessory_standing = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - if(head_organ.ha_style && (head_organ.species.bodyflags & HAS_HEAD_ACCESSORY)) + if(head_organ.ha_style && (head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY)) var/datum/sprite_accessory/head_accessory/head_accessory_style = head_accessory_styles_list[head_organ.ha_style] if(head_accessory_style && head_accessory_style.species_allowed) - if(head_organ.species.name in head_accessory_style.species_allowed) + if(head_organ.dna.species.name in head_accessory_style.species_allowed) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) head_accessory_s.Blend(head_organ.headacc_colour, ICON_ADD) @@ -448,12 +449,12 @@ var/global/list/damage_icon_parts = list() if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()))) var/datum/sprite_accessory/hair/hair_style = hair_styles_full_list[head_organ.h_style] - //if(!src.get_int_organ(/obj/item/organ/internal/brain) && src.get_species() != "Machine" )//make it obvious we have NO BRAIN + //if(!src.get_int_organ(/obj/item/organ/internal/brain) && !ismachine(src))//make it obvious we have NO BRAIN // hair_standing.Blend(debrained_s, ICON_OVERLAY) if(hair_style && hair_style.species_allowed) - if((head_organ.species.name in hair_style.species_allowed) || (head_organ.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... + if((head_organ.dna.species.name in hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(head_organ.species.name == "Slime People") // I am el worstos + if(istype(head_organ.dna.species, /datum/species/slime)) // I am el worstos hair_s.Blend("[skin_colour]A0", ICON_AND) else if(hair_style.do_colouration) hair_s.Blend(head_organ.hair_colour, ICON_ADD) @@ -497,9 +498,9 @@ var/global/list/damage_icon_parts = list() if(head_organ.f_style) var/datum/sprite_accessory/facial_hair/facial_hair_style = facial_hair_styles_list[head_organ.f_style] if(facial_hair_style && facial_hair_style.species_allowed) - if((head_organ.species.name in facial_hair_style.species_allowed) || (head_organ.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... + if((head_organ.dna.species.name in facial_hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(head_organ.species.name == "Slime People") // I am el worstos + if(istype(head_organ.dna.species, /datum/species/slime)) // I am el worstos facial_s.Blend("[skin_colour]A0", ICON_AND) else if(facial_hair_style.do_colouration) facial_s.Blend(head_organ.facial_colour, ICON_ADD) @@ -644,11 +645,11 @@ var/global/list/damage_icon_parts = list() if(w_uniform.icon_override) standing.icon = w_uniform.icon_override - else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[species.name]) - standing.icon = w_uniform.sprite_sheets[species.name] + else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[dna.species.name]) + standing.icon = w_uniform.sprite_sheets[dna.species.name] if(w_uniform.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "uniformblood") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "uniformblood") bloodsies.color = w_uniform.blood_color standing.overlays += bloodsies @@ -658,8 +659,8 @@ var/global/list/damage_icon_parts = list() if(!tie_color) tie_color = A.icon_state if(A.icon_override) standing.overlays += image("icon" = A.icon_override, "icon_state" = "[A.icon_state]") - else if(A.sprite_sheets && A.sprite_sheets[species.name]) - standing.overlays += image("icon" = A.sprite_sheets[species.name], "icon_state" = "[A.icon_state]") + else if(A.sprite_sheets && A.sprite_sheets[dna.species.name]) + standing.overlays += image("icon" = A.sprite_sheets[dna.species.name], "icon_state" = "[A.icon_state]") else standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]") @@ -720,19 +721,19 @@ var/global/list/damage_icon_parts = list() var/image/standing if(gloves.icon_override) standing = image("icon" = gloves.icon_override, "icon_state" = "[t_state]") - else if(gloves.sprite_sheets && gloves.sprite_sheets[species.name]) - standing = image("icon" = gloves.sprite_sheets[species.name], "icon_state" = "[t_state]") + else if(gloves.sprite_sheets && gloves.sprite_sheets[dna.species.name]) + standing = image("icon" = gloves.sprite_sheets[dna.species.name], "icon_state" = "[t_state]") else standing = image("icon" = 'icons/mob/hands.dmi', "icon_state" = "[t_state]") if(gloves.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "bloodyhands") bloodsies.color = gloves.blood_color standing.overlays += bloodsies overlays_standing[GLOVES_LAYER] = standing else if(blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "bloodyhands") bloodsies.color = hand_blood_color overlays_standing[GLOVES_LAYER] = bloodsies else @@ -759,8 +760,8 @@ var/global/list/damage_icon_parts = list() if(glasses.icon_override) new_glasses = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]") - else if(glasses.sprite_sheets && glasses.sprite_sheets[head_organ.species.name]) - new_glasses = image("icon" = glasses.sprite_sheets[head_organ.species.name], "icon_state" = "[glasses.icon_state]") + else if(glasses.sprite_sheets && glasses.sprite_sheets[head_organ.dna.species.name]) + new_glasses = image("icon" = glasses.sprite_sheets[head_organ.dna.species.name], "icon_state" = "[glasses.icon_state]") else new_glasses = image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]") @@ -795,9 +796,9 @@ var/global/list/damage_icon_parts = list() if(l_ear.icon_override) t_type = "[t_type]_l" overlays_standing[EARS_LAYER] = image("icon" = l_ear.icon_override, "icon_state" = "[t_type]") - else if(l_ear.sprite_sheets && l_ear.sprite_sheets[species.name]) + else if(l_ear.sprite_sheets && l_ear.sprite_sheets[dna.species.name]) t_type = "[t_type]_l" - overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[species.name], "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[dna.species.name], "icon_state" = "[t_type]") else overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") @@ -811,9 +812,9 @@ var/global/list/damage_icon_parts = list() if(r_ear.icon_override) t_type = "[t_type]_r" overlays_standing[EARS_LAYER] = image("icon" = r_ear.icon_override, "icon_state" = "[t_type]") - else if(r_ear.sprite_sheets && r_ear.sprite_sheets[species.name]) + else if(r_ear.sprite_sheets && r_ear.sprite_sheets[dna.species.name]) t_type = "[t_type]_r" - overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[species.name], "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[dna.species.name], "icon_state" = "[t_type]") else overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") @@ -837,20 +838,20 @@ var/global/list/damage_icon_parts = list() var/image/standing if(shoes.icon_override) standing = image("icon" = shoes.icon_override, "icon_state" = "[shoes.icon_state]") - else if(shoes.sprite_sheets && shoes.sprite_sheets[species.name]) - standing = image("icon" = shoes.sprite_sheets[species.name], "icon_state" = "[shoes.icon_state]") + else if(shoes.sprite_sheets && shoes.sprite_sheets[dna.species.name]) + standing = image("icon" = shoes.sprite_sheets[dna.species.name], "icon_state" = "[shoes.icon_state]") else standing = image("icon" = 'icons/mob/feet.dmi', "icon_state" = "[shoes.icon_state]") if(shoes.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "shoeblood") bloodsies.color = shoes.blood_color standing.overlays += bloodsies overlays_standing[SHOES_LAYER] = standing else if(feet_blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "shoeblood") bloodsies.color = feet_blood_color overlays_standing[SHOES_LAYER] = bloodsies else @@ -891,13 +892,13 @@ var/global/list/damage_icon_parts = list() var/image/standing if(head.icon_override) standing = image("icon" = head.icon_override, "icon_state" = "[head.icon_state]") - else if(head.sprite_sheets && head.sprite_sheets[species.name]) - standing = image("icon" = head.sprite_sheets[species.name], "icon_state" = "[head.icon_state]") + else if(head.sprite_sheets && head.sprite_sheets[dna.species.name]) + standing = image("icon" = head.sprite_sheets[dna.species.name], "icon_state" = "[head.icon_state]") else standing = image("icon" = 'icons/mob/head.dmi', "icon_state" = "[head.icon_state]") if(head.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "helmetblood") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "helmetblood") bloodsies.color = head.blood_color standing.overlays += bloodsies overlays_standing[HEAD_LAYER] = standing @@ -925,8 +926,8 @@ var/global/list/damage_icon_parts = list() if(belt.icon_override) t_state = "[t_state]_be" overlays_standing[BELT_LAYER] = image("icon" = belt.icon_override, "icon_state" = "[t_state]") - else if(belt.sprite_sheets && belt.sprite_sheets[species.name]) - overlays_standing[BELT_LAYER] = image("icon" = belt.sprite_sheets[species.name], "icon_state" = "[t_state]") + else if(belt.sprite_sheets && belt.sprite_sheets[dna.species.name]) + overlays_standing[BELT_LAYER] = image("icon" = belt.sprite_sheets[dna.species.name], "icon_state" = "[t_state]") else overlays_standing[BELT_LAYER] = image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[t_state]") else @@ -949,8 +950,8 @@ var/global/list/damage_icon_parts = list() var/image/standing if(wear_suit.icon_override) standing = image("icon" = wear_suit.icon_override, "icon_state" = "[wear_suit.icon_state]") - else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.name]) - standing = image("icon" = wear_suit.sprite_sheets[species.name], "icon_state" = "[wear_suit.icon_state]") + else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[dna.species.name]) + standing = image("icon" = wear_suit.sprite_sheets[dna.species.name], "icon_state" = "[wear_suit.icon_state]") else if(FAT in mutations) if(wear_suit.flags_size & ONESIZEFITSALL) standing = image("icon" = 'icons/mob/suit_fat.dmi', "icon_state" = "[wear_suit.icon_state]") @@ -969,7 +970,7 @@ var/global/list/damage_icon_parts = list() if(wear_suit.blood_DNA) var/obj/item/clothing/suit/S = wear_suit - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "[S.blood_overlay_type]blood") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "[S.blood_overlay_type]blood") bloodsies.color = wear_suit.blood_color standing.overlays += bloodsies @@ -1035,14 +1036,14 @@ var/global/list/damage_icon_parts = list() if(wear_mask.icon_override) mask_icon = new(wear_mask.icon_override) standing = image("icon" = wear_mask.icon_override, "icon_state" = "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]") - else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[species.name]) - mask_icon = new(wear_mask.sprite_sheets[species.name]) - standing = image("icon" = wear_mask.sprite_sheets[species.name], "icon_state" = "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]") + else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[dna.species.name]) + mask_icon = new(wear_mask.sprite_sheets[dna.species.name]) + standing = image("icon" = wear_mask.sprite_sheets[dna.species.name], "icon_state" = "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]") else standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]") if(!istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "maskblood") + var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "maskblood") bloodsies.color = wear_mask.blood_color standing.overlays += bloodsies overlays_standing[FACEMASK_LAYER] = standing @@ -1062,8 +1063,8 @@ var/global/list/damage_icon_parts = list() //If this is a rig and a mob_icon is set, it will take species into account in the rig update_icon() proc. var/obj/item/rig/rig = back standing = rig.mob_icon - else if(back.sprite_sheets && back.sprite_sheets[species.name]) - standing = image("icon" = back.sprite_sheets[species.name], "icon_state" = "[back.icon_state]") + else if(back.sprite_sheets && back.sprite_sheets[dna.species.name]) + standing = image("icon" = back.sprite_sheets[dna.species.name], "icon_state" = "[back.icon_state]") else standing = image("icon" = 'icons/mob/back.dmi', "icon_state" = "[back.icon_state]") @@ -1163,7 +1164,7 @@ var/global/list/damage_icon_parts = list() var/icon/tail_marking_icon var/datum/sprite_accessory/body_markings/tail/tail_marking_style - if(m_styles["tail"] != "None" && (species.bodyflags & HAS_TAIL_MARKINGS)) + if(m_styles["tail"] != "None" && (dna.species.bodyflags & HAS_TAIL_MARKINGS)) var/tail_marking = m_styles["tail"] tail_marking_style = marking_styles_list[tail_marking] tail_marking_icon = new/icon("icon" = tail_marking_style.icon, "icon_state" = "[tail_marking_style.icon_state]_s") @@ -1172,11 +1173,11 @@ var/global/list/damage_icon_parts = list() if(body_accessory) if(body_accessory.try_restrictions(src)) var/icon/accessory_s = new/icon("icon" = body_accessory.icon, "icon_state" = body_accessory.icon_state) - if(species.bodyflags & HAS_SKIN_COLOR) + if(dna.species.bodyflags & HAS_SKIN_COLOR) accessory_s.Blend(skin_colour, body_accessory.blend_mode) if(tail_marking_icon && (body_accessory.name in tail_marking_style.tails_allowed)) accessory_s.Blend(tail_marking_icon, ICON_OVERLAY) - if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) + if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/under = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "accessory_none_s") under.Insert(new/icon(accessory_s, dir=SOUTH), dir=SOUTH) @@ -1194,14 +1195,14 @@ var/global/list/damage_icon_parts = list() else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation. overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) - else if(tail && species.bodyflags & HAS_TAIL) //no tailless tajaran + else if(tail && dna.species.bodyflags & HAS_TAIL) //no tailless tajaran if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]_s") - if(species.bodyflags & HAS_SKIN_COLOR) + if(dna.species.bodyflags & HAS_SKIN_COLOR) tail_s.Blend(skin_colour, ICON_ADD) if(tail_marking_icon && !tail_marking_style.tails_allowed) tail_s.Blend(tail_marking_icon, ICON_OVERLAY) - if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) + if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "blank") under.Insert(new/icon(tail_s, dir=SOUTH), dir=SOUTH) @@ -1230,7 +1231,7 @@ var/global/list/damage_icon_parts = list() var/icon/tail_marking_icon var/datum/sprite_accessory/body_markings/tail/tail_marking_style - if(m_styles["tail"] != "None" && (species.bodyflags & HAS_TAIL_MARKINGS)) + if(m_styles["tail"] != "None" && (dna.species.bodyflags & HAS_TAIL_MARKINGS)) var/tail_marking = m_styles["tail"] tail_marking_style = marking_styles_list[tail_marking] tail_marking_icon = new/icon("icon" = tail_marking_style.icon, "icon_state" = "[tail_marking_style.icon_state]w_s") @@ -1238,15 +1239,15 @@ var/global/list/damage_icon_parts = list() if(body_accessory) var/icon/accessory_s = new/icon("icon" = body_accessory.get_animated_icon(), "icon_state" = body_accessory.get_animated_icon_state()) - if(species.bodyflags & HAS_SKIN_COLOR) + if(dna.species.bodyflags & HAS_SKIN_COLOR) accessory_s.Blend(skin_colour, body_accessory.blend_mode) if(tail_marking_icon && (body_accessory.name in tail_marking_style.tails_allowed)) accessory_s.Blend(tail_marking_icon, ICON_OVERLAY) - if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) + if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "Vulpkanin_tail_delay") - if(body_accessory.allowed_species && (species.name in body_accessory.allowed_species)) - under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.name]_tail_delay") + if(body_accessory.allowed_species && (dna.species.name in body_accessory.allowed_species)) + under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") under.Insert(new/icon(accessory_s, dir=SOUTH), dir=SOUTH) under.Insert(new/icon(accessory_s, dir=EAST), dir=EAST) under.Insert(new/icon(accessory_s, dir=WEST), dir=WEST) @@ -1255,23 +1256,23 @@ var/global/list/damage_icon_parts = list() // Creates a blank icon, and copies accessory_s' north direction sprite into it before passing that to the tail layer that overlays uniforms and such. var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "Vulpkanin_tail_delay") - if(body_accessory.allowed_species && (species.name in body_accessory.allowed_species)) // If the user's species is in the list of allowed species for the currently selected body accessory, use the appropriate animation timing blank - over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.name]_tail_delay") + if(body_accessory.allowed_species && (dna.species.name in body_accessory.allowed_species)) // If the user's species is in the list of allowed species for the currently selected body accessory, use the appropriate animation timing blank + over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") over.Insert(new/icon(accessory_s, dir=NORTH), dir=NORTH) overlays_standing[TAIL_LAYER] = image(over, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation. overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) - else if(tail && species.bodyflags & HAS_TAIL) + else if(tail && dna.species.bodyflags & HAS_TAIL) var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]w_s") - if(species.bodyflags & HAS_SKIN_COLOR) + if(dna.species.bodyflags & HAS_SKIN_COLOR) tailw_s.Blend(skin_colour, ICON_ADD) if(tail_marking_icon && !tail_marking_style.tails_allowed) tailw_s.Blend(tail_marking_icon, ICON_OVERLAY) - if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) + if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. - var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.name]_tail_delay") + var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") under.Insert(new/icon(tailw_s, dir=SOUTH), dir=SOUTH) under.Insert(new/icon(tailw_s, dir=EAST), dir=EAST) under.Insert(new/icon(tailw_s, dir=WEST), dir=WEST) @@ -1279,7 +1280,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(under) // Creates a blank icon, and copies accessory_s' north direction sprite into it before passing that to the tail layer that overlays uniforms and such. - var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.name]_tail_delay") + var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") over.Insert(new/icon(tailw_s, dir=NORTH), dir=NORTH) overlays_standing[TAIL_LAYER] = image(over) @@ -1314,8 +1315,8 @@ var/global/list/damage_icon_parts = list() var/icon/icon_file = new(icon_path) if(wear_suit.icon_state in icon_file.IconStates()) standing = image("icon" = icon_file, "icon_state" = "[wear_suit.icon_state]") - else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.name]) - var/icon_path = "[wear_suit.sprite_sheets[species.name]]" + else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[dna.species.name]) + var/icon_path = "[wear_suit.sprite_sheets[dna.species.name]]" icon_path = "[copytext(icon_path, 1, findtext(icon_path, "/suit.dmi"))]/collar.dmi" //If this file doesn't exist, the end result is that COLLAR_LAYER will be unchanged (empty). if(fexists(icon_path)) //Just ensuring the nonexistance of a file with the above path won't cause a runtime. var/icon/icon_file = new(icon_path) diff --git a/code/modules/mob/living/carbon/slime/life.dm b/code/modules/mob/living/carbon/slime/life.dm index 80ed9fdbffd..5b0ee885ce7 100644 --- a/code/modules/mob/living/carbon/slime/life.dm +++ b/code/modules/mob/living/carbon/slime/life.dm @@ -337,7 +337,7 @@ if(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men var/mob/living/carbon/human/H = L - if(H.species.name == "Slime People") + if(isslimeperson(H)) continue if(!L.canmove) // Only one slime can latch on at a time. diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm index ecb233a2ebf..506cc804bd3 100644 --- a/code/modules/mob/living/carbon/slime/slime.dm +++ b/code/modules/mob/living/carbon/slime/slime.dm @@ -234,8 +234,27 @@ adjustBruteLoss(damage) updatehealth() +/mob/living/carbon/slime/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + if(Victim || Target) + Victim = null + Target = null + anchored = 0 + if(prob(80) && !client) + Discipline++ + spawn(0) + step_away(src, user, 15) + sleep(3) + step_away(src, user, 15) + ..(user, TRUE) + playsound(loc, "punch", 25, 1, -1) + visible_message("[user] has punched [src]!", "[user] has punched [src]!") + adjustBruteLoss(15) + return TRUE + /mob/living/carbon/slime/attack_hand(mob/living/carbon/human/M) if(Victim) + M.do_attack_animation(src, ATTACK_EFFECT_DISARM) if(Victim == M) if(prob(60)) visible_message("[M] attempts to wrestle \the [name] off!") @@ -259,7 +278,6 @@ return else - M.do_attack_animation(src) if(prob(30)) visible_message("[M] attempts to wrestle \the [name] off of [Victim]!") playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) @@ -297,24 +315,10 @@ grabbedby(M) else - M.do_attack_animation(src) + M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) var/damage = rand(1, 9) attacked += 10 if(prob(90)) - if(HULK in M.mutations) - damage += 15 - if(Victim || Target) - Victim = null - Target = null - anchored = 0 - if(prob(80) && !client) - Discipline++ - spawn(0) - step_away(src,M,15) - sleep(3) - step_away(src,M,15) - - playsound(loc, "punch", 25, 1, -1) add_attack_logs(M, src, "Melee attacked with fists") visible_message("[M] has punched [src]!", \ diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm index d850caf658f..50b22a2c8ed 100644 --- a/code/modules/mob/living/carbon/superheroes.dm +++ b/code/modules/mob/living/carbon/superheroes.dm @@ -188,15 +188,15 @@ switch(progress) if(1) to_chat(user, "You begin by introducing yourself and explaining what you're about.") - user.visible_message("[user] introduces \himself and explains \his plans.") + user.visible_message("[user] introduces [user.p_them()]self and explains [user.p_their()] plans.") if(2) to_chat(user, "You begin the recruitment of [target].") - user.visible_message("[user] leans over towards [target], whispering excitedly as he gives a speech.") + user.visible_message("[user] leans over towards [target], whispering excitedly as [user.p_they()] give[user.p_s()] a speech.") to_chat(target, "You feel yourself agreeing with [user], and a surge of loyalty begins building.") target.Weaken(12) sleep(20) if(ismindshielded(target)) - to_chat(user, "They are enslaved by Nanotrasen. You feel their interest in your cause wane and disappear.") + to_chat(user, "[target.p_they(TRUE)] are enslaved by Nanotrasen. You feel [target.p_their()] interest in your cause wane and disappear.") user.visible_message("[user] stops talking for a moment, then moves back away from [target].") to_chat(target, "Your mindshield implant activates, protecting you from conversion.") return @@ -214,10 +214,10 @@ recruiting = 0 to_chat(user, "You have recruited [target] as your henchman!") to_chat(target, "You have decided to enroll as a henchman for [user]. You are now part of the feared 'Greyshirts'.") - to_chat(target, "You must follow the orders of [user], and help him succeed in \his dastardly schemes.") + to_chat(target, "You must follow the orders of [user], and help [user.p_them()] succeed in [user.p_their()] dastardly schemes.") to_chat(target, "You may not harm other Greyshirt or [user]. However, you do not need to obey other Greyshirts.") ticker.mode.greyshirts += target.mind - target.set_species("Human") + target.set_species(/datum/species/human) head_organ.h_style = "Bald" head_organ.f_style = "Shaved" target.s_tone = 35 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 4f3265fc619..4cfdc7bb1f4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1,4 +1,4 @@ -/mob/living/New() +/mob/living/Initialize() . = ..() var/datum/atom_hud/data/human/medical/advanced/medhud = huds[DATA_HUD_MEDICAL_ADVANCED] medhud.add_to_hud(src) @@ -137,10 +137,12 @@ if(!AM.anchored) now_pushing = 1 var/t = get_dir(src, AM) - if(istype(AM, /obj/structure/window/full)) - for(var/obj/structure/window/win in get_step(AM, t)) - now_pushing = 0 - return + if(istype(AM, /obj/structure/window)) + var/obj/structure/window/W = AM + if(W.fulltile) + for(var/obj/structure/window/win in get_step(W, t)) + now_pushing = 0 + return if(pulling == AM) stop_pulling() var/current_dir @@ -658,14 +660,14 @@ TH.transfer_mob_blood_dna(src) if(ishuman(src)) var/mob/living/carbon/human/H = src - if(H.species.blood_color) - TH.color = H.species.blood_color + if(H.dna.species.blood_color) + TH.color = H.dna.species.blood_color else TH.color = "#A10808" /mob/living/carbon/human/makeTrail(turf/T) - if((NO_BLOOD in species.species_traits) || species.exotic_blood || !bleed_rate || bleedsuppress) + if((NO_BLOOD in dna.species.species_traits) || dna.species.exotic_blood || !bleed_rate || bleedsuppress) return ..() @@ -816,7 +818,7 @@ who.unEquip(what) if(silent) put_in_hands(what) - add_attack_logs(src, who, "Stripped of [what]", isLivingSSD(who)) + add_attack_logs(src, who, "Stripped of [what]") // The src mob is trying to place an item on someone // Override if a certain mob should be behave differently when placing items (can't, for example) @@ -835,8 +837,7 @@ if(what && Adjacent(who)) unEquip(what) who.equip_to_slot_if_possible(what, where, 0, 1) - add_attack_logs(src, who, "Equipped [what]", isLivingSSD(who)) - + add_attack_logs(src, who, "Equipped [what]") /mob/living/singularity_act() var/gain = 20 @@ -852,81 +853,11 @@ makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, null, 1) spawn_dust() gib() - return -/atom/movable/proc/do_attack_animation(atom/A, end_pixel_y) - var/pixel_x_diff = 0 - var/pixel_y_diff = 0 - var/final_pixel_y = initial(pixel_y) - if(end_pixel_y) - final_pixel_y = end_pixel_y - - var/direction = get_dir(src, A) - if(direction & NORTH) - pixel_y_diff = 8 - else if(direction & SOUTH) - pixel_y_diff = -8 - - if(direction & EAST) - pixel_x_diff = 8 - else if(direction & WEST) - pixel_x_diff = -8 - - animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2) - animate(pixel_x = initial(pixel_x), pixel_y = final_pixel_y, time = 2) - - -/mob/living/do_attack_animation(atom/A) - var/final_pixel_y = get_standard_pixel_y_offset(lying) - ..(A, final_pixel_y) - floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. - - // What icon do we use for the attack? - var/image/I - if(hand && l_hand) // Attacked with item in left hand. - I = image(l_hand.icon, A, l_hand.icon_state, A.layer + 1) - else if(!hand && r_hand) // Attacked with item in right hand. - I = image(r_hand.icon, A, r_hand.icon_state, A.layer + 1) - else // Attacked with a fist? - return - - // Who can see the attack? - var/list/viewing = list() - for(var/mob/M in viewers(A)) - if(M.client && M.client.prefs.show_ghostitem_attack) - viewing |= M.client - flick_overlay(I, viewing, 5) // 5 ticks/half a second - - // Scale the icon. - I.transform *= 0.75 - // The icon should not rotate. - I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA - - // Set the direction of the icon animation. - var/direction = get_dir(src, A) - if(direction & NORTH) - I.pixel_y = -16 - else if(direction & SOUTH) - I.pixel_y = 16 - - if(direction & EAST) - I.pixel_x = -16 - else if(direction & WEST) - I.pixel_x = 16 - - if(!direction) // Attacked self?! - I.pixel_z = 16 - - // And animate the attack! - animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) - -/atom/movable/proc/receiving_damage(atom/A) - var/pixel_x_diff = rand(-3,3) - var/pixel_y_diff = rand(-3,3) - animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2) - animate(pixel_x = initial(pixel_x), pixel_y = initial(pixel_y), time = 2) - -/mob/living/receiving_damage(atom/A) +/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y) + end_pixel_y = get_standard_pixel_y_offset(lying) + if(!used_item) + used_item = get_active_hand() ..() floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 38065ac1f2c..aaeb26fe2c6 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -129,7 +129,7 @@ add_attack_logs(M.occupant, src, "Mecha-meleed with [M]") else step_away(src,M) - add_attack_logs(M.occupant, src, "Mecha-pushed with [M]", FALSE) + add_attack_logs(M.occupant, src, "Mecha-pushed with [M]", ATKLOG_ALL) M.occupant_message("You push [src] out of the way.") visible_message("[M] pushes [src] out of the way.") return @@ -240,11 +240,11 @@ to_chat(user, "You already grabbed [src].") return - add_attack_logs(user, src, "Grabbed passively", admin_notify = FALSE) + add_attack_logs(user, src, "Grabbed passively", ATKLOG_ALL) var/obj/item/grab/G = new /obj/item/grab(user, src) if(buckled) - to_chat(user, "You cannot grab [src], \he is buckled in!") + to_chat(user, "You cannot grab [src]; [p_they()] [p_are()] buckled in!") if(!G) //the grab will delete itself in New if src is anchored return 0 user.put_in_active_hand(G) @@ -333,6 +333,9 @@ if(INTENT_GRAB) grabbedby(M) return FALSE - else + if(INTENT_HARM) M.do_attack_animation(src) return TRUE + if(INTENT_DISARM) + M.do_attack_animation(src, ATTACK_EFFECT_DISARM) + return TRUE diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index b2755e2b7d8..55e8536cd10 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -164,10 +164,10 @@ proc/get_radio_key_from_channel(var/channel) if(is_muzzled()) var/obj/item/clothing/mask/muzzle/G = wear_mask - if(G.mute == MUTE_ALL) //if the mask is supposed to mute you completely or just muffle you + if(G.mute == MUZZLE_MUTE_ALL) //if the mask is supposed to mute you completely or just muffle you to_chat(src, "You're muzzled and cannot speak!") return - else if(G.mute == MUTE_MUFFLE) + else if(G.mute == MUZZLE_MUTE_MUFFLE) message = muffledspeech(message) verb = "mumbles" diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 09b62f1c89c..c0393d78f92 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -87,11 +87,12 @@ var/list/ai_verbs_default = list( var/mob/living/simple_animal/bot/Bot var/turf/waypoint //Holds the turf of the currently selected waypoint. var/waypoint_mode = 0 //Waypoint mode is for selecting a turf via clicking. + var/apc_override = FALSE //hack for letting the AI use its APC even when visionless var/nuking = 0 var/obj/machinery/doomsday_device/doomsday_device var/obj/machinery/hologram/holopad/holo = null - var/mob/camera/aiEye/eyeobj = new() + var/mob/camera/aiEye/eyeobj var/sprint = 10 var/cooldown = 0 var/acceleration = 1 @@ -191,9 +192,7 @@ var/list/ai_verbs_default = list( spawn(5) new /obj/machinery/ai_powersupply(src) - eyeobj.ai = src - eyeobj.name = "[src.name] (AI Eye)" // Give it a name - eyeobj.loc = src.loc + create_eye() builtInCamera = new /obj/machinery/camera/portable(src) builtInCamera.c_tag = name @@ -1163,6 +1162,17 @@ var/list/ai_verbs_default = list( client.eye = eyeobj return TRUE + +/mob/living/silicon/ai/proc/can_see(atom/A) + if(isturf(loc)) //AI in core, check if on cameras + //get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera + //apc_override is needed here because AIs use their own APC when depowered + return (cameranet && cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override + //AI is carded/shunted + //view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist + var/list/viewscale = getviewsize(client.view) + return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5) + /mob/living/silicon/ai/proc/relay_speech(mob/living/M, text, verb, datum/language/speaking) if(!say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad. if(speaking) @@ -1239,4 +1249,16 @@ var/list/ai_verbs_default = list( to_chat(src, "Unable to locate an airlock near [target].") else - to_chat(src, "Target is not on or near any active cameras on the station.") \ No newline at end of file + to_chat(src, "Target is not on or near any active cameras on the station.") + +/mob/living/silicon/ai/handle_fire() + return + +/mob/living/silicon/ai/update_fire() + return + +/mob/living/silicon/ai/IgniteMob() + return FALSE + +/mob/living/silicon/ai/ExtinguishMob() + return diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index eeeeed8e8bb..6737be463d6 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -28,7 +28,7 @@ eye.visibleCameraChunks += src visible++ seenby += eye - if(changed && !updating) + if(changed) update() // Remove an AI eye from the chunk, then update if changed. diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 71a2e6cba36..2728a1af55e 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -20,7 +20,6 @@ // It will also stream the chunk that the new loc is in. /mob/camera/aiEye/setLoc(T) - if(ai) if(!isturf(ai.loc)) return @@ -30,8 +29,9 @@ if(ai.client) ai.client.eye = src //Holopad - if(ai.holo) - ai.holo.move_hologram() + if(istype(ai.current, /obj/machinery/hologram/holopad)) + var/obj/machinery/hologram/holopad/H = ai.current + H.move_hologram(ai, T) /mob/camera/aiEye/Move() return 0 @@ -41,8 +41,22 @@ return ai.client return null + +/mob/camera/aiEye/proc/RemoveImages() + var/client/C = GetViewerClient() + if(C) + for(var/V in visibleCameraChunks) + var/datum/camerachunk/chunk = V + C.images -= chunk.obscured + + /mob/camera/aiEye/Destroy() - ai = null + if(ai) + //ai.all_eyes -= src + ai = null + for(var/V in visibleCameraChunks) + var/datum/camerachunk/chunk = V + chunk.remove(src) return ..() /atom/proc/move_camera_by_click() @@ -102,12 +116,18 @@ src.eyeobj.loc = src.loc else to_chat(src, "ERROR: Eyeobj not found. Creating new eye...") - src.eyeobj = new(src.loc) - src.eyeobj.ai = src - src.eyeobj.name = "[src.name] (AI Eye)" // Give it a name + create_eye() eyeobj.setLoc(loc) +/mob/living/silicon/ai/proc/create_eye() + if(eyeobj) + return + eyeobj = new /mob/camera/aiEye() + eyeobj.ai = src + eyeobj.setLoc(loc) + eyeobj.name = "[name] (AI Eye)" + /mob/living/silicon/ai/proc/toggle_acceleration() set category = "AI Commands" set name = "Toggle Camera Acceleration" diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 1755674b4f6..42f132e39d4 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -129,8 +129,10 @@ to_chat(src, "Receiving control information from APC.") sleep(2) //bring up APC dialog - aiRestorePowerRoutine = 3 + apc_override = 1 theAPC.attack_ai(src) + apc_override = 0 + aiRestorePowerRoutine = 3 to_chat(src, "Here are your current laws:") src.show_laws() //WHY THE FUCK IS THIS HERE sleep(50) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 54ebdaf4da2..d28ce620a0c 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -114,8 +114,6 @@ pda.name = pda.owner + " (" + pda.ownjob + ")" var/datum/data/pda/app/messenger/M = pda.find_program(/datum/data/pda/app/messenger) M.toff = 1 - var/datum/data/pda/app/chatroom/C = pda.find_program(/datum/data/pda/app/chatroom) - C.toff = 1 ..() /mob/living/silicon/pai/Destroy() @@ -599,7 +597,7 @@ var/mob/living/carbon/human/H = over_object //changed to human to avoid stupid issues like xenos holding pAIs. if(!istype(H) || !Adjacent(H)) return ..() if(usr == src) - switch(alert(H, "[src] wants you to pick them up. Do it?",,"Yes","No")) + switch(alert(H, "[src] wants you to pick [p_them()] up. Do it?",,"Yes","No")) if("Yes") if(Adjacent(H)) get_scooped(H) diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 32bef5d7494..48c1c1d7d10 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -71,7 +71,7 @@ if(answer == "Yes") var/turf/T = get_turf_or_move(P.loc) for(var/mob/v in viewers(T)) - v.show_message("[M] presses \his thumb against [P].", 3, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2) + v.show_message("[M] presses [M.p_their()] thumb against [P].", 3, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2) var/datum/dna/dna = M.dna to_chat(P, "

    [M]'s UE string : [dna.unique_enzymes]

    ") if(dna.unique_enzymes == P.master_dna) @@ -79,7 +79,7 @@ else to_chat(P, "DNA does not match stored Master DNA.") else - to_chat(P, "[M] does not seem like \he is going to provide a DNA sample willingly.") + to_chat(P, "[M] does not seem like [M.p_they()] [M.p_are()] going to provide a DNA sample willingly.") return 1 /datum/pai_software/radio_config @@ -226,123 +226,6 @@ M.create_message(P, target, 1) return 1 -/datum/pai_software/chatroom - name = "Digital Chatroom" - ram_cost = 5 - id = "chatroom" - toggle = 0 - - autoupdate = 1 - template_file = "pai_chatroom.tmpl" - ui_title = "Digital Chatroom" - -/datum/pai_software/chatroom/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) - var/data[0] - - if(!user.pda) - log_runtime(EXCEPTION("pAI found without PDA."), user) - return data - var/datum/data/pda/app/chatroom/M = user.pda.find_program(/datum/data/pda/app/chatroom) - if(!M) - log_runtime(EXCEPTION("pAI PDA lacks a chatroom program"), user) - return data - - data["receiver_off"] = M.toff - data["ringer_off"] = M.notify_silent - - var/list/rooms[0] - for(var/datum/chatroom/c in chatrooms) - if((M in c.users) || (M in c.invites) || c.is_public) - rooms += list(list(name = "[c]", ref = "\ref[c]")) - data["rooms"] = rooms - - if(M.disconnected || !M.messaging_available(1)) - data["disconnected"] = 1 - else if(M.current_room) - data["current_room"] = "\ref[M.current_room]" - data["current_room_name"] = M.current_room.name - data["current_room_topic"] = M.current_room.topic - data["messages"] = M.current_room.logs - var/list/users[0] - for(var/U in M.current_room.users) - var/datum/data/pda/app/chatroom/ch = U - users += "[ch.pda.owner]" - for(var/U in (M.current_room.invites - M.current_room.users)) - var/datum/data/pda/app/chatroom/ch = U - users += "[ch.pda.owner]" - data["users"] = users - - return data - -/datum/pai_software/chatroom/Topic(href, href_list) - var/mob/living/silicon/pai/P = usr - if(!istype(P)) - return - - if(!isnull(P.pda) && P.pda.can_use()) - var/datum/data/pda/app/chatroom/M = P.pda.find_program(/datum/data/pda/app/chatroom) - if(!M) - return - - if(href_list["toggler"]) - M.toff = href_list["toggler"] != "1" - return 1 - else if(href_list["ringer"]) - M.notify_silent = href_list["ringer"] != "1" - return 1 - else if(href_list["topic"]) - if(!M.current_room) - return 1 - - var/t = input("Enter new topic:", M.current_room, M.current_room.topic) as text|null - spawn() - if(!t || !M.check_messaging_available() || !P.pda.can_use()) - return - t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) - t = readd_quotes(t) - if(!t) - return - - M.current_room.topic = t - M.current_room.announce(M, "Topic has been changed to '[t]' by [P.pda.owner].") - return 1 - else if(href_list["select"]) - var/s = href_list["select"] - if(s == "*NONE*") - M.current_room = null - else - var/datum/chatroom/CR = locate(s) - if(istype(CR)) - if(!(M in CR.users)) - if(!CR.login(M)) - return - M.current_room = CR - return 1 - else if(href_list["target"]) - if(P.silence_time) - return alert("Communications circuits remain uninitialized.") - - var/datum/chatroom/target = locate(href_list["target"]) - if(istype(target)) - if(!(M in target.users)) - if(!target.login(M)) - return - var/t = input("Please enter message", target) as text|null - spawn() - if(!t || !M.check_messaging_available()) - return - t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) - t = readd_quotes(t) - if(!t || !P.pda.can_use()) - return - - target.post(M, t) - return 1 - else if(href_list["reconnect"]) - spawn() - M.messaging_available() - return 1 - /datum/pai_software/med_records name = "Medical Records" ram_cost = 15 diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index e3407c06f3d..cc5108d89f8 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -234,10 +234,10 @@ var/organ_found if(H.internal_organs.len) for(var/obj/item/organ/external/E in H.bodyparts) - if(!(E.status & ORGAN_ROBOT)) + if(!E.is_robotic()) continue organ_found = 1 - to_chat(user, "[E.name]: [round(E.brute_dam)] [round(E.burn_dam)]") + to_chat(user, "[E.name]: [E.brute_dam] [E.burn_dam]") if(!organ_found) to_chat(user, "No prosthetics located.") to_chat(user, "
    ") @@ -245,7 +245,7 @@ organ_found = null if(H.internal_organs.len) for(var/obj/item/organ/internal/O in H.internal_organs) - if(!(O.status & ORGAN_ROBOT)) + if(!O.is_robotic()) continue organ_found = 1 to_chat(user, "[capitalize(O.name)]: [O.damage]") diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index bd06f7045ae..aaaeb15b283 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -142,7 +142,7 @@ to_chat(usr, "The reboot system is currently offline. Please wait another [cooldown_time] seconds.") return - user.visible_message("\the [user] swipes \his ID card through \the [src], attempting to reboot it.", "You swipe your ID card through \the [src], attempting to reboot it.") + user.visible_message("\the [user] swipes [user.p_their()] ID card through [src], attempting to reboot it.", "You swipe your ID card through [src], attempting to reboot it.") last_reboot = world.time / 10 var/drones = 0 for(var/mob/living/silicon/robot/drone/D in world) @@ -153,7 +153,7 @@ return else - user.visible_message("\the [user] swipes \his ID card through \the [src], attempting to shut it down.", "You swipe your ID card through \the [src], attempting to shut it down.") + user.visible_message("\the [user] swipes [user.p_their()] ID card through [src], attempting to shut it down.", "You swipe your ID card through \the [src], attempting to shut it down.") if(emagged) return diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index d0733547cc8..adf6e2f7682 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -146,7 +146,7 @@ wrapped = A.cell A.cell.add_fingerprint(user) - A.cell.updateicon() + A.cell.update_icon() A.cell.forceMove(src) A.cell = null diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 9be14600a3a..755b874667a 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -131,8 +131,8 @@ var/list/robot_verbs_default = list( camera.status = 0 if(mmi == null) - mmi = new /obj/item/mmi/posibrain(src) //Give the borg an MMI if he spawns without for some reason. (probably not the correct way to spawn a posibrain, but it works) - mmi.icon_state="posibrain-occupied" + mmi = new /obj/item/mmi/robotic_brain(src) //Give the borg an MMI if he spawns without for some reason. (probably not the correct way to spawn a robotic brain, but it works) + mmi.icon_state = "boris" initialize_components() //if(!unfinished) @@ -210,7 +210,7 @@ var/list/robot_verbs_default = list( if(prefix) modtype = prefix if(mmi) - if(istype(mmi, /obj/item/mmi/posibrain)) + if(istype(mmi, /obj/item/mmi/robotic_brain)) braintype = "Android" else braintype = "Cyborg" @@ -738,7 +738,7 @@ var/list/robot_verbs_default = list( else if(istype(W, /obj/item/borg/upgrade/)) var/obj/item/borg/upgrade/U = W if(!opened) - to_chat(user, "You must access the borgs internals!") + to_chat(user, "You must access the borg's internals!") else if(!src.module && U.require_module) to_chat(user, "The borg must choose a module before it can be upgraded!") else if(U.locked) @@ -752,6 +752,21 @@ var/list/robot_verbs_default = list( else to_chat(user, "Upgrade error.") + else if(istype(W, /obj/item/mmi_radio_upgrade)) + if(!opened) + to_chat(user, "You must access the borg's internals!") + return + else if(!mmi) + to_chat(user, "This cyborg does not have an MMI to augment!") + return + else if(mmi.radio) + to_chat(user, "A radio upgrade is already installed in the MMI!") + return + else if(user.drop_item()) + to_chat(user, "You apply the upgrade to [src].") + to_chat(src, "MMI radio capability installed.") + mmi.install_radio() + qdel(W) else return ..() @@ -794,7 +809,7 @@ var/list/robot_verbs_default = list( laws = new /datum/ai_laws/syndicate_override var/time = time2text(world.realtime,"hh:mm:ss") lawchanges.Add("[time] : [M.name]([M.key]) emagged [name]([key])") - set_zeroth_law("Only [M.real_name] and people he designates as being such are Syndicate Agents.") + set_zeroth_law("Only [M.real_name] and people [M.p_they()] designate[M.p_s()] as being such are Syndicate Agents.") to_chat(src, "ALERT: Foreign software detected.") sleep(5) to_chat(src, "Initiating diagnostics...") @@ -810,7 +825,7 @@ var/list/robot_verbs_default = list( to_chat(src, "ERRORERRORERROR") to_chat(src, "Obey these laws:") laws.show_laws(src) - to_chat(src, "ALERT: [M.real_name] is your new master. Obey your new laws and his commands.") + to_chat(src, "ALERT: [M.real_name] is your new master. Obey your new laws and [M.p_their()] commands.") SetLockdown(0) if(src.module && istype(src.module, /obj/item/robot_module/miner)) for(var/obj/item/pickaxe/drill/cyborg/D in src.module.modules) @@ -883,9 +898,10 @@ var/list/robot_verbs_default = list( icon_state = "[base_icon]-roll" else icon_state = base_icon - for(var/obj/item/borg/combat/shield/S in module.modules) - if(activated(S)) - overlays += "[base_icon]-shield" + if(module) + for(var/obj/item/borg/combat/shield/S in module.modules) + if(activated(S)) + overlays += "[base_icon]-shield" update_fire() /mob/living/silicon/robot/proc/installed_modules() @@ -1381,7 +1397,7 @@ var/list/robot_verbs_default = list( mind = new mind.current = src mind.original = src - mind.assigned_role = "MODE" + mind.assigned_role = SPECIAL_ROLE_ERT mind.special_role = SPECIAL_ROLE_ERT if(cyborg_unlock) crisis = 1 @@ -1441,4 +1457,4 @@ var/list/robot_verbs_default = list( return eye_protection /mob/living/silicon/robot/check_ear_prot() - return ear_protection \ No newline at end of file + return ear_protection diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 033b244cf8c..e18ca8d6a17 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -1,7 +1,7 @@ /mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) if(M.a_intent == INTENT_DISARM) if(!lying) - M.do_attack_animation(src) + M.do_attack_animation(src, ATTACK_EFFECT_DISARM) if(prob(85)) Stun(7) step(src, get_dir(M,src)) @@ -42,7 +42,7 @@ if(opened && !wiresexposed && !issilicon(user)) if(cell) - cell.updateicon() + cell.update_icon() cell.add_fingerprint(user) user.put_in_active_hand(cell) to_chat(user, "You remove \the [cell].") diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index f549c07b66a..e9aadf5086a 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -198,7 +198,7 @@ modules += new /obj/item/multitool/cyborg(src) modules += new /obj/item/t_scanner(src) modules += new /obj/item/analyzer(src) - modules += new /obj/item/taperoll/engineering(src) + modules += new /obj/item/holosign_creator/engineering(src) modules += new /obj/item/gripper(src) modules += new /obj/item/matter_decompiler(src) modules += new /obj/item/floor_painter(src) @@ -222,7 +222,7 @@ modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src) modules += new /obj/item/melee/baton/loaded(src) modules += new /obj/item/gun/energy/disabler/cyborg(src) - modules += new /obj/item/taperoll/police(src) + modules += new /obj/item/holosign_creator/security(src) modules += new /obj/item/clothing/mask/gas/sechailer/cyborg(src) emag = new /obj/item/gun/energy/laser/cyborg(src) diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 0de811224dc..0a3ed47b933 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -74,8 +74,8 @@ if(!message) return - var/obj/machinery/hologram/holopad/T = src.holo - if(T && T.hologram && T.master == src)//If there is a hologram and its master is the user. + var/obj/machinery/hologram/holopad/T = current + if(istype(T) && T.masters[src]) //Human-like, sorta, heard by those who understand humans. var/rendered_a @@ -112,8 +112,8 @@ if(!message) return - var/obj/machinery/hologram/holopad/T = src.holo - if(T && T.hologram && T.master == src) + var/obj/machinery/hologram/holopad/T = current + if(istype(T) && T.masters[src]) var/rendered = "[name] [message]" to_chat(src, "Holopad action relayed, [real_name] [message]") @@ -127,8 +127,8 @@ return 1 /mob/living/silicon/ai/emote(var/act, var/type, var/message) - var/obj/machinery/hologram/holopad/T = src.holo - if(T && T.hologram && T.master == src) //Is the AI using a holopad? + var/obj/machinery/hologram/holopad/T = current + if(istype(T) && T.masters[src])//Is the AI using a holopad? src.holopad_emote(message) else //Emote normally, then. ..() diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 480c9442bd7..a903b6999dc 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -41,6 +41,15 @@ if(L.a_intent == INTENT_HELP) visible_message("[L.name] rubs its head against [src].") +/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + ..(user, TRUE) + adjustBruteLoss(rand(10, 15)) + playsound(loc, "punch", 25, 1, -1) + visible_message("[user] has punched [src]!", "[user] has punched [src]!") + return TRUE + return FALSE + /mob/living/silicon/attack_hand(mob/living/carbon/human/M) switch(M.a_intent) if(INTENT_HELP) @@ -49,17 +58,8 @@ if("grab") grabbedby(M) else - M.do_attack_animation(src) + M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) playsound(loc, 'sound/effects/bang.ogg', 10, 1) - if(HULK in M.mutations) - var/damage = rand(10,15) - adjustBruteLoss(damage) - add_attack_logs(M, src, "Melee attacked with fists") - playsound(loc, "punch", 25, 1, -1) - visible_message("[M] has punched [src]!", \ - "[M] has punched [src]!") - return 1 - else - visible_message("[M] punches [src], but doesn't leave a dent.", \ + visible_message("[M] punches [src], but doesn't leave a dent.", \ "[M] punches [src], but doesn't leave a dent.!") - return 0 + return FALSE diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index b122decd322..309a13468a3 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -11,7 +11,7 @@ grabbedby(M) if(INTENT_HARM, INTENT_DISARM) - M.do_attack_animation(src) + M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) visible_message("[M] [response_harm] [src]!") playsound(loc, "punch", 25, 1, -1) attack_threshold_check(harm_intent_damage) @@ -19,6 +19,14 @@ updatehealth() return 1 +/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + if(user.a_intent == INTENT_HARM) + ..(user, TRUE) + playsound(loc, "punch", 25, 1, -1) + visible_message("[user] has punched [src]!", "[user] has punched [src]!") + adjustBruteLoss(15) + return TRUE + /mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) if(..()) //if harm or disarm intent. var/damage = rand(15, 30) @@ -58,3 +66,11 @@ visible_message("[src] looks unharmed.") else apply_damage(damage, damagetype) + +/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) + if(!no_effect && !visual_effect_icon && melee_damage_upper) + if(melee_damage_upper < 10) + visual_effect_icon = ATTACK_EFFECT_PUNCH + else + visual_effect_icon = ATTACK_EFFECT_SMASH + ..() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 986795ccd1e..5e79c315f42 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -276,7 +276,7 @@ return apply_damage(M.melee_damage_upper, BRUTE) visible_message("[M] has [M.attacktext] [src]!") - add_attack_logs(M, src, "Animal attacked", FALSE) + add_attack_logs(M, src, "Animal attacked", ATKLOG_ALL) if(prob(10)) new /obj/effect/decal/cleanable/blood/oil(loc) diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 1ced2db841c..90c44f19286 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -30,9 +30,10 @@ var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return created_name = t + log_game("[key_name(user)] has renamed a robot to [t]") //Edbot Assembly @@ -53,9 +54,10 @@ var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return created_name = t + log_game("[key_name(user)] has renamed a robot to [t]") return switch(build_step) @@ -253,10 +255,11 @@ var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return created_name = t + log_game("[key_name(user)] has renamed a robot to [t]") /obj/item/toolbox_tiles_sensor/attackby(obj/item/W, mob/user, params) ..() @@ -272,113 +275,110 @@ var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return created_name = t + log_game("[key_name(user)] has renamed a robot to [t]") //Medbot Assembly -/obj/item/firstaid_arm_assembly - name = "incomplete medibot assembly." - desc = "A first aid kit with a robot arm permanently grafted to it." - icon = 'icons/obj/aibots.dmi' - icon_state = "firstaid_arm" - var/build_step = 0 - var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess - var/skin = null //Same as medbot, set to tox or ointment for the respective kits. - w_class = WEIGHT_CLASS_NORMAL - var/treatment_brute = "salglu_solution" - var/treatment_oxy = "salbutamol" - var/treatment_fire = "salglu_solution" - var/treatment_tox = "charcoal" - var/treatment_virus = "spaceacillin" - req_one_access = list(access_medical, access_robotics) - - /obj/item/firstaid_arm_assembly/New() - ..() - spawn(5) - if(skin) - overlays += image('icons/obj/aibots.dmi', "kit_skin_[skin]") - -/obj/item/storage/firstaid/attackby(obj/item/robot_parts/S, mob/user, params) - - if((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm))) - ..() - return +/obj/item/storage/firstaid/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/robot_parts/l_arm) && !istype(I, /obj/item/robot_parts/r_arm)) + return ..() //Making a medibot! - if(contents.len >= 1) + if(contents.len) to_chat(user, "You need to empty [src] out first!") return - var/obj/item/firstaid_arm_assembly/A = new /obj/item/firstaid_arm_assembly - if(istype(src,/obj/item/storage/firstaid/fire)) - A.skin = "ointment" - else if(istype(src,/obj/item/storage/firstaid/toxin)) - A.skin = "tox" - else if(istype(src,/obj/item/storage/firstaid/o2)) - A.skin = "o2" - else if(istype(src,/obj/item/storage/firstaid/brute)) - A.skin = "brute" - else if(istype(src,/obj/item/storage/firstaid/adv)) - A.skin = "adv" - else if(istype(src,/obj/item/storage/firstaid/tactical)) - A.skin = "bezerk" - else if(istype(src,/obj/item/storage/firstaid/aquatic_kit)) - A.skin = "fish" + var/obj/item/firstaid_arm_assembly/A = new /obj/item/firstaid_arm_assembly(loc, med_bot_skin) A.req_one_access = req_one_access + A.syndicate_aligned = syndicate_aligned A.treatment_oxy = treatment_oxy A.treatment_brute = treatment_brute A.treatment_fire = treatment_fire A.treatment_tox = treatment_tox A.treatment_virus = treatment_virus - qdel(S) + qdel(I) user.put_in_hands(A) to_chat(user, "You add the robot arm to the first aid kit.") user.unEquip(src, 1) qdel(src) +/obj/item/firstaid_arm_assembly + name = "incomplete medibot assembly." + desc = "A first aid kit with a robot arm permanently grafted to it." + icon = 'icons/obj/aibots.dmi' + icon_state = "firstaid_arm" + w_class = WEIGHT_CLASS_NORMAL + req_one_access = list(access_medical, access_robotics) + var/build_step = 0 + var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess + var/skin = null //Same as medbot, set to tox or ointment for the respective kits. + var/syndicate_aligned = FALSE + var/treatment_brute = "salglu_solution" + var/treatment_oxy = "salbutamol" + var/treatment_fire = "salglu_solution" + var/treatment_tox = "charcoal" + var/treatment_virus = "spaceacillin" -/obj/item/firstaid_arm_assembly/attackby(obj/item/W, mob/user, params) +/obj/item/firstaid_arm_assembly/New(loc, new_skin) ..() - if(istype(W, /obj/item/pen)) - var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) + if(new_skin) + skin = new_skin + update_icon() + +/obj/item/firstaid_arm_assembly/update_icon() + overlays.Cut() + if(skin) + overlays += image('icons/obj/aibots.dmi', "kit_skin_[skin]") + if(build_step > 0) + overlays += image('icons/obj/aibots.dmi', "na_scanner") + + +/obj/item/firstaid_arm_assembly/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/pen)) + var/t = stripped_input(user, "Enter new robot name", name, created_name, MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return created_name = t + log_game("[key_name(user)] has renamed a robot to [t]") else switch(build_step) if(0) - if(istype(W, /obj/item/healthanalyzer)) - if(!user.unEquip(W)) + if(istype(I, /obj/item/healthanalyzer)) + if(!user.drop_item()) return - qdel(W) + qdel(I) build_step++ to_chat(user, "You add the health sensor to [src].") name = "First aid/robot arm/health analyzer assembly" - overlays += image('icons/obj/aibots.dmi', "na_scanner") + update_icon() if(1) - if(isprox(W)) - if(!user.unEquip(W)) + if(isprox(I)) + if(!user.drop_item()) return - qdel(W) + qdel(I) build_step++ to_chat(user, "You complete the Medibot. Beep boop!") var/turf/T = get_turf(src) - var/mob/living/simple_animal/bot/medbot/S = new /mob/living/simple_animal/bot/medbot(T) - S.skin = skin - S.name = created_name - S.bot_core.req_one_access = req_one_access - S.treatment_oxy = treatment_oxy - S.treatment_brute = treatment_brute - S.treatment_fire = treatment_fire - S.treatment_tox = treatment_tox - S.treatment_virus = treatment_virus + if(!syndicate_aligned) + var/mob/living/simple_animal/bot/medbot/S = new /mob/living/simple_animal/bot/medbot(T, skin) + S.name = created_name + S.bot_core.req_one_access = req_one_access + S.treatment_oxy = treatment_oxy + S.treatment_brute = treatment_brute + S.treatment_fire = treatment_fire + S.treatment_tox = treatment_tox + S.treatment_virus = treatment_virus + else + new /mob/living/simple_animal/bot/medbot/syndicate(T) //Syndicate medibots are a special case that have so many unique vars on them, it's not worth passing them through construction phases user.unEquip(src, 1) qdel(src) @@ -457,9 +457,10 @@ var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return created_name = t + log_game("[key_name(user)] has renamed a robot to [t]") else if(istype(I, /obj/item/screwdriver)) if(!build_step) diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 576ad200d5c..9d7fa39ed87 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -17,7 +17,7 @@ bot_filter = RADIO_SECBOT model = "ED-209" bot_purpose = "seek out criminals, handcuff them, and report their location to security" - bot_core = /obj/machinery/bot_core/secbot + bot_core_type = /obj/machinery/bot_core/secbot window_id = "autoed209" window_name = "Automatic Security Unit v2.6" path_image_color = "#FF0000" @@ -61,12 +61,14 @@ shot_delay = 6//Longer shot delay because JESUS CHRIST check_records = 0//Don't actively target people set to arrest arrest_type = 1//Don't even try to cuff - bot_core.req_access = list(access_maint_tunnels, access_theatre) - arrest_type = 1 - if((lasercolor == "b") && (name == "\improper ED-209 Security Robot"))//Picks a name if there isn't already a custome one - name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") - if((lasercolor == "r") && (name == "\improper ED-209 Security Robot")) - name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") + declare_arrests = 0 // Don't spam sec + bot_core.req_access = list(access_maint_tunnels, access_theatre, access_robotics) + + if(created_name == initial(name) || !created_name) + if(lasercolor == "b") + name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") + else if (lasercolor == "r") + name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") //SECHUD var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED] @@ -94,37 +96,37 @@ /mob/living/simple_animal/bot/ed209/set_custom_texts() text_hack = "You disable [name]'s combat inhibitor." text_dehack = "You restore [name]'s combat inhibitor." - text_dehack_fail = "[name] ignores your attempts to restrict him!" + text_dehack_fail = "[name] ignores your attempts to restrict [p_them()]!" /mob/living/simple_animal/bot/ed209/get_controls(mob/user) var/dat dat += hack(user) dat += showpai(user) dat += text({" -Security Unit v2.6 controls

    -Status: []
    -Behaviour controls are [locked ? "locked" : "unlocked"]
    -Maintenance panel panel is [open ? "opened" : "closed"]
    "}, + Security Unit v2.6 controls

    + Status: []
    + Behaviour controls are [locked ? "locked" : "unlocked"]
    + Maintenance panel panel is [open ? "opened" : "closed"]
    "}, -"[on ? "On" : "Off"]" ) + "[on ? "On" : "Off"]" ) if(!locked || issilicon(user) || user.can_admin_interact()) + dat += "Auto Patrol [auto_patrol ? "On" : "Off"]
    " + if(!lasercolor) dat += text({"
    -Arrest Unidentifiable Persons: []
    -Arrest for Unauthorized Weapons: []
    -Arrest for Warrant: []
    -
    -Operating Mode: []
    -Report Arrests[]
    -Auto Patrol[]"}, + Arrest Unidentifiable Persons: []
    + Arrest for Unauthorized Weapons: []
    + Arrest for Warrant: []
    +
    + Operating Mode: []
    + Report Arrests[]
    "}, -"[idcheck ? "Yes" : "No"]", -"[weaponscheck ? "Yes" : "No"]", -"[check_records ? "Yes" : "No"]", -"[arrest_type ? "Detain" : "Arrest"]", -"[declare_arrests ? "Yes" : "No"]", -"[auto_patrol ? "On" : "Off"]" ) + "[idcheck ? "Yes" : "No"]", + "[weaponscheck ? "Yes" : "No"]", + "[check_records ? "Yes" : "No"]", + "[arrest_type ? "Detain" : "Arrest"]", + "[declare_arrests ? "Yes" : "No"]") return dat @@ -239,13 +241,18 @@ Auto Patrol[]"}, if(target) // make sure target exists if(Adjacent(target) && isturf(target.loc)) // if right next to perp stun_attack(target) + if(!lasercolor) + mode = BOT_PREP_ARREST + anchored = 1 + target_lastloc = target.loc + return + else + mode = BOT_HUNT + target = null + target_lastloc = null + return - mode = BOT_PREP_ARREST - anchored = 1 - target_lastloc = target.loc - return - - else // not next to perp + else if(!disabled) // not next to perp var/turf/olddist = get_dist(src, target) walk_to(src, target,1,4) if((get_dist(src, target)) >= (olddist)) @@ -406,7 +413,7 @@ Auto Patrol[]"}, shoot_sound = 'sound/weapons/laser.ogg' if(emagged == 2) if(lasercolor) - projectile = /obj/item/projectile/beam/lasertag + projectile = /obj/item/projectile/beam/disabler else projectile = /obj/item/projectile/beam else @@ -501,6 +508,7 @@ Auto Patrol[]"}, if(lasertag_check) icon_state = "[lasercolor]ed2090" disabled = 1 + walk_to(src, 0) target = null spawn(100) disabled = 0 @@ -569,4 +577,4 @@ Auto Patrol[]"}, if(!C.handcuffed) C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C) C.update_handcuffed() - back_to_idle() + back_to_idle() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index c531a6ed067..b1133cb0e08 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -14,7 +14,7 @@ bot_filter = RADIO_FLOORBOT model = "Floorbot" bot_purpose = "seek out damaged or missing floor tiles, and repair or replace them as necessary" - bot_core = /obj/machinery/bot_core/floorbot + bot_core_type = /obj/machinery/bot_core/floorbot window_id = "autofloor" window_name = "Automatic Station Floor Repairer v1.1" path_image_color = "#FFA500" @@ -58,7 +58,7 @@ /mob/living/simple_animal/bot/floorbot/set_custom_texts() text_hack = "You corrupt [name]'s construction protocols." - text_dehack = "You detect errors in [name] and reset his programming." + text_dehack = "You detect errors in [name] and reset [p_their()] programming." text_dehack_fail = "[name] is not responding to reset commands!" /mob/living/simple_animal/bot/floorbot/get_controls(mob/user) @@ -98,7 +98,7 @@ T.use(loaded) amount += loaded if(loaded > 0) - to_chat(user, "You load [loaded] tiles into the floorbot. He now contains [amount] tiles.") + to_chat(user, "You load [loaded] tiles into the floorbot. [p_they(TRUE)] now contains [amount] tiles.") nagged = 0 update_icon() else diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index 7c737690ec0..a60dfc344ca 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -44,6 +44,7 @@ var/treatment_virus = "spaceacillin" var/treat_virus = 1 //If on, the bot will attempt to treat viral infections, curing them if possible. var/shut_up = 0 //self explanatory :) + var/syndicate_aligned = FALSE // Will it only treat operatives? /mob/living/simple_animal/bot/medbot/tox skin = "tox" @@ -68,8 +69,8 @@ desc = "International Medibot of mystery." skin = "bezerk" treatment_oxy = "perfluorodecalin" - treatment_brute = "styptic_powder" - treatment_fire = "silver_sulfadiazine" + treatment_brute = "bicaridine" + treatment_fire = "kelotane" treatment_tox = "charcoal" /mob/living/simple_animal/bot/medbot/syndicate @@ -77,9 +78,10 @@ desc = "You'd better have insurance!" skin = "bezerk" treatment_oxy = "perfluorodecalin" - treatment_brute = "styptic_powder" - treatment_fire = "silver_sulfadiazine" + treatment_brute = "bicaridine" + treatment_fire = "kelotane" treatment_tox = "charcoal" + syndicate_aligned = TRUE bot_core_type = /obj/machinery/bot_core/medbot/syndicate control_freq = BOT_FREQ + 1000 // make it not show up on lists radio_channel = "Syndicate" @@ -90,6 +92,9 @@ Radio.syndie = 1 /mob/living/simple_animal/bot/medbot/update_icon() + overlays.Cut() + if(skin) + overlays += "medskin_[skin]" if(!on) icon_state = "medibot0" return @@ -101,22 +106,21 @@ else icon_state = "medibot1" -/mob/living/simple_animal/bot/medbot/New() +/mob/living/simple_animal/bot/medbot/New(loc, new_skin) ..() - update_icon() - - spawn(4) - if(skin) - overlays += image('icons/obj/aibots.dmi', "medskin_[skin]") - - var/datum/job/doctor/J = new/datum/job/doctor - access_card.access += J.get_access() - prev_access = access_card.access + var/datum/job/doctor/J = new /datum/job/doctor + access_card.access += J.get_access() + prev_access = access_card.access + qdel(J) var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED] medsensor.add_hud_to(src) permanent_huds |= medsensor + if(new_skin) + skin = new_skin + update_icon() + /mob/living/simple_animal/bot/medbot/bot_reset() ..() patient = null @@ -271,8 +275,10 @@ if(assess_patient(H)) last_found = world.time if((last_newpatient_speak + 300) < world.time) //Don't spam these messages! - var/message = pick("Hey, [H.name]! Hold on, I'm coming.","Wait [H.name]! I want to help!","[H.name], you appear to be injured!") + var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/mcoming.ogg', "Wait [H.name]! I want to help!" = 'sound/voice/mhelp.ogg', "[H.name], you appear to be injured!" = 'sound/voice/minjured.ogg') + var/message = pick(messagevoice) speak(message) + playsound(loc, messagevoice[message], 50, 0) last_newpatient_speak = world.time return H else @@ -304,8 +310,10 @@ if(!patient) if(!shut_up && prob(1)) - var/message = pick("Radar, put a mask on!","There's always a catch, and it's the best there is.","I knew it, I should've been a plastic surgeon.","What kind of medbay is this? Everyone's dropping like dead flies.","Delicious!") + var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/mradar.ogg', "There's always a catch, and I'm the best there is." = 'sound/voice/mcatch.ogg', "I knew it, I should've been a plastic surgeon." = 'sound/voice/msurgeon.ogg', "What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/mflies.ogg', "Delicious!" = 'sound/voice/mdelicious.ogg') + var/message = pick(messagevoice) speak(message) + playsound(loc, messagevoice[message], 50, 0) var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients. patient = scan(/mob/living/carbon/human, oldpatient, scan_range) oldpatient = patient @@ -365,13 +373,13 @@ // is secretly a silicon if(ishuman(C)) var/mob/living/carbon/human/H = C - if(H.species && H.species.reagent_tag == PROCESS_SYN) + if(H.dna.species && H.dna.species.reagent_tag == PROCESS_SYN) return 0 if(emagged == 2) //Everyone needs our medicine. (Our medicine is toxins) return 1 - if((skin == "bezerk") && (!("syndicate" in C.faction))) + if(syndicate_aligned && (!("syndicate" in C.faction))) return 0 if(declare_crit && C.health <= 0) //Critical condition! Call for help! @@ -440,9 +448,11 @@ soft_reset() return - if(C.stat == 2) - var/death_message = pick("No! NO!","Live, damnit! LIVE!","I...I've never lost a patient before. Not today, I mean.") - speak(death_message) + if(C.stat == DEAD || (C.status_flags & FAKEDEATH)) + var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/mno.ogg', "Live, damnit! LIVE!" = 'sound/voice/mlive.ogg', "I...I've never lost a patient before. Not today, I mean." = 'sound/voice/mlost.ogg') + var/message = pick(messagevoice) + speak(message) + playsound(loc, messagevoice[message], 50, 0) oldpatient = patient soft_reset() return @@ -492,8 +502,10 @@ break if(!reagent_id) //If they don't need any of that they're probably cured! - var/message = pick("All patched up!","An apple a day keeps me away.","Feel better soon!") + var/list/messagevoice = list("All patched up!" = 'sound/voice/mpatchedup.ogg', "An apple a day keeps me away." = 'sound/voice/mapple.ogg', "Feel better soon!" = 'sound/voice/mfeelbetter.ogg') + var/message = pick(messagevoice) speak(message) + playsound(loc, messagevoice[message], 50, 0) bot_reset() return else @@ -554,7 +566,8 @@ if("adv") new /obj/item/storage/firstaid/adv/empty(Tsec) if("bezerk") - new /obj/item/storage/firstaid/tactical/empty(Tsec) + var/obj/item/storage/firstaid/tactical/empty/T = new(Tsec) + T.syndicate_aligned = syndicate_aligned //This is a special case since Syndicate medibots and the mysterious medibot look the same; we also dont' want crew building Syndicate medibots if the mysterious medibot blows up. if("fish") new /obj/item/storage/firstaid/aquatic_kit(Tsec) else @@ -571,6 +584,9 @@ if(prob(50)) new /obj/item/robot_parts/l_arm(Tsec) + if(emagged && prob(25)) + playsound(loc, 'sound/voice/minsult.ogg', 50, 0) + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(3, 1, src) s.start() @@ -579,7 +595,7 @@ /mob/living/simple_animal/bot/medbot/proc/declare(crit_patient) if(declare_cooldown) return - if((skin == "bezerk")) + if(syndicate_aligned) return var/area/location = get_area(src) speak("Medical emergency! [crit_patient ? "[crit_patient]" : "A patient"] is in critical condition at [location]!", radio_channel) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 1f38c83b502..0efaefcce07 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -188,7 +188,7 @@ visible_message("[usr] switches [on ? "on" : "off"] [src].") if("cellremove") if(open && cell && !usr.get_active_hand()) - cell.updateicon() + cell.update_icon() usr.put_in_active_hand(cell) cell.add_fingerprint(usr) cell = null @@ -715,7 +715,7 @@ var/list/blood_dna = H.get_blood_dna_list() if(blood_dna) transfer_blood_dna(blood_dna) - currentBloodColor = H.species.blood_color + currentBloodColor = H.dna.species.blood_color return /mob/living/simple_animal/bot/mulebot/bot_control_message(command, mob/user, user_turf) diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 613f91e024c..2514af0eebd 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -75,10 +75,10 @@ //helmet and armor = 100% protection if( istype(inventory_head,/obj/item/clothing/head/helmet) && istype(inventory_back,/obj/item/clothing/suit/armor) ) if( O.force ) - to_chat(user, "[src] is wearing too much armor! You can't cause \him any damage.") + to_chat(user, "[src] is wearing too much armor! You can't cause [p_them()] any damage.") visible_message(" [user] hits [src] with [O], however [src] is too armored.") else - to_chat(user, "[src] is wearing too much armor! You can't reach \his skin.") + to_chat(user, "[src] is wearing too much armor! You can't reach [p_their()] skin.") visible_message("[user] gently taps [src] with [O].") if(health>0 && prob(15)) custom_emote(1, "looks at [user] with [pick("an amused","an annoyed","a confused","a resentful", "a happy", "an excited")] expression.") @@ -180,7 +180,7 @@ ) if( ! ( item_to_add.type in allowed_types ) ) - to_chat(usr, "You set [item_to_add] on [src]'s back, but \he shakes it off!") + to_chat(usr, "You set [item_to_add] on [src]'s back, but [p_they()] shake[p_s()] it off!") if(!usr.drop_item()) to_chat(usr, "\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s back!") return @@ -379,10 +379,10 @@ to_chat(user, "\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s head!") return 0 if(health <= 0) - to_chat(user, "There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on \him.") + to_chat(user, "There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on [p_them()].") else if(user) user.visible_message("[user] puts [item_to_add] on [real_name]'s head. [src] looks at [user] and barks once.", - "You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags \his tail once and barks.", + "You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags [p_their()] tail once and barks.", "You hear a friendly-sounding bark.") item_to_add.loc = src src.inventory_head = item_to_add @@ -392,7 +392,7 @@ if(user && !user.drop_item()) to_chat(user, "\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s head!") return 0 - to_chat(user, "You set [item_to_add] on [src]'s head, but \he shakes it off!") + to_chat(user, "You set [item_to_add] on [src]'s head, but [p_they()] shake[p_s()] it off!") item_to_add.loc = loc if(prob(25)) step_rand(item_to_add) diff --git a/code/modules/mob/living/simple_animal/friendly/diona.dm b/code/modules/mob/living/simple_animal/friendly/diona.dm index 64fe7d05b9b..669271f3ead 100644 --- a/code/modules/mob/living/simple_animal/friendly/diona.dm +++ b/code/modules/mob/living/simple_animal/friendly/diona.dm @@ -54,7 +54,7 @@ /mob/living/simple_animal/diona/attack_hand(mob/living/carbon/human/M) //Let people pick the little buggers up. if(M.a_intent == INTENT_HELP) - if(M.species && M.species.name == "Diona") + if(isdiona(M)) to_chat(M, "You feel your being twine with that of [src] as it merges with your biomass.") to_chat(src, "You feel your being twine with that of [M] as you merge with its biomass.") verbs += /mob/living/simple_animal/diona/proc/split @@ -82,7 +82,7 @@ if(ishuman(C)) var/mob/living/carbon/human/D = C - if(D.species && D.species.name == "Diona") + if(isdiona(D)) choices += C var/mob/living/M = input(src,"Who do you wish to merge with?") in null|choices @@ -142,7 +142,7 @@ visible_message("[src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.","You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.") var/mob/living/carbon/human/diona/adult = new(get_turf(loc)) - adult.set_species("Diona") + adult.set_species(/datum/species/diona) if(istype(loc, /obj/item/holder/diona)) var/obj/item/holder/diona/L = loc @@ -156,8 +156,7 @@ adult.name = "diona ([rand(100,999)])" adult.real_name = adult.name adult.ckey = ckey - adult.real_name = pick(diona_names) //I hate this being here of all places but unfortunately dna is based on real_name! - adult.rename_self("diona") + adult.real_name = adult.dna.species.get_random_name() //I hate this being here of all places but unfortunately dna is based on real_name! for(var/obj/item/W in contents) unEquip(W) @@ -178,7 +177,7 @@ if(!M || !src) return - if(NO_BLOOD in M.species.species_traits) + if(NO_BLOOD in M.dna.species.species_traits) to_chat(src, "That donor has no blood to take.") return diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index a8784a6d150..370418134c3 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -234,7 +234,7 @@ var/global/chicken_count = 0 can_hide = 1 can_collar = 1 var/list/feedMessages = list("It clucks happily.","It clucks happily.") - var/list/layMessage = list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.") + var/list/layMessage = EGG_LAYING_MESSAGES var/list/validColors = list("brown","black","white") gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm index 70a64d2dbcb..37ed25f15e8 100644 --- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm @@ -35,7 +35,7 @@ var/emagged = 0 //is it getting ready to explode? var/obj/item/mmi/mmi = null - var/emagged_master = null //for administrative purposes, to see who emagged the spiderbot; also for a holder for if someone emags an empty frame first then inserts an MMI. + var/mob/emagged_master = null //for administrative purposes, to see who emagged the spiderbot; also for a holder for if someone emags an empty frame first then inserts an MMI. /mob/living/simple_animal/spiderbot/Destroy() if(emagged) @@ -135,8 +135,8 @@ else emagged = 1 to_chat(user, "You short out the security protocols and rewrite [src]'s internal memory.") - to_chat(src, "You have been emagged; you are now completely loyal to [user] and their every order!") - emagged_master = user.name + to_chat(src, "You have been emagged; you are now completely loyal to [user] and [user.p_their()] every order!") + emagged_master = user add_attack_logs(user, src, "Emagged") maxHealth = 60 health = 60 @@ -150,14 +150,14 @@ ckey = M.brainmob.ckey name = "Spider-bot ([M.brainmob.name])" if(emagged) - to_chat(src, "You have been emagged; you are now completely loyal to [emagged_master] and their every order!") + to_chat(src, "You have been emagged; you are now completely loyal to [emagged_master] and [emagged_master.p_their()] every order!") /mob/living/simple_animal/spiderbot/proc/update_icon() if(mmi) if(istype(mmi, /obj/item/mmi)) icon_state = "spiderbot-chassis-mmi" icon_living = "spiderbot-chassis-mmi" - if(istype(mmi, /obj/item/mmi/posibrain)) + if(istype(mmi, /obj/item/mmi/robotic_brain)) icon_state = "spiderbot-chassis-posi" icon_living = "spiderbot-chassis-posi" diff --git a/code/modules/mob/living/simple_animal/hostile/deathsquid.dm b/code/modules/mob/living/simple_animal/hostile/deathsquid.dm index e825bb2d273..065247a538d 100644 --- a/code/modules/mob/living/simple_animal/hostile/deathsquid.dm +++ b/code/modules/mob/living/simple_animal/hostile/deathsquid.dm @@ -11,6 +11,8 @@ icon_state = "deathsquid" icon_living = "deathsquid" icon_dead = "deathsquiddead" + pixel_x = -24 + pixel_y = -24 attacktext = "slices" attack_sound = 'sound/weapons/bladeslice.ogg' diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 283936acb44..f3e31925228 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -178,7 +178,7 @@ if(ishuman(the_target)) var/mob/living/carbon/human/H = the_target - if(is_type_in_list(src, H.species.ignored_by)) + if(is_type_in_list(src, H.dna.species.ignored_by)) return 0 if(istype(the_target, /obj/mecha)) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 971adc431cc..3c72042efce 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -117,7 +117,7 @@ Difficulty: Hard bloodspell.phased = 1 internal_gps = new/obj/item/gps/internal/bubblegum(src) -/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon) +/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) if(!charging) ..() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm index 5c25e9820e1..6027070dfc9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm @@ -229,7 +229,7 @@ Difficulty: Medium playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1) for(var/mob/living/L in orange(1, src)) if(L.stat) - visible_message("[src] slams down on [L], crushing them!") + visible_message("[src] slams down on [L], crushing [L.p_them()]!") L.gib() else L.adjustBruteLoss(75) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm index 3462e8e18e7..7b10c0e828a 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm @@ -27,4 +27,41 @@ speak_emote = list("gnashes") faction = list("carp") - flying = 1 \ No newline at end of file + flying = 1 + + +/mob/living/simple_animal/hostile/retaliate/carp/koi + name = "space koi" + desc = "A gentle space-faring koi." + icon = 'icons/obj/fish_items.dmi' + icon_state = "koi1" + icon_living = "koi1" + icon_dead = "koi1-dead" + + harm_intent_damage = 1 + melee_damage_lower = 2 + melee_damage_upper = 2 + speak_emote = list("blurps") + butcher_results = null + + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 + maxbodytemp = 1500 + + gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE + +/mob/living/simple_animal/hostile/retaliate/carp/koi/New() + ..() + var/koinum = rand(1, 4) + icon_state = "koi[koinum]" + icon_living = "koi[koinum]" + icon_dead = "koi[koinum]-dead" + + +/mob/living/simple_animal/hostile/retaliate/carp/koi/Process_Spacemove(var/movement_dir) + return TRUE + +/mob/living/simple_animal/hostile/retaliate/carp/koi/honk + icon_state = "koi5" + icon_living = "koi5" + icon_dead = "koi5-dead" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm index d63d43b4919..cdbc64eea1e 100644 --- a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm +++ b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm @@ -328,7 +328,7 @@ //Jiggle the whole worm forwards towards the next segment -/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A) +/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) ..() if(previousWorm) previousWorm.do_attack_animation(src) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm index 982a0eaae90..377b8ff335a 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm @@ -36,7 +36,7 @@ L.reagents.add_reagent("terror_black_toxin", 30) // inject our special poison visible_message("[src] buries its long fangs deep into the [inject_target] of [target]!") else - visible_message("[src] bites [target], but cannot inject venom into their [inject_target]!") + visible_message("[src] bites [target], but cannot inject venom into [target.p_their()] [inject_target]!") L.attack_animal(src) if(!ckey && (!(target in enemies) || L.reagents.has_reagent("terror_black_toxin", 60))) step_away(src, L) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm index 06b28c6400e..43c0e7b0be5 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm @@ -33,7 +33,7 @@ if(W) melee_damage_lower = initial(melee_damage_lower) * 2 melee_damage_upper = initial(melee_damage_upper) * 2 - visible_message("[src] savagely mauls [target] while they are stuck in the web!") + visible_message("[src] savagely mauls [target] while [L.p_theyre()] stuck in the web!") else melee_damage_lower = initial(melee_damage_lower) melee_damage_upper = initial(melee_damage_upper) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm index 9d6f977a1ae..64ef285ded8 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm @@ -93,5 +93,5 @@ // instead of having a venom that only lasts seconds, we just add the eyeblur directly. visible_message("[src] buries its fangs deep into the [inject_target] of [target]!") else - visible_message("[src] bites [target], but cannot inject venom into their [inject_target]!") + visible_message("[src] bites [target], but cannot inject venom into [target.p_their()] [inject_target]!") L.attack_animal(src) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm index 21b1276425c..66e88af1e1b 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm @@ -43,7 +43,7 @@ /mob/living/simple_animal/hostile/poison/terror_spider/prince/spider_specialattack(mob/living/carbon/human/L) if(prob(15)) - visible_message("[src] rams into [L], knocking them to the floor!") + visible_message("[src] rams into [L], knocking [L.p_them()] to the floor!") L.Weaken(5) L.Stun(5) else diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm index 9133b8cc14c..532c2b7357a 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm @@ -39,7 +39,7 @@ var/lastnestsetup = 0 var/neststep = 0 var/hasnested = 0 - var/spider_max_per_nest = 25 // above this, AI queens become stable + var/spider_max_per_nest = 35 // above this, AI queens become stable var/canlay = 4 // main counter for egg-laying ability! # = num uses, incremented at intervals var/eggslaid = 0 var/spider_can_fakelings = 3 // spawns defective spiderlings that don't grow up, used to freak out crew, atmosphere diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm index ef456ddcb0e..693ca724ac6 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm @@ -196,16 +196,11 @@ var/global/list/ts_spiderling_list = list() var/can_poison = 1 if(ishuman(G)) var/mob/living/carbon/human/H = G - if(!(H.species.reagent_tag & PROCESS_ORG) || (!H.species.tox_mod)) + if(!(H.dna.species.reagent_tag & PROCESS_ORG) || (!H.dna.species.tox_mod)) can_poison = 0 spider_specialattack(G,can_poison) else G.attack_animal(src) - else if(istype(target, /obj/structure/alien/resin)) - var/obj/structure/alien/resin/E = target - do_attack_animation(E) - E.health -= rand(melee_damage_lower, melee_damage_upper) - E.healthcheck() else target.attack_animal(src) diff --git a/code/modules/mob/living/simple_animal/pony.dm b/code/modules/mob/living/simple_animal/pony.dm index 437c9b0ac4d..960f8fc0998 100644 --- a/code/modules/mob/living/simple_animal/pony.dm +++ b/code/modules/mob/living/simple_animal/pony.dm @@ -27,7 +27,7 @@ ..() if(stat == 2) new /obj/item/reagent_containers/food/snacks/ectoplasm(src.loc) - src.visible_message("\The [src] lets out a contented sigh as their form unwinds.") + src.visible_message("[src] lets out a contented sigh as [p_their()] form unwinds.") src.ghostize() qdel(src) return diff --git a/code/modules/mob/living/simple_animal/posessed_object.dm b/code/modules/mob/living/simple_animal/posessed_object.dm index 9ba666ce96a..22901f4d29a 100644 --- a/code/modules/mob/living/simple_animal/posessed_object.dm +++ b/code/modules/mob/living/simple_animal/posessed_object.dm @@ -26,7 +26,7 @@ to_chat(usr, "[src] appears to be having trouble staying afloat!") -/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A) +/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) ..() animate_ghostly_presence(src, -1, 20, 1) // Restart the floating animation after the attack animation, as it will be cancelled. diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index c7b82dc44b8..5a88373f6f2 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -61,7 +61,8 @@ var/obj/item/clothing/accessory/petcollar/collar = null var/can_collar = 0 // can add collar to mob or not -//Hot simple_animal baby making vars + //Hot simple_animal baby making vars + var/childtype = null var/scan_ready = 1 var/simplespecies //Sorry, no spider+corgi buttbabies. @@ -79,7 +80,7 @@ var/death_sound = null //The sound played on death -/mob/living/simple_animal/New() +/mob/living/simple_animal/Initialize() ..() simple_animal_list += src verbs -= /mob/verb/observe @@ -130,8 +131,8 @@ if(..()) //alive if(health < 1) death() - return 0 - return 1 + return FALSE + return TRUE /mob/living/simple_animal/proc/handle_automated_action() return @@ -270,7 +271,7 @@ if((Proj.damage_type != STAMINA)) adjustBruteLoss(Proj.damage) Proj.on_hit(src, 0) - return 0 + return FALSE /mob/living/simple_animal/attackby(obj/item/O, mob/living/user) if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar)) @@ -342,7 +343,7 @@ /mob/living/simple_animal/proc/adjustHealth(amount) if(status_flags & GODMODE) - return 0 + return FALSE bruteloss = Clamp(bruteloss + amount, 0, maxHealth) handle_regular_status_updates() @@ -372,20 +373,20 @@ /mob/living/simple_animal/proc/CanAttack(var/atom/the_target) if(see_invisible < the_target.invisibility) - return 0 + return FALSE if(isliving(the_target)) var/mob/living/L = the_target if(L.stat != CONSCIOUS) - return 0 + return FALSE if(istype(the_target, /obj/mecha)) var/obj/mecha/M = the_target if(M.occupant) - return 0 + return FALSE if(istype(the_target,/obj/spacepod)) var/obj/spacepod/S = the_target if(S.pilot) - return 0 - return 1 + return FALSE + return TRUE /mob/living/simple_animal/handle_fire() return @@ -394,7 +395,7 @@ return /mob/living/simple_animal/IgniteMob() - return 0 + return FALSE /mob/living/simple_animal/ExtinguishMob() return @@ -502,19 +503,19 @@ switch(slot) if(slot_collar) if(collar) - return 0 + return FALSE if(!can_collar) - return 0 + return FALSE if(!istype(I, /obj/item/clothing/accessory/petcollar)) - return 0 - return 1 + return FALSE + return TRUE /mob/living/simple_animal/equip_to_slot(obj/item/W, slot) if(!istype(W)) - return 0 + return FALSE if(!slot) - return 0 + return FALSE W.forceMove(src) W.equipped(src, slot) @@ -570,3 +571,4 @@ /mob/living/simple_animal/SetEarDeaf() return + diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 63b248ffd41..a5883fe93f2 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -4,6 +4,7 @@ lastKnownIP = client.address computer_id = client.computer_id log_access_in(client) + create_attack_log("Logged in at [atom_loc_line(get_turf(src))]") if(config.log_access) for(var/mob/M in player_list) if(M == src) continue @@ -55,11 +56,7 @@ if(abilities) client.verbs |= abilities - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - if(H.species && H.species.abilities) - client.verbs |= H.species.abilities - + if(ishuman(src)) client.screen += client.void //HUD updates (antag hud, etc) diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index a0f8594e870..cbcd51c44a7 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -3,6 +3,7 @@ unset_machine() player_list -= src log_access_out(src) + create_attack_log("Logged out at [atom_loc_line(get_turf(src))]") // `holder` is nil'd out by now, so we check the `admin_datums` array directly //Only report this stuff if we are currently playing. if(admin_datums[ckey] && ticker && ticker.current_state == GAME_STATE_PLAYING) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 897f092a517..fc09105e948 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -24,7 +24,7 @@ ..() return QDEL_HINT_HARDDEL -/mob/New() +/mob/Initialize() mob_list += src if(stat == DEAD) dead_mob_list += src @@ -170,6 +170,16 @@ return 0 /mob/proc/Life(seconds, times_fired) + if(forced_look) + if(!isnum(forced_look)) + var/atom/A = locateUID(forced_look) + if(istype(A)) + var/view = client ? client.view : world.view + if(get_dist(src, A) > view || !(src in viewers(view, A))) + forced_look = null + to_chat(src, "Your direction target has left your view, you are no longer facing anything.") + return + setDir() // handle_typing_indicator() return @@ -533,6 +543,17 @@ var/list/slot_equipment_priority = list( \ client.screen = list() hud_used.show_hud(hud_used.hud_version) +/mob/setDir(new_dir) + if(forced_look) + if(isnum(forced_look)) + dir = forced_look + else + var/atom/A = locateUID(forced_look) + if(istype(A)) + dir = get_cardinal_dir(src, A) + return + . = ..() + /mob/proc/show_inv(mob/user) user.set_machine(src) var/dat = {" @@ -571,7 +592,7 @@ var/list/slot_equipment_priority = list( \ return if(!src || !isturf(src.loc)) return 0 - if(istype(A, /obj/effect/decal/point)) + if(istype(A, /obj/effect/temp_visual/point)) return 0 var/tile = get_turf(A) @@ -579,12 +600,8 @@ var/list/slot_equipment_priority = list( \ return 0 changeNext_move(CLICK_CD_POINT) - var/obj/P = new /obj/effect/decal/point(tile) + var/obj/P = new /obj/effect/temp_visual/point(tile) P.invisibility = invisibility - spawn (20) - if(P) - qdel(P) - return 1 /mob/proc/ret_grab(obj/effect/list_container/mobl/L as obj, flag) @@ -1063,9 +1080,6 @@ var/list/slot_equipment_priority = list( \ /mob/proc/activate_hand(selhand) return -/mob/proc/get_species() - return "" - /mob/dead/observer/verb/respawn() set name = "Respawn as NPC" set category = "Ghost" @@ -1158,7 +1172,7 @@ var/list/slot_equipment_priority = list( \ new /obj/effect/decal/cleanable/vomit/green(location) else if(!no_text) - visible_message("[src] pukes all over \himself!","You puke all over yourself!") + visible_message("[src] pukes all over [p_them()]self!","You puke all over yourself!") location.add_vomit_floor(src, 1) playsound(location, 'sound/effects/splat.ogg', 50, 1) @@ -1308,4 +1322,4 @@ var/list/slot_equipment_priority = list( \ if(WEST) D = NORTH setDir(D) - spintime -= speed \ No newline at end of file + spintime -= speed diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 9154591c2fe..57b5aeb4996 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -198,3 +198,5 @@ var/list/progressbars = null //for stacking do_after bars var/list/tkgrabbed_objects = list() // Assoc list of items to TK grabs + + var/forced_look = null // This can either be a numerical direction or a soft object reference (UID). It makes the mob always face towards the selected thing. \ No newline at end of file diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 1c4b0f38fbe..93941d6e7d2 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -263,17 +263,17 @@ state = GRAB_AGGRESSIVE icon_state = "grabbed1" hud.icon_state = "reinforce1" - add_attack_logs(assailant, affecting, "Aggressively grabbed", admin_notify = FALSE) + add_attack_logs(assailant, affecting, "Aggressively grabbed", ATKLOG_ALL) else if(state < GRAB_NECK) if(isslime(affecting)) to_chat(assailant, "You squeeze [affecting], but nothing interesting happens.") return - assailant.visible_message("[assailant] has reinforced \his grip on [affecting] (now neck)!") + assailant.visible_message("[assailant] has reinforced [assailant.p_their()] grip on [affecting] (now neck)!") state = GRAB_NECK icon_state = "grabbed+1" assailant.setDir(get_dir(assailant, affecting)) - add_attack_logs(assailant, affecting, "Neck grabbed", admin_notify = FALSE) + add_attack_logs(assailant, affecting, "Neck grabbed", ATKLOG_ALL) if(!iscarbon(assailant)) affecting.LAssailant = null else @@ -282,11 +282,11 @@ hud.name = "kill" affecting.Stun(10) //10 ticks of ensured grab else if(state < GRAB_UPGRADING) - assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!") + assailant.visible_message("[assailant] starts to tighten [assailant.p_their()] grip on [affecting]'s neck!") hud.icon_state = "kill1" state = GRAB_KILL - assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!") + assailant.visible_message("[assailant] has tightened [assailant.p_their()] grip on [affecting]'s neck!") add_attack_logs(assailant, affecting, "Strangled") assailant.next_move = world.time + 10 @@ -332,7 +332,7 @@ if(last_hit_zone == "head") //This checks the hitzone the user has selected. In this specific case, they have the head selected. if(affecting.lying) return - assailant.visible_message("[assailant] thrusts \his head into [affecting]'s skull!") //A visible message for what is going on. + assailant.visible_message("[assailant] thrusts [assailant.p_their()] head into [affecting]'s skull!") //A visible message for what is going on. var/damage = 5 var/obj/item/clothing/hat = attacker.head if(istype(hat)) @@ -354,7 +354,7 @@ if(!affected.internal_bodyparts_by_name["eyes"]) to_chat(assailant, "You cannot locate any eyes on [affecting]!") return - assailant.visible_message("[assailant] presses \his fingers into [affecting]'s eyes!") + assailant.visible_message("[assailant] presses [assailant.p_their()] fingers into [affecting]'s eyes!") to_chat(affecting, "You feel immense pain as digits are being pressed into your eyes!") add_attack_logs(assailant, affecting, "Eye-fucked with their fingers") var/obj/item/organ/internal/eyes/eyes = affected.get_int_organ(/obj/item/organ/internal/eyes) @@ -410,7 +410,7 @@ return 1 var/mob/living/carbon/human/H = attacker - if(ishuman(H) && is_type_in_list(prey, H.species.allowed_consumed_mobs)) //species eating of other mobs + if(ishuman(H) && is_type_in_list(prey, H.dna.species.allowed_consumed_mobs)) //species eating of other mobs return 1 return 0 diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index d06028625b8..46b5d1b0606 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -1,7 +1,7 @@ /proc/issmall(A) if(A && istype(A, /mob/living/carbon/human)) var/mob/living/carbon/human/H = A - if(H.species && H.species.is_small) + if(H.dna.species && H.dna.species.is_small) return 1 return 0 @@ -16,9 +16,9 @@ return 0 /mob/living/carbon/human/isSynthetic() - if(get_species() == "Machine") - return 1 - return 0 + if(ismachine(src)) + return TRUE + return FALSE /mob/proc/get_screen_colour() @@ -356,7 +356,7 @@ var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM) if(hud_used && hud_used.action_intent) hud_used.action_intent.icon_state = "[a_intent]" - else if(isrobot(src) || islarva(src)) + else if(isrobot(src) || islarva(src) || isanimal(src)) switch(input) if(INTENT_HELP) a_intent = INTENT_HELP diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index a92e548d42b..f26961eace9 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -268,6 +268,8 @@ else . = ..() + mob.setDir(direct) + for(var/obj/item/grab/G in mob) if(G.state == GRAB_NECK) mob.setDir(reverse_dir[direct]) diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index bbecb8e6458..99047b0382c 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -30,11 +30,11 @@ callHook("mob_login", list("client" = client, "mob" = src)) new_player_panel() - + spawn(30) // Annoy the player with polls. establish_db_connection() - if(dbcon.IsConnected() && client.can_vote()) + if(dbcon.IsConnected() && client && client.can_vote()) var/isadmin = 0 if(client && client.holder) isadmin = 1 @@ -46,7 +46,7 @@ break if(newpoll) client.handle_player_polling() - + if(ckey in deadmins) verbs += /client/proc/readmin spawn(40) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index bf6526c856e..a2586dd65a1 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -4,6 +4,7 @@ var/spawning = 0 //Referenced when you want to delete the new_player later on in the code. var/totalPlayers = 0 //Player counts for the Lobby tab var/totalPlayersReady = 0 + var/tos_consent = FALSE universal_speak = 1 invisibility = 101 @@ -19,7 +20,40 @@ /mob/new_player/verb/new_player_panel() set src = usr - new_player_panel_proc() + + if(handle_tos_consent()) + new_player_panel_proc() + +/mob/new_player/proc/handle_tos_consent() + if(!GLOB.join_tos) + tos_consent = TRUE + return TRUE + + establish_db_connection() + if(!dbcon.IsConnected()) + tos_consent = TRUE + return TRUE + + var/DBQuery/query = dbcon.NewQuery("SELECT * FROM [format_table_name("privacy")] WHERE ckey='[src.ckey]' AND consent=1") + query.Execute() + while(query.NextRow()) + tos_consent = TRUE + return TRUE + + privacy_consent() + return FALSE + +/mob/new_player/proc/privacy_consent() + src << browse(null, "window=playersetup") + var/output = GLOB.join_tos + output += "

    I consent" + output += "

    I DO NOT consent" + src << browse(output,"window=privacy_consent;size=500x300") + var/datum/browser/popup = new(src, "privacy_consent", "

    Privacy Consent
    ", 500, 400) + popup.set_window_options("can_close=0") + popup.set_content(output) + popup.open(0) + return /mob/new_player/proc/new_player_panel_proc() @@ -43,6 +77,9 @@ output += "

    Observe

    " + if(GLOB.join_tos) + output += "

    Terms of Service

    " + if(!IsGuestKey(src.key)) establish_db_connection() @@ -109,11 +146,28 @@ /mob/new_player/Topic(href, href_list[]) if(!client) return 0 + if(href_list["consent_signed"]) + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/DBQuery/query = dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 1)") + query.Execute() + src << browse(null, "window=privacy_consent") + tos_consent = 1 + new_player_panel_proc() + if(href_list["consent_rejected"]) + tos_consent = 0 + to_chat(usr, "You must consent to the terms of service before you can join!") + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/DBQuery/query = dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 0)") + query.Execute() + if(href_list["show_preferences"]) client.prefs.ShowChoices(src) return 1 if(href_list["ready"]) + if(!tos_consent) + to_chat(usr, "You must consent to the terms of service before you can join!") + return 0 ready = !ready new_player_panel_proc() @@ -126,6 +180,9 @@ new_player_panel_proc() if(href_list["observe"]) + if(!tos_consent) + to_chat(usr, "You must consent to the terms of service before you can join!") + return 0 if(alert(src,"Are you sure you wish to observe? You cannot normally join the round after doing this!","Player Setup","Yes","No") == "Yes") if(!client) return 1 @@ -155,8 +212,14 @@ respawnable_list += observer qdel(src) return 1 + if(href_list["tos"]) + privacy_consent() + return 0 if(href_list["late_join"]) + if(!tos_consent) + to_chat(usr, "You must consent to the terms of service before you can join!") + return 0 if(!ticker || ticker.current_state != GAME_STATE_PLAYING) to_chat(usr, "The round is either not ready, or has already finished...") return @@ -326,19 +389,19 @@ if(ailist.len) var/mob/living/silicon/ai/announcer = pick(ailist) if(character.mind) - if((character.mind.assigned_role != "Cyborg") && (character.mind.special_role != "MODE")) + if((character.mind.assigned_role != "Cyborg") && (character.mind.assigned_role != character.mind.special_role)) if(character.mind.role_alt_title) rank = character.mind.role_alt_title var/arrivalmessage = announcer.arrivalmsg arrivalmessage = replacetext(arrivalmessage,"$name",character.real_name) arrivalmessage = replacetext(arrivalmessage,"$rank",rank ? "[rank]" : "visitor") - arrivalmessage = replacetext(arrivalmessage,"$species",character.species.name) + arrivalmessage = replacetext(arrivalmessage,"$species",character.dna.species.name) arrivalmessage = replacetext(arrivalmessage,"$age",num2text(character.age)) arrivalmessage = replacetext(arrivalmessage,"$gender",character.gender == FEMALE ? "Female" : "Male") announcer.say(";[arrivalmessage]") else if(character.mind) - if((character.mind.assigned_role != "Cyborg") && (character.mind.special_role != "MODE")) + if((character.mind.assigned_role != "Cyborg") && (character.mind.assigned_role != character.mind.special_role)) if(character.mind.role_alt_title) rank = character.mind.role_alt_title global_announcer.autosay("[character.real_name],[rank ? " [rank]," : " visitor," ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") @@ -351,12 +414,12 @@ if(ailist.len) var/mob/living/silicon/ai/announcer = pick(ailist) if(character.mind) - if((character.mind.special_role != "MODE")) + if(character.mind.assigned_role != character.mind.special_role) var/arrivalmessage = "A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"]." announcer.say(";[arrivalmessage]") else if(character.mind) - if((character.mind.special_role != "MODE")) + if(character.mind.assigned_role != character.mind.special_role) // can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc. global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") @@ -474,9 +537,6 @@ else if(mind.assigned_role == "Mime") new_character.real_name = pick(mime_names) new_character.rename_self("mime") - else if(new_character.species == "Diona") - new_character.real_name = pick(diona_names) //I hate this being here of all places but unfortunately dna is based on real_name! - new_character.rename_self("diona") mind.original = new_character mind.transfer_to(new_character) //won't transfer key since the mind is not active @@ -489,7 +549,7 @@ /mob/new_player/proc/check_prefs_are_sane() var/datum/species/chosen_species if(client.prefs.species) - chosen_species = all_species[client.prefs.species] + chosen_species = GLOB.all_species[client.prefs.species] if(!(chosen_species && (is_species_whitelisted(chosen_species) || has_admin_rights()))) // Have to recheck admin due to no usr at roundstart. Latejoins are fine though. log_runtime(EXCEPTION("[src] had species [client.prefs.species], though they weren't supposed to. Setting to Human."), src) @@ -528,19 +588,6 @@ if(!S) return 1 return is_alien_whitelisted(src, S.name) || !config.usealienwhitelist || !(IS_WHITELISTED in S.species_traits) -/mob/new_player/get_species() - var/datum/species/chosen_species - if(client.prefs.species) - chosen_species = all_species[client.prefs.species] - - if(!chosen_species) - return "Human" - - if(is_species_whitelisted(chosen_species) || has_admin_rights()) - return chosen_species.name - - return "Human" - /mob/new_player/get_gender() if(!client || !client.prefs) ..() return client.prefs.gender diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index d57c46e513c..fc97658896f 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -1,10 +1,10 @@ /datum/preferences //The mob should have a gender you want before running this proc. Will run fine without H /datum/preferences/proc/random_character(gender_override) - var/datum/species/S = all_species[species] + var/datum/species/S = GLOB.all_species[species] if(!istype(S)) //The species was invalid. Set the species to the default, fetch the datum for that species and generate a random character. species = initial(species) - S = all_species[species] + S = GLOB.all_species[species] var/datum/robolimb/robohead if(S.bodyflags & ALL_RPARTS) @@ -216,20 +216,20 @@ if(gender == FEMALE) g = "f" var/icon/icobase - var/datum/species/current_species = all_species[species] + var/datum/species/current_species = GLOB.all_species[species] //Icon-based species colour. var/coloured_tail if(current_species) if(current_species.bodyflags & HAS_ICON_SKIN_TONE) //Handling species-specific icon-based skin tones by flagged race. var/mob/living/carbon/human/H = new - H.species = current_species + H.dna.species = current_species H.s_tone = s_tone - H.species.updatespeciescolor(H, 0) //The mob's species wasn't set, so it's almost certainly different than the character's species at the moment. Thus, we need to be owner-insensitive. + H.dna.species.updatespeciescolor(H, 0) //The mob's species wasn't set, so it's almost certainly different than the character's species at the moment. Thus, we need to be owner-insensitive. var/obj/item/organ/external/chest/C = H.get_organ("chest") - icobase = C.icobase ? C.icobase : C.species.icobase - if(H.species.bodyflags & HAS_TAIL) - coloured_tail = H.tail ? H.tail : H.species.tail + icobase = C.icobase ? C.icobase : C.dna.species.icobase + if(H.dna.species.bodyflags & HAS_TAIL) + coloured_tail = H.tail ? H.tail : H.dna.species.tail qdel(H) else diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index ace8ab1b621..1cb1bc5f3b0 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -208,3 +208,7 @@ /mob/proc/AdjustWeakened() return + +/mob/proc/adjust_bodytemperature(amount, min_temp = 0, max_temp = INFINITY) + if(bodytemperature > min_temp && bodytemperature < max_temp) + bodytemperature = Clamp(bodytemperature + amount, min_temp, max_temp) \ No newline at end of file diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 82aebda3a42..a1ed4f0bde9 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -86,7 +86,7 @@ if(O.mind && O.mind.assigned_role == "Cyborg") if(O.mind.role_alt_title == "Android") - O.mmi = new /obj/item/mmi/posibrain(O) + O.mmi = new /obj/item/mmi/robotic_brain(O) else if(O.mind.role_alt_title == "Robot") O.mmi = null //Robots do not have removable brains. else diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index 6e0be3b385f..5dd324945fa 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -36,6 +36,7 @@ var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/power_monitor()) hard_drive.store_file(new/datum/computer_file/program/alarm_monitor()) + hard_drive.store_file(new/datum/computer_file/program/supermatter_monitor()) // ===== RESEARCH CONSOLE ===== /obj/machinery/modular_computer/console/preset/research diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm index 6ebf9228848..b570687569a 100644 --- a/code/modules/modular_computers/file_system/programs/command/card.dm +++ b/code/modules/modular_computers/file_system/programs/command/card.dm @@ -238,7 +238,7 @@ jobdatum = J break if(!jobdatum) - to_chat(usr, "\red No log exists for this job: [t1]") + to_chat(usr, "No log exists for this job: [t1]") return access = jobdatum.get_access() diff --git a/code/modules/modular_computers/file_system/programs/command/comms.dm b/code/modules/modular_computers/file_system/programs/command/comms.dm index ef6cf016cd5..2ca6d9928a3 100644 --- a/code/modules/modular_computers/file_system/programs/command/comms.dm +++ b/code/modules/modular_computers/file_system/programs/command/comms.dm @@ -325,7 +325,7 @@ to_chat(usr, "Arrays recycling. Please stand by.") SSnanoui.update_uis(src) return 1 - var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","") as text|null + var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) SSnanoui.update_uis(src) return 1 @@ -344,7 +344,7 @@ to_chat(usr, "Arrays recycling. Please stand by.") SSnanoui.update_uis(src) return 1 - var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") as text|null + var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) SSnanoui.update_uis(src) return 1 @@ -363,7 +363,7 @@ to_chat(usr, "Arrays recycling. Please stand by.") SSnanoui.update_uis(src) return 1 - var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") as text|null + var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) SSnanoui.update_uis(src) return 1 diff --git a/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm new file mode 100644 index 00000000000..db9081f6ad1 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm @@ -0,0 +1,139 @@ +/datum/computer_file/program/supermatter_monitor + filename = "smmonitor" + filedesc = "Supermatter Monitoring" + ui_header = "smmon_0.gif" + program_icon_state = "smmon_0" + extended_desc = "This program connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines." + requires_ntnet = TRUE + transfer_access = access_construction + network_destination = "supermatter monitoring system" + size = 5 + var/last_status = SUPERMATTER_INACTIVE + var/list/supermatters + var/obj/machinery/power/supermatter_shard/active // Currently selected supermatter crystal. + + +/datum/computer_file/program/supermatter_monitor/process_tick() + ..() + var/new_status = get_status() + if(last_status != new_status) + last_status = new_status + if(last_status == SUPERMATTER_ERROR) + last_status = SUPERMATTER_INACTIVE + ui_header = "smmon_[last_status].gif" + program_icon_state = "smmon_[last_status]" + if(istype(computer)) + computer.update_icon() + +/datum/computer_file/program/supermatter_monitor/run_program(mob/living/user) + . = ..(user) + refresh() + +/datum/computer_file/program/supermatter_monitor/kill_program(forced = FALSE) + active = null + supermatters = null + ..() + +// Refreshes list of active supermatter crystals +/datum/computer_file/program/supermatter_monitor/proc/refresh() + supermatters = list() + var/turf/T = get_turf(nano_host()) + if(!T) + return + for(var/obj/machinery/power/supermatter_shard/S in SSair.atmos_machinery) + // Delaminating, not within coverage, not on a tile. + if(!(is_station_level(S.z) || is_mining_level(S.z) || atoms_share_level(S, T) || !istype(S.loc, /turf/simulated/))) + continue + supermatters.Add(S) + + if(!(active in supermatters)) + active = null + +/datum/computer_file/program/supermatter_monitor/proc/get_status() + . = SUPERMATTER_INACTIVE + for(var/obj/machinery/power/supermatter_shard/S in supermatters) + . = max(., S.get_status()) + +/datum/computer_file/program/supermatter_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers) + assets.send(user) + ui = new(user, src, ui_key, "supermatter_monitor.tmpl", "Supermatter Monitoring", 600, 400) + ui.set_auto_update(TRUE) + ui.set_layout_key("program") + ui.open() + +/datum/computer_file/program/supermatter_monitor/ui_data() + var/list/data = get_header_data() + + if(istype(active)) + var/turf/T = get_turf(active) + if(!T) + active = null + refresh() + return + var/datum/gas_mixture/air = T.return_air() + if(!air) + active = null + return + + data["active"] = TRUE + data["SM_integrity"] = active.get_integrity() + data["SM_power"] = active.power + data["SM_ambienttemp"] = air.temperature + data["SM_ambientpressure"] = air.return_pressure() + //data["SM_EPR"] = round((air.total_moles / air.group_multiplier) / 23.1, 0.01) + var/other_moles = 0.0 + for(var/datum/gas/G in air.trace_gases) + other_moles+=G.moles + var/TM = air.total_moles() + if(TM) + data["SM_gas_O2"] = round(100*air.oxygen/TM,0.01) + data["SM_gas_CO2"] = round(100*air.carbon_dioxide/TM,0.01) + data["SM_gas_N2"] = round(100*air.nitrogen/TM,0.01) + data["SM_gas_PL"] = round(100*air.toxins/TM,0.01) + if(other_moles) + data["SM_gas_OTHER"] = round(100*other_moles/TM,0.01) + else + data["SM_gas_OTHER"] = 0 + else + data["SM_gas_O2"] = 0 + data["SM_gas_CO2"] = 0 + data["SM_gas_N2"] = 0 + data["SM_gas_PH"] = 0 + data["SM_gas_OTHER"] = 0 + else + var/list/SMS = list() + for(var/obj/machinery/power/supermatter_shard/S in supermatters) + var/area/A = get_area(S) + if(!A) + continue + + SMS.Add(list(list( + "area_name" = A.name, + "integrity" = S.get_integrity(), + "uid" = S.uid + ))) + + data["active"] = FALSE + data["supermatters"] = SMS + + return data + + +/datum/computer_file/program/supermatter_monitor/Topic(href, href_list) + if(..()) + return TRUE + if(href_list["clear"]) + active = null + return TRUE + if(href_list["refresh"]) + refresh() + return TRUE + if(href_list["set"]) + var/newuid = text2num(href_list["set"]) + for(var/obj/machinery/power/supermatter_shard/S in supermatters) + if(S.uid == newuid) + active = S + return TRUE diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm index 3f9155ed162..e5062bc0b12 100644 --- a/code/modules/nano/interaction/default.dm +++ b/code/modules/nano/interaction/default.dm @@ -59,10 +59,14 @@ return STATUS_CLOSE -//Some atoms such as vehicles might have special rules for how mobs inside them interact with NanoUI. +//Some atoms such as vehicles might have special limitations for how mobs inside them interact with NanoUI. /atom/proc/contents_nano_distance(var/src_object, var/mob/living/user) return user.shared_living_nano_distance(src_object) +//Some atoms such as vehicles might have special benefits for how mobs inside them interact with NanoUI. +/atom/proc/contents_nano_interact(var/src_object, var/mob/living/user) + return STATUS_CLOSE // No help at all by default + /mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object) if(!(src_object in view(4, src))) // If the src object is not in visable, disable updates return STATUS_CLOSE @@ -84,6 +88,16 @@ if(STATUS_INTERACTIVE) return STATUS_UPDATE +/mob/living/carbon/brain/default_can_use_topic(var/src_object) + . = shared_nano_interaction(src_object) + if(. <= STATUS_DISABLED) + return + // Maybe add a handler here to call an "interaction state" thing on the MMI, + // later + if(loc) + . = max(., loc.contents_nano_interact(src_object, src)) // This is an "augment" on interaction + . = min(., loc.contents_nano_distance(src_object, src)) // This is a "limit" on interaction + /mob/living/carbon/human/default_can_use_topic(var/src_object) . = shared_nano_interaction(src_object) if(. != STATUS_CLOSE) diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index ad7a8f5cff6..07810eb92a0 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -31,7 +31,8 @@ if(href_list["race"]) if(can_change(APPEARANCE_RACE) && (href_list["race"] in valid_species)) - if(owner.change_species(href_list["race"])) + var/datum/species/S = GLOB.all_species[href_list["race"]] + if(owner.set_species(S.type)) cut_and_generate_data() // Species change creates new organs - runtimes ahoy if we forget this head_organ = owner.get_organ("head") @@ -44,24 +45,24 @@ if(href_list["skin_tone"]) if(can_change_skin_tone()) var/new_s_tone = null - if(owner.species.bodyflags & HAS_SKIN_TONE) + if(owner.dna.species.bodyflags & HAS_SKIN_TONE) new_s_tone = input(usr, "Choose your character's skin tone:\n(Light 1 - 220 Dark)", "Skin Tone", owner.s_tone) as num|null if(isnum(new_s_tone) && can_still_topic(state)) new_s_tone = 35 - max(min(round(new_s_tone), 220),1) - else if(owner.species.bodyflags & HAS_ICON_SKIN_TONE) + else if(owner.dna.species.bodyflags & HAS_ICON_SKIN_TONE) var/const/MAX_LINE_ENTRIES = 4 - var/prompt = "Choose your character's skin tone: 1-[owner.species.icon_skin_tones.len]\n(" - for(var/i = 1 to owner.species.icon_skin_tones.len) + var/prompt = "Choose your character's skin tone: 1-[owner.dna.species.icon_skin_tones.len]\n(" + for(var/i = 1 to owner.dna.species.icon_skin_tones.len) if(i > MAX_LINE_ENTRIES && !((i - 1) % MAX_LINE_ENTRIES)) prompt += "\n" - prompt += "[i] = [owner.species.icon_skin_tones[i]]" - if(i != owner.species.icon_skin_tones.len) + prompt += "[i] = [owner.dna.species.icon_skin_tones[i]]" + if(i != owner.dna.species.icon_skin_tones.len) prompt += ", " prompt += ")" new_s_tone = input(usr, prompt, "Skin Tone", owner.s_tone) as num|null if(isnum(new_s_tone) && can_still_topic(state)) - new_s_tone = max(min(round(new_s_tone), owner.species.icon_skin_tones.len), 1) + new_s_tone = max(min(round(new_s_tone), owner.dna.species.icon_skin_tones.len), 1) if(new_s_tone) return owner.change_skin_tone(new_s_tone) @@ -183,9 +184,9 @@ generate_data(check_whitelist, whitelist, blacklist) var/data[0] - data["specimen"] = owner.species.name + data["specimen"] = owner.dna.species.name data["gender"] = owner.gender - data["has_gender"] = owner.species.has_gender + data["has_gender"] = owner.dna.species.has_gender data["change_race"] = can_change(APPEARANCE_RACE) if(data["change_race"]) var/species[0] @@ -283,25 +284,25 @@ return owner && (flags & flag) /datum/nano_module/appearance_changer/proc/can_change_skin_tone() - return owner && (flags & APPEARANCE_SKIN) && ((owner.species.bodyflags & HAS_SKIN_TONE) || (owner.species.bodyflags & HAS_ICON_SKIN_TONE)) + return owner && (flags & APPEARANCE_SKIN) && ((owner.dna.species.bodyflags & HAS_SKIN_TONE) || (owner.dna.species.bodyflags & HAS_ICON_SKIN_TONE)) /datum/nano_module/appearance_changer/proc/can_change_skin_color() - return owner && (flags & APPEARANCE_SKIN) && (owner.species.bodyflags & HAS_SKIN_COLOR) + return owner && (flags & APPEARANCE_SKIN) && (owner.dna.species.bodyflags & HAS_SKIN_COLOR) /datum/nano_module/appearance_changer/proc/can_change_head_accessory() if(!head_organ) log_runtime(EXCEPTION("Missing head!"), owner) return 0 - return owner && (flags & APPEARANCE_HEAD_ACCESSORY) && (head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + return owner && (flags & APPEARANCE_HEAD_ACCESSORY) && (head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) /datum/nano_module/appearance_changer/proc/can_change_markings(var/location = "body") var/marking_flag = HAS_BODY_MARKINGS - var/body_flags = owner.species.bodyflags + var/body_flags = owner.dna.species.bodyflags if(location == "head") if(!head_organ) log_debug("Missing head!") return 0 - body_flags = head_organ.species.bodyflags + body_flags = head_organ.dna.species.bodyflags marking_flag = HAS_HEAD_MARKINGS if(location == "body") marking_flag = HAS_BODY_MARKINGS @@ -311,13 +312,13 @@ return owner && (flags & APPEARANCE_MARKINGS) && (body_flags & marking_flag) /datum/nano_module/appearance_changer/proc/can_change_body_accessory() - return owner && (flags & APPEARANCE_BODY_ACCESSORY) && (owner.species.bodyflags & HAS_TAIL) + return owner && (flags & APPEARANCE_BODY_ACCESSORY) && (owner.dna.species.bodyflags & HAS_TAIL) /datum/nano_module/appearance_changer/proc/can_change_alt_head() if(!head_organ) log_debug("Missing head!") return 0 - return owner && (flags & APPEARANCE_ALT_HEAD) && (head_organ.species.bodyflags & HAS_ALT_HEADS) + return owner && (flags & APPEARANCE_ALT_HEAD) && (head_organ.dna.species.bodyflags & HAS_ALT_HEADS) /datum/nano_module/appearance_changer/proc/cut_and_generate_data() // Making the assumption that the available species remain constant diff --git a/code/modules/ninja/martial_art.dm b/code/modules/ninja/martial_art.dm index b6562d8377d..c97a3e505c3 100644 --- a/code/modules/ninja/martial_art.dm +++ b/code/modules/ninja/martial_art.dm @@ -20,7 +20,7 @@ /obj/item/creeping_widow_injector/attack_self(mob/living/carbon/human/user as mob) if(!used) user.visible_message("You stick the [src]'s needle into your arm and press the button.", \ - "[user] sticks the [src]'s needle \his arm and presses the button.") + "[user] sticks the [src]'s needle [user.p_their()] arm and presses the button.") to_chat(user, "The nanomachines in the [src] flow through your bloodstream.") var/datum/martial_art/ninja_martial_art/N = new/datum/martial_art/ninja_martial_art(null) @@ -98,8 +98,8 @@ D.silent += 1 D.adjustOxyLoss(1) else - D.visible_message("[A] loses \his grip on [D]'s neck!", \ - "[A] loses \his grip on your neck!") + D.visible_message("[A] loses [A.p_their()] grip on [D]'s neck!", \ + "[A] loses [A.p_their()] grip on your neck!") has_choke_hold = 0 return 0 I++ diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index 2700c8702db..74bee9867ab 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -7,34 +7,28 @@ var/labels_left = 30 var/mode = 0 //off or on. -/obj/item/hand_labeler/afterattack(atom/A, mob/user as mob, proximity) - if(!proximity) return +/obj/item/hand_labeler/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return if(!mode) //if it's off, give up. return - if(A == loc) // if placing the labeller into something (e.g. backpack) - return // don't set a label if(!labels_left) - to_chat(user, "No labels left.") + to_chat(user, "No labels left!") return if(!label || !length(label)) - to_chat(user, "No text set.") + to_chat(user, "No text set!") return if(length(A.name) + length(label) > 64) - to_chat(user, "Label too big.") + to_chat(user, "Label too big!") return - if(ishuman(A)) - to_chat(user, "You can't label humans.") - return - if(issilicon(A)) - to_chat(user, "You can't label cyborgs.") - return - if(istype(A, /obj/item/reagent_containers/glass)) - to_chat(user, "The label can't stick to the [A.name]. (Try using a pen)") + if(ismob(A)) + to_chat(user, "You can't label creatures!") // use a collar return user.visible_message("[user] labels [A] as [label].", \ "You label [A] as [label].") + investigate_log("[key_name(user)] labelled [A] as [label].", INVESTIGATE_LABEL) // Investigate goes BEFORE rename so the original name is preserved in the log A.name = "[A.name] ([label])" /obj/item/hand_labeler/attack_self(mob/user as mob) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index db3f7cddce7..2fe57c5698f 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -34,6 +34,8 @@ var/contact_poison // Reagent ID to transfer on contact var/contact_poison_volume = 0 var/contact_poison_poisoner = null + var/paper_width = 400//Width of the window that opens + var/paper_height = 400//Height of the window that opens var/const/deffont = "Verdana" var/const/signfont = "Times New Roman" @@ -72,12 +74,12 @@ if((!user.say_understands(null, all_languages["Galactic Common"]) && !forceshow) || forcestars) //assuming all paper is written in common is better than hardcoded type checks data = "[name][stars(info)][stamps]" if(view) - usr << browse(data, "window=[name]") + usr << browse(data, "window=[name];size=[paper_width]x[paper_height]") onclose(usr, "[name]") else data = "[name][infolinks ? info_links : info][stamps]" if(view) - usr << browse(data, "window=[name]") + usr << browse(data, "window=[name];size=[paper_width]x[paper_height]") onclose(usr, "[name]") return data @@ -379,7 +381,7 @@ if(is_hot(P)) if((CLUMSY in user.mutations) && prob(10)) - user.visible_message("[user] accidentally ignites themselves!", \ + user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ "You miss the paper and accidentally light yourself on fire!") user.unEquip(P) user.adjust_fire_stacks(1) @@ -403,7 +405,8 @@ stamps += (!stamps || stamps == "" ? "
    " : "") + "" var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - var/{x; y;} + var/x + var/y if(istype(S, /obj/item/stamp/captain) || istype(S, /obj/item/stamp/centcom)) x = rand(-2, 0) y = rand(-1, 2) @@ -476,6 +479,20 @@ /obj/item/paper/crumpled/bloody icon_state = "scrap_bloodied" +/obj/item/paper/fortune + name = "fortune" + icon_state = "slip" + paper_height = 150 + +/obj/item/paper/fortune/New() + ..() + var/fortunemessage = pick(GLOB.fortune_cookie_messages) + info = "

    [fortunemessage]

    " + info += "

    Lucky numbers: [rand(1,49)], [rand(1,49)], [rand(1,49)], [rand(1,49)], [rand(1,49)]

    " + +/obj/item/paper/fortune/update_icon() + ..() + icon_state = initial(icon_state) /* * Premade paper */ diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index 6656eefcdf1..08cb7b6555e 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -79,8 +79,8 @@ if(istype(P, /obj/item/lighter/zippo)) class = "" - user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like \he's trying to burn it!", \ - "[class]You hold \the [P] up to \the [src], burning it slowly.") + user.visible_message("[class][user] holds [P] up to [src], it looks like [user.p_theyre()] trying to burn it!", \ + "[class]You hold [P] up to [src], burning it slowly.") spawn(20) if(get_dist(src, user) < 2 && user.get_active_hand() == P && P.lit) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 1c4c0b357cc..fbbfacb0b8f 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -33,7 +33,7 @@ /obj/item/paperplane/suicide_act(mob/living/user) user.Stun(10) - user.visible_message("[user] jams [name] in \his nose. It looks like \he's trying to commit suicide!") + user.visible_message("[user] jams [name] in [user.p_their()] nose. It looks like [user.p_theyre()] trying to commit suicide!") user.EyeBlurry(6) var/obj/item/organ/internal/eyes/E = user.get_int_organ(/obj/item/organ/internal/eyes) if(E) @@ -73,7 +73,7 @@ else if(is_hot(P)) if(user.disabilities & CLUMSY && prob(10)) - user.visible_message("[user] accidentally ignites themselves!", \ + user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ "You miss [src] and accidentally light yourself on fire!") user.unEquip(P) user.adjust_fire_stacks(1) diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index b4446f67e0e..4e3aaefd1eb 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -25,7 +25,7 @@ pressure_resistance = 2 /obj/item/pen/suicide_act(mob/user) - to_chat(viewers(user), "[user] starts scribbling numbers over \himself with the [src.name]! It looks like \he's trying to commit sudoku.") + to_chat(viewers(user), "[user] starts scribbling numbers over [user.p_them()]self with the [name]! It looks like [user.p_theyre()] trying to commit sudoku.") return (BRUTELOSS) /obj/item/pen/blue diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 0d176753ad4..ed5b7c1cfd4 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -260,7 +260,7 @@ emag_cooldown = world.time + EMAG_DELAY if(ishuman(ass)) //Suit checks are in check_ass var/mob/living/carbon/human/H = ass - temp_img = icon('icons/obj/butts.dmi', H.species.butt_sprite) + temp_img = icon('icons/obj/butts.dmi', H.dna.species.butt_sprite) else if(istype(ass,/mob/living/silicon/robot/drone)) temp_img = icon('icons/obj/butts.dmi', "drone") else if(istype(ass,/mob/living/simple_animal/diona)) @@ -316,11 +316,11 @@ return src.add_fingerprint(user) if(target == user && !user.incapacitated()) - visible_message("[usr] jumps onto the photocopier!") + visible_message("[usr] jumps onto [src]!") else if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis) if(target.anchored) return if(!ishuman(user)) return - visible_message("[usr] drags [target.name] onto the photocopier!") + visible_message("[usr] drags [target.name] onto [src]!") target.forceMove(get_turf(src)) ass = target if(copyitem) @@ -344,9 +344,9 @@ /obj/machinery/photocopier/emag_act(user as mob) if(!emagged) emagged = 1 - to_chat(user, "You overload the photocopier's laser printing mechanism.") + to_chat(user, "You overload [src]'s laser printing mechanism.") else - to_chat(user, "The photocopier's laser printing mechanism is already overloaded!") + to_chat(user, "[src]'s laser printing mechanism is already overloaded!") /obj/item/toner name = "toner cartridge" diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 0ab4db844e9..40759ab792c 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -56,8 +56,8 @@ if(istype(P, /obj/item/lighter/zippo)) class = "" - user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like \he's trying to burn it!", \ - "[class]You hold \the [P] up to \the [src], burning it slowly.") + user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like [user.p_theyre()] trying to burn it!", \ + "[class]You hold [P] up to [src], burning it slowly.") spawn(20) if(get_dist(src, user) < 2 && user.get_active_hand() == P && P.lit) diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm index ad67a53cd5b..5a101629c94 100644 --- a/code/modules/paperwork/stamps.dm +++ b/code/modules/paperwork/stamps.dm @@ -14,7 +14,7 @@ attack_verb = list("stamped") /obj/item/stamp/suicide_act(mob/user) - user.visible_message("[user] stamps 'VOID' on \his forehead, then promptly falls over, dead.") + user.visible_message("[user] stamps 'VOID' on [user.p_their()] forehead, then promptly falls over, dead.") return (OXYLOSS) /obj/item/stamp/qm diff --git a/code/modules/pda/PDA.dm b/code/modules/pda/PDA.dm index 703ec2bd628..38422a89528 100755 --- a/code/modules/pda/PDA.dm +++ b/code/modules/pda/PDA.dm @@ -44,7 +44,6 @@ var/global/list/obj/item/pda/PDAs = list() new/datum/data/pda/app/notekeeper, new/datum/data/pda/app/messenger, new/datum/data/pda/app/manifest, - new/datum/data/pda/app/chatroom, new/datum/data/pda/app/atmos_scanner, new/datum/data/pda/utility/scanmode/notes, new/datum/data/pda/utility/flashlight) diff --git a/code/modules/pda/chatroom.dm b/code/modules/pda/chatroom.dm deleted file mode 100644 index ef9027b888c..00000000000 --- a/code/modules/pda/chatroom.dm +++ /dev/null @@ -1,265 +0,0 @@ -var/list/chatrooms = list(new /datum/chatroom("General Discussion")) - -/datum/chatroom - var/name = "Generic Chatroom" - var/list/users = list() - var/list/invites = list() - var/list/logs = list() // chat logs - var/topic = "Discussion" // topic message for the chatroom - var/is_public = 1 - var/announcer = "CyberiadAI" - -/datum/chatroom/New(n) - name = n - -/datum/chatroom/proc/post(user, message, username) - if(!user || !message) - return - - if(!username) - if(istype(user, /datum/data/pda/app/chatroom)) - var/datum/data/pda/app/chatroom/c = user - if(!c.pda.owner) - return - username = c.pda.owner - else - return - - logs += list(list(username = username, message = message)) - - for(var/datum/data/pda/app/chatroom/u in users) - spawn() - if(u.messaging_available() && !u.toff && user != u) - u.notify("Post from [username] in #[name], \"[message]\" (Post)") - -/datum/chatroom/proc/announce(user, message) - post(user, "[message]", announcer) - -/datum/chatroom/proc/login(datum/data/pda/app/chatroom/user) - if(!user || !user.pda.owner) - return 0 - - if(user in users) - return 1 - - if(!is_public && !(user in invites)) - return 0 - - users |= user - announce(user, "[user.pda.owner] has entered #[name].") - return 1 - -/datum/chatroom/proc/logout(datum/data/pda/app/chatroom/user) - if(!user || !user.pda.owner || !(user in users)) - return - - users -= user - invites -= user - announce(user, "[user.pda.owner] has left #[name].") - -/datum/data/pda/app/chatroom - name = "Chatbuddy" - icon = "hashtag" - notify_icon = "comments" - template = "pda_chatroom" - var/toff = 0 - var/datum/chatroom/current_room = null - var/inviting = 0 - var/channels_created = 0 - var/max_channels_created = 3 - var/latest_post = 0 - var/auto_scroll = 1 - var/disconnected = 0 - -/datum/data/pda/app/chatroom/Destroy() - for(var/C in chatrooms) - var/datum/chatroom/ch = C - if(src in ch.users) - ch.users -= src - if(src in ch.invites) - ch.invites -= src - return ..() - -/datum/data/pda/app/chatroom/start() - . = ..() - unnotify() - latest_post = 0 - -/datum/data/pda/app/chatroom/update_ui(mob/user as mob, list/data) - data["silent"] = notify_silent - data["toff"] = toff - if(disconnected || !messaging_available(1)) - data["no_server"] = 1 - has_back = 0 - else if(current_room) - data["room"] = current_room.name - data["topic"] = current_room.topic - if(inviting) - data["inviting"] = 1 - var/list/pdas = list() - for(var/A in PDAs) - var/obj/item/pda/P = A - var/datum/data/pda/app/chatroom/C = P.find_program(/datum/data/pda/app/chatroom) - var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) - - if(!P.owner || P == pda || PM.m_hidden || (C in current_room.invites) || (C in current_room.users)) - continue - pdas += list(list(name = "[P.owner] ([P.ownjob])", ref = "\ref[C]")) - data["people"] = pdas - else - data["history"] = current_room.logs - var/list/users[0] - for(var/U in current_room.users) - var/datum/data/pda/app/chatroom/ch = U - users += "[ch.pda.owner]" - for(var/U in (current_room.invites - current_room.users)) - var/datum/data/pda/app/chatroom/ch = U - users += "[ch.pda.owner]" - data["users"] = users - data["auto_scroll"] = auto_scroll - data["latest_post"] = latest_post - latest_post = current_room.logs.len - has_back = 1 - else - var/list/rooms[0] - for(var/datum/chatroom/c in chatrooms) - if((src in c.users) || (src in c.invites) || c.is_public) - rooms += list(list(name = "[c]", ref = "\ref[c]")) - data["rooms"] = rooms - has_back = 0 - -/datum/data/pda/app/chatroom/proc/messaging_available(cheap = 0) - . = 0 - if(message_servers) - for(var/A in message_servers) - var/obj/machinery/message_server/MS = A - if(MS.active) - . = cheap || pda.test_telecomms() - disconnected = !. - -/datum/data/pda/app/chatroom/proc/check_messaging_available() - . = messaging_available() - if(!.) - to_chat(usr, "ERROR: Messaging server is not responding.") - -/datum/data/pda/app/chatroom/Topic(href, list/href_list) - if(!pda.can_use()) - return - unnotify() - - switch(href_list["choice"]) - if("Toggle Chatroom") - toff = !toff - if("Toggle Ringer") - notify_silent = !notify_silent - if("Back") - if(inviting) - inviting = 0 - else - current_room = null - latest_post = 0 - if("Join") - if(href_list["room"]) - current_room = locate(href_list["room"]) - if(!(src in current_room.users)) - if(!current_room.login(src)) - current_room = null - latest_post = 0 - if("Post") - var/datum/chatroom/target - if(href_list["target"]) - target = locate(href_list["target"]) - else - target = current_room - - if(!target) - return - - var/t = input("Please enter message", target) as text|null - spawn() - if(!t || !check_messaging_available()) - return - t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) - t = readd_quotes(t) - if(!t || !pda.can_use()) - return - - target.post(src, t) - if("Topic") - if(!current_room) - return - - var/t = input("Enter new topic:", current_room, current_room.topic) as text|null - spawn() - if(!t || !check_messaging_available() || !pda.can_use()) - return - t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) - t = readd_quotes(t) - if(!t) - return - - current_room.topic = t - current_room.announce(src, "Topic has been changed to '[t]' by [pda.owner].") - if("Leave") - if(!current_room) - return - - current_room.logout(src) - current_room = null - latest_post = 0 - if("Invite") - if(!current_room) - return - - inviting = 1 - if("Invite PDA") - spawn() - if(!check_messaging_available() || !current_room || !href_list["user"]) - return - - var/datum/data/pda/app/chatroom/C = locate(href_list["user"]) - if(C) - current_room.invites |= C - spawn() - if(C.messaging_available() && !C.toff) - C.notify("Invite to #[current_room] (Join)") - if("New Room") - if(channels_created >= max_channels_created) - alert("This PDA has already reached its maximum channels created.", name) - return - - var/t = input("Enter room name:", name) as text|null - if(!t) - return - t = sanitize(copytext(t, 1, MAX_NAME_LEN)) - t = readd_quotes(t) - - var/access = input("Room access?", current_room) as null|anything in list("Public", "Private") - if(!access) - return - - spawn() - if(!t || !check_messaging_available() || !pda.can_use()) - return - - // check if already taken - for(var/datum/chatroom/C in chatrooms) - if(C.name == t) - alert("Channel with that name already exists.", name) - return - - channels_created++ - current_room = new /datum/chatroom(t) - chatrooms += current_room - latest_post = 0 - - current_room.invites |= src - current_room.is_public = access == "Public" - current_room.login(src) - if(!current_room.is_public) - current_room.announce(src, "Users must be invited to join this room.") - if("Autoscroll") - auto_scroll = !auto_scroll - if("Reconnect") - spawn() - messaging_available() \ No newline at end of file diff --git a/code/modules/pda/messenger_plugins.dm b/code/modules/pda/messenger_plugins.dm index 7e228445d3f..2666b82c5df 100644 --- a/code/modules/pda/messenger_plugins.dm +++ b/code/modules/pda/messenger_plugins.dm @@ -35,9 +35,6 @@ if(.) user.show_message("Virus sent!", 1) var/datum/data/pda/app/M = P.find_program(/datum/data/pda/app/messenger) - if(M) - M.notify_silent = 1 - M = P.find_program(/datum/data/pda/app/chatroom) if(M) M.notify_silent = 1 P.ttone = "silence" diff --git a/code/modules/pda/pdas.dm b/code/modules/pda/pdas.dm index a9a4cbb9714..676d193a6d3 100644 --- a/code/modules/pda/pdas.dm +++ b/code/modules/pda/pdas.dm @@ -54,9 +54,6 @@ var/datum/data/pda/app/M = find_program(/datum/data/pda/app/messenger) if(M) M.notify_silent = 1 - M = find_program(/datum/data/pda/app/chatroom) - if(M) - M.notify_silent = 1 /obj/item/pda/heads default_cartridge = /obj/item/cartridge/head @@ -161,9 +158,6 @@ var/datum/data/pda/app/M = find_program(/datum/data/pda/app/messenger) if(M) M.notify_silent = 1 //Quiet in the library! - M = find_program(/datum/data/pda/app/chatroom) - if(M) - M.notify_silent = 1 //Quiet in the library! /obj/item/pda/clear icon_state = "pda-transp" diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 9c3d64ef4fc..3ba1a4b5210 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -682,7 +682,7 @@ else user.put_in_hands(cell) cell.add_fingerprint(user) - cell.updateicon() + cell.update_icon() src.cell = null user.visible_message("[user.name] removes the power cell from [src.name]!", "You remove the power cell.") diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 7580621834f..ae64d5d4d6e 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -501,9 +501,9 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list( /obj/item/stack/cable_coil/suicide_act(mob/user) if(locate(/obj/structure/stool) in user.loc) - user.visible_message("[user] is making a noose with the [name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is making a noose with the [name]! It looks like [user.p_theyre()] trying to commit suicide.") else - user.visible_message("[user] is strangling \himself with the [name]! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is strangling [user.p_them()]self with the [name]! It looks like [user.p_theyre()] trying to commit suicide.") return(OXYLOSS) /obj/item/stack/cable_coil/New(loc, length = MAXCOIL, var/paramcolor = null) @@ -528,7 +528,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list( if(!S) return - if(!(S.status & ORGAN_ROBOT) || user.a_intent != INTENT_HELP || S.open == 2) + if(!S.is_robotic() || user.a_intent != INTENT_HELP || S.open == 2) return ..() if(S.burn_dam) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index f08e008089b..3bc2b5bc39b 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -1,8 +1,64 @@ -// the power cell -// charge from 0 to 100% -// fits in APC to provide backup power +/obj/item/stock_parts/cell + name = "power cell" + desc = "A rechargeable electrochemical power cell." + icon = 'icons/obj/power.dmi' + icon_state = "cell" + item_state = "cell" + origin_tech = "powerstorage=1" + force = 5 + throwforce = 5 + throw_speed = 2 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + var/charge = 0 // note %age conveted to actual charge in New + var/maxcharge = 1000 + materials = list(MAT_METAL = 700, MAT_GLASS = 50) + var/rigged = FALSE // true if rigged to explode + var/chargerate = 100 //how much power is given every tick in a recharger + var/self_recharge = 0 //does it self recharge, over time, or not? + var/ratingdesc = TRUE + var/grown_battery = FALSE // If it's a grown that acts as a battery, add a wire overlay to it. + +/obj/item/stock_parts/cell/New() + ..() + processing_objects.Add(src) + charge = maxcharge + if(ratingdesc) + desc += " This one has a power rating of [DisplayPower(maxcharge)], and you should not swallow it." + update_icon() + +/obj/item/stock_parts/cell/Destroy() + processing_objects.Remove(src) + return ..() + +/obj/item/stock_parts/cell/vv_edit_var(var_name, var_value) + switch(var_name) + if("self_recharge") + if(var_value) + processing_objects.Add(src) + else + processing_objects.Remove(src) + . = ..() + +/obj/item/stock_parts/cell/process() + if(self_recharge) + give(chargerate * 0.25) + else + return PROCESS_KILL + +/obj/item/stock_parts/cell/update_icon() + overlays.Cut() + if(grown_battery) + overlays += image('icons/obj/power.dmi', "grown_wires") + if(charge < 0.01) + return + else if(charge/maxcharge >=0.995) + overlays += "cell-o2" + else + overlays += "cell-o1" + /obj/item/stock_parts/cell/proc/percent() // return % charge of cell - return 100.0*charge/maxcharge + return 100 * charge / maxcharge // use power from a cell /obj/item/stock_parts/cell/proc/use(amount) @@ -20,24 +76,23 @@ explode() return 0 if(maxcharge < amount) - return 0 - var/power_used = min(maxcharge-charge,amount) + amount = maxcharge + var/power_used = min(maxcharge - charge, amount) charge += power_used return power_used /obj/item/stock_parts/cell/examine(mob/user) - if(..(user, 1)) - if(maxcharge <= 2500) - to_chat(user, "[desc]\nThe manufacturer's label states this cell has a power rating of [maxcharge], and that you should not swallow it.\nThe charge meter reads [round(src.percent() )]%.") - else - to_chat(user, "This power cell has an exciting chrome finish, as it is an uber-capacity cell type! It has a power rating of [maxcharge]!\nThe charge meter reads [round(src.percent() )]%.") + ..() + if(rigged) + to_chat(user, "This power cell seems to be faulty!") + else + to_chat(user, "The charge meter reads [round(percent() )]%.") -/obj/item/stock_parts/cell/attack_self(mob/user as mob) - src.add_fingerprint(user) - return +/obj/item/stock_parts/cell/suicide_act(mob/user) + to_chat(viewers(user), "[user] is licking the electrodes of the [src]! It looks like [user.p_theyre()] trying to commit suicide.") + return (FIRELOSS) /obj/item/stock_parts/cell/attackby(obj/item/W, mob/user, params) - ..() if(istype(W, /obj/item/reagent_containers/syringe)) var/obj/item/reagent_containers/syringe/S = W @@ -45,34 +100,29 @@ if(S.reagents.has_reagent("plasma", 5) || S.reagents.has_reagent("plasma_dust", 5)) - rigged = 1 + rigged = TRUE log_admin("LOG: [key_name(user)] injected a power cell with plasma, rigging it to explode.") message_admins("LOG: [key_name_admin(user)] injected a power cell with plasma, rigging it to explode.") S.reagents.clear_reagents() + else + return ..() /obj/item/stock_parts/cell/proc/explode() - var/turf/T = get_turf(src.loc) -/* - * 1000-cell explosion(T, -1, 0, 1, 1) - * 2500-cell explosion(T, -1, 0, 1, 1) - * 10000-cell explosion(T, -1, 1, 3, 3) - * 15000-cell explosion(T, -1, 2, 4, 4) - * */ - if(charge==0) + var/turf/T = get_turf(loc) + if(charge == 0) return var/devastation_range = -1 //round(charge/11000) - var/heavy_impact_range = round(sqrt(charge)/60) - var/light_impact_range = round(sqrt(charge)/30) + var/heavy_impact_range = round(sqrt(charge) / 60) + var/light_impact_range = round(sqrt(charge) / 30) var/flash_range = light_impact_range - if(light_impact_range==0) - rigged = 0 + if(light_impact_range == 0) + rigged = FALSE corrupt() return //explosion(T, 0, 1, 2, 2) - log_admin("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") message_admins("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") @@ -81,70 +131,242 @@ /obj/item/stock_parts/cell/proc/corrupt() charge /= 2 - maxcharge /= 2 + maxcharge = max(maxcharge / 2, chargerate) if(prob(10)) - rigged = 1 //broken batterys are dangerous + rigged = TRUE //broken batterys are dangerous /obj/item/stock_parts/cell/emp_act(severity) charge -= 1000 / severity if(charge < 0) charge = 0 - if(reliability != 100 && prob(50/severity)) - reliability -= 10 / severity ..() /obj/item/stock_parts/cell/ex_act(severity) - switch(severity) - if(1.0) + if(EXPLODE_DEVASTATE) qdel(src) - return - if(2.0) + if(EXPLODE_HEAVY) if(prob(50)) qdel(src) return if(prob(50)) corrupt() - if(3.0) + if(EXPLODE_LIGHT) if(prob(25)) qdel(src) return if(prob(25)) corrupt() - return /obj/item/stock_parts/cell/blob_act() - ex_act(1) + ex_act(EXPLODE_DEVASTATE) /obj/item/stock_parts/cell/proc/get_electrocute_damage() switch(charge) -/* if(9000 to INFINITY) - return min(rand(90,150),rand(90,150)) - if(2500 to 9000-1) - return min(rand(70,145),rand(70,145)) - if(1750 to 2500-1) - return min(rand(35,110),rand(35,110)) - if(1500 to 1750-1) - return min(rand(30,100),rand(30,100)) - if(750 to 1500-1) - return min(rand(25,90),rand(25,90)) - if(250 to 750-1) - return min(rand(20,80),rand(20,80)) - if(100 to 250-1) - return min(rand(20,65),rand(20,65))*/ if(5000000 to INFINITY) - return min(rand(200,300),rand(200,300)) - if(4000000 to 5000000-1) - return min(rand(80,180),rand(80,180)) - if(1000000 to 4000000-1) - return min(rand(50,160),rand(50,160)) - if(200000 to 1000000-1) - return min(rand(25,80),rand(25,80)) - if(100000 to 200000-1)//Ave powernet - return min(rand(20,60),rand(20,60)) - if(50000 to 100000-1) - return min(rand(15,40),rand(15,40)) - if(1000 to 50000-1) - return min(rand(10,20),rand(10,20)) + return min(rand(200, 300),rand(200, 300)) + if(4000000 to 5000000 - 1) + return min(rand(80, 180),rand(80, 180)) + if(1000000 to 4000000 - 1) + return min(rand(50, 160),rand(50, 160)) + if(200000 to 1000000 - 1) + return min(rand(25, 80),rand(25, 80)) + if(100000 to 200000 - 1)//Ave powernet + return min(rand(20, 60),rand(20, 60)) + if(50000 to 100000 - 1) + return min(rand(15, 40),rand(15, 40)) + if(1000 to 50000 - 1) + return min(rand(10, 20),rand(10, 20)) else return 0 + +// Cell variants +/obj/item/stock_parts/cell/empty/New() + ..() + charge = 0 + +/obj/item/stock_parts/cell/crap + name = "\improper Nanotrasen brand rechargeable AA battery" + desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT + maxcharge = 500 + materials = list(MAT_GLASS = 40) + rating = 2 + +/obj/item/stock_parts/cell/crap/empty/New() + ..() + charge = 0 + update_icon() + +/obj/item/stock_parts/cell/upgraded + name = "upgraded power cell" + desc = "A power cell with a slightly higher capacity than normal!" + maxcharge = 2500 + materials = list(MAT_GLASS = 50) + rating = 2 + chargerate = 1000 + +/obj/item/stock_parts/cell/upgraded/plus + name = "upgraded power cell+" + desc = "A power cell with an even higher capacity than the base model!" + maxcharge = 5000 + +/obj/item/stock_parts/cell/secborg + name = "security borg rechargeable D battery" + origin_tech = null + maxcharge = 600 //600 max charge / 100 charge per shot = six shots + materials = list(MAT_GLASS = 40) + rating = 2.5 + +/obj/item/stock_parts/cell/secborg/empty/New() + ..() + charge = 0 + update_icon() + +/obj/item/stock_parts/cell/pulse //200 pulse shots + name = "pulse rifle power cell" + maxcharge = 40000 + rating = 3 + chargerate = 1500 + +/obj/item/stock_parts/cell/pulse/carbine //25 pulse shots + name = "pulse carbine power cell" + maxcharge = 5000 + +/obj/item/stock_parts/cell/pulse/pistol //10 pulse shots + name = "pulse pistol power cell" + maxcharge = 2000 + +/obj/item/stock_parts/cell/high + name = "high-capacity power cell" + origin_tech = "powerstorage=2" + icon_state = "hcell" + maxcharge = 10000 + materials = list(MAT_GLASS = 60) + rating = 3 + chargerate = 1500 + +/obj/item/stock_parts/cell/high/plus + name = "high-capacity power cell+" + desc = "Where did these come from?" + icon_state = "h+cell" + maxcharge = 15000 + chargerate = 2250 + +/obj/item/stock_parts/cell/high/empty/New() + ..() + charge = 0 + update_icon() + +/obj/item/stock_parts/cell/super + name = "super-capacity power cell" + origin_tech = "powerstorage=3;materials=3" + icon_state = "scell" + maxcharge = 20000 + materials = list(MAT_GLASS = 300) + rating = 4 + chargerate = 2000 + +/obj/item/stock_parts/cell/super/empty/New() + ..() + charge = 0 + update_icon() + +/obj/item/stock_parts/cell/hyper + name = "hyper-capacity power cell" + origin_tech = "powerstorage=4;engineering=4;materials=4" + icon_state = "hpcell" + maxcharge = 30000 + materials = list(MAT_GLASS = 400) + rating = 5 + chargerate = 3000 + +/obj/item/stock_parts/cell/hyper/empty/New() + ..() + charge = 0 + update_icon() + +/obj/item/stock_parts/cell/bluespace + name = "bluespace power cell" + desc = "A rechargeable transdimensional power cell." + origin_tech = "powerstorage=5;bluespace=4;materials=4;engineering=4" + icon_state = "bscell" + maxcharge = 40000 + materials = list(MAT_GLASS = 600) + rating = 6 + chargerate = 4000 + +/obj/item/stock_parts/cell/bluespace/empty/New() + ..() + charge = 0 + update_icon() + +/obj/item/stock_parts/cell/infinite + name = "infinite-capacity power cell!" + icon_state = "icell" + origin_tech = "powerstorage=7" + maxcharge = 30000 + materials = list(MAT_GLASS=1000) + rating = 6 + chargerate = 30000 + +/obj/item/stock_parts/cell/infinite/use() + return 1 + +/obj/item/stock_parts/cell/infinite/abductor + name = "void core" + desc = "An alien power cell that produces energy seemingly out of nowhere." + icon = 'icons/obj/abductor.dmi' + icon_state = "cell" + maxcharge = 50000 + rating = 12 + ratingdesc = FALSE + +/obj/item/stock_parts/cell/infinite/abductor/update_icon() + return + + +/obj/item/stock_parts/cell/potato + name = "potato battery" + desc = "A rechargeable starch based power cell." + icon = 'icons/obj/hydroponics/harvest.dmi' + icon_state = "potato" + origin_tech = "powerstorage=1;biotech=1" + charge = 100 + maxcharge = 300 + materials = list() + rating = 1 + grown_battery = TRUE //it has the overlays for wires + +/obj/item/stock_parts/cell/high/slime + name = "charged slime core" + desc = "A yellow slime core infused with plasma, it crackles with power." + origin_tech = "powerstorage=5;biotech=4" + icon = 'icons/mob/slimes.dmi' + icon_state = "yellow slime extract" + materials = list() + rating = 5 //self-recharge makes these desirable + self_recharge = 1 // Infused slime cores self-recharge, over time + chargerate = 500 + +/obj/item/stock_parts/cell/emproof + name = "\improper EMP-proof cell" + desc = "An EMP-proof cell." + maxcharge = 500 + rating = 3 + +/obj/item/stock_parts/cell/emproof/empty/New() + ..() + charge = 0 + update_icon() + +/obj/item/stock_parts/cell/emproof/emp_act(severity) + return + +/obj/item/stock_parts/cell/emproof/corrupt() + return + +/obj/item/stock_parts/cell/ninja + name = "spider-clan power cell" + desc = "A standard ninja-suit power cell." + maxcharge = 10000 + materials = list(MAT_GLASS = 60) \ No newline at end of file diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 3eac3486791..df12267015f 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -726,7 +726,7 @@ update() /obj/item/light/suicide_act(mob/living/carbon/human/user) - user.visible_message("[user] touches \the [src], burning their hands off!", "You touch \the [src], burning your hands off!") + user.visible_message("[user] touches [src], burning [user.p_their()] hands off!", "You touch [src], burning your hands off!") for(var/oname in list("l_hand", "r_hand")) var/obj/item/organ/external/limb = user.get_organ(oname) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 70cd75bf85d..a6c86d3f2ef 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -121,7 +121,7 @@ if(radio_controller) radio_controller.remove_object(src, frequency) radio_connection = null - msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", 0, 1) + msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", ATKLOG_FEW) log_game("Emitter deleted at ([x],[y],[z])") investigate_log("deleted at ([x],[y],[z])","singulo") return ..() diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 9a911400fd5..0520630dcac 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -10,6 +10,7 @@ move_self = 1 //Do we move on our own? grav_pull = 5 //How many tiles out do we pull? consume_range = 6 //How many tiles out do we eat + gender = FEMALE /obj/singularity/narsie/large name = "Nar-Sie" diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index b8570de2c78..42fbb784f49 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -227,7 +227,7 @@ active = !active investigate_log("turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]","singulo") if(active) - msg_admin_attack("PA Control Computer turned ON by [key_name_admin(usr)]",0,1) + msg_admin_attack("PA Control Computer turned ON by [key_name_admin(usr)]", ATKLOG_FEW) log_game("PA Control Computer turned ON by [key_name(usr)] in ([x],[y],[z])") use_log += text("\[[time_stamp()]\] [key_name(usr)] has turned on the PA Control Computer.") if(active) diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index e69abc5b00f..e5a669ef860 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -13,6 +13,7 @@ icon_state = "smes" density = 1 anchored = 1 + defer_process = 1 var/capacity = 5e6 // maximum charge var/charge = 0 // actual charge @@ -39,7 +40,6 @@ var/building_terminal = 0 //Suggestions about how to avoid clickspam building several terminals accepted! var/obj/machinery/power/terminal/terminal = null - /obj/machinery/power/smes/New() ..() component_parts = list() @@ -224,8 +224,6 @@ /obj/machinery/power/smes/proc/chargedisplay() return round(5.5*charge/(capacity ? capacity : 5e6)) -#define SMESRATE 0.05 - /obj/machinery/power/smes/process() if(stat & BROKEN) return diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index be17b3f65db..125706bff28 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -1,21 +1,33 @@ -//Ported from /vg/station13, which was in turn forked from baystation12; -//Please do not bother them with bugs from this port, however, as it has been modified quite a bit. -//Modifications include removing the world-ending full supermatter variation, and leaving only the shard. +#define NITROGEN_RETARDATION_FACTOR 0.15 //Higher == N2 slows reaction more +#define THERMAL_RELEASE_MODIFIER 10000 //Higher == more heat released during reaction +#define PLASMA_RELEASE_MODIFIER 1500 //Higher == less phor.. plasma released by reaction +#define OXYGEN_RELEASE_MODIFIER 15000 //Higher == less oxygen released at high temperature/power +#define REACTION_POWER_MODIFIER 1.1 //Higher == more overall power -#define NITROGEN_RETARDATION_FACTOR 2 //Higher == N2 slows reaction more -#define THERMAL_RELEASE_MODIFIER 5 //Higher == less heat released during reaction -#define PLASMA_RELEASE_MODIFIER 750 //Higher == less plasma released by reaction -#define OXYGEN_RELEASE_MODIFIER 325 //Higher == less oxygen released at high temperature/power -#define REACTION_POWER_MODIFIER 0.55 //Higher == more overall power +/* + How to tweak the SM + POWER_FACTOR directly controls how much power the SM puts out at a given level of excitation (power var). Making this lower means you have to work the SM harder to get the same amount of power. + CRITICAL_TEMPERATURE The temperature at which the SM starts taking damage. + CHARGING_FACTOR Controls how much emitter shots excite the SM. + DAMAGE_RATE_LIMIT Controls the maximum rate at which the SM will take damage due to high temperatures. +*/ + +//Controls how much power is produced by each collector in range - this is the main parameter for tweaking SM balance, as it basically controls how the power variable relates to the rest of the game. +#define POWER_FACTOR 1.0 +#define DECAY_FACTOR 700 //Affects how fast the supermatter power decays +#define CRITICAL_TEMPERATURE 10000 //K +#define CHARGING_FACTOR 0.05 +#define DAMAGE_RATE_LIMIT 4.5 //damage rate cap at power = 300, scales linearly with power -//These would be what you would get at point blank, decreases with distance +// Base variants are applied to everyone on the same Z level +// Range variants are applied on per-range basis: numbers here are on point blank, it scales with the map size (assumes square shaped Z levels) #define DETONATION_RADS 200 #define DETONATION_HALLUCINATION 600 -#define WARNING_DELAY 30 //seconds between warnings. +#define WARNING_DELAY 20 //seconds between warnings. /obj/machinery/power/supermatter_shard name = "supermatter shard" desc = "A strangely translucent and iridescent crystal that looks like it used to be part of a larger structure. You get headaches just from looking at it." @@ -35,15 +47,16 @@ var/safe_alert = "Crystalline hyperstructure returning to safe operating levels." var/warning_point = 50 var/warning_alert = "Danger! Crystal hyperstructure instability!" - var/emergency_point = 500 + var/emergency_point = 400 var/emergency_alert = "CRYSTAL DELAMINATION IMMINENT." - var/explosion_point = 900 + var/explosion_point = 600 var/emergency_issued = 0 var/explosion_power = 8 var/lastwarning = 0 // Time in 1/10th of seconds since the last sent warning + var/last_zap = 0 // Time in 1/10th of seconds since the last tesla zap var/power = 0 var/oxygen = 0 // Moving this up here for easier debugging. @@ -51,38 +64,90 @@ //Temporary values so that we can optimize this //How much the bullets damage should be multiplied by when it is added to the internal variables var/config_bullet_energy = 2 - //How much of the power is left after processing is finished? -// var/config_power_reduction_per_tick = 0.5 //How much hallucination should it produce per unit of power? var/config_hallucination_power = 0.1 + var/debug = 0 + + var/disable_adminwarn = FALSE + + var/aw_normal = FALSE + var/aw_notify = FALSE + var/aw_warning = FALSE + var/aw_danger = FALSE + var/aw_emerg = FALSE + var/aw_delam = FALSE + var/obj/item/radio/radio //for logging var/has_been_powered = 0 var/has_reached_emergency = 0 +/obj/machinery/power/supermatter_shard/crystal + name = "supermatter crystal" + desc = "A strangely translucent and iridescent crystal." + base_icon_state = "darkmatter" + icon_state = "darkmatter" + anchored = TRUE + warning_point = 200 + emergency_point = 2000 + explosion_point = 3600 + gasefficency = 0.25 + explosion_power = 24 + + /obj/machinery/power/supermatter_shard/New() . = ..() poi_list |= src + //Added to the atmos_machine process as the SM is highly coupled with the atmospherics system. + //Having the SM run at a different rate then atmospherics causes odd behavior. + SSair.atmos_machinery += src radio = new(src) radio.listening = 0 investigate_log("has been created.", "supermatter") +/obj/machinery/power/supermatter_shard/proc/handle_admin_warnings() + if(disable_adminwarn) + return + + // Generic checks, similar to checks done by supermatter monitor program. + aw_normal = status_adminwarn_check(SUPERMATTER_NORMAL, aw_normal, "INFO: Supermatter crystal has been energised.(JMP).", FALSE) + aw_notify = status_adminwarn_check(SUPERMATTER_NOTIFY, aw_notify, "INFO: Supermatter crystal is approaching unsafe operating temperature.(JMP).", FALSE) + aw_warning = status_adminwarn_check(SUPERMATTER_WARNING, aw_warning, "WARN: Supermatter crystal is taking integrity damage!(JMP).", FALSE) + aw_danger = status_adminwarn_check(SUPERMATTER_DANGER, aw_danger, "WARN: Supermatter integrity is below 75%!(JMP).", TRUE) + aw_emerg = status_adminwarn_check(SUPERMATTER_EMERGENCY, aw_emerg, "CRIT: Supermatter integrity is below 50%!(JMP).", FALSE) + aw_delam = status_adminwarn_check(SUPERMATTER_DELAMINATING, aw_delam, "CRIT: Supermatter is delaminating!(JMP).", TRUE) + +/obj/machinery/power/supermatter_shard/proc/status_adminwarn_check(var/min_status, var/current_state, var/message, var/send_to_irc = FALSE) + var/status = get_status() + if(status >= min_status) + if(!current_state) + log_and_message_admins(message) + if(send_to_irc) + send2adminirc(message) + return TRUE + else + return FALSE + + /obj/machinery/power/supermatter_shard/Destroy() investigate_log("has been destroyed.", "supermatter") + if(damage > emergency_point) + emergency_lighting(0) QDEL_NULL(radio) poi_list.Remove(src) + SSair.atmos_machinery -= src return ..() /obj/machinery/power/supermatter_shard/proc/explode() investigate_log("has exploded.", "supermatter") - explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1) + explosion(get_turf(src), explosion_power, explosion_power * 1.2, explosion_power * 1.5, explosion_power * 2, 1, 1) qdel(src) return -/obj/machinery/power/supermatter_shard/process() +/obj/machinery/power/supermatter_shard/process_atmos() var/turf/L = loc if(isnull(L)) // We have a null turf...something is wrong, stop processing this entity. @@ -91,11 +156,10 @@ if(!istype(L)) //We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now. return //Yeah just stop. - if(istype(L, /turf/space)) // Stop processing this stuff if we've been ejected. - return - if(damage > warning_point) // while the core is still damaged and it's still worth noting its status if((world.timeofday - lastwarning) / 10 >= WARNING_DELAY) + alarm() + emergency_lighting(1) var/stability = num2text(round((damage / explosion_point) * 100)) if(damage > emergency_point) @@ -112,6 +176,7 @@ else // Phew, we're safe radio.autosay("[safe_alert]", src.name) + emergency_lighting(0) lastwarning = world.timeofday if(damage > explosion_point) @@ -128,6 +193,11 @@ mob.apply_effect(rads, IRRADIATE) explode() + emergency_lighting(0) + + if(damage > warning_point && world.timeofday > last_zap) + last_zap = world.timeofday + rand(80,200) + supermatter_zap() //Ok, get the air from the turf var/datum/gas_mixture/env = L.return_air() @@ -135,52 +205,57 @@ //Remove gas from surrounding area var/datum/gas_mixture/removed = env.remove(gasefficency * env.total_moles()) - if(!removed || !removed.total_moles()) - damage += max((power-1600)/10, 0) - power = min(power, 1600) - return 1 + //ensure that damage doesn't increase too quickly due to super high temperatures resulting from no coolant, for example. We dont want the SM exploding before anyone can react. + //We want the cap to scale linearly with power (and explosion_point). Let's aim for a cap of 5 at power = 300 (based on testing, equals roughly 5% per SM alert announcement). + var/damage_inc_limit = (power/300)*(explosion_point/1000)*DAMAGE_RATE_LIMIT + + if(!env || !removed || !removed.total_moles()) + damage += max((power - 15*POWER_FACTOR)/10, 0) + else + damage_archived = damage + + damage = max(0, damage + between(-DAMAGE_RATE_LIMIT, (removed.temperature - CRITICAL_TEMPERATURE) / 150, damage_inc_limit)) - damage_archived = damage - damage = max( damage + ( (removed.temperature - 800) / 150 ) , 0 ) - //Ok, 100% oxygen atmosphere = best reaction //Maxes out at 100% oxygen pressure - oxygen = max(min((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / MOLES_CELLSTANDARD, 1), 0) - - var/temp_factor = 50 + oxygen = Clamp((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / removed.total_moles(), 0, 1) + var/temp_factor + var/equilibrium_power if(oxygen > 0.8) - // with a perfect gas mix, make the power less based on heat + //If chain reacting at oxygen > 0.8, we want the power at 800 K to stabilize at a power level of 400 + equilibrium_power = 400 icon_state = "[base_icon_state]_glow" else - // in normal mode, base the produced energy around the heat - temp_factor = 30 + //Otherwise, we want the power at 800 K to stabilize at a power level of 250 + equilibrium_power = 250 icon_state = base_icon_state - power = max( (removed.temperature * temp_factor / T0C) * oxygen + power, 0) //Total laser power plus an overload - - //We've generated power, now let's transfer it to the collectors for storing/usage - transfer_energy() + temp_factor = ((equilibrium_power / DECAY_FACTOR) ** 3) / 800 + power = max((removed.temperature * temp_factor) * oxygen + power, 0) var/device_energy = power * REACTION_POWER_MODIFIER - //To figure out how much temperature to add each tick, consider that at one atmosphere's worth - //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature - //that the device energy is around 2140. At that stage, we don't want too much heat to be put out - //Since the core is effectively "cold" + var/heat_capacity = removed.heat_capacity() - //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock - //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall. - removed.temperature += (device_energy / THERMAL_RELEASE_MODIFIER) - - removed.temperature = max(0, min(removed.temperature, 2500)) - - //Calculate how much gas to release removed.toxins += max(device_energy / PLASMA_RELEASE_MODIFIER, 0) removed.oxygen += max((device_energy + removed.temperature - T0C) / OXYGEN_RELEASE_MODIFIER, 0) + var/thermal_power = THERMAL_RELEASE_MODIFIER * device_energy + if(debug) + var/heat_capacity_new = removed.heat_capacity() + visible_message("[src]: Releasing [round(thermal_power)] W.") + visible_message("[src]: Releasing additional [round((heat_capacity_new - heat_capacity)*removed.temperature)] W with exhaust gasses.") + + removed.temperature += (device_energy) + + removed.temperature = max(0, min(removed.temperature, 10000)) + env.merge(removed) + air_update_turf() + transfer_energy() + for(var/mob/living/carbon/human/l in view(src, min(7, round(sqrt(power/6))))) // If they can see it without mesons on. Bad on them. if(l.glasses && istype(l.glasses, /obj/item/clothing/glasses/meson)) @@ -196,7 +271,8 @@ var/rads = (power / 10) * sqrt( 1 / max(get_dist(l, src),1) ) l.apply_effect(rads, IRRADIATE) - power -= (power/500)**3 + power -= (power/DECAY_FACTOR)**3 + handle_admin_warnings() return 1 @@ -217,12 +293,13 @@ has_been_powered = 1 else damage += Proj.damage * config_bullet_energy + supermatter_zap() return 0 /obj/machinery/power/supermatter_shard/singularity_act() var/gain = 100 investigate_log("Supermatter shard consumed by singularity.","singulo") - message_admins("Singularity has consumed a supermatter shard and can now become stage six.") + message_admins("Singularity has consumed a supermatter shard and can now become stage six.(JMP).") visible_message("[src] is consumed by the singularity!") for(var/mob/M in mob_list) M << 'sound/effects/supermatter.ogg' //everyone gunna know bout this @@ -244,7 +321,7 @@ ui_interact(user) /obj/machinery/power/supermatter_shard/attack_hand(mob/user as mob) - user.visible_message("\The [user] reaches out and touches \the [src], inducing a resonance... \his body starts to glow and bursts into flames before flashing into ash.",\ + user.visible_message("\The [user] reaches out and touches \the [src], inducing a resonance... [user.p_their(TRUE)] body starts to glow and bursts into flames before flashing into ash.",\ "You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"",\ "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.") @@ -306,10 +383,9 @@ user.apply_effect(150, IRRADIATE) - /obj/machinery/power/supermatter_shard/Bumped(atom/AM as mob|obj) if(istype(AM, /mob/living)) - AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... \his body starts to glow and catch flame before flashing into ash.",\ + AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... [AM.p_their(TRUE)] body starts to glow and catch flame before flashing into ash.",\ "You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\ "You hear an unearthly noise as a wave of heat washes over you.") else if(isobj(AM) && !istype(AM, /obj/effect)) @@ -335,6 +411,8 @@ qdel(AM) power += 200 + supermatter_zap() + //Some poor sod got eaten, go ahead and irradiate people nearby. for(var/mob/living/L in range(10)) @@ -346,3 +424,51 @@ "The unearthly ringing subsides and you notice you have new radiation burns.", 2) else L.show_message("You hear an uneartly ringing and notice your skin is covered in fresh radiation burns.", 2) + +/obj/machinery/power/supermatter_shard/proc/get_status() + var/turf/T = get_turf(src) + if(!T) + return SUPERMATTER_ERROR + var/datum/gas_mixture/air = T.return_air() + if(!air) + return SUPERMATTER_ERROR + + if(get_integrity() < 25) + return SUPERMATTER_DELAMINATING + + if(get_integrity() < 50) + return SUPERMATTER_EMERGENCY + + if(get_integrity() < 75) + return SUPERMATTER_DANGER + + if((get_integrity() < 100) || (air.temperature > CRITICAL_TEMPERATURE)) + return SUPERMATTER_WARNING + + if(air.temperature > (CRITICAL_TEMPERATURE * 0.8)) + return SUPERMATTER_NOTIFY + + if(power > 5) + return SUPERMATTER_NORMAL + return SUPERMATTER_INACTIVE + +/obj/machinery/power/supermatter_shard/proc/alarm() + switch(get_status()) + if(SUPERMATTER_DELAMINATING) + playsound(src, 'sound/misc/bloblarm.ogg', 100) + if(SUPERMATTER_EMERGENCY) + playsound(src, 'sound/machines/engine_alert1.ogg', 100) + if(SUPERMATTER_DANGER) + playsound(src, 'sound/machines/engine_alert2.ogg', 100) + if(SUPERMATTER_WARNING) + playsound(src, 'sound/machines/terminal_alert.ogg', 75) + +/obj/machinery/power/supermatter_shard/proc/emergency_lighting(active) + if(active) + post_status("alert", "radiation") + else + post_status("shuttle") + +/obj/machinery/power/supermatter_shard/proc/supermatter_zap() + playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5) + tesla_zap(src, 10, max(1000,power * damage / explosion_point)) diff --git a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm index 11873b5acdf..3e43c5638d1 100644 --- a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm +++ b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm @@ -38,4 +38,4 @@ if(get_step(T,direction) in mother.map) continue return 1 - return 0 \ No newline at end of file + return 0 diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 6ad60248a28..24b77ee9bb5 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -119,6 +119,9 @@ ammo_type = /obj/item/ammo_casing/shotgun/rubbershot max_ammo = 6 +/obj/item/ammo_box/magazine/internal/shot/riot/short + max_ammo = 3 + /obj/item/ammo_box/magazine/internal/grenadelauncher name = "grenade launcher internal magazine" ammo_type = /obj/item/ammo_casing/a40mm @@ -198,13 +201,6 @@ desc= "A gun magazine. Loaded with rounds which penetrate armour, but are less effective against normal targets" ammo_type = /obj/item/ammo_casing/c10mm/ap -/obj/item/ammo_box/magazine/m10mm/empty //for maint drops - desc = "A gun magazine. Seems to be broken and can only hold one bullet. Pretty useless." - max_ammo = 1 - -/obj/item/ammo_box/magazine/m10mm/empty/update_icon() - icon_state = "[initial(icon_state)]-[stored_ammo.len ? "8" : "0"]" - /obj/item/ammo_box/magazine/m45 name = "handgun magazine (.45)" icon_state = "45" diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index b54d5bff21f..165e75f1875 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -153,10 +153,10 @@ process_fire(target,user,1,params) -/obj/item/gun/proc/can_trigger_gun(var/mob/living/user) +/obj/item/gun/proc/can_trigger_gun(mob/living/user) if(!user.can_use_guns(src)) return 0 - if(restricted_species && restricted_species.len && !(user.get_species() in restricted_species)) + if(restricted_species && restricted_species.len && !is_type_in_list(user.dna.species, restricted_species)) to_chat(user, "[src] is incompatible with your biology!") return 0 return 1 @@ -347,7 +347,7 @@ obj/item/gun/proc/newshot() return if(user == target) - target.visible_message("[user] sticks [src] in their mouth, ready to pull the trigger...", \ + target.visible_message("[user] sticks [src] in [user.p_their()] mouth, ready to pull the trigger...", \ "You stick [src] in your mouth, ready to pull the trigger...") else target.visible_message("[user] points [src] at [target]'s head, ready to pull the trigger...", \ diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm index 7093d587b3c..95e1a586469 100644 --- a/code/modules/projectiles/guns/alien.dm +++ b/code/modules/projectiles/guns/alien.dm @@ -11,7 +11,7 @@ can_suppress = 0 var/charge_tick = 0 var/charge_delay = 15 - restricted_species = list("Vox", "Vox Armalis") + restricted_species = list(/datum/species/vox) /obj/item/gun/projectile/automatic/spikethrower/New() ..() @@ -79,7 +79,7 @@ force = 10 ammo_type = list(/obj/item/ammo_casing/energy/sonic) cell_type = /obj/item/stock_parts/cell/super - restricted_species = list("Vox Armalis") + restricted_species = list(/datum/species/vox/armalis) /obj/item/gun/energy/noisecannon/update_icon() return diff --git a/code/modules/projectiles/guns/dartgun.dm b/code/modules/projectiles/guns/dartgun.dm index 5ae089d5522..c279abdc5c1 100644 --- a/code/modules/projectiles/guns/dartgun.dm +++ b/code/modules/projectiles/guns/dartgun.dm @@ -178,7 +178,8 @@ else M.LAssailant = user - add_attack_logs(user, M, "Shot with dartgun containing [R]", !!M.ckey) + add_attack_logs(user, M, "Shot with dartgun containing [R]") + if(D.reagents) D.reagents.trans_to(M, 15) to_chat(M, "You feel a slight prick.") diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index fd6c14c4e6b..795b5942845 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -146,10 +146,10 @@ /obj/item/gun/energy/suicide_act(mob/user) if(can_shoot()) - user.visible_message("[user] is putting the barrel of the [name] in \his mouth. It looks like \he's trying to commit suicide.") + user.visible_message("[user] is putting the barrel of the [name] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide.") sleep(25) if(user.l_hand == src || user.r_hand == src) - user.visible_message("[user] melts \his face off with the [name]!") + user.visible_message("[user] melts [user.p_their()] face off with the [name]!") playsound(loc, fire_sound, 50, 1, -1) var/obj/item/ammo_casing/energy/shot = ammo_type[select] power_supply.use(shot.e_cost) @@ -159,7 +159,7 @@ user.visible_message("[user] panics and starts choking to death!") return(OXYLOSS) else - user.visible_message("[user] is pretending to blow \his brains out with the [name]! It looks like \he's trying to commit suicide!") + user.visible_message("[user] is pretending to blow [user.p_their()] brains out with the [name]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/weapons/empty.ogg', 50, 1, -1) return (OXYLOSS) diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index e2067467ddb..7169b3d1443 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -28,7 +28,7 @@ /obj/item/gun/energy/gun/mini name = "miniature energy gun" - desc = "A small, pistol-sized energy gun with a built-in flashlight. It has two settings: stun and kill." + desc = "A small, pistol-sized energy gun with a built-in flashlight. It has two settings: disable and kill." icon_state = "mini" w_class = WEIGHT_CLASS_SMALL ammo_x_offset = 2 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 8965432aac0..1f1a02a78e2 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -128,7 +128,7 @@ /obj/item/gun/energy/kinetic_accelerator/suicide_act(mob/user) if(!suppressed) playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) - user.visible_message("[user] cocks the [name] and pretends to blow \his brains out! It looks like \he's trying to commit suicide!") + user.visible_message("[user] cocks the [name] and pretends to blow [user.p_their()] brains out! It looks like [user.p_theyre()] trying to commit suicide!") shoot_live_shot() return (OXYLOSS) @@ -196,7 +196,7 @@ /obj/item/gun/energy/wormhole_projector/process_chamber() ..() - select_fire() + select_fire(usr) /obj/item/gun/energy/wormhole_projector/proc/portal_destroyed(obj/effect/portal/P) if(P.icon_state == "portal") @@ -342,9 +342,9 @@ user << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x120") onclose(user, "tempgun") -/obj/item/gun/energy/temperature/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/card/emag) && !emagged) - emagged = 1 +/obj/item/gun/energy/temperature/emag_act(mob/user) + if(!emagged) + emagged = TRUE to_chat(user, "You double the gun's temperature cap! Targets hit by searing beams will burst into flames!") desc = "A gun that changes the body temperature of its targets. Its temperature cap has been hacked." diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm index a1840663350..94f397b45bf 100644 --- a/code/modules/projectiles/guns/magic.dm +++ b/code/modules/projectiles/guns/magic.dm @@ -76,6 +76,6 @@ return /obj/item/gun/magic/suicide_act(mob/user) - user.visible_message("[user] is twisting the [name] above \his head, releasing a magical blast! It looks like \he's trying to commit suicide.") + user.visible_message("[user] is twisting the [name] above [user.p_their()] head, releasing a magical blast! It looks like [user.p_theyre()] trying to commit suicide.") playsound(loc, fire_sound, 50, 1, -1) return FIRELOSS diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm index 1a8e5e45946..cae9d11cbb6 100644 --- a/code/modules/projectiles/guns/magic/wand.dm +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -48,9 +48,9 @@ update_icon() /obj/item/gun/magic/wand/proc/zap_self(mob/living/user) - user.visible_message("[user] zaps \himself with [src].") + user.visible_message("[user] zaps [user.p_them()]self with [src].") playsound(user, fire_sound, 50, 1) - user.create_attack_log("[key_name(user)] zapped \himself with a [src]") + user.create_attack_log("[key_name(user)] zapped [user.p_them()]self with a [src]") ///////////////////////////////////// //WAND OF DEATH diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm index f6881208a32..89cceab6cd3 100644 --- a/code/modules/projectiles/guns/misc/blastcannon.dm +++ b/code/modules/projectiles/guns/misc/blastcannon.dm @@ -76,7 +76,7 @@ var/heavy = power * 0.2 var/medium = power * 0.5 var/light = power - user.visible_message("[user] opens [bomb] on \his [name] and fires a blast wave at [target]!","You open [bomb] on your [name] and fire a blast wave at [target]!") + user.visible_message("[user] opens [bomb] on [user.p_their()] [name] and fires a blast wave at [target]!","You open [bomb] on your [name] and fire a blast wave at [target]!") playsound(user, "explosion", 100, 1) var/turf/starting = get_turf(user) var/turf/targturf = get_turf(target) diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 2b8ff6a59f8..0ff5e57e7c5 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -137,17 +137,17 @@ /obj/item/gun/projectile/suicide_act(mob/user) if(chambered && chambered.BB && !chambered.BB.nodamage) - user.visible_message("[user] is putting the barrel of the [name] in \his mouth. It looks like \he's trying to commit suicide.") + user.visible_message("[user] is putting the barrel of the [name] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide.") sleep(25) if(user.l_hand == src || user.r_hand == src) process_fire(user, user, 0, zone_override = "head") - user.visible_message("[user] blows \his brains out with the [name]!") + user.visible_message("[user] blows [user.p_their()] brains out with the [name]!") return(BRUTELOSS) else user.visible_message("[user] panics and starts choking to death!") return(OXYLOSS) else - user.visible_message("[user] is pretending to blow \his brains out with the [name]! It looks like \he's trying to commit suicide!") + user.visible_message("[user] is pretending to blow [user.p_their()] brains out with the [name]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/weapons/empty.ogg', 50, 1, -1) return (OXYLOSS) diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index 103595d7242..7ac82f99d5c 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -26,12 +26,6 @@ mag_type = /obj/item/ammo_box/magazine/m45 can_suppress = 0 -/obj/item/gun/projectile/automatic/pistol/empty //empty stetchshit for maint spawns - -/obj/item/gun/projectile/automatic/pistol/empty/New() - magazine = new /obj/item/ammo_box/magazine/m10mm/empty(src) - ..() - /obj/item/gun/projectile/automatic/pistol/enforcer name = "Enforcer .45" desc = "A pistol of modern design." diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 502c69bed9c..c4c6f76a963 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -244,7 +244,7 @@ if(zone == "head" || zone == "eyes" || zone == "mouth") shoot_self(user, zone) else - user.visible_message("[user.name] cowardly fires [src] at \his [zone]!", "You cowardly fire [src] at your [zone]!", "You hear a gunshot!") + user.visible_message("[user.name] cowardly fires [src] at [user.p_their()] [zone]!", "You cowardly fire [src] at your [zone]!", "You hear a gunshot!") return user.visible_message("*click*") @@ -252,7 +252,7 @@ /obj/item/gun/projectile/revolver/russian/proc/shoot_self(mob/living/carbon/human/user, affecting = "head") user.apply_damage(300, BRUTE, affecting) - user.visible_message("[user.name] fires [src] at \his head!", "You fire [src] at your head!", "You hear a gunshot!") + user.visible_message("[user.name] fires [src] at [user.p_their()] head!", "You fire [src] at your head!", "You hear a gunshot!") /obj/item/gun/projectile/revolver/capgun name = "cap gun" diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index c0678323409..903d18798d7 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -81,6 +81,7 @@ icon_state = "riotshotgun" mag_type = /obj/item/ammo_box/magazine/internal/shot/riot sawn_desc = "Come with me if you want to live." + sawn_state = SAWN_INTACT /obj/item/gun/projectile/shotgun/riot/attackby(obj/item/A, mob/user, params) ..() @@ -90,6 +91,109 @@ var/obj/item/melee/energy/W = A if(W.active) sawoff(user) + if(istype(A, /obj/item/pipe)) + unsaw(A, user) + +/obj/item/gun/projectile/sawoff(mob/user) + if(sawn_state == SAWN_OFF) + to_chat(user, "[src] has already been shortened!") + return + if(istype(loc, /obj/item/storage)) //To prevent inventory exploits + to_chat(user, "How do you plan to modify [src] while it's in a bag.") + return + if(chambered) //if the gun is chambering live ammo, shoot self, if chambering empty ammo, 'click' + if(chambered.BB) + afterattack(user, user) + user.visible_message("\The [src] goes off!", "\The [src] goes off in your face!") + return + else + afterattack(user, user) + user.visible_message("The [src] goes click!", "The [src] you are holding goes click.") + if(magazine.ammo_count()) //Spill the mag onto the floor + user.visible_message("[user.name] opens [src] up and the shells go goes flying around!", "You open [src] up and the shells go goes flying everywhere!!") + while(get_ammo(0) > 0) + var/obj/item/ammo_casing/CB + CB = magazine.get_round(0) + if(CB) + CB.loc = get_turf(loc) + CB.update_icon() + + if(do_after(user, 30, target = src)) + user.visible_message("[user] shortens \the [src]!", "You shorten \the [src].") + post_sawoff() + return 1 + + +/obj/item/gun/projectile/proc/post_sawoff() + name = "assault shotgun" + desc = sawn_desc + w_class = WEIGHT_CLASS_NORMAL + current_skin = "riotshotgun-short" + item_state = "gun" //phil235 is it different with different skin? + slot_flags &= ~SLOT_BACK //you can't sling it on your back + slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) + sawn_state = SAWN_OFF + magazine.max_ammo = 3 + update_icon() + + +/obj/item/gun/projectile/proc/unsaw(obj/item/A, mob/user) + if(sawn_state == SAWN_INTACT) + to_chat(user, "[src] has not been shortened!") + return + if(istype(loc, /obj/item/storage)) //To prevent inventory exploits + to_chat(user, "How do you plan to modify [src] while it's in a bag.") + return + if(chambered) //if the gun is chambering live ammo, shoot self, if chambering empty ammo, 'click' + if(chambered.BB) + afterattack(user, user) + user.visible_message("\The [src] goes off!", "\The [src] goes off in your face!") + return + else + afterattack(user, user) + user.visible_message("The [src] goes click!", "The [src] you are holding goes click.") + if(magazine.ammo_count()) //Spill the mag onto the floor + user.visible_message("[user.name] opens [src] up and the shells go goes flying around!", "You open [src] up and the shells go goes flying everywhere!!") + while(get_ammo() > 0) + var/obj/item/ammo_casing/CB + CB = magazine.get_round(0) + if(CB) + CB.loc = get_turf(loc) + CB.update_icon() + + if(do_after(user, 30, target = src)) + qdel(A) + user.visible_message("[user] lengthens [src]!", "You lengthen [src].") + post_unsaw(user) + return 1 + +/obj/item/gun/projectile/proc/post_unsaw() + name = initial(name) + desc = initial(desc) + w_class = initial(w_class) + current_skin = "riotshotgun" + item_state = initial(item_state) + slot_flags &= ~SLOT_BELT + slot_flags |= SLOT_BACK + sawn_state = SAWN_INTACT + magazine.max_ammo = 6 + update_icon() + +/obj/item/gun/projectile/shotgun/riot/update_icon() //Can't use the old proc as it makes it go to riotshotgun-short_sawn + ..() + if(current_skin) + icon_state = "[current_skin]" + else + icon_state = "[initial(icon_state)]" + +/obj/item/gun/projectile/shotgun/riot/short + mag_type = /obj/item/ammo_box/magazine/internal/shot/riot/short + +/obj/item/gun/projectile/shotgun/riot/short/New() + ..() + post_sawoff() + + /////////////////////// // BOLT ACTION RIFLE // diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index a378e291e7c..e19cd1165b5 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -83,7 +83,7 @@ var/blood_color = "#C80000" if(ishuman(target)) H = target - blood_color = H.species.blood_color + blood_color = H.dna.species.blood_color new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, blood_color) if(prob(33)) var/list/shift = list("x" = 0, "y" = 0) @@ -114,13 +114,18 @@ "[L] is hit by \a [src][organ_hit_text]!") //X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter var/reagent_note + var/has_reagents = FALSE if(reagents && reagents.reagent_list) reagent_note = " REAGENTS:" for(var/datum/reagent/R in reagents.reagent_list) reagent_note += R.id + " (" reagent_note += num2text(R.volume) + ") " + has_reagents = TRUE if(!log_override && firer && original) - add_attack_logs(firer, L, "Shot with a [type] (potentially containing [reagent_note])") + if(has_reagents) + add_attack_logs(firer, L, "Shot with a [type] (containing [reagent_note])") + else + add_attack_logs(firer, L, "Shot with a [type]") return L.apply_effects(stun, weaken, paralyze, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter) /obj/item/projectile/proc/get_splatter_blockage(var/turf/step_over, var/atom/target, var/splatter_dir, var/target_loca) //Check whether the place we want to splatter blood is blocked (i.e. by windows). diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index becada9f19e..761fb50179c 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -77,7 +77,7 @@ /obj/item/projectile/beam/lasertag name = "laser tag beam" icon_state = "omnilaser" - hitsound = null + hitsound = 'sound/weapons/tap.ogg' damage = 0 damage_type = STAMINA flag = "laser" diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 4521dc8d7ba..854fd1edbaf 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -24,15 +24,15 @@ var/exp_flash = 3 var/exp_fire = 2 -/obj/item/projectile/magic/death/on_hit(var/mob/living/carbon/G) +/obj/item/projectile/magic/death/on_hit(mob/living/carbon/C) . = ..() - if(isliving(G)) - if(G.get_species() == "Machine") //speshul snowfleks deserv speshul treetment - G.adjustFireLoss(6969) //remember - slimes love fire + if(isliving(C)) + if(ismachine(C)) //speshul snowfleks deserv speshul treetment + C.adjustFireLoss(6969) //remember - slimes love fire else - G.death() + C.death() - visible_message("[G] topples backwards as the death bolt impacts them!") + visible_message("[C] topples backwards as the death bolt impacts [C.p_them()]!") /obj/item/projectile/magic/fireball/Range() var/turf/T1 = get_step(src,turn(dir, -45)) @@ -146,117 +146,120 @@ . = ..() wabbajack(change) -proc/wabbajack(mob/living/M) - if(istype(M)) - if(istype(M, /mob/living) && M.stat != DEAD) - if(M.notransform) - return - M.notransform = 1 - M.canmove = 0 - M.icon = null - M.overlays.Cut() - M.invisibility = 101 +/proc/wabbajack(mob/living/M) + if(istype(M) && M.stat != DEAD && !M.notransform) + M.notransform = TRUE + M.canmove = FALSE + M.icon = null + M.overlays.Cut() + M.invisibility = 101 - if(istype(M, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/Robot = M - if(Robot.mmi) - qdel(Robot.mmi) - Robot.notify_ai(1) - else - if(ishuman(M)) - var/mob/living/carbon/human/H = M - // Make sure there are no organs or limbs to drop - for(var/t in H.bodyparts) - qdel(t) - for(var/i in H.internal_organs) - qdel(i) - for(var/obj/item/W in M) - M.unEquip(W, 1) - qdel(W) + if(isrobot(M)) + var/mob/living/silicon/robot/Robot = M + QDEL_NULL(Robot.mmi) + Robot.notify_ai(1) + else + if(ishuman(M)) + var/mob/living/carbon/human/H = M + // Make sure there are no organs or limbs to drop + for(var/t in H.bodyparts) + qdel(t) + for(var/i in H.internal_organs) + qdel(i) + for(var/obj/item/W in M) + M.unEquip(W, 1) + qdel(W) - var/mob/living/new_mob + var/mob/living/new_mob - var/randomize = pick("robot","slime","xeno","human","animal") - switch(randomize) - if("robot") - if(prob(30)) - new_mob = new /mob/living/silicon/robot/syndicate(M.loc) - else - new_mob = new /mob/living/silicon/robot(M.loc) - new_mob.gender = M.gender - new_mob.invisibility = 0 - new_mob.job = "Cyborg" - var/mob/living/silicon/robot/Robot = new_mob - Robot.mmi = new /obj/item/mmi(new_mob) - if(ishuman(M)) - Robot.mmi.transfer_identity(M) //Does not transfer key/client. - if("slime") - new_mob = new /mob/living/carbon/slime/random(M.loc) - new_mob.universal_speak = 1 - if("xeno") - if(prob(50)) - new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) - else - new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) - new_mob.universal_speak = 1 - if("animal") - if(prob(50)) - var/beast = pick("carp","bear","mushroom","statue", "bat", "goat", "tomato") - switch(beast) - if("carp") new_mob = new /mob/living/simple_animal/hostile/carp(M.loc) - if("bear") new_mob = new /mob/living/simple_animal/hostile/bear(M.loc) - if("mushroom") new_mob = new /mob/living/simple_animal/hostile/mushroom(M.loc) - if("statue") new_mob = new /mob/living/simple_animal/hostile/statue(M.loc) - if("bat") new_mob = new /mob/living/simple_animal/hostile/scarybat(M.loc) - if("goat") new_mob = new /mob/living/simple_animal/hostile/retaliate/goat(M.loc) - if("tomato") new_mob = new /mob/living/simple_animal/hostile/killertomato(M.loc) - else - var/animal = pick("parrot","corgi","crab","pug","cat","mouse","chicken","cow","lizard","chick","fox") - switch(animal) - if("parrot") new_mob = new /mob/living/simple_animal/parrot(M.loc) - if("corgi") new_mob = new /mob/living/simple_animal/pet/corgi(M.loc) - if("crab") new_mob = new /mob/living/simple_animal/crab(M.loc) - if("cat") new_mob = new /mob/living/simple_animal/pet/cat(M.loc) - if("mouse") new_mob = new /mob/living/simple_animal/mouse(M.loc) - if("chicken") new_mob = new /mob/living/simple_animal/chicken(M.loc) - if("cow") new_mob = new /mob/living/simple_animal/cow(M.loc) - if("lizard") new_mob = new /mob/living/simple_animal/lizard(M.loc) - if("fox") new_mob = new /mob/living/simple_animal/pet/fox(M.loc) - else new_mob = new /mob/living/simple_animal/chick(M.loc) - new_mob.universal_speak = 1 - if("human") - new_mob = new /mob/living/carbon/human/human(M.loc) - // Include standard, whitelisted, and monkey species... - var/list/new_species = list("Human","Tajaran","Skrell","Unathi","Diona","Vulpkanin") - new_species |= whitelisted_species - for(var/SN in all_species) - var/datum/species/S = all_species[SN] - if(S.greater_form) // Monkeys - new_species |= SN - new_species -= "Vox Armalis" // ... but not Armalis. They're not really designed to be playable - new_species |= "Golem" // Also, golems, sure, why not - var/picked_species = pick(new_species) - var/mob/living/carbon/human/H = new_mob - H.set_species(picked_species) - randomize = picked_species - var/datum/preferences/A = new() //Randomize appearance for the human - A.copy_to(new_mob) + var/randomize = pick("robot", "slime", "xeno", "human", "animal") + switch(randomize) + if("robot") + if(prob(30)) + new_mob = new /mob/living/silicon/robot/syndicate(M.loc) else - return - - M.create_attack_log("[key_name(M)] became [new_mob.real_name].") - new_mob.attack_log = M.attack_log - - new_mob.a_intent = INTENT_HARM - if(M.mind) - M.mind.transfer_to(new_mob) + new_mob = new /mob/living/silicon/robot(M.loc) + new_mob.gender = M.gender + new_mob.invisibility = 0 + new_mob.job = "Cyborg" + var/mob/living/silicon/robot/Robot = new_mob + Robot.mmi = new /obj/item/mmi(new_mob) + if(ishuman(M)) + Robot.mmi.transfer_identity(M) //Does not transfer key/client. + if("slime") + new_mob = new /mob/living/carbon/slime/random(M.loc) + new_mob.universal_speak = TRUE + if("xeno") + if(prob(50)) + new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) + else + new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) + new_mob.universal_speak = TRUE + if("animal") + if(prob(50)) + var/beast = pick("carp","bear","mushroom","statue", "bat", "goat", "tomato") + switch(beast) + if("carp") + new_mob = new /mob/living/simple_animal/hostile/carp(M.loc) + if("bear") + new_mob = new /mob/living/simple_animal/hostile/bear(M.loc) + if("mushroom") + new_mob = new /mob/living/simple_animal/hostile/mushroom(M.loc) + if("statue") + new_mob = new /mob/living/simple_animal/hostile/statue(M.loc) + if("bat") + new_mob = new /mob/living/simple_animal/hostile/scarybat(M.loc) + if("goat") + new_mob = new /mob/living/simple_animal/hostile/retaliate/goat(M.loc) + if("tomato") + new_mob = new /mob/living/simple_animal/hostile/killertomato(M.loc) + else + var/animal = pick("parrot", "corgi", "crab", "pug", "cat", "mouse", "chicken", "cow", "lizard", "chick", "fox") + switch(animal) + if("parrot") + new_mob = new /mob/living/simple_animal/parrot(M.loc) + if("corgi") + new_mob = new /mob/living/simple_animal/pet/corgi(M.loc) + if("crab") + new_mob = new /mob/living/simple_animal/crab(M.loc) + if("cat") + new_mob = new /mob/living/simple_animal/pet/cat(M.loc) + if("mouse") + new_mob = new /mob/living/simple_animal/mouse(M.loc) + if("chicken") + new_mob = new /mob/living/simple_animal/chicken(M.loc) + if("cow") + new_mob = new /mob/living/simple_animal/cow(M.loc) + if("lizard") + new_mob = new /mob/living/simple_animal/lizard(M.loc) + if("fox") + new_mob = new /mob/living/simple_animal/pet/fox(M.loc) + else + new_mob = new /mob/living/simple_animal/chick(M.loc) + new_mob.universal_speak = TRUE + if("human") + new_mob = new /mob/living/carbon/human(M.loc) + var/mob/living/carbon/human/H = new_mob + var/datum/preferences/A = new() //Randomize appearance for the human + A.species = get_random_species(TRUE) + A.copy_to(new_mob) + randomize = H.dna.species.name else - new_mob.key = M.key + return - to_chat(new_mob, "Your form morphs into that of a [randomize].") + M.create_attack_log("[key_name(M)] became [new_mob.real_name].") + new_mob.attack_log = M.attack_log - qdel(M) - return new_mob + new_mob.a_intent = INTENT_HARM + if(M.mind) + M.mind.transfer_to(new_mob) + else + new_mob.key = M.key + + to_chat(new_mob, "Your form morphs into that of a [randomize].") + + qdel(M) + return new_mob /obj/item/projectile/magic/animate name = "bolt of animation" diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 16cedc0244d..2003e78b780 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -8,14 +8,14 @@ /obj/item/projectile/ion/on_hit(var/atom/target, var/blocked = 0) ..() - empulse(target, 1, 1) + empulse(target, 1, 1, 1) return 1 /obj/item/projectile/ion/weak /obj/item/projectile/ion/weak/on_hit(atom/target, blocked = 0) ..() - empulse(target, 0, 0) + empulse(target, 0, 0, 1) return 1 /obj/item/projectile/bullet/gyro @@ -52,7 +52,7 @@ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE /obj/item/projectile/temp/New(loc, shot_temp) - ..(loc) + ..() if(!isnull(shot_temp)) temperature = shot_temp switch(temperature) @@ -86,7 +86,6 @@ else name = "temperature beam"//failsafe icon_state = "temp_4" - ..() /obj/item/projectile/temp/on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob @@ -134,11 +133,11 @@ var/mob/living/M = target if(ishuman(target)) var/mob/living/carbon/human/H = M - if(IS_PLANT in H.species.species_traits) + if(IS_PLANT in H.dna.species.species_traits) if(prob(15)) M.apply_effect((rand(30,80)),IRRADIATE) M.Weaken(5) - M.visible_message("[M] writhes in pain as \his vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.") + M.visible_message("[M] writhes in pain as [M.p_their()] vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.") if(prob(35)) if(prob(80)) randmutb(M) @@ -167,7 +166,7 @@ var/mob/M = target if(ishuman(target)) //These rays make plantmen fat. var/mob/living/carbon/human/H = M - if(IS_PLANT in H.species.species_traits) + if(IS_PLANT in H.dna.species.species_traits) H.nutrition = min(H.nutrition+30, NUTRITION_LEVEL_FULL) else if(iscarbon(target)) M.show_message("The radiation beam dissipates harmlessly through your body.") diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 83a000fa693..73a591f9ddb 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -209,17 +209,17 @@ var/const/INGEST = 2 //Check if this mob's species is set and can process this type of reagent var/can_process = 0 //If we somehow avoided getting a species or reagent_tag set, we'll assume we aren't meant to process ANY reagents (CODERS: SET YOUR SPECIES AND TAG!) - if(H.species && H.species.reagent_tag) - if((R.process_flags & SYNTHETIC) && (H.species.reagent_tag & PROCESS_SYN)) //SYNTHETIC-oriented reagents require PROCESS_SYN + if(H.dna.species && H.dna.species.reagent_tag) + if((R.process_flags & SYNTHETIC) && (H.dna.species.reagent_tag & PROCESS_SYN)) //SYNTHETIC-oriented reagents require PROCESS_SYN can_process = 1 - if((R.process_flags & ORGANIC) && (H.species.reagent_tag & PROCESS_ORG)) //ORGANIC-oriented reagents require PROCESS_ORG + if((R.process_flags & ORGANIC) && (H.dna.species.reagent_tag & PROCESS_ORG)) //ORGANIC-oriented reagents require PROCESS_ORG can_process = 1 //Species with PROCESS_DUO are only affected by reagents that affect both organics and synthetics, like acid and hellwater - if((R.process_flags & ORGANIC) && (R.process_flags & SYNTHETIC) && (H.species.reagent_tag & PROCESS_DUO)) + if((R.process_flags & ORGANIC) && (R.process_flags & SYNTHETIC) && (H.dna.species.reagent_tag & PROCESS_DUO)) can_process = 1 //If handle_reagents returns 0, it's doing the reagent removal on its own - var/species_handled = !(H.species.handle_reagents(H, R)) + var/species_handled = !(H.dna.species.handle_reagents(H, R)) can_process = can_process && !species_handled //If the mob can't process it, remove the reagent at it's normal rate without doing any addictions, overdoses, or on_mob_life() for the reagent if(can_process == 0) @@ -481,13 +481,13 @@ var/const/INGEST = 2 if(ishuman(M)) var/mob/living/carbon/human/H = M //Check if this mob's species is set and can process this type of reagent - if(H.species && H.species.reagent_tag) - if((R.process_flags & SYNTHETIC) && (H.species.reagent_tag & PROCESS_SYN)) //SYNTHETIC-oriented reagents require PROCESS_SYN + if(H.dna.species && H.dna.species.reagent_tag) + if((R.process_flags & SYNTHETIC) && (H.dna.species.reagent_tag & PROCESS_SYN)) //SYNTHETIC-oriented reagents require PROCESS_SYN can_process = 1 - if((R.process_flags & ORGANIC) && (H.species.reagent_tag & PROCESS_ORG)) //ORGANIC-oriented reagents require PROCESS_ORG + if((R.process_flags & ORGANIC) && (H.dna.species.reagent_tag & PROCESS_ORG)) //ORGANIC-oriented reagents require PROCESS_ORG can_process = 1 //Species with PROCESS_DUO are only affected by reagents that affect both organics and synthetics, like acid and hellwater - if((R.process_flags & ORGANIC) && (R.process_flags & SYNTHETIC) && (H.species.reagent_tag & PROCESS_DUO)) + if((R.process_flags & ORGANIC) && (R.process_flags & SYNTHETIC) && (H.dna.species.reagent_tag & PROCESS_DUO)) can_process = 1 //We'll assume that non-human mobs lack the ability to process synthetic-oriented reagents (adjust this if we need to change that assumption) else diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index e589936a935..d4d232d2ed7 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -1,7 +1,3 @@ -#define SOLID 1 -#define LIQUID 2 -#define GAS 3 - /obj/machinery/chem_dispenser name = "chem dispenser" density = 1 diff --git a/code/modules/reagents/chemistry/reagents/drugs.dm b/code/modules/reagents/chemistry/reagents/drugs.dm index 6a4ede5fe50..a2bd35ae75a 100644 --- a/code/modules/reagents/chemistry/reagents/drugs.dm +++ b/code/modules/reagents/chemistry/reagents/drugs.dm @@ -208,7 +208,7 @@ M.reagents.add_reagent("jagged_crystals", 5) else if(effect <= 7) M.emote("scream") - M.visible_message("[M] nervously scratches at their skin!") + M.visible_message("[M] nervously scratches at [M.p_their()] skin!") M.Jitter(10) M.adjustBruteLoss(5) M.emote("twitch_s") @@ -315,7 +315,7 @@ var/effect = ..() if(severity == 1) if(effect <= 2) - M.visible_message("[M] can't seem to control their legs!") + M.visible_message("[M] can't seem to control [M.p_their()] legs!") M.AdjustConfused(20) M.Weaken(4) else if(effect <= 4) @@ -356,7 +356,7 @@ head_organ.f_style = "Very Long Beard" H.update_hair() H.update_fhair() - H.visible_message("[H] has a wild look in their eyes!") + H.visible_message("[H] has a wild look in [H.p_their()] eyes!") if(check < 60) M.SetParalysis(0) M.SetStunned(0) @@ -368,7 +368,7 @@ M.AdjustConfused(10) if(check < 8) M.reagents.add_reagent(pick("methamphetamine", "crank", "neurotoxin"), rand(1,5)) - M.visible_message("[M] scratches at something under their skin!") + M.visible_message("[M] scratches at something under [M.p_their()] skin!") M.adjustBruteLoss(5) else if(check < 16) M.AdjustHallucinate(30) @@ -427,7 +427,7 @@ M.reagents.add_reagent("jagged_crystals", 5) else if(effect <= 7) M.emote("scream") - M.visible_message("[M] tears at their own skin!") + M.visible_message("[M] tears at [M.p_their()] own skin!") M.adjustBruteLoss(5) M.reagents.add_reagent("jagged_crystals", 5) M.emote("twitch") @@ -541,7 +541,7 @@ var/effect = ..() if(severity == 1) if(effect <= 2) - M.visible_message("[M] can't seem to control their legs!") + M.visible_message("[M] can't seem to control [M.p_their()] legs!") M.AdjustConfused(33) M.Weaken(2) else if(effect <= 4) diff --git a/code/modules/reagents/chemistry/reagents/food.dm b/code/modules/reagents/chemistry/reagents/food.dm index bdabfd21956..7426844e292 100644 --- a/code/modules/reagents/chemistry/reagents/food.dm +++ b/code/modules/reagents/chemistry/reagents/food.dm @@ -31,7 +31,7 @@ if(H.can_eat(diet_flags)) //Make sure the species has it's dietflag set, otherwise it can't digest any nutrients if(prob(50)) M.adjustBruteLoss(-1) - if(!(NO_BLOOD in H.species.species_traits))//do not restore blood on things with no blood by nature. + if(!(NO_BLOOD in H.dna.species.species_traits))//do not restore blood on things with no blood by nature. if(H.blood_volume < BLOOD_VOLUME_NORMAL) H.blood_volume += 0.4 ..() @@ -66,7 +66,7 @@ M.satiety += 30 if(ishuman(M)) var/mob/living/carbon/human/H = M - if(!(NO_BLOOD in H.species.species_traits))//do not restore blood on things with no blood by nature. + if(!(NO_BLOOD in H.dna.species.species_traits))//do not restore blood on things with no blood by nature. if(H.blood_volume < BLOOD_VOLUME_NORMAL) H.blood_volume += 0.5 ..() diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index ada22d5b139..f603d5eb0d1 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -73,7 +73,7 @@ M.visible_message("[M] suddenly and violently vomits!") M.fakevomit(no_text = 1) else if(effect <= 5) - M.visible_message("[M] staggers and drools, their eyes bloodshot!") + M.visible_message("[M] staggers and drools, [M.p_their()] eyes bloodshot!") M.Dizzy(8) M.Weaken(4) if(effect <= 15) @@ -92,13 +92,14 @@ //Mitocholide is hard enough to get, it's probably fair to make this all internal organs for(var/obj/item/organ/internal/I in H.internal_organs) - I.receive_damage(-0.4) + I.heal_internal_damage(0.4) ..() /datum/reagent/medicine/mitocholide/reaction_obj(obj/O, volume) if(istype(O, /obj/item/organ)) var/obj/item/organ/Org = O - Org.rejuvenate() + if(!Org.is_robotic()) + Org.rejuvenate() /datum/reagent/medicine/cryoxadone name = "Cryoxadone" @@ -115,7 +116,11 @@ M.adjustToxLoss(-3) M.adjustBruteLoss(-12) M.adjustFireLoss(-12) - M.status_flags &= ~DISFIGURED + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head = H.get_organ("head") + if(head) + head.disfigured = FALSE ..() /datum/reagent/medicine/rezadone @@ -131,7 +136,11 @@ M.adjustCloneLoss(-1) //What? We just set cloneloss to 0. Why? Simple; this is so external organs properly unmutate. M.adjustBruteLoss(-1) M.adjustFireLoss(-1) - M.status_flags &= ~DISFIGURED + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head = H.get_organ("head") + if(head) + head.disfigured = FALSE ..() /datum/reagent/medicine/rezadone/overdose_process(mob/living/M, severity) @@ -212,7 +221,7 @@ M.adjustFireLoss(-2*REAGENTS_EFFECT_MULTIPLIER) if(ishuman(M) && prob(33)) var/mob/living/carbon/human/H = M - if(!(NO_BLOOD in H.species.species_traits))//do not restore blood on things with no blood by nature. + if(!(NO_BLOOD in H.dna.species.species_traits))//do not restore blood on things with no blood by nature. if(H.blood_volume < BLOOD_VOLUME_NORMAL) H.blood_volume += 1 ..() @@ -277,7 +286,7 @@ if(severity == 1) //lesser M.stuttering += 1 if(effect <= 1) - M.visible_message("[M] suddenly cluches their gut!") + M.visible_message("[M] suddenly cluches [M.p_their()] gut!") M.emote("scream") M.Stun(4) M.Weaken(4) @@ -293,7 +302,7 @@ M.Jitter(30) else if(severity == 2) // greater if(effect <= 2) - M.visible_message("[M] suddenly cluches their gut!") + M.visible_message("[M] suddenly cluches [M.p_their()] gut!") M.emote("scream") M.Stun(7) M.Weaken(7) @@ -446,7 +455,7 @@ M.visible_message("[M] suddenly and violently vomits!") M.fakevomit(no_text = 1) else if(effect <= 5) - M.visible_message("[M.name] staggers and drools, their eyes bloodshot!") + M.visible_message("[M.name] staggers and drools, [M.p_their()] eyes bloodshot!") M.Dizzy(2) M.Weaken(3) if(effect <= 15) @@ -512,7 +521,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes) if(istype(E)) - E.receive_damage(-1) + E.heal_internal_damage(1) M.AdjustEyeBlurry(-1) M.AdjustEarDamage(-1) if(prob(50)) @@ -597,7 +606,7 @@ M.visible_message("[M] suddenly and violently vomits!") M.fakevomit(no_text = 1) else if(effect <= 5) - M.visible_message("[M] staggers and drools, their eyes bloodshot!") + M.visible_message("[M] staggers and drools, [M.p_their()] eyes bloodshot!") M.Dizzy(2) M.Weaken(3) if(effect <= 15) diff --git a/code/modules/reagents/chemistry/reagents/misc.dm b/code/modules/reagents/chemistry/reagents/misc.dm index a67fcd0f751..fdddea44bd2 100644 --- a/code/modules/reagents/chemistry/reagents/misc.dm +++ b/code/modules/reagents/chemistry/reagents/misc.dm @@ -155,7 +155,7 @@ /datum/reagent/iron/on_mob_life(mob/living/M) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(!H.species.exotic_blood && !(NO_BLOOD in H.species.species_traits)) + if(!H.dna.species.exotic_blood && !(NO_BLOOD in H.dna.species.species_traits)) if(H.blood_volume < BLOOD_VOLUME_NORMAL) H.blood_volume += 0.8 ..() @@ -313,8 +313,8 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/head_organ = H.get_organ("head") - head_organ.h_style = random_hair_style(H.gender, head_organ.species.name) - head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species.name) + head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.name) + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.dna.species.name) H.update_hair() H.update_fhair() ..() @@ -335,14 +335,14 @@ var/datum/sprite_accessory/tmp_hair_style = hair_styles_full_list["Very Long Hair"] var/datum/sprite_accessory/tmp_facial_hair_style = facial_hair_styles_list["Very Long Beard"] - if(head_organ.species.name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. + if(head_organ.dna.species.name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. head_organ.h_style = "Very Long Hair" else //Otherwise, give them a random hair style. - head_organ.h_style = random_hair_style(H.gender, head_organ.species.name) - if(head_organ.species.name in tmp_facial_hair_style.species_allowed) //If 'Very Long Beard' is a style the person's species can have, give it to them. + head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.name) + if(head_organ.dna.species.name in tmp_facial_hair_style.species_allowed) //If 'Very Long Beard' is a style the person's species can have, give it to them. head_organ.f_style = "Very Long Beard" else //Otherwise, give them a random facial hair style. - head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species.name) + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.dna.species.name) H.update_hair() H.update_fhair() if(!H.wear_mask || H.wear_mask && !istype(H.wear_mask, /obj/item/clothing/mask/fakemoustache)) diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm index b54444ee2d4..f2a5e8b9e24 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm @@ -221,7 +221,7 @@ /datum/reagent/pyrosium name = "Pyrosium" id = "pyrosium" - description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Pyrosium slowly cools all other reagents in the mob down to 0K." + description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Pyrosium slowly heats all other reagents." color = "#B20000" // rgb: 139, 166, 233 process_flags = ORGANIC | SYNTHETIC diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm index 8cad5400c02..a3fc113339e 100644 --- a/code/modules/reagents/chemistry/reagents/toxins.dm +++ b/code/modules/reagents/chemistry/reagents/toxins.dm @@ -61,12 +61,12 @@ /datum/reagent/slimetoxin/on_mob_life(mob/living/M) if(ishuman(M)) var/mob/living/carbon/human/human = M - if(human.species.name != "Shadow") + if(!isshadowperson(human)) to_chat(M, "Your flesh rapidly mutates!") to_chat(M, "You are now a Shadow Person, a mutant race of darkness-dwelling humanoids.") to_chat(M, "Your body reacts violently to light. However, it naturally heals in darkness.") to_chat(M, "Aside from your new traits, you are mentally unchanged and retain your prior obligations.") - human.set_species("Shadow") + human.set_species(/datum/species/shadow) ..() /datum/reagent/aslimetoxin @@ -217,7 +217,7 @@ if(method == TOUCH) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.get_species() == "Grey") + if(isgrey(H)) return if(volume > 25) @@ -246,7 +246,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.get_species() == "Grey") + if(isgrey(H)) return if(volume >=10 && volume <=25) @@ -557,7 +557,7 @@ M.adjustBruteLoss(5) M.Weaken(5) M.AdjustJitter(6) - M.visible_message("[M] falls to the floor, scratching themselves violently!") + M.visible_message("[M] falls to the floor, scratching [M.p_them()]self violently!") M.emote("scream") ..() @@ -611,11 +611,11 @@ return if(!H.unacidable) - var/obj/item/organ/external/affecting = H.get_organ("head") - affecting.receive_damage(0, 75) + var/obj/item/organ/external/head/affecting = H.get_organ("head") + if(affecting) + affecting.receive_damage(0, 75) H.UpdateDamageIcon() H.emote("scream") - H.status_flags |= DISFIGURED /datum/reagent/facid/reaction_obj(obj/O, volume) if((istype(O, /obj/item) || istype(O, /obj/structure/glowshroom))) @@ -947,8 +947,7 @@ /datum/reagent/glyphosate/reaction_obj(obj/O, volume) if(istype(O,/obj/structure/alien/weeds)) var/obj/structure/alien/weeds/alien_weeds = O - alien_weeds.health -= rand(15,35) // Kills alien weeds pretty fast - alien_weeds.healthcheck() + alien_weeds.take_damage(rand(15, 35), BRUTE, 0) // Kills alien weeds pretty fast else if(istype(O, /obj/structure/glowshroom)) //even a small amount is enough to kill it qdel(O) else if(istype(O, /obj/structure/spacevine)) @@ -962,7 +961,7 @@ C.adjustToxLoss(lethality) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(IS_PLANT in H.species.species_traits) //plantmen take a LOT of damage + if(IS_PLANT in H.dna.species.species_traits) //plantmen take a LOT of damage H.adjustToxLoss(50) ..() else if(istype(M, /mob/living/simple_animal/diona)) //plantmen monkeys (diona) take EVEN MORE damage @@ -996,7 +995,7 @@ C.adjustToxLoss(2) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.get_species() == "Kidan") //RIP + if(iskidan(H)) //RIP H.adjustToxLoss(20) /datum/reagent/capulettium @@ -1016,7 +1015,7 @@ M.Drowsy(10) if(11) M.Paralyse(10) - M.visible_message("[M] seizes up and falls limp, their eyes dead and lifeless...") //so you can't trigger deathgasp emote on people. Edge case, but necessary. + M.visible_message("[M] seizes up and falls limp, [M.p_their()] eyes dead and lifeless...") //so you can't trigger deathgasp emote on people. Edge case, but necessary. if(12 to 60) M.Paralyse(10) if(61 to INFINITY) diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm index cd338cb048d..199edb72fb4 100644 --- a/code/modules/reagents/chemistry/reagents/water.dm +++ b/code/modules/reagents/chemistry/reagents/water.dm @@ -29,7 +29,7 @@ var/mob/living/carbon/human/H = M - if(H.get_species() != "Grey") //God this is so gross I hate it. + if(!isgrey(H)) //God this is so gross I hate it. return if(volume > 25) @@ -58,7 +58,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.get_species() != "Grey") + if(!isgrey(H)) return if(volume < 10) diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index c7acc705150..a5d37cb8b60 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -26,6 +26,33 @@ empulse(location, round(created_volume / 24), round(created_volume / 14), 1) holder.clear_reagents() +/datum/chemical_reaction/beesplosion + name = "Bee Explosion" + id = "beesplosion" + result = null + required_reagents = list("honey" = 1, "strange_reagent" = 1, "radium" = 1) + result_amount = 1 + +/datum/chemical_reaction/beesplosion/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + if(created_volume < 5) + playsound(location,'sound/effects/sparks1.ogg', 100, 1) + else + playsound(location,'sound/creatures/bee.ogg', 100, 1) + var/list/beeagents = list() + for(var/X in holder.reagent_list) + var/datum/reagent/R = X + if(R.id in required_reagents) + continue + if(!R.can_synth) + continue + beeagents += R + var/bee_amount = round(created_volume * 0.2) + for(var/i in 1 to bee_amount) + var/mob/living/simple_animal/hostile/poison/bees/new_bee = new(location) + if(LAZYLEN(beeagents)) + new_bee.assign_reagent(pick(beeagents)) + /datum/chemical_reaction/nitroglycerin name = "Nitroglycerin" id = "nitroglycerin" diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index aa5e16adc04..4df7a525b88 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -334,7 +334,7 @@ /datum/chemical_reaction/slimeoverload/on_reaction(datum/reagents/holder, created_volume) feedback_add_details("slime_cores_used","[type]") - empulse(get_turf(holder.my_atom), 3, 7) + empulse(get_turf(holder.my_atom), 3, 7, 1) /datum/chemical_reaction/slimecell diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 28d8857efe1..e3e0daee333 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -61,10 +61,10 @@ /obj/item/reagent_containers/afterattack(obj/target, mob/user , flag) return -/obj/item/reagent_containers/proc/reagentlist(obj/item/reagent_containers/snack) //Attack logs for regents in pills +/obj/item/reagent_containers/proc/reagentlist() //Return reagents in a reagent_container, default to source var/data - if(snack && snack.reagents && snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries - for(var/datum/reagent/R in snack.reagents.reagent_list) //no reagents will be left behind + if(reagents && reagents.reagent_list && reagents.reagent_list.len) //find a reagent list if there is and check if it has entries + for(var/datum/reagent/R in reagents.reagent_list) //no reagents will be left behind data += "[R.id]([R.volume] units); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. return data else return "No reagents" diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 057a339649c..ad8b3438ee4 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -85,7 +85,7 @@ var/datum/reagent/injected = chemical_reagents_list[reagent_ids[mode]] var/contained = injected.name var/trans = R.trans_to(M, amount_per_transfer_from_this) - add_attack_logs(M, user, "Injected with [name] containing [contained], transfered [trans] units", !!M.ckey) + add_attack_logs(M, user, "Injected with [name] containing [contained], transfered [trans] units") M.LAssailant = user to_chat(user, "[trans] units injected. [R.total_volume] units remaining.") return diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm index 39d3babf4bc..d20ef6f82ee 100644 --- a/code/modules/reagents/reagent_containers/glass_containers.dm +++ b/code/modules/reagents/reagent_containers/glass_containers.dm @@ -42,7 +42,8 @@ /obj/machinery/constructable_frame, /obj/machinery/icemachine, /obj/item/bombcore/chemical, - /obj/machinery/vending) + /obj/machinery/vending, + /obj/machinery/fishtank) /obj/item/reagent_containers/glass/New() ..() @@ -82,7 +83,7 @@ for(var/datum/reagent/R in reagents.reagent_list) injected += R.name var/contained = english_list(injected) - add_attack_logs(M, user, "Splashed with [name] containing [contained]", !!M.ckey) + add_attack_logs(M, user, "Splashed with [name] containing [contained]", !!M.ckey ? null : ATKLOG_ALL) if(!iscarbon(user)) M.LAssailant = null else diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index feee1bab8b4..771d627b421 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -13,7 +13,9 @@ possible_transfer_amounts = list(1,2,3,4,5,10,15,20,25,30) flags = OPENCONTAINER slot_flags = SLOT_BELT - var/ignore_flags = 0 + var/ignore_flags = FALSE + var/emagged = FALSE + var/safety_hypo = FALSE /obj/item/reagent_containers/hypospray/attack(mob/living/M, mob/user) if(!reagents.total_volume) @@ -31,8 +33,13 @@ for(var/datum/reagent/R in reagents.reagent_list) injected += R.name + var/primary_reagent_name = reagents.get_master_reagent_name() var/trans = reagents.trans_to(M, amount_per_transfer_from_this) + if(safety_hypo) + visible_message("[user] injects [M] with [trans] units of [primary_reagent_name].") + playsound(loc, 'sound/goonstation/items/hypo.ogg', 80, 0) + to_chat(user, "[trans] unit\s injected. [reagents.total_volume] unit\s remaining in [src].") var/contained = english_list(injected) @@ -41,6 +48,31 @@ return TRUE +/obj/item/reagent_containers/hypospray/on_reagent_change() + if(safety_hypo && !emagged) + var/found_forbidden_reagent = FALSE + for(var/datum/reagent/R in reagents.reagent_list) + if(!safe_chem_list.Find(R.id)) + reagents.del_reagent(R.id) + found_forbidden_reagent = TRUE + if(found_forbidden_reagent) + if(ismob(loc)) + to_chat(loc, "[src] identifies and removes a harmful substance.") + else + visible_message("[src] identifies and removes a harmful substance.") + +/obj/item/reagent_containers/hypospray/emag_act(mob/user) + if(safety_hypo && !emagged) + emagged = TRUE + ignore_flags = TRUE + to_chat(user, "You short out the safeties on [src].") + +/obj/item/reagent_containers/hypospray/safety + name = "medical hypospray" + desc = "A modified hypospray for quickly injecting safe medicinal chemicals." + icon_state = "combat_hypo" + safety_hypo = TRUE + /obj/item/reagent_containers/hypospray/CMO list_reagents = list("omnizine" = 30) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index e405dbe169c..02ab4408acb 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -49,14 +49,14 @@ user.newtonian_move(get_dir(A, user)) if(reagents.has_reagent("sacid")) - msg_admin_attack("[key_name_admin(user)] fired sulphuric acid from \a [src].") - log_game("[key_name(user)] fired sulphuric acid from \a [src].") + msg_admin_attack("[key_name_admin(user)] fired sulphuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) + log_game("[key_name(user)] fired sulphuric acid from \a [src] at [COORD(user)].") if(reagents.has_reagent("facid")) - msg_admin_attack("[key_name_admin(user)] fired fluorosulfuric acid from \a [src].") - log_game("[key_name(user)] fired fluorosulfuric Acid from \a [src].") + msg_admin_attack("[key_name_admin(user)] fired fluorosulfuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) + log_game("[key_name(user)] fired fluorosulfuric Acid from \a [src] at [COORD(user)].") if(reagents.has_reagent("lube")) - msg_admin_attack("[key_name_admin(user)] fired space lube from \a [src].") - log_game("[key_name(user)] fired space lube from \a [src].") + msg_admin_attack("[key_name_admin(user)] fired space lube from \a [src] at [COORD(user)].") + log_game("[key_name(user)] fired space lube from \a [src] at [COORD(user)].") return diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index a80c4142d87..bcbcad6bc98 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -9,6 +9,7 @@ var/tank_volume = 1000 //In units, how much the dispenser can hold var/reagent_id = "water" //The ID of the reagent that the dispenser uses + var/lastrigger = "" // The last person to rig this fuel tank - Stored with the object. Only the last person matter for investigation /obj/structure/reagent_dispensers/attackby(obj/item/W, mob/user, params) return @@ -77,11 +78,16 @@ ..() if(!QDELETED(src)) //wasn't deleted by the projectile's effects. if(!P.nodamage && ((P.damage_type == BURN) || (P.damage_type == BRUTE))) - message_admins("[key_name_admin(P.firer)] triggered a fueltank explosion.") - log_game("[key_name(P.firer)] triggered a fueltank explosion.") + message_admins("[key_name_admin(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)] ") + log_game("[key_name(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)]") + investigate_log("[key_name(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)]", INVESTIGATE_BOMB) boom() -/obj/structure/reagent_dispensers/fueltank/boom() +/obj/structure/reagent_dispensers/fueltank/boom(var/rigtrigger = FALSE) // Prevent case where someone who rigged the tank is blamed for the explosion when the rig isn't what triggered the explosion + if(rigtrigger == TRUE) // If the explosion is triggered by an assembly holder + message_admins("A fueltank, last rigged by [lastrigger], exploded at [COORD(loc)]") // Then admin is informed of the last person who rigged the fuel tank + log_game("A fueltank, last rigged by [lastrigger], exploded at [COORD(loc)]") + investigate_log("A fueltank, last rigged by [lastrigger], exploded at [COORD(loc)]", INVESTIGATE_BOMB) explosion(loc, 0, 1, 5, 7, 10, flame_range = 5) qdel(src) @@ -111,6 +117,7 @@ usr.visible_message("[usr] detaches [rig] from [src].", "You detach [rig] from [src].") rig.forceMove(get_turf(usr)) rig = null + lastrigger = null overlays.Cut() /obj/structure/reagent_dispensers/fueltank/attackby(obj/item/I, mob/user, params) @@ -124,9 +131,11 @@ var/obj/item/assembly_holder/H = I if(istype(H.a_left, /obj/item/assembly/igniter) || istype(H.a_right, /obj/item/assembly/igniter)) - msg_admin_attack("[key_name_admin(user)] rigged a fueltank for explosion (JMP)") - log_game("[key_name(user)] rigged fueltank a fueltank for explosion at [loc.x], [loc.y], [loc.z]") + msg_admin_attack("[key_name_admin(user)] rigged [src.name] with [I.name] for explosion (JMP)", ATKLOG_FEW) + log_game("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]") + investigate_log("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]", INVESTIGATE_BOMB) + lastrigger = "[key_name(user)]" rig = H user.drop_item() H.forceMove(src) @@ -146,13 +155,14 @@ to_chat(user, "Your [W] is already full!") return reagents.trans_to(W, W.max_fuel) - user.visible_message("[user] refills \his [W].", "You refill [W].") + user.visible_message("[user] refills [user.p_their()] [W].", "You refill [W].") playsound(src, 'sound/effects/refill.ogg', 50, 1) W.update_icon() else - user.visible_message("[user] catastrophically fails at refilling \his [W]!", "That was stupid of you.") - message_admins("[key_name_admin(user)] triggered a fueltank explosion.") - log_game("[key_name(user)] triggered a fueltank explosion.") + user.visible_message("[user] catastrophically fails at refilling [user.p_their()] [W]!", "That was stupid of you.") + message_admins("[key_name_admin(user)] triggered a fueltank explosion at [COORD(loc)]") + log_game("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]") + investigate_log("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]", INVESTIGATE_BOMB) boom() else ..() diff --git a/code/modules/recycling/belt-placer.dm b/code/modules/recycling/belt-placer.dm new file mode 100644 index 00000000000..1b473bef814 --- /dev/null +++ b/code/modules/recycling/belt-placer.dm @@ -0,0 +1,46 @@ +/obj/item/storage/conveyor //Stores conveyor belts, click floor to make belt, use a conveyor switch on this to link all belts to that lever. + name = "conveyor belt placer" + desc = "This device facilitates the rapid deployment of conveyor belts." + icon_state = "belt_placer" + item_state = "belt_placer" + w_class = WEIGHT_CLASS_BULKY //Because belts are large things, you know? + can_hold = list(/obj/item/conveyor_construct) + flags = CONDUCT + max_w_class = WEIGHT_CLASS_BULKY + max_combined_w_class = 28 //7 belts + allow_quick_gather = TRUE + allow_quick_empty = TRUE + display_contents_with_number = TRUE + use_to_pickup = TRUE + origin_tech = "engineering=1" + +/obj/item/storage/conveyor/bluespace + name = "bluespace conveyor belt placer" + desc = "This device facilitates the rapid deployment of conveyor belts. It utilises bluespace in order to hold many more belts than its regular counterpart." + icon_state = "bluespace_belt_placer" + item_state = "bluespace_belt_placer" + w_class = WEIGHT_CLASS_NORMAL + storage_slots = 50 + max_combined_w_class = 200 //50 belts + origin_tech = "engineering=2;bluespace=1" + +/obj/item/storage/conveyor/attackby(obj/item/I, mob/user, params) //So we can link belts en masse + if(istype(I, /obj/item/conveyor_switch_construct)) + var/obj/item/conveyor_switch_construct/S = I + var/linked = FALSE //For nice message + for(var/obj/item/conveyor_construct/C in src) + C.id = S.id + linked = TRUE + if(linked) + to_chat(user, "All belts in [src] linked with [S].") + else + return ..() + +/obj/item/storage/conveyor/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + var/obj/item/conveyor_construct/C = locate() in src + if(!C) + to_chat(user, "There are no belts in [src].") + else + C.afterattack(A, user, proximity) diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm index ba193744467..c7e276cae17 100644 --- a/code/modules/recycling/disposal-construction.dm +++ b/code/modules/recycling/disposal-construction.dm @@ -11,66 +11,57 @@ density = 0 pressure_resistance = 5*ONE_ATMOSPHERE level = 2 - var/ptype = 0 - // 0=straight, 1=bent, 2=junction-j1, 3=junction-j2, 4=junction-y, 5=trunk, 6=disposal bin, 7=outlet, 8=inlet - + var/ptype = PIPE_DISPOSALS_STRAIGHT //Use the defines + var/base_state var/dpdir = 0 // directions as disposalpipe - var/base_state = "pipe-s" + +/obj/structure/disposalconstruct/New(loc, pipe_type, direction) + ..() + if(pipe_type) + ptype = pipe_type + if(dir) + dir = direction + update() // update iconstate and dpdir due to dir and type /obj/structure/disposalconstruct/proc/update() + base_state = get_pipe_icon(ptype) + icon_state = "con[base_state]" var/flip = turn(dir, 180) var/left = turn(dir, 90) var/right = turn(dir, -90) - + name = get_pipe_name(ptype, PIPETYPE_DISPOSAL) switch(ptype) - if(0) - base_state = "pipe-s" + if(PIPE_DISPOSALS_STRAIGHT) dpdir = dir | flip - if(1) - base_state = "pipe-c" + if(PIPE_DISPOSALS_BENT) dpdir = dir | right - if(2) - base_state = "pipe-j1" + if(PIPE_DISPOSALS_JUNCTION_RIGHT) dpdir = dir | right | flip - if(3) - base_state = "pipe-j2" + if(PIPE_DISPOSALS_JUNCTION_LEFT) dpdir = dir | left | flip - if(4) - base_state = "pipe-y" + if(PIPE_DISPOSALS_Y_JUNCTION) dpdir = dir | left | right - if(5) - base_state = "pipe-t" + if(PIPE_DISPOSALS_TRUNK) dpdir = dir - // disposal bin has only one dir, thus we don't need to care about setting it - if(6) - if(anchored) - base_state = "disposal" - else - base_state = "condisposal" - - if(7) - base_state = "outlet" - dpdir = dir - - if(8) - base_state = "intake" - dpdir = dir - - if(9) - base_state = "pipe-j1s" + if(PIPE_DISPOSALS_SORT_RIGHT) dpdir = dir | right | flip - - if(10) - base_state = "pipe-j2s" + if(PIPE_DISPOSALS_SORT_LEFT) dpdir = dir | left | flip - - - if(ptype<6 || ptype>8) + // disposal bin has only one dir, thus we don't need to care about setting it + if(PIPE_DISPOSALS_BIN) + if(!anchored) + icon_state = "[base_state]-unanchored" + else + icon_state = base_state + if(PIPE_DISPOSALS_OUTLET) + dpdir = dir + icon_state = base_state + if(PIPE_DISPOSALS_CHUTE) + dpdir = dir + icon_state = base_state + if(!(ptype in list(PIPE_DISPOSALS_BIN, PIPE_DISPOSALS_OUTLET, PIPE_DISPOSALS_CHUTE))) icon_state = "con[base_state]" - else - icon_state = base_state - if(invisibility) // if invisible, fade icon icon -= rgb(0,0,0,128) @@ -116,33 +107,33 @@ dir = turn(dir, 180) switch(ptype) - if(2) - ptype = 3 - if(3) - ptype = 2 - if(9) - ptype = 10 - if(10) - ptype = 9 + if(PIPE_DISPOSALS_JUNCTION_RIGHT) + ptype = PIPE_DISPOSALS_JUNCTION_LEFT + if(PIPE_DISPOSALS_JUNCTION_LEFT) + ptype = PIPE_DISPOSALS_JUNCTION_RIGHT + if(PIPE_DISPOSALS_SORT_RIGHT) + ptype = PIPE_DISPOSALS_SORT_LEFT + if(PIPE_DISPOSALS_SORT_LEFT) + ptype = PIPE_DISPOSALS_SORT_RIGHT update() // returns the type path of disposalpipe corresponding to this item dtype /obj/structure/disposalconstruct/proc/dpipetype() switch(ptype) - if(0,1) + if(PIPE_DISPOSALS_STRAIGHT, PIPE_DISPOSALS_BENT) return /obj/structure/disposalpipe/segment - if(2,3,4) + if(PIPE_DISPOSALS_JUNCTION_RIGHT, PIPE_DISPOSALS_JUNCTION_LEFT, PIPE_DISPOSALS_Y_JUNCTION) return /obj/structure/disposalpipe/junction - if(5) + if(PIPE_DISPOSALS_TRUNK) return /obj/structure/disposalpipe/trunk - if(6) + if(PIPE_DISPOSALS_BIN) return /obj/machinery/disposal - if(7) + if(PIPE_DISPOSALS_OUTLET) return /obj/structure/disposaloutlet - if(8) + if(PIPE_DISPOSALS_CHUTE) return /obj/machinery/disposal/deliveryChute - if(9,10) + if(PIPE_DISPOSALS_SORT_RIGHT, PIPE_DISPOSALS_SORT_LEFT) return /obj/structure/disposalpipe/sortjunction return @@ -157,13 +148,13 @@ var/ispipe = 0 // Indicates if we should change the level of this pipe src.add_fingerprint(user) switch(ptype) - if(6) + if(PIPE_DISPOSALS_BIN) nicetype = "disposal bin" - if(7) + if(PIPE_DISPOSALS_OUTLET) nicetype = "disposal outlet" - if(8) + if(PIPE_DISPOSALS_CHUTE) nicetype = "delivery chute" - if(9, 10) + if(PIPE_DISPOSALS_SORT_RIGHT, PIPE_DISPOSALS_SORT_LEFT) nicetype = "sorting pipe" ispipe = 1 else @@ -197,7 +188,7 @@ return var/obj/structure/disposalpipe/CP = locate() in T - if(ptype>=6 && ptype <= 8) // Disposal or outlet + if(ptype in list(PIPE_DISPOSALS_BIN, PIPE_DISPOSALS_OUTLET, PIPE_DISPOSALS_CHUTE)) // Disposal or outlet if(CP) // There's something there if(!istype(CP,/obj/structure/disposalpipe/trunk)) to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.") @@ -236,24 +227,22 @@ P.update_icon() //Needs some special treatment ;) - if(ptype==9 || ptype==10) + if(ptype == PIPE_DISPOSALS_SORT_RIGHT || ptype == PIPE_DISPOSALS_SORT_LEFT) var/obj/structure/disposalpipe/sortjunction/SortP = P SortP.updatedir() - else if(ptype==6) // Disposal bin + else if(ptype == PIPE_DISPOSALS_BIN) // Disposal bin var/obj/machinery/disposal/P = new /obj/machinery/disposal(src.loc) src.transfer_fingerprints_to(P) P.mode = 0 // start with pump off - else if(ptype==7) // Disposal outlet + else if(ptype == PIPE_DISPOSALS_OUTLET) // Disposal outlet var/obj/structure/disposaloutlet/P = new /obj/structure/disposaloutlet(src.loc) src.transfer_fingerprints_to(P) P.dir = dir - var/obj/structure/disposalpipe/trunk/Trunk = CP - Trunk.linked = P - else if(ptype==8) // Disposal outlet + else if(ptype==PIPE_DISPOSALS_CHUTE) // Disposal outlet var/obj/machinery/disposal/deliveryChute/P = new /obj/machinery/disposal/deliveryChute(src.loc) src.transfer_fingerprints_to(P) @@ -267,3 +256,13 @@ else to_chat(user, "You need to attach it to the plating first!") return + +/obj/structure/disposalconstruct/rpd_act(mob/user, obj/item/rpd/our_rpd) + if(our_rpd.mode == RPD_ROTATE_MODE) + rotate() + else if(our_rpd.mode == RPD_FLIP_MODE) + flip() + else if(our_rpd.mode == RPD_DELETE_MODE) + our_rpd.delete_single_pipe(user, src) + else + ..() diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 3907ed052a6..476028b4532 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -36,19 +36,19 @@ update() /obj/machinery/disposal/proc/trunk_check() - trunk = locate() in src.loc - if(!trunk) + var/obj/structure/disposalpipe/trunk/T = locate() in loc + if(!T) mode = 0 flush = 0 else mode = initial(mode) flush = initial(flush) - trunk.linked = src // link the pipe trunk to self + T.nicely_link_to_other_stuff(src) /obj/machinery/disposal/Destroy() eject() if(trunk) - trunk.linked = null + trunk.remove_trunk_links() return ..() /obj/machinery/disposal/Initialize() @@ -97,7 +97,7 @@ to_chat(user, "You sliced the floorweld off the disposal unit.") var/obj/structure/disposalconstruct/C = new (src.loc) src.transfer_fingerprints_to(C) - C.ptype = 6 // 6 = disposal unit + C.ptype = PIPE_DISPOSALS_BIN C.anchored = 1 C.density = 1 C.update() @@ -133,7 +133,7 @@ for(var/mob/C in viewers(src)) C.show_message("[GM.name] has been placed in the [src] by [user].", 3) qdel(G) - add_attack_logs(usr, GM, "Disposal'ed", !!GM.ckey) + add_attack_logs(usr, GM, "Disposal'ed", !!GM.ckey ? null : ATKLOG_ALL) return if(!I) @@ -179,7 +179,7 @@ msg = "[user.name] stuffs [target.name] into the [src]!" to_chat(user, "You stuff [target.name] into the [src]!") - add_attack_logs(user, target, "Disposal'ed", !!target.ckey) + add_attack_logs(user, target, "Disposal'ed", !!target.ckey ? null : ATKLOG_ALL) else return target.forceMove(src) @@ -889,21 +889,21 @@ var/obj/structure/disposalconstruct/C = new (src.loc) switch(base_icon_state) if("pipe-s") - C.ptype = 0 + C.ptype = PIPE_DISPOSALS_STRAIGHT if("pipe-c") - C.ptype = 1 + C.ptype = PIPE_DISPOSALS_BENT if("pipe-j1") - C.ptype = 2 + C.ptype = PIPE_DISPOSALS_JUNCTION_RIGHT if("pipe-j2") - C.ptype = 3 + C.ptype = PIPE_DISPOSALS_JUNCTION_LEFT if("pipe-y") - C.ptype = 4 + C.ptype = PIPE_DISPOSALS_Y_JUNCTION if("pipe-t") - C.ptype = 5 + C.ptype = PIPE_DISPOSALS_TRUNK if("pipe-j1s") - C.ptype = 9 + C.ptype = PIPE_DISPOSALS_SORT_RIGHT if("pipe-j2s") - C.ptype = 10 + C.ptype = PIPE_DISPOSALS_SORT_LEFT src.transfer_fingerprints_to(C) C.dir = dir C.density = 0 @@ -1149,24 +1149,39 @@ if(D.trunk == src) D.go_out() D.trunk = null - - linked = null + remove_trunk_links() return ..() /obj/structure/disposalpipe/trunk/proc/getlinked() - linked = null var/obj/machinery/disposal/D = locate() in src.loc if(D) - linked = D - if(!D.trunk) - D.trunk = src - + nicely_link_to_other_stuff(D) + return var/obj/structure/disposaloutlet/O = locate() in src.loc if(O) - linked = O + nicely_link_to_other_stuff(O) - update() - return +/obj/structure/disposalpipe/trunk/proc/remove_trunk_links() //disposals is well-coded + if(!linked) + return + else if(istype(linked, /obj/machinery/disposal)) //jk lol + var/obj/machinery/disposal/D = linked + D.trunk = null + else if(istype(linked, /obj/structure/disposaloutlet)) //God fucking damn it + var/obj/structure/disposaloutlet/D = linked + D.linkedtrunk = null + linked = null + +/obj/structure/disposalpipe/trunk/proc/nicely_link_to_other_stuff(obj/O) + remove_trunk_links() //Breaks the connections between this trunk and the linked machinery so we don't get sent to nullspace or some shit like that + if(istype(O, /obj/machinery/disposal)) + var/obj/machinery/disposal/D = O + linked = D + D.trunk = src + else if(istype(O, /obj/structure/disposaloutlet)) + var/obj/structure/disposaloutlet/D = O + linked = D + D.linkedtrunk = src // Override attackby so we disallow trunkremoval when somethings ontop /obj/structure/disposalpipe/trunk/attackby(var/obj/item/I, var/mob/user, params) @@ -1271,77 +1286,72 @@ var/obj/structure/disposalpipe/trunk/linkedtrunk var/mode = 0 - New() - ..() - - spawn(1) - target = get_ranged_target_turf(src, dir, 10) - - - linkedtrunk = locate() in src.loc - if(linkedtrunk) - linkedtrunk.linked = src +/obj/structure/disposaloutlet/New() + ..() + spawn(1) + target = get_ranged_target_turf(src, dir, 10) + var/obj/structure/disposalpipe/trunk/T = locate() in loc + if(T) + T.nicely_link_to_other_stuff(src) // expel the contents of the holder object, then delete it // called when the holder exits the outlet - proc/expel(var/obj/structure/disposalholder/H, animation = 1) - - if(animation) - flick("outlet-open", src) - playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0) - sleep(20) //wait until correct animation frame - playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - - if(H) - for(var/atom/movable/AM in H) - AM.forceMove(loc) - AM.pipe_eject(dir) - if(!istype(AM,/mob/living/silicon/robot/drone)) //Drones keep smashing windows from being fired out of chutes. Bad for the station. ~Z - spawn(5) - if(AM) - AM.throw_at(target, 3, 1) - H.vent_gas(src.loc) - qdel(H) +/obj/structure/disposaloutlet/proc/expel(var/obj/structure/disposalholder/H, animation = 1) + if(animation) + flick("outlet-open", src) + playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0) + sleep(20) //wait until correct animation frame + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + if(H) + for(var/atom/movable/AM in H) + AM.forceMove(loc) + AM.pipe_eject(dir) + if(!istype(AM,/mob/living/silicon/robot/drone)) //Drones keep smashing windows from being fired out of chutes. Bad for the station. ~Z + spawn(5) + if(AM) + AM.throw_at(target, 3, 1) + H.vent_gas(src.loc) + qdel(H) - attackby(var/obj/item/I, var/mob/user, params) - if(!I || !user) +/obj/structure/disposaloutlet/attackby(var/obj/item/I, var/mob/user, params) + if(!I || !user) + return + src.add_fingerprint(user) + if(istype(I, /obj/item/screwdriver)) + if(mode==0) + mode=1 + playsound(src.loc, I.usesound, 50, 1) + to_chat(user, "You remove the screws around the power connection.") + return + else if(mode==1) + mode=0 + playsound(src.loc, I.usesound, 50, 1) + to_chat(user, "You attach the screws around the power connection.") + return + else if(istype(I,/obj/item/weldingtool) && mode==1) + var/obj/item/weldingtool/W = I + if(W.remove_fuel(0,user)) + playsound(src.loc, W.usesound, 100, 1) + to_chat(user, "You start slicing the floorweld off the disposal outlet.") + if(do_after(user, 20 * W.toolspeed, target = src)) + if(!src || !W.isOn()) return + to_chat(user, "You sliced the floorweld off the disposal outlet.") + var/obj/structure/disposalconstruct/C = new (src.loc) + src.transfer_fingerprints_to(C) + C.ptype = PIPE_DISPOSALS_OUTLET + C.update() + C.anchored = 1 + C.density = 1 + qdel(src) + return + else + to_chat(user, "You need more welding fuel to complete this task.") return - src.add_fingerprint(user) - if(istype(I, /obj/item/screwdriver)) - if(mode==0) - mode=1 - playsound(src.loc, I.usesound, 50, 1) - to_chat(user, "You remove the screws around the power connection.") - return - else if(mode==1) - mode=0 - playsound(src.loc, I.usesound, 50, 1) - to_chat(user, "You attach the screws around the power connection.") - return - else if(istype(I,/obj/item/weldingtool) && mode==1) - var/obj/item/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(src.loc, W.usesound, 100, 1) - to_chat(user, "You start slicing the floorweld off the disposal outlet.") - if(do_after(user, 20 * W.toolspeed, target = src)) - if(!src || !W.isOn()) return - to_chat(user, "You sliced the floorweld off the disposal outlet.") - var/obj/structure/disposalconstruct/C = new (src.loc) - src.transfer_fingerprints_to(C) - C.ptype = 7 // 7 = outlet - C.update() - C.anchored = 1 - C.density = 1 - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return /obj/structure/disposaloutlet/Destroy() if(linkedtrunk) - linkedtrunk.linked = null + linkedtrunk.remove_trunk_links() return ..() // called when movable is expelled from a disposal pipe or outlet diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index c40ed9fe73b..8b2f7c4197f 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -349,7 +349,7 @@ if(!src || !W.isOn()) return to_chat(user, "You sliced the floorweld off the delivery chute.") var/obj/structure/disposalconstruct/C = new (src.loc) - C.ptype = 8 // 8 = Delivery chute + C.ptype = PIPE_DISPOSALS_CHUTE C.update() C.anchored = 1 C.density = 1 diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index b7919662514..bba85a5ff00 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -591,6 +591,14 @@ build_path = /obj/item/reagent_containers/syringe category = list("initial", "Medical") +/datum/design/safety_hypo + name = "Medical Hypospray" + id = "safetyhypo" + build_type = AUTOLATHE + materials = list(MAT_METAL = 500, MAT_GLASS = 500) + build_path = /obj/item/reagent_containers/hypospray/safety + category = list("initial", "Medical") + /datum/design/prox_sensor name = "Proximity Sensor" id = "prox_sensor" @@ -800,6 +808,14 @@ build_path = /obj/item/conveyor_switch_construct category = list("initial", "Construction") +/datum/design/conveyor_belt_placer + name = "Conveyor Belt Placer" + id = "conveyor_belt_placer" + build_type = AUTOLATHE + materials = list(MAT_METAL = 5000, MAT_GLASS = 1000) //This thing doesn't need to be very resource-intensive as the belts are already expensive + build_path = /obj/item/storage/conveyor + category = list("initial", "Construction") + /datum/design/laptop name = "Laptop Frame" id = "laptop" diff --git a/code/modules/research/designs/bluespace_designs.dm b/code/modules/research/designs/bluespace_designs.dm index 3c555c40849..cf6e4b53882 100644 --- a/code/modules/research/designs/bluespace_designs.dm +++ b/code/modules/research/designs/bluespace_designs.dm @@ -51,13 +51,23 @@ build_path = /obj/item/storage/bag/ore/holding category = list("Bluespace") +/datum/design/bluespace_belt_holder + name = "Bluespace Conveyor Belt Placer" + desc = "This device facilitates the rapid deployment of conveyor belts. This one is powered by bluespace." + id = "bluespace_belt_holder" + req_tech = list("materials" = 1, "engineering" = 3, "bluespace" = 3) + build_type = PROTOLATHE + materials = list(MAT_METAL = 5000, MAT_GLASS = 1000, MAT_SILVER = 500) //Costs similar materials to the basic one, but this one needs silver + build_path = /obj/item/storage/conveyor/bluespace + category = list("Bluespace") + /datum/design/telepad_beacon name = "Telepad Beacon" desc = "Use to warp in a cargo telepad." id = "telepad_beacon" req_tech = list("programming" = 5, "bluespace" = 4, "engineering" = 4, "plasmatech" = 4) build_type = PROTOLATHE - materials = list (MAT_METAL = 2000, MAT_GLASS = 1750, MAT_SILVER = 500) + materials = list(MAT_METAL = 2000, MAT_GLASS = 1750, MAT_SILVER = 500) build_path = /obj/item/telepad_beacon category = list("Bluespace") @@ -67,6 +77,6 @@ id = "beacon" req_tech = list("bluespace" = 1) build_type = PROTOLATHE - materials = list (MAT_METAL = 150, MAT_GLASS = 100) + materials = list(MAT_METAL = 150, MAT_GLASS = 100) build_path = /obj/item/radio/beacon category = list("Bluespace") diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 7fde20333c7..1589b78438b 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -1120,6 +1120,15 @@ construction_time = 350 category = list("Misc") +/datum/design/integrated_robotic_chassis + name = "Integrated Robotic Chassis" + id = "integrated_robotic_chassis" + build_type = MECHFAB + build_path = /mob/living/carbon/human/machine/created + materials = list(MAT_METAL = 40000) + construction_time = 400 + category = list("Misc") + /datum/design/ipc_cell name = "IPC Microbattery" id = "ipc_cell" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 9d973c1ed74..a7fe42063ff 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -103,26 +103,26 @@ build_path = /obj/item/mass_spectrometer category = list("Medical") -/datum/design/posibrain - name = "Positronic Brain" - desc = "The latest in Artificial Intelligences." - id = "mmi_posi" +/datum/design/robotic_brain + name = "Robotic Brain" + desc = "The latest in non-sentient Artificial Intelligences." + id = "mmi_robotic" req_tech = list("programming" = 5, "biotech" = 4, "plasmatech" = 3) build_type = PROTOLATHE | MECHFAB materials = list(MAT_METAL = 1700, MAT_GLASS = 1350, MAT_GOLD = 500) //Gold, because SWAG. construction_time = 75 - build_path = /obj/item/mmi/posibrain + build_path = /obj/item/mmi/robotic_brain category = list("Misc","Medical") -/datum/design/mmi_radio - name = "Radio-Enabled Man-Machine Interface" - desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity. This one comes with a built-in radio." - id = "mmi_radio" +/datum/design/mmi_radio_upgrade + name = "Man-Machine Interface Radio Upgrade" + desc = "Enables radio capability on MMIs when either installed directly on the MMI, or through a cyborg's chassis." + id = "mmi_radio_upgrade" req_tech = list("programming" = 3, "biotech" = 2, "engineering" = 2) build_type = PROTOLATHE | MECHFAB - materials = list(MAT_METAL = 1200, MAT_GLASS = 500) - construction_time = 75 - build_path = /obj/item/mmi/radio_enabled + materials = list(MAT_METAL = 200) + construction_time = 50 + build_path = /obj/item/mmi_radio_upgrade category = list("Misc","Medical") /datum/design/nanopaste @@ -181,7 +181,7 @@ id = "scalpel_manager" req_tech = list("biotech" = 4, "materials" = 7, "magnets" = 5, "programming" = 4) build_type = PROTOLATHE - materials = list (MAT_METAL = 2000, MAT_GLASS = 1500, MAT_SILVER = 1000, MAT_GOLD = 1000, MAT_DIAMOND = 1000) + materials = list(MAT_METAL = 2000, MAT_GLASS = 1500, MAT_SILVER = 1000, MAT_GOLD = 1000, MAT_DIAMOND = 1000) build_path = /obj/item/scalpel/laser/manager category = list("Medical") @@ -245,6 +245,36 @@ materials = list(MAT_METAL = 2000, MAT_SILVER = 1500, MAT_PLASMA = 500, MAT_TITANIUM = 1500) category = list("Medical") +/datum/design/alienbonegel + name = "Alien Bone Gel" + desc = "Advanced bone gel obtained through Abductor technology." + id = "alien_bonegel" + req_tech = list("biotech" = 4, "materials" = 4, "abductor" = 3) + build_path = /obj/item/bonegel/alien + build_type = PROTOLATHE + materials = list(MAT_METAL = 2000, MAT_SILVER = 1500, MAT_PLASMA = 500, MAT_TITANIUM = 1500) + category = list("Medical") + +/datum/design/alienbonesetter + name = "Alien Bone Setter" + desc = "An advanced bone setter obtained through Abductor technology." + id = "alien_bonesetter" + req_tech = list("biotech" = 4, "materials" = 4, "abductor" = 3) + build_path = /obj/item/bonesetter/alien + build_type = PROTOLATHE + materials = list(MAT_METAL = 2000, MAT_SILVER = 1500, MAT_PLASMA = 500, MAT_TITANIUM = 1500) + category = list("Medical") + +/datum/design/alienfixovein + name = "Alien FixOVein" + desc = "An advanced FixOVein obtained through Abductor technology." + id = "alien_fixovein" + req_tech = list("biotech" = 4, "materials" = 4, "abductor" = 3) + build_path = /obj/item/FixOVein/alien + build_type = PROTOLATHE + materials = list(MAT_METAL = 2000, MAT_SILVER = 1500, MAT_PLASMA = 500, MAT_TITANIUM = 1500) + category = list("Medical") + ///////////////////////////////////////// //////////Cybernetic Implants//////////// ///////////////////////////////////////// @@ -271,13 +301,24 @@ build_path = /obj/item/organ/internal/cyberimp/mouth/breathing_tube category = list("Misc", "Medical") +/datum/design/cyberimp_surgical + name = "Surgical Arm Implant" + desc = "A set of surgical tools hidden behind a concealed panel on the user's arm." + id = "ci-surgey" + req_tech = list("materials" = 3, "engineering" = 3, "biotech" = 3, "programming" = 2, "magnets" = 3) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) + construction_time = 200 + build_path = /obj/item/organ/internal/cyberimp/arm/surgery + category = list("Misc", "Medical") + /datum/design/cyberimp_toolset name = "Toolset Arm Implant" desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm." id = "ci-toolset" req_tech = list("materials" = 3, "engineering" = 4, "biotech" = 4, "powerstorage" = 4) build_type = PROTOLATHE | MECHFAB - materials = list (MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) + materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) construction_time = 200 build_path = /obj/item/organ/internal/cyberimp/arm/toolset category = list("Misc", "Medical") @@ -435,3 +476,65 @@ materials = list(MAT_METAL = 500, MAT_GLASS = 500) build_path = /obj/item/implantcase/track category = list("Medical") + +//Cybernetic organs + +/datum/design/cybernetic_eyes + name = "Cybernetic Eyes" + desc = "A cybernetic pair of eyes" + id = "cybernetic_eyes" + req_tech = list("biotech" = 4, "materials" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 500, MAT_GLASS = 500) + build_path = /obj/item/organ/internal/eyes/cybernetic + category = list("Medical") + +/datum/design/cybernetic_liver + name = "Cybernetic Liver" + desc = "A cybernetic liver" + id = "cybernetic_liver" + req_tech = list("biotech" = 4, "materials" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 500, MAT_GLASS = 500) + build_path = /obj/item/organ/internal/liver/cybernetic + category = list("Medical") + +/datum/design/cybernetic_kidneys + name = "Cybernetic Kidneys" + desc = "A cybernetic pair of kidneys" + id = "cybernetic_kidneys" + req_tech = list("biotech" = 4, "materials" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 500, MAT_GLASS = 500) + build_path = /obj/item/organ/internal/kidneys/cybernetic + category = list("Medical") + +/datum/design/cybernetic_heart + name = "Cybernetic Heart" + desc = "A cybernetic heart" + id = "cybernetic_heart" + req_tech = list("biotech" = 4, "materials" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 500, MAT_GLASS = 500) + build_path = /obj/item/organ/internal/heart/cybernetic + category = list("Medical") + +/datum/design/cybernetic_lungs + name = "Cybernetic Lungs" + desc = "A pair of cybernetic lungs." + id = "cybernetic_lungs" + req_tech = list("biotech" = 4, "materials" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 500, MAT_GLASS = 500) + build_path = /obj/item/organ/internal/lungs/cybernetic + category = list("Medical") + +/datum/design/cybernetic_lungs_u + name = "Upgraded Cybernetic Lungs" + desc = "A pair of upgraded cybernetic lungs." + id = "cybernetic_lungs_u" + req_tech = list("biotech" = 5, "materials" = 5, "engineering" = 5) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500) + build_path = /obj/item/organ/internal/lungs/cybernetic/upgraded + category = list("Medical") \ No newline at end of file diff --git a/code/modules/research/designs/power_designs.dm b/code/modules/research/designs/power_designs.dm index 0b41a26256c..ec26ae39644 100644 --- a/code/modules/research/designs/power_designs.dm +++ b/code/modules/research/designs/power_designs.dm @@ -4,7 +4,7 @@ /datum/design/basic_cell name = "Basic Power Cell" - desc = "A basic power cell that holds 1000 units of energy" + desc = "A basic power cell that holds 1 kW of power." id = "basic_cell" req_tech = list("powerstorage" = 1) build_type = PROTOLATHE | AUTOLATHE | MECHFAB | PODFAB @@ -15,7 +15,7 @@ /datum/design/high_cell name = "High-Capacity Power Cell" - desc = "A power cell that holds 10000 units of energy" + desc = "A power cell that holds 10 kW of power." id = "high_cell" req_tech = list("powerstorage" = 2) build_type = PROTOLATHE | AUTOLATHE | MECHFAB | PODFAB @@ -26,7 +26,7 @@ /datum/design/hyper_cell name = "Hyper-Capacity Power Cell" - desc = "A power cell that holds 30000 units of energy" + desc = "A power cell that holds 30 kW of power." id = "hyper_cell" req_tech = list("powerstorage" = 5, "materials" = 5, "engineering" = 5) build_type = PROTOLATHE | MECHFAB | PODFAB @@ -37,7 +37,7 @@ /datum/design/super_cell name = "Super-Capacity Power Cell" - desc = "A power cell that holds 20000 units of energy" + desc = "A power cell that holds 20 kW of power." id = "super_cell" req_tech = list("powerstorage" = 3, "materials" = 3) build_type = PROTOLATHE | MECHFAB | PODFAB @@ -48,7 +48,7 @@ /datum/design/bluespace_cell name = "Bluespace Power Cell" - desc = "A power cell that holds 40000 units of energy." + desc = "A power cell that holds 40 kW of power." id = "bluespace_cell" req_tech = list("powerstorage" = 6, "materials" = 5, "engineering" = 5, "bluespace" = 5) build_type = PROTOLATHE | MECHFAB diff --git a/code/modules/research/designs/smelting_designs.dm b/code/modules/research/designs/smelting_designs.dm index fe45e8dacad..a043d90fb19 100644 --- a/code/modules/research/designs/smelting_designs.dm +++ b/code/modules/research/designs/smelting_designs.dm @@ -25,6 +25,22 @@ build_path = /obj/item/stack/sheet/plasmaglass category = list("initial") +/datum/design/titaniumglass_alloy + name = "Titanium + Glass alloy" + id = "titaniumglass" + build_type = SMELTER + materials = list(MAT_TITANIUM = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) + build_path = /obj/item/stack/sheet/titaniumglass + category = list("initial") + +/datum/design/plastitaniumglass_alloy + name = "Plasma + Titanium + Glass alloy" + id = "plastitaniumglass" + build_type = SMELTER + materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT, MAT_TITANIUM = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) + build_path = /obj/item/stack/sheet/plastitaniumglass + category = list("initial") + /datum/design/alienalloy name = "Alien Alloy" desc = "A sheet of reverse-engineered alien alloy." diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index 6fb2a891214..51b4f8512e1 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -43,15 +43,15 @@ if(shocked) shock(user,50) if(panel_open) - var/dat as text + var/list/dat = list() dat += "[src.name] Wires:
    " - for(var/wire in src.wires) - dat += text("[wire] Wire: [src.wires[wire] ? "Mend" : "Cut"] Pulse
    ") + for(var/wire in wires) + dat += "[wire] Wire: [src.wires[wire] ? "Mend" : "Cut"] Pulse
    " - dat += text("The red light is [src.disabled ? "off" : "on"].
    ") - dat += text("The green light is [src.shocked ? "off" : "on"].
    ") - dat += text("The blue light is [src.hacked ? "off" : "on"].
    ") - user << browse("[src.name] Hacking[dat]","window=hack_win") + dat += "The red light is [src.disabled ? "off" : "on"].
    " + dat += "The green light is [src.shocked ? "off" : "on"].
    " + dat += "The blue light is [src.hacked ? "off" : "on"].
    " + user << browse("[src.name] Hacking[dat.Join("")]","window=hack_win") return diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index ee884bc20a4..dcae187b028 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -22,7 +22,6 @@ desc = "A computer used for remotely handling slimes." networks = list("SS13") circuit = /obj/item/circuitboard/xenobiology - off_action = new /datum/action/innate/camera_off/xenobio var/datum/action/innate/slime_place/slime_place_action = new var/datum/action/innate/slime_pick_up/slime_up_action = new var/datum/action/innate/feed_slime/feed_slime_action = new @@ -43,23 +42,27 @@ eyeobj.icon_state = "camera_target" /obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/carbon/user) - off_action.target = user - off_action.Grant(user) + ..() + if(slime_up_action) + slime_up_action.target = src + slime_up_action.Grant(user) + actions += slime_up_action + + if(slime_place_action) + slime_place_action.target = src + slime_place_action.Grant(user) + actions += slime_place_action + + if(feed_slime_action) + feed_slime_action.target = src + feed_slime_action.Grant(user) + actions += feed_slime_action + + if(monkey_recycle_action) + monkey_recycle_action.target = src + monkey_recycle_action.Grant(user) + actions += monkey_recycle_action - jump_action.target = user - jump_action.Grant(user) - - slime_up_action.target = src - slime_up_action.Grant(user) - - slime_place_action.target = src - slime_place_action.Grant(user) - - feed_slime_action.target = src - feed_slime_action.Grant(user) - - monkey_recycle_action.target = src - monkey_recycle_action.Grant(user) /obj/machinery/computer/camera_advanced/xenobio/attack_hand(mob/user) @@ -87,31 +90,6 @@ return ..() -/datum/action/innate/camera_off/xenobio/Activate() - if(!target || !ishuman(target)) - return - var/mob/living/carbon/C = target - var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - var/obj/machinery/computer/camera_advanced/xenobio/origin = remote_eye.origin - C.remote_view = 0 - origin.current_user = null - origin.jump_action.Remove(C) - origin.slime_place_action.Remove(C) - origin.slime_up_action.Remove(C) - origin.feed_slime_action.Remove(C) - origin.monkey_recycle_action.Remove(C) - //All of this stuff below could probably be a proc for all advanced cameras, only the action removal needs to be camera specific - remote_eye.eye_user = null - C.reset_perspective(null) - if(C.client) - C.client.images -= remote_eye.user_image - for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks) - C.client.images -= chunk.obscured - C.remote_control = null - C.unset_machine() - src.Remove(C) - - /datum/action/innate/slime_place name = "Place Slimes" button_icon_state = "slime_down" @@ -190,7 +168,7 @@ if(cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/carbon/human/M in remote_eye.loc) if(issmall(M) && M.stat) - M.visible_message("[M] vanishes as they are reclaimed for recycling!") + M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!") X.monkeys = round(X.monkeys + 0.2,0.1) qdel(M) else diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index d8058efbb53..35bdb18caae 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -205,7 +205,7 @@ SM.master_commander = user SM.sentience_act() to_chat(SM, "All at once it makes sense: you know what you are and who you are! Self awareness is yours!") - to_chat(SM, "You are grateful to be self aware and owe [user] a great debt. Serve [user], and assist them in completing their goals at any cost.") + to_chat(SM, "You are grateful to be self aware and owe [user] a great debt. Serve [user], and assist [user.p_them()] in completing [user.p_their()] goals at any cost.") if(SM.flags_2 & HOLOGRAM_2) //Check to see if it's a holodeck creature to_chat(SM, "You also become depressingly aware that you are not a real creature, but instead a holoform. Your existence is limited to the parameters of the holodeck.") to_chat(user, "[M] accepts the potion and suddenly becomes attentive and aware. It worked!") @@ -426,7 +426,7 @@ G.loc = src.loc G.key = ghost.key add_attack_logs(user, G, "Summoned as a golem") - to_chat(G, "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost.") + to_chat(G, "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist [user.p_them()] in completing [user.p_their()] goals at any cost.") qdel(src) /obj/effect/golemrune/Topic(href,href_list) diff --git a/code/modules/scripting/Implementations/Telecomms.dm b/code/modules/scripting/Implementations/Telecomms.dm index 16640a8b4c8..0e9053bbb44 100644 --- a/code/modules/scripting/Implementations/Telecomms.dm +++ b/code/modules/scripting/Implementations/Telecomms.dm @@ -24,14 +24,22 @@ interpreter.GC() +//temp +/datum/TCS_Compiler + var/datum/n_scriptOptions/nS_Options/options + var/datum/n_Scanner/nS_Scanner/scanner + var/list/tokens + var/datum/n_Parser/nS_Parser/parser + var/datum/node/BlockDefinition/GlobalBlock/program + /* -- Compile a raw block of text -- */ -/datum/TCS_Compiler/proc/Compile(code as message) - var/datum/n_scriptOptions/nS_Options/options = new() - var/datum/n_Scanner/nS_Scanner/scanner = new(code, options) - var/list/tokens = scanner.Scan() - var/datum/n_Parser/nS_Parser/parser = new(tokens, options) - var/datum/node/BlockDefinition/GlobalBlock/program = parser.Parse() +/datum/TCS_Compiler/proc/Compile(list/code) + options = new() + scanner = new(code, options) + tokens = scanner.Scan() + parser = new(tokens, options) + program = parser.Parse() var/list/returnerrors = list() @@ -240,7 +248,7 @@ But I like HTML, so back to no sanitizing.*/ var/message = interpreter.GetVar("$content") - var/regex/bannedTags = new ("( object used to configure the scanner. */ -/datum/n_Scanner/nS_Scanner/New(var/code, var/datum/n_scriptOptions/nS_Options/options) +/datum/n_Scanner/nS_Scanner/New(var/list/c, var/datum/n_scriptOptions/nS_Options/options) . = ..() ignore += ascii2text(13) //Carriage return delim += ignore + options.symbols + end_stmt + string_delim src.options = options - LoadCode(code) + LoadCode(c) /datum/n_Scanner/nS_Scanner/Scan() //Creates a list of tokens from source code var/list/tokens = new - for(, src.codepos <= length(code), src.codepos++) - - var/char = copytext(code, codepos, codepos + 1) - var/nextchar = copytext(code, codepos + 1, codepos + 2) + for(, src.codepos <= code.len, src.codepos++) + var/char = code[codepos] + var/nextchar = TCOMMS_SAFE_INDEX(code, codepos + 1) if(char == "\n") line++ linepos = codepos - if(ignore.Find(char)) + if(char in ignore) continue else if(char == "/" && (nextchar == "*" || nextchar == "/")) @@ -139,6 +138,7 @@ else if(options.symbols.Find(char)) tokens += ReadSymbol() + CHECK_TICK codepos = initial(codepos) line = initial(line) @@ -155,12 +155,12 @@ */ /datum/n_Scanner/nS_Scanner/proc/ReadString(start) var/buf - for(, codepos <= length(code), codepos++)//codepos to length(code)) - var/char = copytext(code, codepos, codepos + 1) + for(, codepos <= code.len, codepos++)//codepos to length(code)) + var/char = code[codepos] switch(char) if("\\") //Backslash (\) encountered in string codepos++ //Skip next character in string, since it was escaped by a backslash - char = copytext(code, codepos, codepos+1) + char = TCOMMS_SAFE_INDEX(code, codepos) switch(char) if("\\") //Double backslash buf += "\\" @@ -190,12 +190,14 @@ Reads characters separated by an item in into a token. */ /datum/n_Scanner/nS_Scanner/proc/ReadWord() - var/char = copytext(code, codepos, codepos + 1) + var/char = code[codepos] var/buf - while(!delim.Find(char) && codepos <= length(code)) + while(!delim.Find(char)) buf += char - char = copytext(code, ++codepos, codepos + 1) + if(++codepos > code.len) break + char = code[codepos] + codepos-- //allow main Scan() proc to read the delimiter if(options.keywords.Find(buf)) return new/datum/token/keyword(buf, line, COL) @@ -207,13 +209,13 @@ Reads a symbol into a token. */ /datum/n_Scanner/nS_Scanner/proc/ReadSymbol() - var/char=copytext(code, codepos, codepos + 1) + var/char = code[codepos] var/buf while(options.symbols.Find(buf + char)) buf += char - if(++codepos > length(code)) break - char = copytext(code, codepos, codepos + 1) + if(++codepos > code.len) break + char = code[codepos] codepos-- //allow main Scan() proc to read the next character return new /datum/token/symbol(buf, line, COL) @@ -223,7 +225,7 @@ Reads a number into a token. */ /datum/n_Scanner/nS_Scanner/proc/ReadNumber() - var/char = copytext(code, codepos, codepos + 1) + var/char = code[codepos] var/buf var/dec = 0 @@ -233,7 +235,7 @@ buf += char codepos++ - char = copytext(code, codepos, codepos + 1) + char = TCOMMS_SAFE_INDEX(code, codepos) var/datum/token/number/T = new(buf, line, COL) if(isnull(text2num(buf))) @@ -249,8 +251,8 @@ */ /datum/n_Scanner/nS_Scanner/proc/ReadComment() - var/char = copytext(code, codepos, codepos + 1) - var/nextchar = copytext(code, codepos + 1, codepos + 2) + var/char = code[codepos] + var/nextchar = TCOMMS_SAFE_INDEX(code, codepos + 1) var/charstring = char + nextchar var/comm = 1 // 1: single-line comment @@ -262,23 +264,23 @@ comm = 2 // starts a multi-line comment while(comm) - if(++codepos > length(code)) + if(++codepos > code.len) break if(expectedend) // ending statement expected... - char = copytext(code, codepos, codepos + 1) + char = code[codepos] if(char == "/") // ending statement found - beak the comment comm = 0 break if(comm == 2) // multi-line comments are broken by ending statements - char = copytext(code, codepos, codepos + 1) + char = code[codepos] if(char == "*") expectedend = 1 continue else - char = copytext(code, codepos, codepos + 1) + char = code[codepos] if(char == "\n") comm = 0 break diff --git a/code/modules/scripting/__defines.dm b/code/modules/scripting/__defines.dm new file mode 100644 index 00000000000..52f30e68fdc --- /dev/null +++ b/code/modules/scripting/__defines.dm @@ -0,0 +1 @@ +#define TCOMMS_SAFE_INDEX(list, index) list.len > index ? list[index] : null diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index c8f36cfa37e..54f4836ff5b 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -1,4 +1,5 @@ //use this define to highlight docking port bounding boxes (ONLY FOR DEBUG USE) +// also uncomment the #undef at the bottom of the file //#define DOCKING_PORT_HIGHLIGHT //NORTH default dir @@ -909,7 +910,7 @@ var/global/trade_dockrequest_timelimit = 0 shuttleId = "trade_sol" docking_request_message = "A trading ship of Sol origin has requested docking aboard the NSS Cyberiad for trading. This request can be accepted or denied using a communications console." -#undef DOCKING_PORT_HIGHLIGHT +//#undef DOCKING_PORT_HIGHLIGHT /turf/proc/copyTurf(turf/T) diff --git a/code/modules/space_management/level_traits.dm b/code/modules/space_management/level_traits.dm index ae5d6447aae..39b584df64d 100644 --- a/code/modules/space_management/level_traits.dm +++ b/code/modules/space_management/level_traits.dm @@ -1,62 +1,63 @@ /proc/is_level_reachable(z) - return check_level_trait(z, REACHABLE) + return check_level_trait(z, REACHABLE) /proc/is_station_level(z) - return check_level_trait(z, STATION_LEVEL) + return check_level_trait(z, STATION_LEVEL) /proc/is_station_contact(z) - return check_level_trait(z, STATION_CONTACT) + return check_level_trait(z, STATION_CONTACT) /proc/is_teleport_allowed(z) - return !check_level_trait(z, BLOCK_TELEPORT) + return !check_level_trait(z, BLOCK_TELEPORT) /proc/is_admin_level(z) - return check_level_trait(z, ADMIN_LEVEL) + return check_level_trait(z, ADMIN_LEVEL) /proc/is_away_level(z) - return check_level_trait(z, AWAY_LEVEL) + return check_level_trait(z, AWAY_LEVEL) /proc/is_mining_level(z) - return check_level_trait(z, ORE_LEVEL) + return check_level_trait(z, ORE_LEVEL) /proc/is_ai_allowed(z) - return check_level_trait(z, AI_OK) + return check_level_trait(z, AI_OK) /proc/level_blocks_magic(z) - return check_level_trait(z, IMPEDES_MAGIC) + return check_level_trait(z, IMPEDES_MAGIC) /proc/level_boosts_signal(z) - return check_level_trait(z, BOOSTS_SIGNAL) + return check_level_trait(z, BOOSTS_SIGNAL) // Used for the nuke disk, or for checking if players survived through xenos /proc/is_secure_level(z) - var/secure = check_level_trait(z, STATION_LEVEL) - if(!secure) - // This is to allow further admin levels later, other than centcomm - secure = (z == level_name_to_num(CENTCOMM)) - return secure + var/secure = check_level_trait(z, STATION_LEVEL) + if(!secure) + // This is to allow further admin levels later, other than centcomm + secure = (z == level_name_to_num(CENTCOMM)) + return secure var/list/default_map_traits = MAP_TRANSITION_CONFIG + /proc/check_level_trait(z, trait) - if(!z) - return 0 // If you're nowhere, you have no traits - var/list/trait_list - if(space_manager.initialized) - var/datum/space_level/S = space_manager.get_zlev(z) - trait_list = S.flags - else - trait_list = default_map_traits[z] - trait_list = trait_list["attributes"] - return (trait in trait_list) + if(!z) + return 0 // If you're nowhere, you have no traits + var/list/trait_list + if(space_manager.initialized) + var/datum/space_level/S = space_manager.get_zlev(z) + trait_list = S.flags + else + trait_list = default_map_traits[z] + trait_list = trait_list["attributes"] + return (trait in trait_list) /proc/levels_by_trait(trait) - var/list/result = list() - for(var/A in space_manager.z_list) - var/datum/space_level/S = space_manager.z_list[A] - if(trait in S.flags) - result |= S - return result + var/list/result = list() + for(var/A in space_manager.z_list) + var/datum/space_level/S = space_manager.z_list[A] + if(trait in S.flags) + result |= S.zpos + return result /proc/level_name_to_num(name) - var/datum/space_level/S = space_manager.get_zlev_by_name(name) - return S.zpos + var/datum/space_level/S = space_manager.get_zlev_by_name(name) + return S.zpos \ No newline at end of file diff --git a/code/modules/space_management/space_level.dm b/code/modules/space_management/space_level.dm index 38ec849179a..e2c18699a64 100644 --- a/code/modules/space_management/space_level.dm +++ b/code/modules/space_management/space_level.dm @@ -133,6 +133,10 @@ if(SELFLOOPING) link_to_self() // `link_to_self` is defined in space_transitions.dm +var/list/atmos_machine_typecache = typecacheof(/obj/machinery/atmospherics) +var/list/cable_typecache = typecacheof(/obj/structure/cable) +var/list/maploader_typecache = typecacheof(/obj/effect/landmark/map_loader) + /datum/space_level/proc/resume_init() if(dirt_count > 0) throw EXCEPTION("Init told to resume when z-level still dirty. Z level: '[zpos]'") @@ -140,23 +144,15 @@ log_debug("Beginning initialization!") var/list/our_atoms = init_list // OURS NOW!!! (Keeping this list to ourselves will prevent hijack) init_list = list() - var/list/late_maps = list() - var/list/pipes = list() - var/list/cables = list() var/watch = start_watch() - for(var/schmoo in our_atoms) - var/atom/movable/AM = schmoo - if(AM) // to catch stuff like the nuke disk that no longer exists - - // This can mess with our state - we leave these for last - if(istype(AM, /obj/effect/landmark/map_loader)) - late_maps.Add(AM) - continue - AM.Initialize(TRUE) - if(istype(AM, /obj/machinery/atmospherics)) - pipes.Add(AM) - else if(istype(AM, /obj/structure/cable)) - cables.Add(AM) + listclearnulls(our_atoms) + var/list/late_maps = typecache_filter_list(our_atoms, maploader_typecache) + var/list/pipes = typecache_filter_list(our_atoms, atmos_machine_typecache) + var/list/cables = typecache_filter_list(our_atoms, cable_typecache) + // If we don't carefully add dirt around the map templates, bad stuff happens + // so we separate them out here + our_atoms -= late_maps + SSatoms.InitializeAtoms(our_atoms, FALSE) log_debug("Primary initialization finished in [stop_watch(watch)]s.") our_atoms.Cut() if(pipes.len) @@ -168,13 +164,14 @@ /datum/space_level/proc/do_pipes(list/pipes) var/watch = start_watch() - log_debug("Building pipenets on z-level '[zpos]'!") - for(var/schmoo in pipes) - var/obj/machinery/atmospherics/machine = schmoo - if(machine) - machine.build_network() + log_debug("Initializing atmos machines on z-level '[zpos]'!") + var/init_count = SSair._setup_atmos_machinery(pipes) + log_debug("Initialized [init_count] machines, took [stop_watch(watch)]s") + watch = start_watch() + log_debug("Initializing pipe networks on z-level '[zpos]'!") + init_count = SSair._setup_pipenets(pipes) + log_debug("Initialized pipenets for [init_count] machines, took [stop_watch(watch)]s") pipes.Cut() - log_debug("Took [stop_watch(watch)]s") /datum/space_level/proc/do_cables(list/cables) var/watch = start_watch() @@ -187,10 +184,8 @@ var/watch = start_watch() log_debug("Loading map templates on z-level '[zpos]'!") space_manager.add_dirt(zpos) // Let's not repeatedly resume init for each template - for(var/schmoo in late_maps) - var/obj/effect/landmark/map_loader/ML = schmoo - if(ML) - ML.Initialize() + for(var/atom/movable/AM in late_maps) + AM.Initialize() late_maps.Cut() space_manager.remove_dirt(zpos) log_debug("Took [stop_watch(watch)]s") diff --git a/code/modules/space_management/zlevel_manager.dm b/code/modules/space_management/zlevel_manager.dm index 087a70657ed..acb1cf5c0a0 100644 --- a/code/modules/space_management/zlevel_manager.dm +++ b/code/modules/space_management/zlevel_manager.dm @@ -12,6 +12,8 @@ var/global/datum/zlev_manager/space_manager = new var/datum/spacewalk_grid/linkage_map var/initialized = 0 + var/list/areas_in_z = list() + // Populate our space level list // and prepare space transitions /datum/zlev_manager/proc/initialize() @@ -166,4 +168,4 @@ var/global/datum/zlev_manager/space_manager = new var/datum/space_level/heap/heap = z_list["[C.zpos]"] if(!istype(heap)) throw EXCEPTION("Attempted to free chunk at invalid z-level ([C.x],[C.y],[C.zpos]) [C.width]x[C.height]") - heap.free(C) + heap.free(C) \ No newline at end of file diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm index b845404fa35..52273af71fe 100644 --- a/code/modules/spacepods/equipment.dm +++ b/code/modules/spacepods/equipment.dm @@ -2,6 +2,7 @@ if(my_atom.next_firetime > world.time) to_chat(usr, "Your weapons are recharging.") return + my_atom.next_firetime = world.time + fire_delay var/turf/firstloc var/turf/secondloc if(!my_atom.equipment_system || !my_atom.equipment_system.weapon_system) @@ -41,7 +42,6 @@ projone.dumbfire(my_atom.dir) projtwo.dumbfire(my_atom.dir) sleep(2) - my_atom.next_firetime = world.time + fire_delay /datum/spacepod/equipment var/obj/spacepod/my_atom diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 794e5f69bfe..24123d52fc0 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -1,6 +1,6 @@ #define DAMAGE 1 #define FIRE 2 -#define LIGHT 1 +#define POD_LIGHT 1 #define WINDOW 2 #define RIM 3 #define PAINT 4 @@ -78,7 +78,7 @@ var/part = input(user, "Choose part", null) as null|anything in list("Lights","Rim","Paint","Windows") switch(part) if("Lights") - part_type = LIGHT + part_type = POD_LIGHT if("Rim") part_type = RIM if("Paint") @@ -101,7 +101,7 @@ pod_overlays[FIRE] = image(icon, icon_state="pod_fire") if(!pod_paint_effect) pod_paint_effect = new/list(4) - pod_paint_effect[LIGHT] = image(icon,icon_state = "LIGHTS") + pod_paint_effect[POD_LIGHT] = image(icon,icon_state = "LIGHTS") pod_paint_effect[WINDOW] = image(icon,icon_state = "Windows") pod_paint_effect[RIM] = image(icon,icon_state = "RIM") pod_paint_effect[PAINT] = image(icon,icon_state = "PAINT") @@ -162,7 +162,7 @@ if(!pod_paint_effect) pod_paint_effect = new/list(4) - pod_paint_effect[LIGHT] = image(icon,icon_state = "LIGHTS") + pod_paint_effect[POD_LIGHT] = image(icon,icon_state = "LIGHTS") pod_paint_effect[WINDOW] = image(icon,icon_state = "Windows") pod_paint_effect[RIM] = image(icon,icon_state = "RIM") pod_paint_effect[PAINT] = image(icon,icon_state = "PAINT") @@ -170,9 +170,9 @@ if(has_paint) var/image/to_add - if(!isnull(pod_paint_effect[LIGHT])) - to_add = pod_paint_effect[LIGHT] - to_add.color = colors[LIGHT] + if(!isnull(pod_paint_effect[POD_LIGHT])) + to_add = pod_paint_effect[POD_LIGHT] + to_add.color = colors[POD_LIGHT] overlays += to_add if(!isnull(pod_paint_effect[WINDOW])) to_add = pod_paint_effect[WINDOW] @@ -812,11 +812,18 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/spacepod_equipment/SPE, v if(!istype(user)) return - if(usr.incapacitated()) // unconscious and restrained people can't let themselves out + if(usr.stat != CONSCIOUS) // unconscious people can't let themselves out return occupant_sanity_check() + if(usr.restrained()) + to_chat(usr, "You attempt to stumble out of the [src]. This will take two minutes.") + if(pilot) + to_chat(pilot, "[usr] is trying to escape the [src].") + if(!do_after(usr, 1200, target = src)) + return + if(user == pilot) user.forceMove(get_turf(src)) pilot = null @@ -1077,6 +1084,6 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/spacepod_equipment/SPE, v #undef DAMAGE #undef FIRE #undef WINDOW -#undef LIGHT +#undef POD_LIGHT #undef RIM #undef PAINT diff --git a/code/modules/store/items.dm b/code/modules/store/items.dm index 285c75ad3f3..4c1610474ba 100644 --- a/code/modules/store/items.dm +++ b/code/modules/store/items.dm @@ -46,17 +46,23 @@ cost = 200 /datum/storeitem/dnd - name = "Dungeons & Dragons set" + name = "Dungeons & Dragons Set" desc = "A box containing minifigures suitable for a good game of D&D." typepath = /obj/item/storage/box/characters cost = 200 /datum/storeitem/dice - name = "Dice set" + name = "Dice Set" desc = "A box containing multiple different types of die." typepath = /obj/item/storage/box/dice cost = 200 +/datum/storeitem/candle + name = "Candles" + desc = "A box of candles. Use them to fool others into thinking you're out for a romantic dinner...or something." + typepath = /obj/item/storage/fancy/candle_box/full + cost = 200 + /datum/storeitem/nanomob_booster name = "Nano-Mob Hunter Trading Card Booster Pack" desc = "Contains 6 random Nano-Mob Hunter Trading Cards. May contain a holographic card!" @@ -65,58 +71,52 @@ /datum/storeitem/crayons name = "Crayons" - desc = "Let security know how they're doing by scrawling lovenotes all over their hallways." + desc = "Let security know how they're doing by scrawling love notes all over their hallways." typepath = /obj/item/storage/fancy/crayons cost = 350 /datum/storeitem/pipe - name = "smoking pipe" - desc = "A pipe, for smoking. Probably made of meershaum or something." + name = "Smoking Pipe" + desc = "A pipe, for smoking. Probably made of meerschaum or something." typepath = /obj/item/clothing/mask/cigarette/pipe cost = 350 -/datum/storeitem/candle - name = "Candles" - desc = "A box of chandles. Use them to fool others into thinking you're out for a romantic dinner...or something." - typepath = /obj/item/storage/fancy/candle_box/full - cost = 200 - /datum/storeitem/minigibber - name = "miniature gibber" + name = "Miniature Gibber" desc = "A miniature recreation of Nanotrasen's famous meat grinder." typepath = /obj/item/toy/minigibber cost = 400 /datum/storeitem/katana - name = "replica katana" + name = "Replica Katana" desc = "Woefully underpowered in D20." typepath = /obj/item/toy/katana cost = 500 -/datum/storeitem/piano_synth - name = "piano synthesizer" - desc = "An advanced electronic synthesizer that can be used as various instruments." - typepath = /obj/item/instrument/piano_synth - cost = 1000 - /datum/storeitem/violin - name = "space violin" + name = "Space Violin" desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\"" typepath = /obj/item/instrument/violin cost = 500 /datum/storeitem/guitar - name = "guitar" + name = "Guitar" desc = "It's made of wood and has bronze strings." typepath = /obj/item/instrument/guitar cost = 500 /datum/storeitem/eguitar - name = "electric guitar" + name = "Electric Guitar" desc = "Makes all your shredding needs possible." typepath = /obj/item/instrument/eguitar cost = 500 +/datum/storeitem/piano_synth + name = "Piano Synthesizer" + desc = "An advanced electronic synthesizer that can emulate various instruments." + typepath = /obj/item/instrument/piano_synth + cost = 1000 + /datum/storeitem/baby name = "Toddler" desc = "This baby looks almost real. Wait, did it just burp?" @@ -124,91 +124,91 @@ cost = 1000 /datum/storeitem/flag_slime - name = "Slime People flag" + name = "Slime People Flag" desc = "A flag proudly proclaiming the superior heritage of Slime People." typepath = /obj/item/flag/species/slime cost = 1000 /datum/storeitem/flag_skrell - name = "Skrell flag" + name = "Skrell Flag" desc = "A flag proudly proclaiming the superior heritage of Skrell." typepath = /obj/item/flag/species/skrell cost = 1000 /datum/storeitem/flag_vox - name = "Vox flag" + name = "Vox Flag" desc = "A flag proudly proclaiming the superior heritage of Vox." typepath = /obj/item/flag/species/vox cost = 1000 /datum/storeitem/flag_machine - name = "Synthetics flag" + name = "Synthetics Flag" desc = "A flag proudly proclaiming the superior heritage of Synthetics." typepath = /obj/item/flag/species/machine cost = 1000 /datum/storeitem/flag_diona - name = "Diona flag" + name = "Diona Flag" desc = "A flag proudly proclaiming the superior heritage of Dionae." typepath = /obj/item/flag/species/diona cost = 1000 /datum/storeitem/flag_human - name = "Human flag" + name = "Human Flag" desc = "A flag proudly proclaiming the superior heritage of Humans." typepath = /obj/item/flag/species/human cost = 1000 /datum/storeitem/flag_greys - name = "Greys flag" + name = "Greys Flag" desc = "A flag proudly proclaiming the superior heritage of Greys." typepath = /obj/item/flag/species/greys cost = 1000 /datum/storeitem/flag_kidan - name = "Kidan flag" + name = "Kidan Flag" desc = "A flag proudly proclaiming the superior heritage of Kidan." typepath = /obj/item/flag/species/kidan cost = 1000 /datum/storeitem/flag_taj - name = "Tajaran flag" + name = "Tajaran Flag" desc = "A flag proudly proclaiming the superior heritage of Tajara." typepath = /obj/item/flag/species/taj cost = 1000 /datum/storeitem/flag_unathi - name = "Unathi flag" + name = "Unathi Flag" desc = "A flag proudly proclaiming the superior heritage of Unathi." typepath = /obj/item/flag/species/unathi cost = 1000 /datum/storeitem/flag_vulp - name = "Vulpkanin flag" + name = "Vulpkanin Flag" desc = "A flag proudly proclaiming the superior heritage of Vulpkanin." typepath = /obj/item/flag/species/vulp cost = 1000 /datum/storeitem/flag_drask - name = "Drask flag" + name = "Drask Flag" desc = "A flag proudly proclaiming the superior heritage of Drask." typepath = /obj/item/flag/species/drask cost = 1000 /datum/storeitem/flag_plasma - name = "Plasmaman flag" + name = "Plasmaman Flag" desc = "A flag proudly proclaiming the superior heritage of Plasmamen." typepath = /obj/item/flag/species/plasma cost = 1000 /datum/storeitem/flag_ian - name = "Ian flag" + name = "Ian Flag" desc = "The banner of Ian, because SQUEEEEE." typepath = /obj/item/flag/ian cost = 1500 /datum/storeitem/banhammer - desc = "A banhammer" - name = "banhammer" + name = "Banhammer" + desc = "A Banhammer." typepath = /obj/item/banhammer cost = 2000 diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index dfe2c0feb8c..fb45bddb9ba 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -19,7 +19,7 @@ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 if(affected.cannot_break) return 0 @@ -43,13 +43,13 @@ /datum/surgery_step/glue_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) - return affected && !(affected.status & ORGAN_ROBOT) && !(affected.cannot_break) + return affected && !affected.is_robotic() && !(affected.cannot_break) /datum/surgery_step/glue_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts applying medication to the damaged bones in [target]'s [affected.name] with \the [tool]." , \ "You start applying medication to the damaged bones in [target]'s [affected.name] with \the [tool].") - target.custom_pain("Something in your [affected.name] is causing you a lot of pain!",1) + target.custom_pain("Something in your [affected.name] is causing you a lot of pain!") ..() /datum/surgery_step/glue_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -77,13 +77,13 @@ /datum/surgery_step/set_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) - return affected && !(affected.status & ORGAN_ROBOT) + return affected && !affected.is_robotic() /datum/surgery_step/set_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] is beginning to set the bone in [target]'s [affected.name] in place with \the [tool]." , \ "You are beginning to set the bone in [target]'s [affected.name] in place with \the [tool].") - target.custom_pain("The pain in your [affected.name] is going to make you pass out!",1) + target.custom_pain("The pain in your [affected.name] is going to make you pass out!") ..() /datum/surgery_step/set_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -116,7 +116,7 @@ /datum/surgery_step/mend_skull/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) - return affected && !(affected.status & ORGAN_ROBOT) && affected.limb_name == "head" + return affected && !affected.is_robotic() && affected.limb_name == "head" /datum/surgery_step/mend_skull/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user] is beginning piece together [target]'s skull with \the [tool]." , \ @@ -136,7 +136,7 @@ "Your hand slips, damaging [target]'s face with \the [tool]!") var/obj/item/organ/external/head/h = affected h.receive_damage(10) - h.disfigured = 1 + h.disfigure() return 0 /datum/surgery_step/finish_bone @@ -153,7 +153,7 @@ /datum/surgery_step/finish_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) - return affected && !(affected.status & ORGAN_ROBOT) + return affected && !affected.is_robotic() /datum/surgery_step/finish_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm index 0e88927e1a2..16d1b18dc1b 100644 --- a/code/modules/surgery/cavity_implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -23,7 +23,7 @@ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 return 1 @@ -33,7 +33,7 @@ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) if(!affected) return 0 - return (affected.status & ORGAN_ROBOT) + return affected.is_robotic() /datum/surgery_step/cavity priority = 1 @@ -78,7 +78,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", \ "You start making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]." ) - target.custom_pain("The pain in your chest is living hell!",1) + target.custom_pain("The pain in your chest is living hell!") ..() /datum/surgery_step/cavity/make_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -104,7 +104,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts mending [target]'s [get_cavity(affected)] cavity wall with \the [tool].", \ "You start mending [target]'s [get_cavity(affected)] cavity wall with \the [tool]." ) - target.custom_pain("The pain in your chest is living hell!",1) + target.custom_pain("The pain in your chest is living hell!") ..() /datum/surgery_step/cavity/close_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -155,7 +155,7 @@ else //no internal items..but we still need a message! user.visible_message("[user] checks for items in [target]'s [target_zone].", "You check for items in [target]'s [target_zone]...") - target.custom_pain("The pain in your [target_zone] is living hell!",1) + target.custom_pain("The pain in your [target_zone] is living hell!") ..() /datum/surgery_step/cavity/place_item/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -187,10 +187,10 @@ else user.visible_message(" [user] puts \the [tool] inside [target]'s [get_cavity(affected)] cavity.", \ " You put \the [tool] inside [target]'s [get_cavity(affected)] cavity." ) - if((tool.w_class > get_max_wclass(affected)/2 && prob(50) && !(affected.status & ORGAN_ROBOT))) + if((tool.w_class > get_max_wclass(affected) / 2 && prob(50) && !affected.is_robotic())) to_chat(user, " You tear some vessels trying to fit the object in the cavity.") affected.internal_bleeding = TRUE - affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1) + affected.owner.custom_pain("You feel something rip in your [affected.name]!") user.drop_item() affected.hidden = tool tool.forceMove(affected) diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm index eddf116a45d..e1402083dbd 100644 --- a/code/modules/surgery/encased.dm +++ b/code/modules/surgery/encased.dm @@ -15,7 +15,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) if(!affected) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 return 1 @@ -38,7 +38,7 @@ user.visible_message("[user] begins to cut through [target]'s [affected.encased] with \the [tool].", \ "You begin to cut through [target]'s [affected.encased] with \the [tool].") - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/saw/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -86,7 +86,7 @@ var/msg = "[user] starts to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]." var/self_msg = "You start to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]." user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/retract/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -137,7 +137,7 @@ var/msg = "[user] starts bending [target]'s [affected.encased] back into place with \the [tool]." var/self_msg = "You start bending [target]'s [affected.encased] back into place with \the [tool]." user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/close/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -187,7 +187,7 @@ var/msg = "[user] starts applying \the [tool] to [target]'s [affected.encased]." var/self_msg = "You start applying \the [tool] to [target]'s [affected.encased]." user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your [affected.name]!",1) + target.custom_pain("Something hurts horribly in your [affected.name]!") ..() /datum/surgery_step/open_encased/mend/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm deleted file mode 100644 index d96db814b78..00000000000 --- a/code/modules/surgery/face.dm +++ /dev/null @@ -1,147 +0,0 @@ -//Procedures in this file: Facial reconstruction surgery -////////////////////////////////////////////////////////////////// -// FACE SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery/plastic_surgery - name = "Face Repair" - steps = list(/datum/surgery_step/generic/cut_face, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/face/mend_vocal, /datum/surgery_step/face/fix_face,/datum/surgery_step/face/cauterize) - possible_locs = list("head") - - - -/datum/surgery/plastic_surgery/can_start(mob/user, mob/living/carbon/target) - if(istype(target,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) - if(!affected) - return 0 - if(affected.status & ORGAN_ROBOT) - return 0 - if(!affected.disfigured) - return 0 - return 1 - -/datum/surgery_step/face - priority = 2 - can_infect = 0 - -/datum/surgery_step/generic/cut_face - name = "make incision" - allowed_tools = list( - /obj/item/scalpel = 100, \ - /obj/item/kitchen/knife = 90, \ - /obj/item/shard = 60, \ - ) - - time = 16 - -/datum/surgery_step/generic/cut_face/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] starts to cut open [target]'s face and neck with \the [tool].", \ - "You start to cut open [target]'s face and neck with \the [tool].") - ..() - -/datum/surgery_step/generic/cut_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user] has cut open [target]'s face and neck with \the [tool]." , \ - " You have cut open [target]'s face and neck with \the [tool].",) - - return 1 - -/datum/surgery_step/generic/cut_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, slicing [target]'s throat wth \the [tool]!" , \ - " Your hand slips, slicing [target]'s throat wth \the [tool]!" ) - affected.receive_damage(60) - target.AdjustLoseBreath(4) - - return 0 - -/datum/surgery_step/face/mend_vocal - name = "mend vocal cords" - allowed_tools = list( - /obj/item/scalpel/laser/manager = 100, \ - /obj/item/hemostat = 100, \ - /obj/item/stack/cable_coil = 90, \ - /obj/item/assembly/mousetrap = 12 //I don't know. Don't ask me. But I'm leaving it because hilarity. - ) - - time = 24 - -/datum/surgery_step/face/mend_vocal/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] starts mending [target]'s vocal cords with \the [tool].", \ - "You start mending [target]'s vocal cords with \the [tool].") - ..() - -/datum/surgery_step/face/mend_vocal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user] mends [target]'s vocal cords with \the [tool].", \ - " You mend [target]'s vocal cords with \the [tool].") - return 1 - -/datum/surgery_step/face/mend_vocal/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user]'s hand slips, clamping [target]'s trachea shut for a moment with \the [tool]!", \ - " Your hand slips, clamping [user]'s trachea shut for a moment with \the [tool]!") - target.AdjustLoseBreath(4) - return 0 - -/datum/surgery_step/face/fix_face - name = "reshape face" - allowed_tools = list( - /obj/item/scalpel/laser/manager = 100, \ - /obj/item/retractor = 100, \ - /obj/item/crowbar = 65, \ - /obj/item/kitchen/utensil/fork = 90) - - time = 64 - -/datum/surgery_step/face/fix_face/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] starts pulling skin on [target]'s face back in place with \the [tool].", \ - "You start pulling skin on [target]'s face back in place with \the [tool].") - ..() - -/datum/surgery_step/face/fix_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message(" [user] pulls skin on [target]'s face back in place with \the [tool].", \ - " You pull skin on [target]'s face back in place with \the [tool].") - return 1 - -/datum/surgery_step/face/fix_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, tearing skin on [target]'s face with \the [tool]!", \ - " Your hand slips, tearing skin on [target]'s face with \the [tool]!") - target.apply_damage(10, BRUTE, affected, sharp = 1) - return 0 - -/datum/surgery_step/face/cauterize - name = "close incision" - allowed_tools = list( - /obj/item/scalpel/laser = 100, \ - /obj/item/cautery = 100, \ - /obj/item/clothing/mask/cigarette = 90, \ - /obj/item/lighter = 60, \ - /obj/item/weldingtool = 30 - ) - - time = 24 - -/datum/surgery_step/face/cauterize/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - user.visible_message("[user] is beginning to cauterize the incision on [target]'s face and neck with \the [tool]." , \ - "You are beginning to cauterize the incision on [target]'s face and neck with \the [tool].") - ..() - -/datum/surgery_step/face/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user] cauterizes the incision on [target]'s face and neck with \the [tool].", \ - " You cauterize the incision on [target]'s face and neck with \the [tool].") - affected.open = 0 - var/obj/item/organ/external/head/h = affected - h.disfigured = 0 - h.update_icon() - target.regenerate_icons() - - return 1 - -/datum/surgery_step/face/cauterize/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, leaving a small burn on [target]'s face with \the [tool]!", \ - " Your hand slips, leaving a small burn on [target]'s face with \the [tool]!") - target.apply_damage(4, BURN, affected) - - return 0 diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 158656f8c01..c66d95df899 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -12,7 +12,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) if(affected == null) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 return 1 @@ -37,7 +37,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts the incision on [target]'s [affected.name] with \the [tool].", \ "You start the incision on [target]'s [affected.name] with \the [tool].") - target.custom_pain("You feel a horrible pain as if from a sharp knife in your [affected.name]!",1) + target.custom_pain("You feel a horrible pain as if from a sharp knife in your [affected.name]!") ..() /datum/surgery_step/generic/cut_open/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -71,7 +71,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts clamping bleeders in [target]'s [affected.name] with \the [tool].", \ "You start clamping bleeders in [target]'s [affected.name] with \the [tool].") - target.custom_pain("The pain in your [affected.name] is maddening!",1) + target.custom_pain("The pain in your [affected.name] is maddening!") ..() /datum/surgery_step/generic/clamp_bleeders/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -111,7 +111,7 @@ msg = "[user] starts to pry open the incision and rearrange the organs in [target]'s lower abdomen with \the [tool]." self_msg = "You start to pry open the incision and rearrange the organs in [target]'s lower abdomen with \the [tool]." user.visible_message(msg, self_msg) - target.custom_pain("It feels like the skin on your [affected.name] is on fire!",1) + target.custom_pain("It feels like the skin on your [affected.name] is on fire!") ..() /datum/surgery_step/generic/retract_skin/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -160,7 +160,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] is beginning to cauterize the incision on [target]'s [affected.name] with \the [tool]." , \ "You are beginning to cauterize the incision on [target]'s [affected.name] with \the [tool].") - target.custom_pain("Your [affected.name] is being burned!",1) + target.custom_pain("Your [affected.name] is being burned!") ..() /datum/surgery_step/generic/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -219,7 +219,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] is beginning to amputate [target]'s [affected.name] with \the [tool]." , \ "You are beginning to cut through [target]'s [affected.amputation_point] with \the [tool].") - target.custom_pain("Your [affected.amputation_point] is being ripped apart!",1) + target.custom_pain("Your [affected.amputation_point] is being ripped apart!") ..() /datum/surgery_step/generic/amputate/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/surgery/helpers.dm b/code/modules/surgery/helpers.dm index 986ce671860..1ae29143496 100644 --- a/code/modules/surgery/helpers.dm +++ b/code/modules/surgery/helpers.dm @@ -21,7 +21,7 @@ for(var/datum/surgery/S in all_surgeries) if(!S.possible_locs.Find(selected_zone)) continue - if(affecting && S.requires_organic_bodypart && affecting.status == ORGAN_ROBOT) + if(affecting && S.requires_organic_bodypart && affecting.is_robotic()) continue if(!S.can_start(user, M)) continue @@ -39,7 +39,7 @@ S = available_surgeries["Apply Robotic Prosthetic"] if(istype(I,/obj/item/organ/external)) var/obj/item/organ/external/E = I - if(E.robotic == 2) + if(E.is_robotic()) S = available_surgeries["Synthetic Limb Reattachment"] if(S) var/datum/surgery/procedure = new S.type @@ -84,7 +84,7 @@ /proc/get_pain_modifier(mob/living/carbon/human/M) //returns modfier to make surgery harder if patient is conscious and feels pain if(M.stat) //stat=0 if CONSCIOUS, 1=UNCONSCIOUS and 2=DEAD. Operating on dead people is easy, too. Just sleeping won't work, though. return 1 - if(NO_PAIN in M.species.species_traits)//if you don't feel pain, you can hold still + if(NO_PAIN in M.dna.species.species_traits)//if you don't feel pain, you can hold still return 1 if(M.reagents.has_reagent("hydrocodone"))//really good pain killer return 0.99 diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index 7518cc701af..435ce92b94e 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -19,7 +19,7 @@ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 return 1 @@ -29,7 +29,7 @@ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) return 0 return 1 @@ -45,7 +45,7 @@ I = locate(/obj/item/implant) in target user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \ "You start poking around inside [target]'s [affected.name] with \the [tool]." ) - target.custom_pain("The pain in your [affected.name] is living hell!",1) + target.custom_pain("The pain in your [affected.name] is living hell!") ..() /datum/surgery_step/extract_implant/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index 9674f4aec49..d2f11364cfe 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -1,7 +1,7 @@ /datum/surgery/limb_augmentation name = "Augment Limb" steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/augment) - possible_locs = list("chest","l_arm","r_arm","r_leg","l_leg") + possible_locs = list("head", "chest","l_arm","r_arm","r_leg","l_leg") /datum/surgery/limb_augmentation/can_start(mob/user, mob/living/carbon/target) if(ishuman(target)) @@ -11,7 +11,7 @@ return 0 if(affected.status & ORGAN_BROKEN) //The arm has to be in prime condition to augment it. return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 return 1 diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index d64d00c34bb..42db2e97da1 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -15,7 +15,7 @@ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 if(affected.cannot_amputate) return 0 @@ -32,7 +32,7 @@ if(ishuman(target)) var/mob/living/carbon/human/H = target var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) - if(target.get_species() == "Machine") + if(ismachine(target)) // RIP bi-centennial man return 0 if(!affected) @@ -76,7 +76,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) if(affected) return 0 - var/list/organ_data = target.species.has_limbs["[target_zone]"] + var/list/organ_data = target.dna.species.has_limbs["[target_zone]"] return !isnull(organ_data) /datum/surgery_step/limb/attach @@ -131,7 +131,7 @@ /datum/surgery_step/limb/attach/proc/is_correct_limb(obj/item/organ/external/E) - if(E.status & ORGAN_ROBOT) + if(E.is_robotic()) return 0 return 1 @@ -149,13 +149,13 @@ name = "attach robotic limb" /datum/surgery_step/limb/attach/robo/is_correct_limb(obj/item/organ/external/E) - if(!(E.status & ORGAN_ROBOT)) + if(!E.is_robotic()) return 0 return 1 /datum/surgery_step/limb/attach/robo/attach_limb(mob/living/user, mob/living/carbon/human/target, obj/item/organ/external/E) // Fixes fabricator IPC heads - if(!(E.dna) && E.robotic == 2 && target.dna) + if(!(E.dna) && E.is_robotic() && target.dna) E.set_dna(target.dna) ..() if(E.limb_name == "head") @@ -233,7 +233,7 @@ for(var/part_name in L.part) if(!isnull(target.get_organ(part_name))) continue - var/list/organ_data = target.species.has_limbs["[part_name]"] + var/list/organ_data = target.dna.species.has_limbs["[part_name]"] if(!organ_data) continue // This will break if there's more than one stump ever diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index d98e40700df..bdc5f763442 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -66,7 +66,7 @@ if(!holder || (holder in src)) return - owner.visible_message("[owner] retracts [holder] back into \his [parent_organ == "r_arm" ? "right" : "left"] arm.", + owner.visible_message("[owner] retracts [holder] back into [owner.p_their()] [parent_organ == "r_arm" ? "right" : "left"] arm.", "[holder] snaps back into your [parent_organ == "r_arm" ? "right" : "left"] arm.", "You hear a short mechanical noise.") @@ -114,7 +114,7 @@ if(parent_organ == "r_arm" ? owner.hand : !owner.hand) owner.swap_hand() - owner.visible_message("[owner] extends [holder] from \his [parent_organ == "r_arm" ? "right" : "left"] arm.", + owner.visible_message("[owner] extends [holder] from [owner.p_their()] [parent_organ == "r_arm" ? "right" : "left"] arm.", "You extend [holder] from your [parent_organ == "r_arm" ? "right" : "left"] arm.", "You hear a short mechanical noise.") playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) @@ -242,7 +242,7 @@ /obj/item/organ/internal/cyberimp/arm/surgery name = "surgical toolset implant" desc = "A set of surgical tools hidden behind a concealed panel on the user's arm" - contents = newlist(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/bonegel, /obj/item/FixOVein, /obj/item/bonesetter) + contents = newlist(/obj/item/retractor/augment, /obj/item/hemostat/augment, /obj/item/cautery/augment, /obj/item/surgicaldrill/augment, /obj/item/scalpel/augment, /obj/item/circular_saw/augment, /obj/item/bonegel/augment, /obj/item/FixOVein/augment, /obj/item/bonesetter/augment) origin_tech = "materials=3;engineering=3;biotech=3;programming=2;magnets=3" // lets make IPCs even *more* vulnerable to EMPs! diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index 305bbb2c603..fe1adce42fb 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -33,7 +33,7 @@ var/mob/living/carbon/human/H = HA if(!istype(H)) H = owner - var/icon/cybereyes_icon = new /icon('icons/mob/human_face.dmi', H.species.eyes) + var/icon/cybereyes_icon = new /icon('icons/mob/human_face.dmi', H.dna.species.eyes) cybereyes_icon.Blend(eye_colour, ICON_ADD) // Eye implants override native DNA eye color return cybereyes_icon diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 64d62d3f6b4..f0b05ad0659 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -7,8 +7,6 @@ var/implant_color = "#FFFFFF" var/implant_overlay tough = TRUE // Immune to damage - sterile = TRUE // Doesn't accumulate germs - robotic = 2 // these are cybernetic after all /obj/item/organ/internal/cyberimp/New(var/mob/M = null) . = ..() diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm index 9f732fdef4d..2a7057516f9 100644 --- a/code/modules/surgery/organs/blood.dm +++ b/code/modules/surgery/organs/blood.dm @@ -18,7 +18,7 @@ /mob/living/carbon/human/handle_blood() var/list/blood_data = get_blood_data(get_blood_id())//PROCCEPTION - if(NO_BLOOD in species.species_traits) + if(NO_BLOOD in dna.species.species_traits) bleed_rate = 0 return @@ -43,14 +43,14 @@ if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) if(prob(5)) to_chat(src, "You feel [word].") - apply_damage_type(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1), species.blood_damage_type) + apply_damage_type(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1), dna.species.blood_damage_type) if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) - apply_damage_type(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1), species.blood_damage_type) + apply_damage_type(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1), dna.species.blood_damage_type) if(prob(5)) EyeBlurry(6) to_chat(src, "You feel very [word].") if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) - apply_damage_type(5, species.blood_damage_type) + apply_damage_type(5, dna.species.blood_damage_type) if(prob(15)) Paralyse(rand(1,3)) to_chat(src, "You feel extremely [word].") @@ -64,7 +64,7 @@ var/obj/item/organ/external/BP = X var/brutedamage = BP.brute_dam - if(BP.status & ORGAN_ROBOT) + if(BP.is_robotic()) continue //We want an accurate reading of .len @@ -99,9 +99,9 @@ add_splatter_floor(loc, 1) /mob/living/carbon/human/bleed(amt) - if(!(NO_BLOOD in species.species_traits)) + if(!(NO_BLOOD in dna.species.species_traits)) ..() - if(species.exotic_blood) + if(dna.species.exotic_blood) var/datum/reagent/R = chemical_reagents_list[get_blood_id()] if(istype(R) && isturf(loc)) R.reaction_turf(get_turf(src), amt) @@ -186,7 +186,7 @@ blood_data["blood_type"] = copytext(src.dna.b_type,1,0) blood_data["gender"] = gender blood_data["real_name"] = real_name - blood_data["blood_color"] = species.blood_color + blood_data["blood_color"] = dna.species.blood_color blood_data["factions"] = faction return blood_data @@ -199,9 +199,9 @@ return "blood" /mob/living/carbon/human/get_blood_id() - if(species.exotic_blood)//some races may bleed water..or kethcup.. - return species.exotic_blood - else if((NO_BLOOD in species.species_traits) || (NOCLONE in mutations)) + if(dna.species.exotic_blood)//some races may bleed water..or kethcup.. + return dna.species.exotic_blood + else if((NO_BLOOD in dna.species.species_traits) || (NOCLONE in mutations)) return return "blood" @@ -279,7 +279,7 @@ B.layer = BELOW_MOB_LAYER //So the blood lands ontop of things like posters, windows, etc. /mob/living/carbon/human/add_splatter_floor(turf/T, small_drip, shift_x, shift_y) - if(!(NO_BLOOD in species.species_traits)) + if(!(NO_BLOOD in dna.species.species_traits)) ..() /mob/living/carbon/alien/add_splatter_floor(turf/T, small_drip, shift_x, shift_y) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm new file mode 100644 index 00000000000..51d73fc9873 --- /dev/null +++ b/code/modules/surgery/organs/eyes.dm @@ -0,0 +1,80 @@ +/obj/item/organ/internal/eyes + name = "eyeballs" + icon_state = "eyes" + gender = PLURAL + organ_tag = "eyes" + parent_organ = "head" + slot = "eyes" + var/eye_colour = "#000000" + var/list/colourmatrix = null + var/list/colourblind_matrix = MATRIX_GREYSCALE //Special colourblindness parameters. By default, it's black-and-white. + var/list/replace_colours = LIST_GREYSCALE_REPLACE + var/dependent_disabilities = null //Gets set by eye-dependent disabilities such as colourblindness so the eyes can transfer the disability during transplantation. + var/dark_view = 2 //Default dark_view for Humans. + var/weld_proof = null //If set, the eyes will not take damage during welding. eg. IPC optical sensors do not take damage when they weld things while all other eyes will. + +/obj/item/organ/internal/eyes/proc/update_colour() + dna.write_eyes_attributes(src) + +/obj/item/organ/internal/eyes/proc/generate_icon(var/mob/living/carbon/human/HA) + var/mob/living/carbon/human/H = HA + if(!istype(H)) + H = owner + var/icon/eyes_icon = new /icon('icons/mob/human_face.dmi', H.dna.species.eyes) + eyes_icon.Blend(eye_colour, ICON_ADD) + + return eyes_icon + +/obj/item/organ/internal/eyes/proc/get_colourmatrix() //Returns a special colour matrix if the eyes are organic and the mob is colourblind, otherwise it uses the current one. + if(!is_robotic() && owner.disabilities & COLOURBLIND) + return colourblind_matrix + else + return colourmatrix + +/obj/item/organ/internal/eyes/proc/get_dark_view() //Returns dark_view (if the eyes are organic) for see_invisible handling in species.dm to be autoprocessed by life(). + return dark_view + +/obj/item/organ/internal/eyes/proc/shine() + if(is_robotic() || (dark_view > EYE_SHINE_THRESHOLD)) + return TRUE + +/obj/item/organ/internal/eyes/insert(mob/living/carbon/human/M, special = 0) + ..() + if(istype(M) && eye_colour) + M.update_body() //Apply our eye colour to the target. + + if(!(M.disabilities & COLOURBLIND) && (dependent_disabilities & COLOURBLIND)) //If the eyes are colourblind and we're not, carry over the gene. + dependent_disabilities &= ~COLOURBLIND + M.dna.SetSEState(COLOURBLINDBLOCK,1) + genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + else + M.update_client_colour() //If we're here, that means the mob acquired the colourblindness gene while they didn't have eyes. Better handle it. + +/obj/item/organ/internal/eyes/remove(mob/living/carbon/human/M, special = 0) + if(!special && (M.disabilities & COLOURBLIND)) //If special is set, that means these eyes are getting deleted (i.e. during set_species()) + if(!(dependent_disabilities & COLOURBLIND)) //We only want to change COLOURBLINDBLOCK and such it the eyes are being surgically removed. + dependent_disabilities |= COLOURBLIND + M.dna.SetSEState(COLOURBLINDBLOCK,0) + genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + . = ..() + +/obj/item/organ/internal/eyes/surgeryize() + if(!owner) + return + owner.CureNearsighted() + owner.CureBlind() + owner.SetEyeBlurry(0) + owner.SetEyeBlind(0) + +/obj/item/organ/internal/eyes/robotize() + colourmatrix = null + ..() //Make sure the organ's got the robotic status indicators before updating the client colour. + if(owner) + owner.update_client_colour(0) //Since mechanical eyes give dark_view of 2 and full colour vision atm, just having this here is fine. + +/obj/item/organ/internal/eyes/cybernetic + name = "cybernetic eyes" + icon_state = "eyes-prosthetic" + desc = "An electronic device designed to mimic the functions of a pair of human eyes. It has no benefits over organic eyes, but is easy to produce." + origin_tech = "biotech=4" + status = ORGAN_ROBOT \ No newline at end of file diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm new file mode 100644 index 00000000000..bd7cca63779 --- /dev/null +++ b/code/modules/surgery/organs/heart.dm @@ -0,0 +1,150 @@ +/obj/item/organ/internal/heart + name = "heart" + icon_state = "heart-on" + organ_tag = "heart" + parent_organ = "chest" + slot = "heart" + origin_tech = "biotech=5" + var/beating = TRUE + dead_icon = "heart-off" + var/icon_base = "heart" + +/obj/item/organ/internal/heart/update_icon() + if(beating) + icon_state = "[icon_base]-on" + else + icon_state = "[icon_base]-off" + +/obj/item/organ/internal/heart/remove(mob/living/carbon/M, special = 0) + . = ..() + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.stat == DEAD) + Stop() + return + + spawn(120) + if(!owner) + Stop() + +/obj/item/organ/internal/heart/emp_act(intensity) + if(!is_robotic() || emp_proof) + return + Stop() + +/obj/item/organ/internal/heart/necrotize() + ..() + Stop() + +/obj/item/organ/internal/heart/attack_self(mob/user) + ..() + if(status & ORGAN_DEAD) + to_chat(user, "You can't restart a dead heart.") + return + if(!beating) + Restart() + spawn(80) + if(!owner) + Stop() + +/obj/item/organ/internal/heart/safe_replace(mob/living/carbon/human/target) + Restart() + ..() + +/obj/item/organ/internal/heart/proc/Stop() + beating = FALSE + update_icon() + return TRUE + +/obj/item/organ/internal/heart/proc/Restart() + beating = TRUE + update_icon() + return TRUE + +/obj/item/organ/internal/heart/prepare_eat() + var/obj/S = ..() + S.icon_state = dead_icon + return S + +/obj/item/organ/internal/heart/cursed + name = "cursed heart" + desc = "it needs to be pumped..." + icon_state = "cursedheart-off" + icon_base = "cursedheart" + origin_tech = "biotech=6" + actions_types = list(/datum/action/item_action/organ_action/cursed_heart) + var/last_pump = 0 + var/pump_delay = 30 //you can pump 1 second early, for lag, but no more (otherwise you could spam heal) + var/blood_loss = 100 //600 blood is human default, so 5 failures (below 122 blood is where humans die because reasons?) + + //How much to heal per pump, negative numbers would HURT the player + var/heal_brute = 0 + var/heal_burn = 0 + var/heal_oxy = 0 + + +/obj/item/organ/internal/heart/cursed/attack(mob/living/carbon/human/H, mob/living/carbon/human/user, obj/target) + if(H == user && istype(H)) + if(NO_BLOOD in H.dna.species.species_traits) + to_chat(H, "\The [src] is not compatible with your form!") + return + playsound(user,'sound/effects/singlebeat.ogg', 40, 1) + user.drop_item() + insert(user) + else + return ..() + +/obj/item/organ/internal/heart/cursed/on_life() + if(world.time > (last_pump + pump_delay)) + if(ishuman(owner) && owner.client) //While this entire item exists to make people suffer, they can't control disconnects. + var/mob/living/carbon/human/H = owner + if(!(NO_BLOOD in H.dna.species.species_traits)) + H.blood_volume = max(H.blood_volume - blood_loss, 0) + to_chat(H, "You have to keep pumping your blood!") + if(H.client) + H.client.color = "red" //bloody screen so real + else + last_pump = world.time //lets be extra fair *sigh* + +/obj/item/organ/internal/heart/cursed/insert(mob/living/carbon/M, special = 0) + ..() + if(owner) + to_chat(owner, "Your heart has been replaced with a cursed one, you have to pump this one manually otherwise you'll die!") + + +/datum/action/item_action/organ_action/cursed_heart + name = "pump your blood" + +//You are now brea- pumping blood manually +/datum/action/item_action/organ_action/cursed_heart/Trigger() + . = ..() + if(. && istype(target,/obj/item/organ/internal/heart/cursed)) + var/obj/item/organ/internal/heart/cursed/cursed_heart = target + + if(world.time < (cursed_heart.last_pump + (cursed_heart.pump_delay-10))) //no spam + to_chat(owner, "Too soon!") + return + + cursed_heart.last_pump = world.time + playsound(owner,'sound/effects/singlebeat.ogg',40,1) + to_chat(owner, "Your heart beats.") + + var/mob/living/carbon/human/H = owner + if(istype(H)) + if(!(NO_BLOOD in H.dna.species.species_traits)) + H.blood_volume = min(H.blood_volume + cursed_heart.blood_loss*0.5, BLOOD_VOLUME_NORMAL) + if(owner.client) + owner.client.color = "" + + H.adjustBruteLoss(-cursed_heart.heal_brute) + H.adjustFireLoss(-cursed_heart.heal_burn) + H.adjustOxyLoss(-cursed_heart.heal_oxy) + +/obj/item/organ/internal/heart/cybernetic + name = "cybernetic heart" + desc = "An electronic device designed to mimic the functions of an organic human heart. Offers no benefit over an organic heart other than being easy to make." + icon_state = "heart-c-on" + icon_base = "heart-c" + dead_icon = "heart-c-off" + origin_tech = "biotech=5" + status = ORGAN_ROBOT \ No newline at end of file diff --git a/code/modules/surgery/organs/kidneys.dm b/code/modules/surgery/organs/kidneys.dm new file mode 100644 index 00000000000..26b59191a7c --- /dev/null +++ b/code/modules/surgery/organs/kidneys.dm @@ -0,0 +1,25 @@ +/obj/item/organ/internal/kidneys + name = "kidneys" + icon_state = "kidneys" + gender = PLURAL + organ_tag = "kidneys" + parent_organ = "groin" + slot = "kidneys" + +/obj/item/organ/internal/kidneys/on_life() + // Coffee is really bad for you with busted kidneys. + // This should probably be expanded in some way, but fucked if I know + // what else kidneys can process in our reagent list. + var/datum/reagent/coffee = locate(/datum/reagent/consumable/drink/coffee) in owner.reagents.reagent_list + if(coffee) + if(is_bruised()) + owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) + else if(is_broken()) + owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) + +/obj/item/organ/internal/kidneys/cybernetic + name = "cybernetic kidneys" + icon_state = "kidneys-c" + desc = "An electronic device designed to mimic the functions of human kidneys. It has no benefits over a pair of organic kidneys, but is easy to produce." + origin_tech = "biotech=4" + status = ORGAN_ROBOT \ No newline at end of file diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm new file mode 100644 index 00000000000..bf6f085275b --- /dev/null +++ b/code/modules/surgery/organs/liver.dm @@ -0,0 +1,58 @@ +/obj/item/organ/internal/liver + name = "liver" + icon_state = "liver" + organ_tag = "liver" + parent_organ = "groin" + slot = "liver" + var/alcohol_intensity = 1 + +/obj/item/organ/internal/liver/on_life() + if(germ_level > INFECTION_LEVEL_ONE) + if(prob(1)) + to_chat(owner, " Your skin itches.") + if(germ_level > INFECTION_LEVEL_TWO) + if(prob(1)) + owner.vomit() + + if(owner.life_tick % PROCESS_ACCURACY == 0) + + //High toxins levels are dangerous + if(owner.getToxLoss() >= 60 && !owner.reagents.has_reagent("charcoal")) + //Healthy liver suffers on its own + if(damage < min_broken_damage) + receive_damage(0.2 * PROCESS_ACCURACY) + //Damaged one shares the fun + else + var/obj/item/organ/internal/O = pick(owner.internal_organs) + if(O) + O.receive_damage(0.2 * PROCESS_ACCURACY) + + //Detox can heal small amounts of damage + if(damage && damage < min_bruised_damage && owner.reagents.has_reagent("charcoal")) + receive_damage(-0.2 * PROCESS_ACCURACY) + + // Get the effectiveness of the liver. + var/filter_effect = 3 + if(is_bruised()) + filter_effect -= 1 + if(is_broken()) + filter_effect -= 2 + + // Damaged liver means some chemicals are very dangerous + if(damage >= min_bruised_damage) + for(var/datum/reagent/R in owner.reagents.reagent_list) + // Ethanol and all drinks are bad + if(istype(R, /datum/reagent/consumable/ethanol)) + owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) + + // Can't cope with toxins at all + for(var/toxin in list("toxin", "plasma", "sacid", "facid", "cyanide", "amanitin", "carpotoxin")) + if(owner.reagents.has_reagent(toxin)) + owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) + +/obj/item/organ/internal/liver/cybernetic + name = "cybernetic liver" + icon_state = "liver-c" + desc = "An electronic device designed to mimic the functions of a human liver. It has no benefits over an organic liver, but is easy to produce." + origin_tech = "biotech=4" + status = ORGAN_ROBOT \ No newline at end of file diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 39c79865b62..3c2b7e1cbd1 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -51,6 +51,12 @@ var/heat_level_3_damage = HEAT_GAS_DAMAGE_LEVEL_3 var/heat_damage_types = list(BURN = 1) +/obj/item/organ/internal/lungs/emp_act() + if(!is_robotic() || emp_proof) + return + if(owner) + owner.LoseBreath(20) + /obj/item/organ/internal/lungs/insert(mob/living/carbon/M, special = 0, dont_remove_slot = 0) ..() for(var/thing in list("oxy", "tox", "co2", "nitro")) @@ -148,12 +154,12 @@ if(safe_nitro_min) if(N2_pp < safe_nitro_min) gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath.nitrogen) - H.throw_alert("nitro", /obj/screen/alert/not_enough_nitro) + H.throw_alert("not_enough_nitro", /obj/screen/alert/not_enough_nitro) else H.failed_last_breath = FALSE H.adjustOxyLoss(-5) gas_breathed = breath.nitrogen - H.clear_alert("nitro") + H.clear_alert("not_enough_nitro") //Exhale breath.nitrogen -= gas_breathed @@ -265,11 +271,11 @@ var/breath_temperature = breath.temperature var/species_traits = list() - if(H && H.species && H.species.species_traits) - species_traits = H.species.species_traits + if(H && H.dna.species && H.dna.species.species_traits) + species_traits = H.dna.species.species_traits if(!(COLDRES in H.mutations) && !(RESISTCOLD in species_traits)) // COLD DAMAGE - var/CM = abs(H.species.coldmod) + var/CM = abs(H.dna.species.coldmod) var/TC = 0 if(breath_temperature < cold_level_3_threshold) TC = cold_level_3_damage @@ -285,7 +291,7 @@ to_chat(H, "You feel [cold_message] in your [name]!") if(!(HEATRES in H.mutations) && !(RESISTHOT in species_traits)) // HEAT DAMAGE - var/HM = abs(H.species.heatmod) + var/HM = abs(H.dna.species.heatmod) var/TH = 0 if(breath_temperature > heat_level_1_threshold && breath_temperature < heat_level_2_threshold) TH = heat_level_1_damage @@ -309,7 +315,6 @@ name = "plasma filter" desc = "A spongy rib-shaped mass for filtering plasma from the air." icon_state = "lungs-plasma" - species = "Plasmaman" safe_oxygen_min = 0 //We don't breath this safe_toxins_min = 16 //We breathe THIS! @@ -318,7 +323,6 @@ /obj/item/organ/internal/lungs/vox name = "Vox lungs" desc = "They're filled with dust....wow." - species = "Vox" safe_oxygen_min = 0 //We don't breathe this safe_oxygen_max = 1 //This is toxic to us @@ -327,11 +331,30 @@ /obj/item/organ/internal/lungs/drask icon = 'icons/obj/surgery_drask.dmi' - species = "Drask" cold_message = "an invigorating coldness" cold_level_3_threshold = 60 cold_level_1_damage = -COLD_GAS_DAMAGE_LEVEL_1 //They heal when the air is cold cold_level_2_damage = -COLD_GAS_DAMAGE_LEVEL_2 cold_level_3_damage = -COLD_GAS_DAMAGE_LEVEL_3 - cold_damage_types = list(BRUTE = 1, BURN = 0.5) \ No newline at end of file + cold_damage_types = list(BRUTE = 1, BURN = 0.5) + +/obj/item/organ/internal/lungs/cybernetic + name = "cybernetic lungs" + desc = "A cybernetic version of the lungs found in traditional humanoid entities. It functions the same as an organic lung and is merely meant as a replacement." + icon_state = "lungs-c" + origin_tech = "biotech=4" + status = ORGAN_ROBOT + +/obj/item/organ/internal/lungs/cybernetic/upgraded + name = "upgraded cybernetic lungs" + desc = "A more advanced version of the stock cybernetic lungs. They are capable of filtering out lower levels of toxins and carbon dioxide." + icon_state = "lungs-c-u" + origin_tech = "biotech=5" + + safe_toxins_max = 20 + safe_co2_max = 20 + + cold_level_1_threshold = 200 + cold_level_2_threshold = 140 + cold_level_3_threshold = 100 \ No newline at end of file diff --git a/code/modules/surgery/organs/mmi_holder.dm b/code/modules/surgery/organs/mmi_holder.dm new file mode 100644 index 00000000000..d4228fb9625 --- /dev/null +++ b/code/modules/surgery/organs/mmi_holder.dm @@ -0,0 +1,36 @@ +// Used for an MMI or robotic brain being installed into a human. +/obj/item/organ/internal/brain/mmi_holder + name = "Man-Machine Interface" + parent_organ = "chest" + status = ORGAN_ROBOT + var/obj/item/mmi/stored_mmi + +/obj/item/organ/internal/brain/mmi_holder/Destroy() + QDEL_NULL(stored_mmi) + return ..() + +/obj/item/organ/internal/brain/mmi_holder/insert(mob/living/target, special = 0) + ..() + // To supersede the over-writing of the MMI's name from `insert` + update_from_mmi() + +/obj/item/organ/internal/brain/mmi_holder/remove(mob/living/user, special = 0) + if(!special) + if(stored_mmi) + . = stored_mmi + if(owner.mind) + owner.mind.transfer_to(stored_mmi.brainmob) + stored_mmi.forceMove(get_turf(owner)) + stored_mmi = null + ..() + if(!QDELETED(src)) + qdel(src) + +/obj/item/organ/internal/brain/mmi_holder/proc/update_from_mmi() + if(!stored_mmi) + return + name = initial(stored_mmi.name) + desc = stored_mmi.desc + icon = stored_mmi.icon + icon_state = stored_mmi.icon_state + set_dna(stored_mmi.brainmob.dna) \ No newline at end of file diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index 0af7781eee4..991a5d252ce 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -4,7 +4,7 @@ var/dead_icon var/mob/living/carbon/human/owner = null var/status = 0 - var/vital //Lose a vital limb, die immediately. + var/vital = FALSE //Lose a vital limb, die immediately. var/damage = 0 // amount of damage to the organ var/min_bruised_damage = 10 @@ -13,14 +13,12 @@ var/organ_tag = "organ" var/parent_organ = "chest" - var/robotic = 0 //For being a robot var/list/datum/autopsy_data/autopsy_data = list() var/list/trace_chemicals = list() // traces of chemicals in the organ, // links chemical IDs to number of ticks for which they'll stay in the blood germ_level = 0 var/datum/dna/dna - var/datum/species/species = "Human" // Stuff for tracking if this is on a tile with an open freezer or not var/last_freezer_update_time = 0 @@ -30,6 +28,8 @@ var/sterile = FALSE //can the organ be infected by germs? var/tough = FALSE //can organ be easily damaged? var/emp_proof = FALSE //is the organ immune to EMPs? + var/hidden_pain = FALSE //will it skip pain messages? + var/requires_robotic_bodypart = FALSE /obj/item/organ/Destroy() @@ -43,15 +43,13 @@ /obj/item/organ/proc/update_health() return -/obj/item/organ/New(var/mob/living/carbon/holder) +/obj/item/organ/New(mob/living/carbon/holder, datum/species/species_override = null) ..(holder) if(!max_damage) max_damage = min_broken_damage * 2 if(istype(holder)) - species = all_species["Human"] if(holder.dna) dna = holder.dna.Clone() - species = all_species[dna.species] else log_runtime(EXCEPTION("[holder] spawned without a proper DNA."), holder) var/mob/living/carbon/human/H = holder @@ -61,8 +59,9 @@ blood_DNA = list() blood_DNA[dna.unique_enzymes] = dna.b_type else - if(istext(species)) - species = all_species[species] + dna = new /datum/dna(null) + if(species_override) + dna.species = new species_override /obj/item/organ/proc/set_dna(var/datum/dna/new_dna) if(new_dna) @@ -73,13 +72,11 @@ blood_DNA = list() blood_DNA[dna.unique_enzymes] = dna.b_type -/obj/item/organ/proc/necrotize(update_sprite=TRUE) - if(status & ORGAN_ROBOT) - return +/obj/item/organ/proc/necrotize(update_sprite = TRUE) damage = max_damage status |= ORGAN_DEAD processing_objects -= src - if(dead_icon) + if(dead_icon && !is_robotic()) icon_state = dead_icon if(owner && vital) owner.death() @@ -94,7 +91,7 @@ return //Process infections - if((status & ORGAN_ROBOT) || sterile || (owner && (IS_PLANT in owner.species.species_traits))) + if(is_robotic() || sterile || (owner && (IS_PLANT in owner.dna.species.species_traits))) germ_level = 0 return @@ -156,7 +153,7 @@ germ_level++ if(germ_level >= INFECTION_LEVEL_ONE) - var/fever_temperature = (owner.species.heat_level_1 - owner.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.species.body_temperature + var/fever_temperature = (owner.dna.species.heat_level_1 - owner.dna.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.dna.species.body_temperature owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature) if(germ_level >= INFECTION_LEVEL_TWO) @@ -174,10 +171,8 @@ /obj/item/organ/proc/rejuvenate() damage = 0 germ_level = 0 - if(status & ORGAN_ROBOT) //Robotic organs stay robotic. + if(is_robotic()) //Robotic organs stay robotic. status = ORGAN_ROBOT - else if(status & ORGAN_ASSISTED) //Assisted organs stay assisted. - status = ORGAN_ASSISTED else status = 0 if(!owner) @@ -223,37 +218,30 @@ /obj/item/organ/proc/receive_damage(amount, silent = 0) if(tough) return - if(status & ORGAN_ROBOT) - damage = between(0, damage + (amount * 0.8), max_damage) - else - damage = between(0, damage + amount, max_damage) + damage = between(0, damage + amount, max_damage) - //only show this if the organ is not robotic - if(owner && parent_organ && amount > 0) - var/obj/item/organ/external/parent = owner.get_organ(parent_organ) - if(parent && !silent) - owner.custom_pain("Something inside your [parent.name] hurts a lot.", 1) + //only show this if the organ is not robotic + if(owner && parent_organ && amount > 0) + var/obj/item/organ/external/parent = owner.get_organ(parent_organ) + if(parent && !silent) + owner.custom_pain("Something inside your [parent.name] hurts a lot.") //check if we've hit max_damage if(damage >= max_damage) necrotize() +/obj/item/organ/proc/heal_internal_damage(amount, robo_repair = FALSE) + if(is_robotic() && !robo_repair) + return + damage = max(damage - amount, 0) + /obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc - robotic = 2 status &= ~ORGAN_BROKEN status &= ~ORGAN_SPLINTED status |= ORGAN_ROBOT -/obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc - robotize(1) //Skip the icon/name setting that occurs in robotize to avoid having to reset the icon file. - status &= ~ORGAN_ROBOT - status |= ORGAN_ASSISTED - robotic = 1 - min_bruised_damage = 15 - min_broken_damage = 35 - /obj/item/organ/external/emp_act(severity) - if(!(status & ORGAN_ROBOT) || emp_proof) + if(!is_robotic() || emp_proof) return if(tough) switch(severity) @@ -273,25 +261,13 @@ receive_damage(0, 7) /obj/item/organ/internal/emp_act(severity) - if(!robotic || emp_proof) + if(!is_robotic() || emp_proof) return - if(robotic == 2) - switch(severity) - if(1.0) - receive_damage(20, 1) - if(2.0) - receive_damage(7, 1) - else if(robotic == 1) - receive_damage(11, 1) - -/obj/item/organ/internal/heart/emp_act(intensity) - if(emp_proof) - return - if(owner && robotic == 2) - Stop() // In the name of looooove~! - owner.visible_message("[owner] clutches their chest and gasps!","You clutch your chest in pain!") - else if(owner && robotic == 1) - receive_damage(11,1) + switch(severity) + if(1) + receive_damage(20, 1) + if(2) + receive_damage(7, 1) /obj/item/organ/proc/remove(var/mob/living/user,special = 0) if(!istype(owner)) @@ -306,7 +282,7 @@ processing_objects |= src if(owner && vital && is_primary_organ()) // I'd do another check for species or whatever so that you couldn't "kill" an IPC by removing a human head from them, but it doesn't matter since they'll come right back from the dead - add_attack_logs(user, owner, "Removed vital organ ([src])", !!user) + add_attack_logs(user, owner, "Removed vital organ ([src])", !!user ? ATKLOG_FEW : ATKLOG_ALL) owner.death() owner = null return src @@ -334,20 +310,15 @@ I use this so that this can be made better once the organ overhaul rolls out -- return 0 return src == O.get_int_organ(organ_tag) -/obj/item/organ/proc/is_robotic(var/purist = FALSE) - if(purist && (robotic > 1 || status & (ORGAN_ROBOT))) //Only the robotiest. +/obj/item/organ/proc/is_robotic() + if(status & ORGAN_ROBOT) return TRUE - if(robotic || status & (ORGAN_ROBOT|ORGAN_ASSISTED)) //Any tech will do. - return TRUE - return FALSE /obj/item/organ/serialize() var/data = ..() if(status != 0) data["status"] = status - if(robotic > 0) - data["robotic"] = robotic // Save the DNA datum if: The owner doesn't exist, or the dna doesn't match // the owner @@ -355,15 +326,10 @@ I use this so that this can be made better once the organ overhaul rolls out -- data["dna"] = dna.serialize() return data -/obj/item/organ/deserialize(var/data) - switch(data["robotic"]) - if(1) - mechassist() - if(2) - robotize() - else - // Nothing +/obj/item/organ/deserialize(data) if(isnum(data["status"])) + if(data["status"] & ORGAN_ROBOT) + robotize() status = data["status"] if(islist(data["dna"])) // The only thing the official proc does is diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 0ebf08c225c..04ce880d5f5 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -105,13 +105,12 @@ /obj/item/organ/external/New(var/mob/living/carbon/holder) ..() var/mob/living/carbon/human/H = holder - icobase = species.icobase - deform = species.deform + icobase = dna.species.icobase + deform = dna.species.deform if(istype(H)) replaced(H) sync_colour_to_human(H) - spawn(1) - get_icon() + get_icon() /obj/item/organ/external/replaced(var/mob/living/carbon/human/target) owner = target @@ -172,7 +171,7 @@ owner.emote("scream") //getting hit on broken hand hurts if(status & ORGAN_SPLINTED && prob((brute + burn)*4)) //taking damage to splinted limbs removes the splints status &= ~ORGAN_SPLINTED - owner.visible_message("The splint on [owner]'s left arm unravels from their [name]!","The splint on your [name] unravels!") + owner.visible_message("The splint on [owner]'s left arm unravels from [owner.p_their()] [name]!","The splint on your [name] unravels!") owner.handle_splints() if(used_weapon) add_autopsy_data("[used_weapon]", brute + burn) @@ -239,10 +238,9 @@ #undef LIMB_SHARP_THRESH_INT_DMG #undef LIMB_THRESH_INT_DMG #undef LIMB_DMG_PROB -#undef LIMB_NO_BONE_DMG_PROB /obj/item/organ/external/proc/heal_damage(brute, burn, internal = 0, robo_repair = 0) - if(status & ORGAN_ROBOT && !robo_repair) + if(is_robotic() && !robo_repair) return brute_dam = max(brute_dam - brute, 0) @@ -261,10 +259,8 @@ This function completely restores a damaged organ to perfect condition. */ /obj/item/organ/external/rejuvenate() damage_state = "00" - if(status & ORGAN_ROBOT) //Robotic organs stay robotic. + if(is_robotic()) //Robotic organs stay robotic. status = ORGAN_ROBOT - else if(status & ORGAN_ASSISTED) //Assisted organs stay assisted. - status = ORGAN_ASSISTED else status = 0 germ_level = 0 @@ -273,8 +269,7 @@ This function completely restores a damaged organ to perfect condition. burn_dam = 0 open = 0 //Closing all wounds. internal_bleeding = FALSE - if(istype(src, /obj/item/organ/external/head) && disfigured) //If their head's disfigured, refigure it. - disfigured = 0 + disfigured = FALSE // handle internal organs for(var/obj/item/organ/internal/current_organ in internal_organs) @@ -283,7 +278,8 @@ This function completely restores a damaged organ to perfect condition. for(var/obj/item/organ/external/EO in contents) EO.rejuvenate() - owner.updatehealth() + if(owner) + owner.updatehealth() update_icon() if(!owner) processing_objects |= src @@ -332,7 +328,7 @@ Note that amputating the affected organ does in fact remove the infection from t */ /obj/item/organ/external/proc/update_germs() - if((status & ORGAN_ROBOT) || (IS_PLANT in owner.species.species_traits)) //Robotic limbs shouldn't be infected, nor should nonexistant limbs. + if(is_robotic() || (IS_PLANT in owner.dna.species.species_traits)) //Robotic limbs shouldn't be infected, nor should nonexistant limbs. germ_level = 0 return @@ -383,12 +379,12 @@ Note that amputating the affected organ does in fact remove the infection from t //spread the infection to child and parent organs if(children) for(var/obj/item/organ/external/child in children) - if(child.germ_level < germ_level && !(child.status & ORGAN_ROBOT)) + if(child.germ_level < germ_level && !child.is_robotic()) if(child.germ_level < INFECTION_LEVEL_ONE*2 || prob(30)) child.germ_level++ if(parent) - if(parent.germ_level < germ_level && !(parent.status & ORGAN_ROBOT)) + if(parent.germ_level < germ_level && !parent.is_robotic()) if(parent.germ_level < INFECTION_LEVEL_ONE*2 || prob(30)) parent.germ_level++ @@ -400,16 +396,16 @@ Note that amputating the affected organ does in fact remove the infection from t //Updates brute_damn and burn_damn from wound damages. Updates BLEEDING status. /obj/item/organ/external/proc/check_fracture() - if(config.bones_can_break && brute_dam > min_broken_damage && !(status & ORGAN_ROBOT)) + if(config.bones_can_break && brute_dam > min_broken_damage && !is_robotic()) fracture() /obj/item/organ/external/proc/check_for_internal_bleeding(damage) - if(NO_BLOOD in owner.species.species_traits) + if(NO_BLOOD in owner.dna.species.species_traits) return var/local_damage = brute_dam + damage - if(damage > 15 && local_damage > 30 && prob(damage) && !(status & ORGAN_ROBOT)) + if(damage > 15 && local_damage > 30 && prob(damage) && !is_robotic()) internal_bleeding = TRUE - owner.custom_pain("You feel something rip in your [name]!", 1) + owner.custom_pain("You feel something rip in your [name]!") // new damage icon system // returns just the brute/burn damage code @@ -442,7 +438,7 @@ Note that amputating the affected organ does in fact remove the infection from t return if(owner.step_count >= splinted_count + SPLINT_LIFE) status &= ~ORGAN_SPLINTED //oh no, we actually need surgery now! - owner.visible_message("[owner] screams in pain as their splint pops off their [name]!","You scream in pain as your splint pops off your [name]!") + owner.visible_message("[owner] screams in pain as [owner.p_their()] splint pops off their [name]!","You scream in pain as your splint pops off your [name]!") owner.emote("scream") owner.Stun(2) owner.handle_splints() @@ -453,7 +449,7 @@ Note that amputating the affected organ does in fact remove the infection from t ****************************************************/ //Handles dismemberment -/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate, var/ignore_children, var/nodamage) +/obj/item/organ/external/proc/droplimb(clean, disintegrate, ignore_children, nodamage) if(cannot_amputate || !owner) return @@ -464,20 +460,20 @@ Note that amputating the affected organ does in fact remove the infection from t switch(disintegrate) if(DROPLIMB_SHARP) if(!clean) - var/gore_sound = "[(status & ORGAN_ROBOT) ? "tortured metal" : "ripping tendons and flesh"]" + var/gore_sound = "[is_robotic() ? "tortured metal" : "ripping tendons and flesh"]" owner.visible_message( "\The [owner]'s [src.name] flies off in an arc!",\ "Your [src.name] goes flying off!",\ "You hear a terrible sound of [gore_sound].") if(DROPLIMB_BURN) - var/gore = "[(status & ORGAN_ROBOT) ? "": " of burning flesh"]" + var/gore = "[is_robotic() ? "" : " of burning flesh"]" owner.visible_message( "\The [owner]'s [src.name] flashes away into ashes!",\ "Your [src.name] flashes away into ashes!",\ "You hear a crackling sound[gore].") if(DROPLIMB_BLUNT) - var/gore = "[(status & ORGAN_ROBOT) ? "": " in shower of gore"]" - var/gore_sound = "[(status & ORGAN_ROBOT) ? "rending sound of tortured metal" : "sickening splatter of gore"]" + var/gore = "[is_robotic() ? "": " in shower of gore"]" + var/gore_sound = "[is_robotic() ? "rending sound of tortured metal" : "sickening splatter of gore"]" owner.visible_message( "\The [owner]'s [src.name] explodes[gore]!",\ "Your [src.name] explodes[gore]!",\ @@ -498,16 +494,17 @@ Note that amputating the affected organ does in fact remove the infection from t parent.receive_damage(total_brute, total_burn, ignore_resists = TRUE) //Transfer the full damage to the parent, bypass limb damage reduction. parent = null - spawn(1) - if(victim) - victim.updatehealth() - victim.UpdateDamageIcon() - victim.regenerate_icons() dir = 2 + + if(victim) + victim.updatehealth() + victim.UpdateDamageIcon() + victim.regenerate_icons() + switch(disintegrate) if(DROPLIMB_SHARP) compile_icon() - add_blood(victim.blood_DNA, victim.species.blood_color) + add_blood(victim.blood_DNA, victim.dna.species.blood_color) var/matrix/M = matrix() M.Turn(rand(180)) src.transform = M @@ -517,7 +514,7 @@ Note that amputating the affected organ does in fact remove the infection from t dropped_part.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) dir = 2 brute_dam = 0 - burn_dam = 0 //Reset the damage on the limb; the damage should have transferred to the parent; we don't want extra damage being re-applie when then limb is re-attached + burn_dam = 0 //Reset the damage on the limb; the damage should have transferred to the parent; we don't want extra damage being re-applied when then limb is re-attached return dropped_part else qdel(src) // If you flashed away to ashes, YOU FLASHED AWAY TO ASHES @@ -575,7 +572,7 @@ Note that amputating the affected organ does in fact remove the infection from t //empties the bodypart from its organs and other things inside it /obj/item/organ/external/proc/drop_organs(mob/user) var/turf/T = get_turf(src) - if(status != ORGAN_ROBOT) + if(!is_robotic()) playsound(T, 'sound/effects/splat.ogg', 25, 1) for(var/obj/item/I in src) I.forceMove(T) @@ -600,7 +597,7 @@ Note that amputating the affected organ does in fact remove the infection from t holder.unEquip(holder.legcuffed) /obj/item/organ/external/proc/fracture() - if(status & ORGAN_ROBOT) + if(is_robotic()) return //ORGAN_BROKEN doesn't have the same meaning for robot limbs if((status & ORGAN_BROKEN) || cannot_break) @@ -610,7 +607,7 @@ Note that amputating the affected organ does in fact remove the infection from t "You hear a loud cracking sound coming from \the [owner].",\ "Something feels like it shattered in your [name]!",\ "You hear a sickening crack.") - if(owner.species && !(NO_PAIN in owner.species.species_traits)) + if(owner.dna.species && !(NO_PAIN in owner.dna.species.species_traits)) owner.emote("scream") status |= ORGAN_BROKEN @@ -622,7 +619,7 @@ Note that amputating the affected organ does in fact remove the infection from t release_restraints() /obj/item/organ/external/proc/mend_fracture() - if(status & ORGAN_ROBOT) + if(is_robotic()) return 0 //ORGAN_BROKEN doesn't have the same meaning for robot limbs if(brute_dam > min_broken_damage) return 0 //will just immediately fracture again @@ -681,12 +678,12 @@ Note that amputating the affected organ does in fact remove the infection from t return FALSE /obj/item/organ/external/proc/is_usable() - if(((status & ORGAN_ROBOT) && get_damage() >= max_damage) && !tough) //robot limbs just become inoperable at max damage + if((is_robotic() && get_damage() >= max_damage) && !tough) //robot limbs just become inoperable at max damage return return !(status & (ORGAN_MUTATED|ORGAN_DEAD)) /obj/item/organ/external/proc/is_malfunctioning() - return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam) && !tough) + return (is_robotic() && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam) && !tough) /obj/item/organ/external/remove(var/mob/living/user, var/ignore_children) @@ -737,19 +734,14 @@ Note that amputating the affected organ does in fact remove the infection from t qdel(spark_system) qdel(src) -/obj/item/organ/external/proc/disfigure(var/type = "brute") +/obj/item/organ/external/proc/disfigure() if(disfigured) return if(owner) - if(type == "brute") - owner.visible_message("You hear a sickening cracking sound coming from \the [owner]'s [name].", \ - "Your [name] becomes a mangled mess!", \ - "You hear a sickening crack.") - else - owner.visible_message("\The [owner]'s [name] melts away, turning into mangled mess!", \ - "Your [name] melts away!", \ - "You hear a sickening sizzle.") - disfigured = 1 + owner.visible_message("You hear a sickening sound coming from \the [owner]'s [name] as it turns into a mangled mess!", \ + "Your [name] becomes a mangled mess!", \ + "You hear a sickening sound.") + disfigured = TRUE /obj/item/organ/external/is_primary_organ(var/mob/living/carbon/human/O = null) if(isnull(O)) @@ -773,7 +765,7 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/serialize() var/list/data = ..() - if(robotic == 2) + if(is_robotic()) data["company"] = model // If we wanted to store wound information, here is where it would go return data diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index e1be25758b5..43d699c0408 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -16,7 +16,7 @@ var/global/list/limb_icon_cache = list() /obj/item/organ/external/proc/change_organ_icobase(var/new_icobase, var/new_deform, var/owner_sensitive) //Change the icobase/deform of this organ. If owner_sensitive is set, that means the proc won't mess with frankenstein limbs. if(owner_sensitive) //This and the below statements mean that the icobase/deform will only get updated if the limb is the same species as and is owned by the mob it's attached to. - if(species && owner.species && species.name != owner.species.name) + if(dna.species && owner.dna.species && dna.species.name != owner.dna.species.name) return if(dna.unique_enzymes != owner.dna.unique_enzymes) // This isn't MY arm return @@ -25,31 +25,31 @@ var/global/list/limb_icon_cache = list() deform = new_deform ? new_deform : deform /obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/H) - if(status & ORGAN_ROBOT && !(species && species.name == "Machine")) //machine people get skin color + if(is_robotic() && !istype(dna.species, /datum/species/machine)) //machine people get skin color return - if(species && H.species && species.name != H.species.name) + if(dna.species && H.dna.species && dna.species.name != H.dna.species.name) return if(dna.unique_enzymes != H.dna.unique_enzymes) // This isn't MY arm - if(!(H.species.bodyflags & HAS_ICON_SKIN_TONE)) + if(!(H.dna.species.bodyflags & HAS_ICON_SKIN_TONE)) sync_colour_to_dna() return - if(!isnull(H.s_tone) && ((H.species.bodyflags & HAS_SKIN_TONE) || (H.species.bodyflags & HAS_ICON_SKIN_TONE))) + if(!isnull(H.s_tone) && ((H.dna.species.bodyflags & HAS_SKIN_TONE) || (H.dna.species.bodyflags & HAS_ICON_SKIN_TONE))) s_col = null s_tone = H.s_tone - if(H.species.bodyflags & HAS_SKIN_COLOR) + if(H.dna.species.bodyflags & HAS_SKIN_COLOR) s_tone = null s_col = H.skin_colour - if(H.species.bodyflags & HAS_ICON_SKIN_TONE) + if(H.dna.species.bodyflags & HAS_ICON_SKIN_TONE) var/obj/item/organ/external/chest/C = H.get_organ("chest") change_organ_icobase(C.icobase, C.deform) /obj/item/organ/external/proc/sync_colour_to_dna() - if(status & ORGAN_ROBOT) + if(is_robotic()) return - if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && ((species.bodyflags & HAS_SKIN_TONE) || (species.bodyflags & HAS_ICON_SKIN_TONE))) + if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && ((dna.species.bodyflags & HAS_SKIN_TONE) || (dna.species.bodyflags & HAS_ICON_SKIN_TONE))) s_col = null s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) - if(species.bodyflags & HAS_SKIN_COLOR) + if(dna.species.bodyflags & HAS_SKIN_COLOR) s_tone = null s_col = rgb(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B)) @@ -64,11 +64,9 @@ var/global/list/limb_icon_cache = list() /obj/item/organ/external/proc/get_icon(skeletal, fat) // Kasparrov, you monster - if(istext(species)) - species = all_species[species] if(force_icon) mob_icon = new /icon(force_icon, "[icon_name]") - if(species && species.name == "Machine") //snowflake for IPC's, sorry. + if(istype(dna.species, /datum/species/machine)) //snowflake for IPC's, sorry. if(s_col) mob_icon.Blend(s_col, ICON_ADD) else @@ -76,7 +74,7 @@ var/global/list/limb_icon_cache = list() var/icon_file = new_icons[1] var/new_icon_state = new_icons[2] mob_icon = new /icon(icon_file, new_icon_state) - if(!skeletal && !(status & ORGAN_ROBOT)) + if(!skeletal && !is_robotic()) if(status & ORGAN_DEAD) mob_icon.ColorTone(rgb(10,50,0)) mob_icon.SetIntensity(0.7) @@ -101,13 +99,13 @@ var/global/list/limb_icon_cache = list() if(!owner) return - if(species.has_organ["eyes"]) + if(dna.species.has_organ["eyes"]) var/icon/eyes_icon = owner.get_eyecon() if(eyes_icon) mob_icon.Blend(eyes_icon, ICON_OVERLAY) overlays |= eyes_icon - if(owner.lip_style && (LIPS in species.species_traits)) + if(owner.lip_style && (LIPS in dna.species.species_traits)) var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) @@ -115,7 +113,7 @@ var/global/list/limb_icon_cache = list() var/head_marking = owner.m_styles["head"] if(head_marking && head_marking != "None") var/datum/sprite_accessory/head_marking_style = marking_styles_list[head_marking] - if(head_marking_style && head_marking_style.species_allowed && (species.name in head_marking_style.species_allowed) && head_marking_style.marking_location == "head") + if(head_marking_style && head_marking_style.species_allowed && (dna.species.name in head_marking_style.species_allowed) && head_marking_style.marking_location == "head") var/icon/h_marking_s = new/icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") if(head_marking_style.do_colouration) h_marking_s.Blend(owner.m_colours["head"], ICON_ADD) @@ -123,7 +121,7 @@ var/global/list/limb_icon_cache = list() if(ha_style) var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[ha_style] - if(head_accessory_style && head_accessory_style.species_allowed && (species.name in head_accessory_style.species_allowed)) + if(head_accessory_style && head_accessory_style.species_allowed && (dna.species.name in head_accessory_style.species_allowed)) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) head_accessory_s.Blend(headacc_colour, ICON_ADD) @@ -131,9 +129,9 @@ var/global/list/limb_icon_cache = list() if(f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style && ((facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) || (src.species.bodyflags & ALL_RPARTS))) + if(facial_hair_style && ((facial_hair_style.species_allowed && (dna.species.name in facial_hair_style.species_allowed)) || (dna.species.bodyflags & ALL_RPARTS))) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(species.name == "Slime People") // I am el worstos + if(istype(dna.species, /datum/species/slime)) // I am el worstos facial_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. else if(facial_hair_style.do_colouration) facial_s.Blend(facial_colour, ICON_ADD) @@ -141,9 +139,9 @@ var/global/list/limb_icon_cache = list() if(h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_full_list[h_style] - if(hair_style && ((species.name in hair_style.species_allowed) || (src.species.bodyflags & ALL_RPARTS))) + if(hair_style && ((dna.species.name in hair_style.species_allowed) || (dna.species.bodyflags & ALL_RPARTS))) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(species.name == "Slime People") // I am el worstos + if(istype(dna.species, /datum/species/slime)) // I am el worstos hair_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. else if(hair_style.do_colouration) hair_s.Blend(hair_colour, ICON_ADD) @@ -172,7 +170,7 @@ var/global/list/limb_icon_cache = list() if(skeletal) icon_file = 'icons/mob/human_races/r_skeleton.dmi' - else if(status & ORGAN_ROBOT) + else if(is_robotic()) icon_file = 'icons/mob/human_races/robotic.dmi' else if(status & ORGAN_MUTATED) @@ -184,7 +182,7 @@ var/global/list/limb_icon_cache = list() /obj/item/organ/external/chest/get_icon_state(skeletal) var/result = ..() - if(fat && !skeletal && !(status & ORGAN_ROBOT) && (CAN_BE_FAT in species.species_traits)) + if(fat && !skeletal && !is_robotic() && (CAN_BE_FAT in dna.species.species_traits)) result[2] += "_fat" return result diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 42d2c98a66d..4858435cc5f 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -1,5 +1,3 @@ -#define PROCESS_ACCURACY 10 - /obj/item/organ/internal origin_tech = "biotech=3" force = 1 @@ -7,7 +5,6 @@ throwforce = 0 var/slot // DO NOT add slots with matching names to different zones - it will break internal_organs_slot list! - vital = 0 var/non_primary = 0 var/unremovable = FALSE //Whether it shows up as an option to remove during surgery. @@ -90,7 +87,7 @@ return /obj/item/organ/internal/proc/prepare_eat() - if(status == ORGAN_ROBOT) + if(is_robotic()) return //no eating cybernetic implants! var/obj/item/reagent_containers/food/snacks/organ/S = new S.name = name @@ -137,310 +134,21 @@ // Brain is defined in brain_item.dm. -/obj/item/organ/internal/heart - name = "heart" - icon_state = "heart-on" - organ_tag = "heart" - parent_organ = "chest" - slot = "heart" - origin_tech = "biotech=5" - var/beating = 1 - dead_icon = "heart-off" - var/icon_base = "heart" - -/obj/item/organ/internal/heart/update_icon() - if(beating) - icon_state = "[icon_base]-on" - else - icon_state = "[icon_base]-off" - -/obj/item/organ/internal/heart/remove(mob/living/carbon/M, special = 0) - . = ..() - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.stat == DEAD) - Stop() - return - - spawn(120) - if(!owner) - Stop() - -/obj/item/organ/internal/heart/attack_self(mob/user) - ..() - if(!beating) - Restart() - spawn(80) - if(!owner) - Stop() - -/obj/item/organ/internal/heart/safe_replace(mob/living/carbon/human/target) - Restart() - ..() - -/obj/item/organ/internal/heart/proc/Stop() - beating = 0 - update_icon() - return 1 - -/obj/item/organ/internal/heart/proc/Restart() - beating = 1 - update_icon() - return 1 - -/obj/item/organ/internal/heart/prepare_eat() - var/obj/S = ..() - S.icon_state = dead_icon - return S - -/obj/item/organ/internal/heart/cursed - name = "cursed heart" - desc = "it needs to be pumped..." - icon_state = "cursedheart-off" - icon_base = "cursedheart" - origin_tech = "biotech=6" - actions_types = list(/datum/action/item_action/organ_action/cursed_heart) - var/last_pump = 0 - var/pump_delay = 30 //you can pump 1 second early, for lag, but no more (otherwise you could spam heal) - var/blood_loss = 100 //600 blood is human default, so 5 failures (below 122 blood is where humans die because reasons?) - - //How much to heal per pump, negative numbers would HURT the player - var/heal_brute = 0 - var/heal_burn = 0 - var/heal_oxy = 0 - - -/obj/item/organ/internal/heart/cursed/attack(mob/living/carbon/human/H, mob/living/carbon/human/user, obj/target) - if(H == user && istype(H)) - if(NO_BLOOD in H.species.species_traits) - to_chat(H, "\The [src] is not compatible with your form!") - return - playsound(user,'sound/effects/singlebeat.ogg', 40, 1) - user.drop_item() - insert(user) - else - return ..() - -/obj/item/organ/internal/heart/cursed/on_life() - if(world.time > (last_pump + pump_delay)) - if(ishuman(owner) && owner.client) //While this entire item exists to make people suffer, they can't control disconnects. - var/mob/living/carbon/human/H = owner - if(!(NO_BLOOD in H.species.species_traits)) - H.blood_volume = max(H.blood_volume - blood_loss, 0) - to_chat(H, "You have to keep pumping your blood!") - if(H.client) - H.client.color = "red" //bloody screen so real - else - last_pump = world.time //lets be extra fair *sigh* - -/obj/item/organ/internal/heart/cursed/insert(mob/living/carbon/M, special = 0) - ..() - if(owner) - to_chat(owner, "Your heart has been replaced with a cursed one, you have to pump this one manually otherwise you'll die!") - - -/datum/action/item_action/organ_action/cursed_heart - name = "pump your blood" - -//You are now brea- pumping blood manually -/datum/action/item_action/organ_action/cursed_heart/Trigger() - . = ..() - if(. && istype(target,/obj/item/organ/internal/heart/cursed)) - var/obj/item/organ/internal/heart/cursed/cursed_heart = target - - if(world.time < (cursed_heart.last_pump + (cursed_heart.pump_delay-10))) //no spam - to_chat(owner, "Too soon!") - return - - cursed_heart.last_pump = world.time - playsound(owner,'sound/effects/singlebeat.ogg',40,1) - to_chat(owner, "Your heart beats.") - - var/mob/living/carbon/human/H = owner - if(istype(H)) - if(!(NO_BLOOD in H.species.species_traits)) - H.blood_volume = min(H.blood_volume + cursed_heart.blood_loss*0.5, BLOOD_VOLUME_NORMAL) - if(owner.client) - owner.client.color = "" - - H.adjustBruteLoss(-cursed_heart.heal_brute) - H.adjustFireLoss(-cursed_heart.heal_burn) - H.adjustOxyLoss(-cursed_heart.heal_oxy) - -/obj/item/organ/internal/kidneys - name = "kidneys" - icon_state = "kidneys" - gender = PLURAL - organ_tag = "kidneys" - parent_organ = "groin" - slot = "kidneys" - -/obj/item/organ/internal/kidneys/on_life() - // Coffee is really bad for you with busted kidneys. - // This should probably be expanded in some way, but fucked if I know - // what else kidneys can process in our reagent list. - var/datum/reagent/coffee = locate(/datum/reagent/consumable/drink/coffee) in owner.reagents.reagent_list - if(coffee) - if(is_bruised()) - owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) - else if(is_broken()) - owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) - - -/obj/item/organ/internal/eyes - name = "eyeballs" - icon_state = "eyes" - gender = PLURAL - organ_tag = "eyes" - parent_organ = "head" - slot = "eyes" - var/eye_colour = "#000000" - var/list/colourmatrix = null - var/list/colourblind_matrix = MATRIX_GREYSCALE //Special colourblindness parameters. By default, it's black-and-white. - var/list/replace_colours = LIST_GREYSCALE_REPLACE - var/dependent_disabilities = null //Gets set by eye-dependent disabilities such as colourblindness so the eyes can transfer the disability during transplantation. - var/dark_view = 2 //Default dark_view for Humans. - var/weld_proof = null //If set, the eyes will not take damage during welding. eg. IPC optical sensors do not take damage when they weld things while all other eyes will. - -/obj/item/organ/internal/eyes/proc/update_colour() - dna.write_eyes_attributes(src) - -/obj/item/organ/internal/eyes/proc/generate_icon(var/mob/living/carbon/human/HA) - var/mob/living/carbon/human/H = HA - if(!istype(H)) - H = owner - var/icon/eyes_icon = new /icon('icons/mob/human_face.dmi', H.species.eyes) - eyes_icon.Blend(eye_colour, ICON_ADD) - - return eyes_icon - -/obj/item/organ/internal/eyes/proc/get_colourmatrix() //Returns a special colour matrix if the eyes are organic and the mob is colourblind, otherwise it uses the current one. - if(!robotic && owner.disabilities & COLOURBLIND) - return colourblind_matrix - else - return colourmatrix - -/obj/item/organ/internal/eyes/proc/get_dark_view() //Returns dark_view (if the eyes are organic) for see_invisible handling in species.dm to be autoprocessed by life(). - return dark_view - -/obj/item/organ/internal/eyes/proc/shine() - if(is_robotic() || (dark_view > EYE_SHINE_THRESHOLD)) - return TRUE - -/obj/item/organ/internal/eyes/insert(mob/living/carbon/human/M, special = 0) - ..() - if(istype(M) && eye_colour) - M.update_body() //Apply our eye colour to the target. - - if(!(M.disabilities & COLOURBLIND) && (dependent_disabilities & COLOURBLIND)) //If the eyes are colourblind and we're not, carry over the gene. - dependent_disabilities &= ~COLOURBLIND - M.dna.SetSEState(COLOURBLINDBLOCK,1) - genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) - else - M.update_client_colour() //If we're here, that means the mob acquired the colourblindness gene while they didn't have eyes. Better handle it. - -/obj/item/organ/internal/eyes/remove(mob/living/carbon/human/M, special = 0) - if(!special && (M.disabilities & COLOURBLIND)) //If special is set, that means these eyes are getting deleted (i.e. during set_species()) - if(!(dependent_disabilities & COLOURBLIND)) //We only want to change COLOURBLINDBLOCK and such it the eyes are being surgically removed. - dependent_disabilities |= COLOURBLIND - M.dna.SetSEState(COLOURBLINDBLOCK,0) - genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) - . = ..() - -/obj/item/organ/internal/eyes/surgeryize() - if(!owner) - return - owner.CureNearsighted() - owner.CureBlind() - owner.SetEyeBlurry(0) - owner.SetEyeBlind(0) - -/obj/item/organ/internal/robotize(var/icon_bypass) //If icon bypass isn't null, skip the processing here and go straight to the parent call. - if(!icon_bypass && !(status & ORGAN_ROBOT)) //Don't override the icons for the already-mechanical IPC organs. +/obj/item/organ/internal/robotize() + if(!is_robotic()) var/list/states = icon_states('icons/obj/surgery.dmi') //Insensitive to specially-defined icon files for species like the Drask or whomever else. Everyone gets the same robotic heart. - if(slot == "heart" && ("[slot]-prosthetic-on" in states) && ("[slot]-prosthetic-off" in states)) //Give the robotic heart its robotic heart icons if they exist. + if(slot == "heart" && ("[slot]-c-on" in states) && ("[slot]-c-off" in states)) //Give the robotic heart its robotic heart icons if they exist. var/obj/item/organ/internal/heart/H = src H.icon = icon('icons/obj/surgery.dmi') - H.icon_base = "[slot]-prosthetic" - H.dead_icon = "[slot]-prosthetic-off" + H.icon_base = "[slot]-c" + H.dead_icon = "[slot]-c-off" H.update_icon() - else if("[slot]-prosthetic" in states) //Give the robotic organ its robotic organ icons if they exist. + else if("[slot]-c" in states) //Give the robotic organ its robotic organ icons if they exist. icon = icon('icons/obj/surgery.dmi') - icon_state = "[slot]-prosthetic" - name = "mechanical [slot]" + icon_state = "[slot]-c" + name = "cybernetic [slot]" ..() //Go apply all the organ flags/robotic statuses. -/obj/item/organ/internal/eyes/robotize() - colourmatrix = null - dark_view = 2 - ..() //Make sure the organ's got the robotic status indicators before updating the client colour. - if(owner) - owner.update_client_colour(0) //Since both mechassisted and mechanical eyes give dark_view of 2 and full colour vision atm, just having this here is fine as mechassist() will call it anyway. - -/obj/item/organ/internal/mechassist() - ..() //Go back, call robotize(), adjust the robotic status indicators and the organ damage parameters. - var/list/states = icon_states(icon) //Sensitive to specially-defined icon files since the organs are not fully synthetic. - if(slot == "heart" && ("[organ_tag]-assisted-on" in states) && ("[organ_tag]-assisted-off" in states)) //Give the mechassisted heart its mechassisted heart icons if they exist. - var/obj/item/organ/internal/heart/H = src - H.icon_base = "[organ_tag]-assisted" - H.dead_icon = "[organ_tag]-assisted-off" - H.update_icon() - else if("[organ_tag]-assisted" in states) //Give the mechassisted organ its mechassisted organ icons if they exist. - icon_state = "[organ_tag]-assisted" - name = "mechanically assisted [initial(name)]" //Avoid setting the organ's name to something like "mechanically assisted mechanical eyes". - -/obj/item/organ/internal/liver - name = "liver" - icon_state = "liver" - organ_tag = "liver" - parent_organ = "groin" - slot = "liver" - var/alcohol_intensity = 1 - -/obj/item/organ/internal/liver/on_life() - if(germ_level > INFECTION_LEVEL_ONE) - if(prob(1)) - to_chat(owner, " Your skin itches.") - if(germ_level > INFECTION_LEVEL_TWO) - if(prob(1)) - spawn owner.vomit() - - if(owner.life_tick % PROCESS_ACCURACY == 0) - - //High toxins levels are dangerous - if(owner.getToxLoss() >= 60 && !owner.reagents.has_reagent("charcoal")) - //Healthy liver suffers on its own - if(damage < min_broken_damage) - receive_damage(0.2 * PROCESS_ACCURACY) - //Damaged one shares the fun - else - var/obj/item/organ/internal/O = pick(owner.internal_organs) - if(O) - O.receive_damage(0.2 * PROCESS_ACCURACY) - - //Detox can heal small amounts of damage - if(damage && damage < min_bruised_damage && owner.reagents.has_reagent("charcoal")) - receive_damage(-0.2 * PROCESS_ACCURACY) - - // Get the effectiveness of the liver. - var/filter_effect = 3 - if(is_bruised()) - filter_effect -= 1 - if(is_broken()) - filter_effect -= 2 - - // Damaged liver means some chemicals are very dangerous - if(damage >= min_bruised_damage) - for(var/datum/reagent/R in owner.reagents.reagent_list) - // Ethanol and all drinks are bad - if(istype(R, /datum/reagent/consumable/ethanol)) - owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) - - // Can't cope with toxins at all - for(var/toxin in list("toxin", "plasma", "sacid", "facid", "cyanide", "amanitin", "carpotoxin")) - if(owner.reagents.has_reagent(toxin)) - owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) - /obj/item/organ/internal/appendix name = "appendix" icon_state = "appendix" diff --git a/code/modules/surgery/organs/pain.dm b/code/modules/surgery/organs/pain.dm index d107c7439c6..4863bd63901 100644 --- a/code/modules/surgery/organs/pain.dm +++ b/code/modules/surgery/organs/pain.dm @@ -1,41 +1,28 @@ -mob/var/list/pain_stored = list() -mob/var/last_pain_message = "" -mob/var/next_pain_time = 0 +/mob/living/carbon/human + var/last_pain_message = "" + var/next_pain_time = 0 // partname is the name of a body part // amount is a num from 1 to 100 -mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0) - if(stat >= 2) return +/mob/living/carbon/human/proc/pain(partname, amount) + if(stat >= UNCONSCIOUS) + return if(reagents.has_reagent("sal_acid")) return if(reagents.has_reagent("morphine")) return if(reagents.has_reagent("hydrocodone")) return - if(world.time < next_pain_time && !force) + if(world.time < next_pain_time) return - if(amount > 10 && istype(src,/mob/living/carbon/human)) - if(paralysis) - AdjustParalysis(-round(amount/10)) - if(amount > 50 && prob(amount / 5)) - src:drop_item() var/msg - if(burning) - switch(amount) - if(1 to 10) - msg = "Your [partname] burns." - if(11 to 90) - msg = "Your [partname] burns badly!" - if(91 to 10000) - msg = "OH GOD! Your [partname] is on fire!" - else - switch(amount) - if(1 to 10) - msg = "Your [partname] hurts." - if(11 to 90) - msg = "Your [partname] hurts badly." - if(91 to 10000) - msg = "OH GOD! Your [partname] is hurting terribly!" + switch(amount) + if(1 to 10) + msg = "Your [partname] hurts." + if(11 to 90) + msg = "Your [partname] hurts badly." + if(91 to INFINITY) + msg = "OH GOD! Your [partname] is hurting terribly!" if(msg && (msg != last_pain_message || prob(10))) last_pain_message = msg to_chat(src, msg) @@ -43,20 +30,18 @@ mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0 // message is the custom message to be displayed -// flash_strength is 0 for weak pain flash, 1 for strong pain flash -mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength) - if(stat >= 1) return - - if(NO_PAIN in species.species_traits) +mob/living/carbon/human/proc/custom_pain(message) + if(stat >= UNCONSCIOUS) return + if(NO_PAIN in dna.species.species_traits) + return if(reagents.has_reagent("morphine")) return if(reagents.has_reagent("hydrocodone")) return - var/msg = "[message]" - if(flash_strength >= 1) - msg = "[message]" + + var/msg = "[message]" // Anti message spam checks if(msg && ((msg != last_pain_message) || (world.time >= next_pain_time))) @@ -67,70 +52,33 @@ mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength) mob/living/carbon/human/proc/handle_pain() // not when sleeping - if(NO_PAIN in species.species_traits) - //While synthetics don't feel pain, they will notice their gears gunking up with residue (toxins) - if(isSynthetic()) - var/toxDamageMessage = null - var/toxMessageProb = 1 - switch(getToxLoss()) - if(25 to 50) - toxMessageProb = 1 - toxDamageMessage = "Your servos seem to be working harder." - if(50 to 75) - toxMessageProb = 2 - toxDamageMessage = "Your joints seem to stick randomly." - if(75 to INFINITY) - toxMessageProb = 5 - toxDamageMessage = "Your motors seem to slip; it really grinds your gears!" - if(toxDamageMessage && prob(toxMessageProb)) - src.custom_pain(toxDamageMessage, getToxLoss() >= 15) + if(stat >= UNCONSCIOUS) + return + if(NO_PAIN in dna.species.species_traits) return - - if(stat >= 2) return if(reagents.has_reagent("morphine")) return if(reagents.has_reagent("hydrocodone")) return + var/maxdam = 0 var/obj/item/organ/external/damaged_organ = null for(var/obj/item/organ/external/E in bodyparts) - if(E.status & ORGAN_DEAD|ORGAN_ROBOT) continue + if((E.status & ORGAN_DEAD|ORGAN_ROBOT) || E.hidden_pain) + continue var/dam = E.get_damage() // make the choice of the organ depend on damage, // but also sometimes use one of the less damaged ones - if(dam > maxdam && (maxdam == 0 || prob(70)) ) + if(dam > maxdam && (maxdam == 0 || prob(70))) damaged_organ = E maxdam = dam if(damaged_organ) - pain(damaged_organ.name, maxdam, 0) - + pain(damaged_organ.name, maxdam) // Damage to internal organs hurts a lot. for(var/obj/item/organ/internal/I in internal_organs) - if(istype(I, /obj/item/organ/internal/brain)) //the brain has no pain receptors, and brain damage is meant to be a stealthy damage type. + if(I.hidden_pain) continue - if(I.damage > 2) if(prob(2)) + if(I.damage > 2 && prob(2)) var/obj/item/organ/external/parent = get_organ(I.parent_organ) - src.custom_pain("You feel a sharp pain in your [parent.limb_name]", 1) - - var/toxDamageMessage = null - var/toxMessageProb = 1 - switch(getToxLoss()) - if(1 to 5) - toxMessageProb = 1 - toxDamageMessage = "Your body stings slightly." - if(6 to 10) - toxMessageProb = 2 - toxDamageMessage = "Your whole body hurts a little." - if(11 to 15) - toxMessageProb = 2 - toxDamageMessage = "Your whole body hurts." - if(15 to 25) - toxMessageProb = 3 - toxDamageMessage = "Your whole body hurts badly." - if(26 to INFINITY) - toxMessageProb = 5 - toxDamageMessage = "Your body aches all over, it's driving you mad." - - if(toxDamageMessage && prob(toxMessageProb)) - src.custom_pain(toxDamageMessage, getToxLoss() >= 15) + custom_pain("You feel a sharp pain in your [parent.limb_name]") \ No newline at end of file diff --git a/code/modules/surgery/organs/parasites.dm b/code/modules/surgery/organs/parasites.dm index 0adca48bfd0..bea8d37ae38 100644 --- a/code/modules/surgery/organs/parasites.dm +++ b/code/modules/surgery/organs/parasites.dm @@ -35,7 +35,8 @@ /obj/item/organ/internal/body_egg/spider_eggs/remove(var/mob/living/carbon/M, var/special = 0) ..() M.reagents.del_reagent("spidereggs") //purge all remaining spider eggs reagent if caught, in time. - qdel(src) //We don't want people re-implanting these for near instant gibbings. + if(!QDELETED(src)) + qdel(src) // prevent people re-implanting them into others return null @@ -82,7 +83,7 @@ // Actually, let's make it slightly worse... just to discourage people from bringing back infections. alternate_ending = 1 to_chat(owner,"The shapes extend tendrils out of your wound... no... those are legs! SPIDER LEGS! You have spiderlings growing inside you! You scratch at the wound, but it just aggrivates them - they swarm out of the wound, biting you all over!") - owner.visible_message("[owner] flails around on the floor as spiderlings erupt from their skin and swarm all over them! ") + owner.visible_message("[owner] flails around on the floor as spiderlings erupt from [owner.p_their()] skin and swarm all over them! ") owner.Stun(20) owner.Weaken(20) // yes, this is a long stun - that's intentional. Gotta give the spiderlings time to escape. @@ -114,5 +115,6 @@ /obj/item/organ/internal/body_egg/terror_eggs/remove(var/mob/living/carbon/M, var/special = 0) ..() - qdel(src) // prevent people re-implanting them into others + if(!QDELETED(src)) + qdel(src) // prevent people re-implanting them into others return null diff --git a/code/modules/surgery/organs/subtypes/abductor.dm b/code/modules/surgery/organs/subtypes/abductor.dm index 6fd234bc501..58efd0094ed 100644 --- a/code/modules/surgery/organs/subtypes/abductor.dm +++ b/code/modules/surgery/organs/subtypes/abductor.dm @@ -1,4 +1,3 @@ /obj/item/organ/internal/eyes/abductor name = "abductor eyeballs" - dark_view = 3 - species = "Abductor" + dark_view = 3 \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/diona.dm b/code/modules/surgery/organs/subtypes/diona.dm index 951ca862317..be05b2917c3 100644 --- a/code/modules/surgery/organs/subtypes/diona.dm +++ b/code/modules/surgery/organs/subtypes/diona.dm @@ -6,7 +6,6 @@ amputation_point = "trunk" encased = null gendered_icon = 0 - species = "Diona" /obj/item/organ/external/groin/diona name = "fork" @@ -14,7 +13,6 @@ cannot_break = 1 amputation_point = "lower trunk" gendered_icon = 0 - species = "Diona" /obj/item/organ/external/arm/diona name = "left upper tendril" @@ -22,7 +20,6 @@ min_broken_damage = 20 cannot_break = 1 amputation_point = "upper left trunk" - species = "Diona" /obj/item/organ/external/arm/right/diona name = "right upper tendril" @@ -30,7 +27,6 @@ min_broken_damage = 20 cannot_break = 1 amputation_point = "upper right trunk" - species = "Diona" /obj/item/organ/external/leg/diona name = "left lower tendril" @@ -38,7 +34,6 @@ min_broken_damage = 20 cannot_break = 1 amputation_point = "lower left fork" - species = "Diona" /obj/item/organ/external/leg/right/diona name = "right lower tendril" @@ -46,7 +41,6 @@ min_broken_damage = 20 cannot_break = 1 amputation_point = "lower right fork" - species = "Diona" /obj/item/organ/external/foot/diona name = "left foot" @@ -54,7 +48,6 @@ min_broken_damage = 10 cannot_break = 1 amputation_point = "branch" - species = "Diona" /obj/item/organ/external/foot/right/diona name = "right foot" @@ -62,19 +55,16 @@ min_broken_damage = 10 cannot_break = 1 amputation_point = "branch" - species = "Diona" /obj/item/organ/external/hand/diona name = "left grasper" cannot_break = 1 amputation_point = "branch" - species = "Diona" /obj/item/organ/external/hand/right/diona name = "right grasper" cannot_break = 1 amputation_point = "branch" - species = "Diona" /obj/item/organ/external/head/diona max_damage = 50 @@ -83,16 +73,6 @@ encased = null amputation_point = "upper trunk" gendered_icon = 0 - species = "Diona" - -//DIONA ORGANS. -/* /obj/item/organ/external/diona/removed() - var/mob/living/carbon/human/H = owner - ..() - if(!istype(H) || !H.bodyparts || !H.bodyparts.len) - H.death() - if(prob(50) && spawn_diona_nymph_from_organ(src)) - qdel(src) */ /obj/item/organ/diona/process() return @@ -101,31 +81,26 @@ name = "neural strata" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - species = "Diona" /obj/item/organ/internal/brain/diona // Turns into a nymph instantly, no transplanting possible. name = "gas bladder" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - species = "Diona" /obj/item/organ/internal/kidneys/diona // Turns into a nymph instantly, no transplanting possible. name = "polyp segment" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - species = "Diona" /obj/item/organ/internal/appendix/diona // Turns into a nymph instantly, no transplanting possible. name = "anchoring ligament" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - species = "Diona" /obj/item/organ/internal/eyes/diona // Turns into a nymph instantly, no transplanting possible. name = "receptor node" icon = 'icons/mob/alien.dmi' icon_state = "claw" - species = "Diona" //TODO:Make absorb rads on insert @@ -133,15 +108,4 @@ name = "nutrient vessel" icon = 'icons/mob/alien.dmi' icon_state = "claw" - alcohol_intensity = 0.5 - species = "Diona" - -//TODO:Make absorb light on insert. - -/*/obj/item/organ/diona/removed(var/mob/living/user) - var/mob/living/carbon/human/H = owner - ..() - if(!istype(H) || !H.bodyparts || !H.bodyparts.len) - H.death() - if(prob(50) && spawn_diona_nymph_from_organ(src)) - qdel(src) */ + alcohol_intensity = 0.5 \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/drask.dm b/code/modules/surgery/organs/subtypes/drask.dm index 8560d2408ec..6e11cf2993e 100644 --- a/code/modules/surgery/organs/subtypes/drask.dm +++ b/code/modules/surgery/organs/subtypes/drask.dm @@ -4,31 +4,26 @@ icon = 'icons/obj/surgery_drask.dmi' icon_state = "innards" desc = "A greenish, slightly translucent organ. It is extremely cold." - species = "Drask" /obj/item/organ/internal/heart/drask name = "drask heart" icon = 'icons/obj/surgery_drask.dmi' parent_organ = "head" - species = "Drask" /obj/item/organ/internal/liver/drask name = "metabolic strainer" icon = 'icons/obj/surgery_drask.dmi' icon_state = "kidneys" alcohol_intensity = 0.8 - species = "Drask" /obj/item/organ/internal/brain/drask icon = 'icons/obj/surgery_drask.dmi' icon_state = "brain2" mmi_icon = 'icons/obj/surgery_drask.dmi' mmi_icon_state = "mmi_full" - species = "Drask" /obj/item/organ/internal/eyes/drask name = "drask eyeballs" icon = 'icons/obj/surgery_drask.dmi' desc = "Drask eyes. They look even stranger disembodied" - dark_view = 5 - species = "Drask" + dark_view = 5 \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/grey.dm b/code/modules/surgery/organs/subtypes/grey.dm index 6c06da373b7..177e4ae5be1 100644 --- a/code/modules/surgery/organs/subtypes/grey.dm +++ b/code/modules/surgery/organs/subtypes/grey.dm @@ -1,11 +1,9 @@ /obj/item/organ/internal/liver/grey alcohol_intensity = 1.6 - species = "Grey" /obj/item/organ/internal/brain/grey icon_state = "brain-x" mmi_icon_state = "mmi_alien" - species = "Grey" /obj/item/organ/internal/brain/grey/insert(var/mob/living/carbon/M, var/special = 0) ..() @@ -17,5 +15,4 @@ /obj/item/organ/internal/eyes/grey name = "grey eyeballs" - dark_view = 5 - species = "Grey" + dark_view = 5 \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/kidan.dm b/code/modules/surgery/organs/subtypes/kidan.dm index 37fd74a6d2a..d8fc67cc542 100644 --- a/code/modules/surgery/organs/subtypes/kidan.dm +++ b/code/modules/surgery/organs/subtypes/kidan.dm @@ -1,6 +1,5 @@ /obj/item/organ/internal/liver/kidan alcohol_intensity = 0.5 - species = "Kidan" #define KIDAN_LANTERN_HUNGERCOST 0.5 #define KIDAN_LANTERN_MINHUNGER 150 diff --git a/code/modules/surgery/organs/subtypes/machine.dm b/code/modules/surgery/organs/subtypes/machine.dm index 2be14a91f14..b66d13612a3 100644 --- a/code/modules/surgery/organs/subtypes/machine.dm +++ b/code/modules/surgery/organs/subtypes/machine.dm @@ -1,105 +1,94 @@ // IPC limbs. /obj/item/organ/external/head/ipc can_intake_reagents = 0 - vital = 0 max_damage = 50 //made same as arm, since it is not vital min_broken_damage = 30 encased = null status = ORGAN_ROBOT - species = "Machine" -/obj/item/organ/external/head/ipc/New() +/obj/item/organ/external/head/ipc/New(mob/living/carbon/holder, datum/species/species_override = null) + ..(holder, /datum/species/machine) // IPC heads need to be explicitly set to this since you can print them robotize("Morpheus Cyberkinetics") - ..() /obj/item/organ/external/chest/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/chest/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/groin/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/groin/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/arm/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/arm/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/arm/right/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/arm/right/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") + /obj/item/organ/external/leg/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/leg/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/leg/right/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/leg/right/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/foot/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/foot/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/foot/right/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/foot/right/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/hand/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/hand/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/external/hand/right/ipc encased = null status = ORGAN_ROBOT - species = "Machine" /obj/item/organ/external/hand/right/ipc/New() - robotize("Morpheus Cyberkinetics") ..() + robotize("Morpheus Cyberkinetics") /obj/item/organ/internal/cell name = "microbattery" @@ -109,86 +98,39 @@ organ_tag = "heart" parent_organ = "chest" slot = "heart" - vital = 1 + vital = TRUE status = ORGAN_ROBOT - species = "Machine" - -/obj/item/organ/internal/cell/New() - robotize() - ..() /obj/item/organ/internal/eyes/optical_sensor name = "optical sensor" icon = 'icons/obj/robot_component.dmi' icon_state = "camera" status = ORGAN_ROBOT - species = "Machine" // dead_icon = "camera_broken" weld_proof = 1 -/obj/item/organ/internal/eyes/optical_sensor/New() - robotize() - ..() - - /obj/item/organ/internal/eyes/optical_sensor/remove(var/mob/living/user,special = 0) if(!special) to_chat(owner, "Error 404:Optical Sensors not found.") . = ..() -// Used for an MMI or posibrain being installed into a human. -/obj/item/organ/internal/brain/mmi_holder - name = "brain" - organ_tag = "brain" - parent_organ = "chest" - vital = 1 - max_damage = 200 - slot = "brain" - status = ORGAN_ROBOT - species = "Machine" - var/obj/item/mmi/stored_mmi - -/obj/item/organ/internal/brain/mmi_holder/Destroy() - QDEL_NULL(stored_mmi) - return ..() - -/obj/item/organ/internal/brain/mmi_holder/insert(var/mob/living/target,special = 0) - ..() - // To supersede the over-writing of the MMI's name from `insert` - update_from_mmi() - -/obj/item/organ/internal/brain/mmi_holder/remove(var/mob/living/user,special = 0) - if(!special) - if(stored_mmi) - . = stored_mmi - if(owner.mind) - owner.mind.transfer_to(stored_mmi.brainmob) - stored_mmi.forceMove(get_turf(owner)) - stored_mmi = null - ..() - qdel(src) - -/obj/item/organ/internal/brain/mmi_holder/proc/update_from_mmi() - if(!stored_mmi) - return - name = stored_mmi.name - desc = stored_mmi.desc - icon = stored_mmi.icon - icon_state = stored_mmi.icon_state - set_dna(stored_mmi.brainmob.dna) +/obj/item/organ/internal/brain/mmi_holder/posibrain + name = "positronic brain" /obj/item/organ/internal/brain/mmi_holder/posibrain/New() - robotize() - stored_mmi = new /obj/item/mmi/posibrain/ipc(src) ..() - spawn(1) - if(owner) - stored_mmi.name = "positronic brain ([owner.real_name])" - stored_mmi.brainmob.real_name = owner.real_name - stored_mmi.brainmob.name = stored_mmi.brainmob.real_name - stored_mmi.icon_state = "posibrain-occupied" - update_from_mmi() - else - stored_mmi.loc = get_turf(src) - qdel(src) + stored_mmi = new /obj/item/mmi/robotic_brain/positronic(src) + if(!owner) + stored_mmi.forceMove(get_turf(src)) + qdel(src) + +/obj/item/organ/internal/brain/mmi_holder/posibrain/remove(mob/living/user, special = 0) + if(stored_mmi && dna) + stored_mmi.name = "[initial(name)] ([dna.real_name])" + stored_mmi.brainmob.real_name = dna.real_name + stored_mmi.brainmob.name = stored_mmi.brainmob.real_name + stored_mmi.icon_state = "posibrain-occupied" + if(!stored_mmi.brainmob.dna) + stored_mmi.brainmob.dna = dna.Clone() + . = ..() \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/nucleation.dm b/code/modules/surgery/organs/subtypes/nucleation.dm index 4223834501d..3be564fc800 100644 --- a/code/modules/surgery/organs/subtypes/nucleation.dm +++ b/code/modules/surgery/organs/subtypes/nucleation.dm @@ -3,7 +3,6 @@ name = "nucleation organ" icon = 'icons/obj/surgery.dmi' desc = "A crystalized human organ. /red It has a strangely iridescent glow." - species = "Nucleation" /obj/item/organ/internal/nucleation/resonant_crystal name = "resonant crystal" @@ -11,7 +10,6 @@ organ_tag = "resonant crystal" parent_organ = "head" slot = "res_crystal" - species = "Nucleation" /obj/item/organ/internal/nucleation/strange_crystal name = "strange crystal" @@ -19,14 +17,12 @@ organ_tag = "strange crystal" parent_organ = "chest" slot = "heart" - species = "Nucleation" /obj/item/organ/internal/eyes/luminescent_crystal name = "luminescent eyes" icon_state = "crystal-eyes" organ_tag = "luminescent eyes" light_color = "#1C1C00" - species = "Nucleation" /obj/item/organ/internal/eyes/luminescent_crystal/New() set_light(2) @@ -35,5 +31,4 @@ /obj/item/organ/internal/brain/crystal name = "crystallized brain" icon_state = "crystal-brain" - organ_tag = "crystallized brain" - species = "Nucleation" + organ_tag = "crystallized brain" \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/shadow.dm b/code/modules/surgery/organs/subtypes/shadow.dm index f81fc54bfb1..26a0bc50577 100644 --- a/code/modules/surgery/organs/subtypes/shadow.dm +++ b/code/modules/surgery/organs/subtypes/shadow.dm @@ -1,4 +1,3 @@ /obj/item/organ/internal/eyes/shadow name = "dark orbs" - dark_view = 8 - species = "Shadow" + dark_view = 8 \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/skrell.dm b/code/modules/surgery/organs/subtypes/skrell.dm index cb87d1c11c1..fd8a02f18d3 100644 --- a/code/modules/surgery/organs/subtypes/skrell.dm +++ b/code/modules/surgery/organs/subtypes/skrell.dm @@ -1,6 +1,5 @@ /obj/item/organ/internal/liver/skrell alcohol_intensity = 4 - species = "Skrell" /obj/item/organ/internal/headpocket name = "headpocket" @@ -10,7 +9,6 @@ w_class = WEIGHT_CLASS_TINY parent_organ = "head" slot = "headpocket" - species = "Skrell" actions_types = list(/datum/action/item_action/organ_action/toggle) var/obj/item/storage/internal/pocket diff --git a/code/modules/surgery/organs/subtypes/standard.dm b/code/modules/surgery/organs/subtypes/standard.dm index 3fd8effd56a..e04c27284ae 100644 --- a/code/modules/surgery/organs/subtypes/standard.dm +++ b/code/modules/surgery/organs/subtypes/standard.dm @@ -10,7 +10,7 @@ min_broken_damage = 35 w_class = WEIGHT_CLASS_HUGE body_part = UPPER_TORSO - vital = 1 + vital = TRUE amputation_point = "spine" gendered_icon = 1 parent_organ = null @@ -44,7 +44,7 @@ min_broken_damage = 35 w_class = WEIGHT_CLASS_BULKY // if you know what I mean ;) body_part = LOWER_TORSO - vital = 1 + vital = TRUE parent_organ = "chest" amputation_point = "lumbar" gendered_icon = 1 @@ -136,9 +136,9 @@ if(owner.gloves) owner.unEquip(owner.gloves) if(owner.l_hand) - owner.unEquip(owner.l_hand,1) + owner.unEquip(owner.l_hand, TRUE) if(owner.r_hand) - owner.unEquip(owner.r_hand,1) + owner.unEquip(owner.r_hand, TRUE) . = ..() @@ -158,7 +158,6 @@ min_broken_damage = 35 w_class = WEIGHT_CLASS_NORMAL body_part = HEAD - vital = 1 parent_organ = "chest" amputation_point = "neck" gendered_icon = 1 @@ -195,27 +194,21 @@ owner.unEquip(owner.r_ear) if(owner.wear_mask) owner.unEquip(owner.wear_mask) - spawn(1) - if(owner)//runtimer no runtiming - owner.update_hair() - owner.update_fhair() - owner.update_head_accessory() - owner.update_markings() + owner.update_hair() + owner.update_fhair() + owner.update_head_accessory() + owner.update_markings() . = ..() /obj/item/organ/external/head/replaced() name = limb_name - ..() /obj/item/organ/external/head/receive_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list(), ignore_resists = FALSE) ..(brute, burn, sharp, used_weapon, forbidden_limbs, ignore_resists) if(!disfigured) - if(brute_dam > 40) - if(prob(50)) - disfigure("brute") - if(burn_dam > 40) - disfigure("burn") + if(brute_dam + burn_dam > 50) + disfigure() /obj/item/organ/external/head/proc/handle_alt_icon() if(alt_head && alt_heads_list[alt_head]) @@ -228,6 +221,11 @@ alt_head = initial(alt_head) icon_name = initial(icon_name) +/obj/item/organ/external/head/robotize(company, make_tough = 0, convert_all = 1) //Undoes alt_head business to avoid getting in the way of robotization. Make sure we pass all args down the line... + alt_head = initial(alt_head) + icon_name = initial(icon_name) + ..() + /obj/item/organ/external/head/set_dna(datum/dna/new_dna) ..() new_dna.write_head_attributes(src) diff --git a/code/modules/surgery/organs/subtypes/tajaran.dm b/code/modules/surgery/organs/subtypes/tajaran.dm index a1313934037..1857fc5e45a 100644 --- a/code/modules/surgery/organs/subtypes/tajaran.dm +++ b/code/modules/surgery/organs/subtypes/tajaran.dm @@ -1,17 +1,14 @@ /obj/item/organ/internal/liver/tajaran alcohol_intensity = 1.4 - species = "Tajaran" /obj/item/organ/internal/eyes/tajaran name = "tajaran eyeballs" - species = "Tajaran" colourblind_matrix = MATRIX_TAJ_CBLIND //The colour matrix and darksight parameters that the mob will recieve when they get the disability. replace_colours = LIST_TAJ_REPLACE dark_view = 8 /obj/item/organ/internal/eyes/tajaran/farwa //Being the lesser form of Tajara, Farwas have an utterly incurable version of their colourblindness. name = "farwa eyeballs" - species = "Farwa" colourmatrix = MATRIX_TAJ_CBLIND dark_view = 8 replace_colours = LIST_TAJ_REPLACE diff --git a/code/modules/surgery/organs/subtypes/unathi.dm b/code/modules/surgery/organs/subtypes/unathi.dm index 0fb45319ce5..219ef0447e6 100644 --- a/code/modules/surgery/organs/subtypes/unathi.dm +++ b/code/modules/surgery/organs/subtypes/unathi.dm @@ -1,8 +1,6 @@ /obj/item/organ/internal/liver/unathi alcohol_intensity = 0.8 - species = "Unathi" /obj/item/organ/internal/eyes/unathi name = "unathi eyeballs" - dark_view = 3 - species = "Unathi" + dark_view = 3 \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/vox.dm b/code/modules/surgery/organs/subtypes/vox.dm index bb56c41030d..960acf920a8 100644 --- a/code/modules/surgery/organs/subtypes/vox.dm +++ b/code/modules/surgery/organs/subtypes/vox.dm @@ -1,16 +1,12 @@ /obj/item/organ/internal/liver/vox alcohol_intensity = 1.6 - species = "Vox" /obj/item/organ/internal/stack - name = "cortical stack" + name = "vox cortical stack" icon_state = "brain-prosthetic" parent_organ = "head" organ_tag = "stack" slot = "vox_stack" - robotic = 2 - vital = 1 - -/obj/item/organ/internal/stack/vox - name = "vox cortical stack" \ No newline at end of file + status = ORGAN_ROBOT + vital = TRUE \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/vulpkanin.dm b/code/modules/surgery/organs/subtypes/vulpkanin.dm index be851c43486..959fbcc926c 100644 --- a/code/modules/surgery/organs/subtypes/vulpkanin.dm +++ b/code/modules/surgery/organs/subtypes/vulpkanin.dm @@ -1,18 +1,14 @@ /obj/item/organ/internal/liver/vulpkanin alcohol_intensity = 1.4 - species = "Vulpkanin" - /obj/item/organ/internal/eyes/vulpkanin name = "vulpkanin eyeballs" - species = "Vulpkanin" colourblind_matrix = MATRIX_VULP_CBLIND //The colour matrix and darksight parameters that the mob will recieve when they get the disability. replace_colours = LIST_VULP_REPLACE dark_view = 8 /obj/item/organ/internal/eyes/vulpkanin/wolpin //Being the lesser form of Vulpkanin, Wolpins have an utterly incurable version of their colourblindness. name = "wolpin eyeballs" - species = "Wolpin" colourmatrix = MATRIX_VULP_CBLIND dark_view = 8 - replace_colours = LIST_VULP_REPLACE + replace_colours = LIST_VULP_REPLACE \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/wryn.dm b/code/modules/surgery/organs/subtypes/wryn.dm index ee1a12fd1ab..ab30c16f61f 100644 --- a/code/modules/surgery/organs/subtypes/wryn.dm +++ b/code/modules/surgery/organs/subtypes/wryn.dm @@ -6,8 +6,6 @@ icon_state = "antennae" parent_organ = "head" slot = "hivenode" - species = "Wryn" /obj/item/organ/internal/eyes/wryn - dark_view = 3 - species = "Wryn" + dark_view = 3 \ No newline at end of file diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 1af925c3166..32270c329c2 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -32,7 +32,7 @@ if(!affected) // I'd like to see you do surgery on LITERALLY NOTHING return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 if(!affected.encased) //no bone, problem. return 0 @@ -43,7 +43,7 @@ var/mob/living/carbon/human/H = target var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) - if(affected && (affected.status & ORGAN_ROBOT)) + if(affected && affected.is_robotic()) return 0//no operating on robotic limbs in an organic surgery if(!affected) // I'd like to see you do surgery on LITERALLY NOTHING @@ -101,6 +101,9 @@ if(is_int_organ(tool)) current_type = "insert" I = tool + if(I.requires_robotic_bodypart) + to_chat(user, "[I] is an organ that requires a robotic interface[target].") + return -1 if(target_zone != I.parent_organ || target.get_organ_slot(I.slot)) to_chat(user, "There is no room for [I] in [target]'s [parse_zone(target_zone)]!") return -1 @@ -116,7 +119,7 @@ if(affected) user.visible_message("[user] starts transplanting [tool] into [target]'s [affected.name].", \ "You start transplanting [tool] into [target]'s [affected.name].") - H.custom_pain("Someone's rooting around in your [affected.name]!",1) + H.custom_pain("Someone's rooting around in your [affected.name]!") else user.visible_message("[user] starts transplanting [tool] into [target]'s [parse_zone(target_zone)].", \ "You start transplanting [tool] into [target]'s [parse_zone(target_zone)].") @@ -143,7 +146,7 @@ self_msg = "You begin injecting [tool] into [target]'s [I.name]." user.visible_message(msg, self_msg) if(H && affected) - H.custom_pain("Something burns horribly in your [affected.name]!",1) + H.custom_pain("Something burns horribly in your [affected.name]!") else if(implement_type in implements_finsh) //same as surgery step /datum/surgery_step/open_encased/close/ @@ -159,7 +162,7 @@ user.visible_message(msg, self_msg) if(H && affected) - H.custom_pain("Something hurts horribly in your [affected.name]!",1) + H.custom_pain("Something hurts horribly in your [affected.name]!") else if(implement_type in implements_extract) current_type = "extract" @@ -188,7 +191,7 @@ user.visible_message("[user] starts to separate [target]'s [I] with [tool].", \ "You start to separate [target]'s [I] with [tool] for removal." ) if(H && affected) - H.custom_pain("The pain in your [affected.name] is living hell!",1) + H.custom_pain("The pain in your [affected.name] is living hell!") else return -1 @@ -208,12 +211,12 @@ for(var/obj/item/organ/internal/I in affected.internal_organs) if(I && I.damage) - if(I.robotic < 2 && !istype (tool, /obj/item/stack/nanopaste)) + if(!I.is_robotic() && !istype (tool, /obj/item/stack/nanopaste)) if(!(I.sterile)) spread_germs_to_organ(I, user, tool) user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \ "You start treating damage to [target]'s [I.name] with [tool_name]." ) - else if(I.robotic >= 2 && istype(tool, /obj/item/stack/nanopaste)) + else if(I.is_robotic() && istype(tool, /obj/item/stack/nanopaste)) user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \ "You start treating damage to [target]'s [I.name] with [tool_name]." ) @@ -221,7 +224,7 @@ to_chat(user, "[I] does not appear to be damaged.") if(affected) - H.custom_pain("The pain in your [affected.name] is living hell!", 1) + H.custom_pain("The pain in your [affected.name] is living hell!") else if(istype(tool, /obj/item/reagent_containers/food/snacks/organ)) to_chat(user, "[tool] was bitten by someone! It's too damaged to use!") @@ -246,23 +249,25 @@ if(I) I.surgeryize() if(I && I.damage) - if(I.robotic < 2 && !istype (tool, /obj/item/stack/nanopaste)) + if(!I.is_robotic() && !istype (tool, /obj/item/stack/nanopaste)) user.visible_message(" [user] treats damage to [target]'s [I.name] with [tool_name].", \ " You treat damage to [target]'s [I.name] with [tool_name]." ) I.damage = 0 - else if(I.robotic >= 2 && istype (tool, /obj/item/stack/nanopaste)) + else if(I.is_robotic() && istype (tool, /obj/item/stack/nanopaste)) user.visible_message(" [user] treats damage to [target]'s [I.name] with [tool_name].", \ " You treat damage to [target]'s [I.name] with [tool_name]." ) I.damage = 0 else if(current_type == "insert") I = tool - user.drop_item() - I.insert(target) - spread_germs_to_organ(I, user, tool) - if(!user.canUnEquip(I, 0)) + if(I.requires_robotic_bodypart) + to_chat(user, "[I] is an organ that requires a robotic interface[target].") + return FALSE + if(!user.drop_item()) to_chat(user, "[I] is stuck to your hand, you can't put it in [target]!") return 0 + I.insert(target) + spread_germs_to_organ(I, user, tool) if(affected) user.visible_message(" [user] has transplanted [tool] into [target]'s [affected.name].", diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 012f7ad3c5b..bcb5151d359 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -24,7 +24,7 @@ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 return 1 return 0 @@ -80,7 +80,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts patching the damaged vein in [target]'s [affected.name] with \the [tool]." , \ "You start patching the damaged vein in [target]'s [affected.name] with \the [tool].") - target.custom_pain("The pain in [affected.name] is unbearable!",1) + target.custom_pain("The pain in [affected.name] is unbearable!") ..() /datum/surgery_step/fix_vein/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -133,7 +133,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts cutting away necrotic tissue in [target]'s [affected.name] with \the [tool]." , \ "You start cutting away necrotic tissue in [target]'s [affected.name] with \the [tool].") - target.custom_pain("The pain in [affected.name] is unbearable!",1) + target.custom_pain("The pain in [affected.name] is unbearable!") ..() /datum/surgery_step/fix_dead_tissue/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -191,7 +191,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts applying medication to the affected tissue in [target]'s [affected.name] with \the [tool]." , \ "You start applying medication to the affected tissue in [target]'s [affected.name] with \the [tool].") - target.custom_pain("Something in your [affected.name] is causing you a lot of pain!",1) + target.custom_pain("Something in your [affected.name] is causing you a lot of pain!") ..() /datum/surgery_step/treat_necrosis/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -241,7 +241,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery/remove_thrall name = "Remove Shadow Tumor" - steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/open_encased/saw,/datum/surgery_step/open_encased/retract, /datum/surgery_step/internal/dethrall, /datum/surgery_step/glue_bone, /datum/surgery_step/set_bone,/datum/surgery_step/finish_bone,/datum/surgery_step/generic/cauterize) + steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/internal/dethrall, /datum/surgery_step/generic/cauterize) possible_locs = list("head", "chest", "groin") /datum/surgery/remove_thrall/synth @@ -260,7 +260,7 @@ if(!B) // No brain to remove the tumor from return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 if(!(B in affected.internal_organs)) return 0 @@ -276,7 +276,7 @@ if(!B) // No brain to remove the tumor from return 0 - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) return 0 if(!(B in affected.internal_organs)) return 0 @@ -303,7 +303,7 @@ ..() /datum/surgery_step/internal/dethrall/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - if(target.get_species() == "Lesser Shadowling") //Empowered thralls cannot be deconverted + if(isshadowlinglesser(target)) //Empowered thralls cannot be deconverted to_chat(target, "NOT LIKE THIS!") user.visible_message("[target] suddenly slams upward and knocks down [user]!", \ "[target] suddenly bolts up and slams you with tremendous force!") diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm new file mode 100644 index 00000000000..9483818d153 --- /dev/null +++ b/code/modules/surgery/plastic_surgery.dm @@ -0,0 +1,56 @@ +/datum/surgery/plastic_surgery + name = "Plastic Surgery" + steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/reshape_face, /datum/surgery_step/generic/cauterize) + possible_locs = list("head") + +/datum/surgery/plastic_surgery/can_start(mob/user, mob/living/carbon/target) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/obj/item/organ/external/head/head = H.get_organ(user.zone_sel.selecting) + if(!head) + return FALSE + if(head.is_robotic()) + return FALSE + return TRUE + + +/datum/surgery_step/reshape_face + name = "reshape face" + allowed_tools = list(/obj/item/scalpel = 100, /obj/item/kitchen/knife = 50, /obj/item/wirecutters = 35) + time = 64 + +/datum/surgery_step/reshape_face/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] begins to alter [target]'s appearance.", "You begin to alter [target]'s appearance...") + +/datum/surgery_step/reshape_face/end_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/obj/item/organ/external/head/head = target.get_organ(target_zone) + var/species_names = target.dna.species.name + if(head.disfigured) + head.disfigured = FALSE + user.visible_message("[user] successfully restores [target]'s appearance!", "You successfully restore [target]'s appearance.") + else + var/list/names = list() + if(!isabductor(user)) + for(var/i in 1 to 10) + names += random_name(target.gender, species_names) + else + for(var/_i in 1 to 9) + names += "Subject [target.gender == MALE ? "i" : "o"]-[pick("a", "b", "c", "d", "e")]-[rand(10000, 99999)]" + names += random_name(target.gender, species_names) //give one normal name in case they want to do regular plastic surgery + var/chosen_name = input(user, "Choose a new name to assign.", "Plastic Surgery") as null|anything in names + if(!chosen_name) + return + var/oldname = target.real_name + target.real_name = chosen_name + var/newname = target.real_name //something about how the code handles names required that I use this instead of target.real_name + user.visible_message("[user] alters [oldname]'s appearance completely, [target.p_they()] [target.p_are()] now [newname]!", "You alter [oldname]'s appearance completely, [target.p_they()] [target.p_are()] now [newname].") + target.sec_hud_set_ID() + return TRUE + + +/datum/surgery_step/reshape_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/obj/item/organ/external/head/head = target.get_organ(target_zone) + user.visible_message(" [user]'s hand slips, tearing skin on [target]'s face with [tool]!", \ + " Your hand slips, tearing skin on [target]'s face with [tool]!") + target.apply_damage(10, BRUTE, head, sharp = TRUE) + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/remove_embedded_object.dm b/code/modules/surgery/remove_embedded_object.dm index 56162dcabc8..3dde9ce1a09 100644 --- a/code/modules/surgery/remove_embedded_object.dm +++ b/code/modules/surgery/remove_embedded_object.dm @@ -13,7 +13,7 @@ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(affected.status & ORGAN_ROBOT) + if(affected.is_robotic()) return 0 return 1 @@ -23,7 +23,7 @@ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) return 0 return 1 diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 58b570eb5e3..f9fb2ac20c2 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -28,7 +28,7 @@ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) return 0 return 1 @@ -38,7 +38,7 @@ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) if(!affected) return 0 - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) return 0 if(affected.cannot_amputate) return 0 @@ -64,7 +64,7 @@ if(!..()) return 0 var/obj/item/organ/external/affected = target.get_organ(target_zone) - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) return 0 return 1 @@ -248,10 +248,7 @@ user.visible_message(" [user] finishes patching damage to [target]'s [affected.name] with \the [tool].", \ " You finish patching damage to [target]'s [affected.name] with \the [tool].") affected.heal_damage(rand(30,50),0,1,1) - if(affected.disfigured) - affected.disfigured = 0 - affected.update_icon() - target.regenerate_icons() + affected.disfigured = FALSE if("burn") user.visible_message(" [user] finishes splicing cable into [target]'s [affected.name].", \ " You finishes splicing new cable into [target]'s [affected.name].") @@ -308,7 +305,7 @@ current_type = "insert" var/obj/item/organ/internal/I = tool - if(I.status != ORGAN_ROBOT || I.robotic != 2) + if(!I.is_robotic()) to_chat(user, "You can only implant cybernetic organs.") if(target_zone != I.parent_organ || target.get_organ_slot(I.slot)) @@ -325,7 +322,7 @@ user.visible_message("[user] begins reattaching [target]'s [tool].", \ "You start reattaching [target]'s [tool].") - target.custom_pain("Someone's rooting around in your [affected.name]!",1) + target.custom_pain("Someone's rooting around in your [affected.name]!") else if(istype(tool,/obj/item/mmi)) current_type = "install" @@ -346,16 +343,16 @@ to_chat(user, "That brain is not usable.") return -1 - if(!(affected.status & ORGAN_ROBOT)) + if(!affected.is_robotic()) to_chat(user, "You cannot install a computer brain into a meat enclosure.") return -1 - if(!target.species) + if(!target.dna.species) to_chat(user, "You have no idea what species this person is. Report this on the bug tracker.") return -1 - if(!target.species.has_organ["brain"]) - to_chat(user, "You're pretty sure [target.species.name_plural] don't normally have a brain.") + if(!target.dna.species.has_organ["brain"]) + to_chat(user, "You're pretty sure [target.dna.species.name_plural] don't normally have a brain.") return -1 if(target.get_int_organ(/obj/item/organ/internal/brain/)) @@ -368,7 +365,7 @@ else if(implement_type in implements_extract) current_type = "extract" var/list/organs = target.get_organs_zone(target_zone) - if(!(affected && (affected.status & ORGAN_ROBOT))) + if(!(affected && affected.is_robotic())) return -1 if(!organs.len) to_chat(user, "There is no removeable organs in [target]'s [parse_zone(target_zone)]!") @@ -386,7 +383,7 @@ user.visible_message("[user] starts to decouple [target]'s [I] with \the [tool].", \ "You start to decouple [target]'s [I] with \the [tool]." ) - target.custom_pain("The pain in your [affected.name] is living hell!",1) + target.custom_pain("The pain in your [affected.name] is living hell!") else return -1 @@ -398,7 +395,7 @@ var/found_damaged_organ = FALSE for(var/obj/item/organ/internal/I in affected.internal_organs) - if(I && I.damage && I.robotic >= 2) + if(I && I.damage && I.is_robotic()) user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \ "You start mending the damage to [target]'s [I.name]'s mechanisms.") found_damaged_organ = TRUE @@ -407,7 +404,7 @@ to_chat(user, "There are no damaged components in [affected].") return -1 - target.custom_pain("The pain in your [affected.name] is living hell!",1) + target.custom_pain("The pain in your [affected.name] is living hell!") else if(implement_type in implements_finish) current_type = "finish" @@ -424,7 +421,7 @@ return for(var/obj/item/organ/internal/I in affected.internal_organs) if(I && I.damage) - if(I.robotic >= 2) + if(I.is_robotic()) user.visible_message(" [user] repairs [target]'s [I.name] with [tool].", \ " You repair [target]'s [I.name] with [tool]." ) I.damage = 0 @@ -522,7 +519,7 @@ user.visible_message("[user] starts to decouple [target]'s [affected.name] with \the [tool].", \ "You start to decouple [target]'s [affected.name] with \the [tool]." ) - target.custom_pain("Your [affected.amputation_point] is being ripped apart!",1) + target.custom_pain("Your [affected.amputation_point] is being ripped apart!") ..() /datum/surgery_step/robotics/external/amputate/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -544,3 +541,60 @@ user.visible_message(" [user]'s hand slips!", \ " Your hand slips!") return 0 + +/datum/surgery/cybernetic_customization + name = "Cybernetic Appearance Customization" + steps = list(/datum/surgery_step/robotics/external/unscrew_hatch, /datum/surgery_step/robotics/external/customize_appearance) + possible_locs = list("head", "chest", "l_arm", "r_arm", "r_leg", "l_leg") + requires_organic_bodypart = FALSE + +/datum/surgery/cybernetic_customization/can_start(mob/user, mob/living/carbon/human/target) + if(ishuman(target)) + var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) + if(!affected) + return FALSE + if(!(affected.status & ORGAN_ROBOT)) + return FALSE + return TRUE + +/datum/surgery_step/robotics/external/customize_appearance + name = "reprogram limb" + allowed_tools = list(/obj/item/multitool = 100) + time = 48 + +/datum/surgery_step/robotics/external/customize_appearance/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) + if(..()) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(!affected) + return FALSE + return TRUE + +/datum/surgery_step/robotics/external/customize_appearance/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] begins to reprogram the appearance of [target]'s [affected.name] with [tool]." , \ + "You begin to reprogram the appearance of [target]'s [affected.name] with [tool].") + ..() + +/datum/surgery_step/robotics/external/customize_appearance/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) + var/chosen_appearance = input(user, "Select the company appearance for this limb.", "Limb Company Selection") as null|anything in selectable_robolimbs + if(!chosen_appearance) + return FALSE + var/obj/item/organ/external/affected = target.get_organ(target_zone) + affected.robotize(chosen_appearance, convert_all = FALSE) + if(istype(affected, /obj/item/organ/external/head)) + var/obj/item/organ/external/head/head = affected + head.h_style = "Bald" // nearly all the appearance changes for heads are non-monitors; we want to get rid of a floating screen + target.update_hair() + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + user.visible_message(" [user] reprograms the appearance of [target]'s [affected.name] with [tool].", \ + " You reprogram the appearance of [target]'s [affected.name] with [tool].") + affected.open = 0 + return TRUE + +/datum/surgery_step/robotics/external/customize_appearance/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message(" [user]'s [tool.name] slips, failing to reprogram [target]'s [affected.name].", + " Your [tool.name] slips, failing to reprogram [target]'s [affected.name].") + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/slime.dm b/code/modules/surgery/slime.dm index ced21be08b4..77614d41430 100644 --- a/code/modules/surgery/slime.dm +++ b/code/modules/surgery/slime.dm @@ -98,6 +98,6 @@ return 1 /datum/surgery_step/slime/saw_core/fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message(" [user]'s hand slips, causing \him to miss the core!", \ + user.visible_message(" [user]'s hand slips, causing [user.p_them()] to miss the core!", \ " Your hand slips, causing you to miss the core!") - return 0 \ No newline at end of file + return 0 diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index 56da8f031e3..72bf70c7e81 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -67,10 +67,6 @@ //How much blood this step can get on surgeon. 1 - hands, 2 - full body. var/blood_level = 0 - var/list/allowed_mob = list() - var/list/disallowed_mob = list() - - /datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) var/success = 0 if(accept_hand) @@ -146,19 +142,8 @@ // Checks if this step applies to the user mob at all /datum/surgery_step/proc/is_valid_target(mob/living/carbon/human/target) if(!hasorgans(target)) - return 0 - - if(allowed_mob)//can i just remove this and/or change it? - for(var/species in allowed_mob) - if(target.get_species() == species) - return 1 - - if(disallowed_mob) - for(var/species in disallowed_mob) - if(target.get_species() == species) - return 0 - - return 1 + return FALSE + return TRUE // checks whether this step can be applied with the given user and target /datum/surgery_step/proc/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) @@ -187,7 +172,7 @@ return null /proc/spread_germs_to_organ(obj/item/organ/E, mob/living/carbon/human/user, obj/item/tool) - if(!istype(user) || !istype(E) || !(E.status & ORGAN_ROBOT) || E.sterile) + if(!istype(user) || !istype(E) || E.is_robotic() || E.sterile) return var/germ_level = user.germ_level @@ -195,7 +180,7 @@ //germ spread from surgeon touching the patient if(user.gloves) germ_level = user.gloves.germ_level - E.germ_level += germ_level + E.germ_level = max(germ_level, E.germ_level) spread_germs_by_incision(E, tool) //germ spread from environement to patient /proc/spread_germs_by_incision(obj/item/organ/external/E,obj/item/tool) @@ -206,7 +191,7 @@ for(var/mob/living/carbon/human/H in view(2, E.loc))//germs from people if(AStar(E.loc, H.loc, /turf/proc/Distance, 2, simulated_only = 0)) - if((!(BREATHLESS in H.mutations) || !(NO_BREATHE in H.species.species_traits)) && !H.wear_mask) //wearing a mask helps preventing people from breathing cooties into open incisions + if((!(BREATHLESS in H.mutations) || !(NO_BREATHE in H.dna.species.species_traits)) && !H.wear_mask) //wearing a mask helps preventing people from breathing cooties into open incisions germs += H.germ_level * 0.25 for(var/obj/effect/decal/cleanable/M in view(2, E.loc))//germs from messes @@ -220,7 +205,7 @@ if(E.internal_organs.len) germs = germs / (E.internal_organs.len + 1) // +1 for the external limb this eventually applies to; let's not multiply germs now. for(var/obj/item/organ/internal/O in E.internal_organs) - if(!(O.status & ORGAN_ROBOT)) + if(!O.is_robotic()) O.germ_level += germs E.germ_level += germs diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 85880048f9b..53691dd0264 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -8,6 +8,10 @@ w_class = WEIGHT_CLASS_SMALL origin_tech = "materials=1;biotech=1" +/obj/item/retractor/augment + desc = "Micro-mechanical manipulator for retracting stuff." + w_class = WEIGHT_CLASS_TINY + toolspeed = 0.5 /obj/item/hemostat name = "hemostat" @@ -20,6 +24,9 @@ origin_tech = "materials=1;biotech=1" attack_verb = list("attacked", "pinched") +/obj/item/hemostat/augment + desc = "Tiny servos power a pair of pincers to stop bleeding." + toolspeed = 0.5 /obj/item/cautery name = "cautery" @@ -32,6 +39,9 @@ origin_tech = "materials=1;biotech=1" attack_verb = list("burnt") +/obj/item/cautery/augment + desc = "A heated element that cauterizes wounds." + toolspeed = 0.5 /obj/item/surgicaldrill name = "surgical drill" @@ -48,10 +58,16 @@ attack_verb = list("drilled") suicide_act(mob/user) - to_chat(viewers(user), pick("[user] is pressing [src] to \his temple and activating it! It looks like \he's trying to commit suicide.", - "[user] is pressing [src] to \his chest and activating it! It looks like \he's trying to commit suicide.")) + to_chat(viewers(user), pick("[user] is pressing [src] to [user.p_their()] temple and activating it! It looks like [user.p_theyre()] trying to commit suicide.", + "[user] is pressing [src] to [user.p_their()] chest and activating it! It looks like [user.p_theyre()] trying to commit suicide.")) return (BRUTELOSS) +/obj/item/surgicaldrill/augment + desc = "Effectively a small power drill contained within your arm, edges dulled to prevent tissue damage. May or may not pierce the heavens." + hitsound = 'sound/weapons/circsawhit.ogg' + force = 10 + w_class = WEIGHT_CLASS_SMALL + toolspeed = 0.5 /obj/item/scalpel name = "scalpel" @@ -72,12 +88,16 @@ hitsound = 'sound/weapons/bladeslice.ogg' suicide_act(mob/user) - to_chat(viewers(user), pick("[user] is slitting \his wrists with [src]! It looks like \he's trying to commit suicide.", - "[user] is slitting \his throat with [src]! It looks like \he's trying to commit suicide.", - "[user] is slitting \his stomach open with [src]! It looks like \he's trying to commit seppuku.")) + to_chat(viewers(user), pick("[user] is slitting [user.p_their()] wrists with [src]! It looks like [user.p_theyre()] trying to commit suicide.", + "[user] is slitting [user.p_their()] throat with [src]! It looks like [user.p_theyre()] trying to commit suicide.", + "[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku.")) return (BRUTELOSS) +/obj/item/scalpel/augment + desc = "Ultra-sharp blade attached directly to your bone for extra-accuracy." + toolspeed = 0.5 + /* * Researchable Scalpels */ @@ -129,6 +149,12 @@ origin_tech = "biotech=1;combat=1" attack_verb = list("attacked", "slashed", "sawed", "cut") +/obj/item/circular_saw/augment + desc = "A small but very fast spinning saw. Edges dulled to prevent accidental cutting inside of the surgeon." + force = 10 + w_class = WEIGHT_CLASS_SMALL + toolspeed = 0.5 + //misc, formerly from code/defines/weapons.dm /obj/item/bonegel name = "bone gel" @@ -139,6 +165,9 @@ throwforce = 1.0 origin_tech = "materials=1;biotech=1" +/obj/item/bonegel/augment + toolspeed = 0.5 + /obj/item/FixOVein name = "FixOVein" icon = 'icons/obj/surgery.dmi' @@ -148,6 +177,9 @@ origin_tech = "materials=1;biotech=1" w_class = WEIGHT_CLASS_SMALL +/obj/item/FixOVein/augment + toolspeed = 0.5 + /obj/item/bonesetter name = "bone setter" icon = 'icons/obj/surgery.dmi' @@ -160,6 +192,9 @@ attack_verb = list("attacked", "hit", "bludgeoned") origin_tech = "materials=1;biotech=1" +/obj/item/bonesetter/augment + toolspeed = 0.5 + /obj/item/surgical_drapes name = "surgical drapes" desc = "Nanotrasen brand surgical drapes provide optimal safety and infection control." diff --git a/code/modules/vr/vr_controller.dm b/code/modules/vr/vr_controller.dm index 45bf2a6cc74..564291b2999 100644 --- a/code/modules/vr/vr_controller.dm +++ b/code/modules/vr/vr_controller.dm @@ -31,12 +31,12 @@ proc/build_virtual_avatar(mob/living/carbon/human/H, location, datum/map_templat var/mob/living/carbon/human/virtual_reality/vr_avatar location = get_turf(location) vr_avatar = new /mob/living/carbon/human/virtual_reality(location) - vr_avatar.set_species(H.species.name) if(istype(H, /mob/living/carbon/human/virtual_reality)) var/mob/living/carbon/human/virtual_reality/V = H vr_avatar.real_me = V.real_me else vr_avatar.real_me = H + vr_avatar.set_species(H.dna.species.type) vr_avatar.dna = H.dna.Clone() vr_avatar.name = H.name vr_avatar.real_name = H.real_name diff --git a/config/example/config.txt b/config/example/config.txt index 46d03c48aaa..c8bdc8cffc9 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -37,6 +37,9 @@ LOG_SAY ## log admin actions LOG_ADMIN +## log admin chat +LOG_ADMINCHAT + ## log client access (logon/logoff) LOG_ACCESS @@ -301,7 +304,13 @@ PLAYER_REROUTE_CAP 0 #DISABLE_AWAY_MISSIONS ## Disable the loading of space ruins -DISABLE_SPACE_RUINS +#DISABLE_SPACE_RUINS + +## Minimum number of space ruins levels to generate +EXTRA_SPACE_RUINS_LEVELS_MIN 2 + +## Maximum number of space ruins levels to generate +EXTRA_SPACE_RUINS_LEVELS_MAX 4 ## Uncomment to disable the OOC/LOOC channel by default. #DISABLE_OOC diff --git a/config/example/dbconfig.txt b/config/example/dbconfig.txt index a962b4b685c..563768b69bc 100644 --- a/config/example/dbconfig.txt +++ b/config/example/dbconfig.txt @@ -9,7 +9,7 @@ ## This value must be set to the version of the paradise schema in use. ## If this value does not match, the SQL database will not be loaded and an error will be generated. ## Roundstart will be delayed. -DB_VERSION 2 +DB_VERSION 4 ## Server the MySQL database can be found at. # Examples: localhost, 200.135.5.43, www.mysqldb.com, etc. @@ -26,11 +26,11 @@ FEEDBACK_DATABASE feedback ## Note, this does not change the table names in the database, you will have to do that yourself. ## IE: ## FEEDBACK_TABLEPREFIX erro_ -## FEEDBACK_TABLEPREFIX +## FEEDBACK_TABLEPREFIX ## FEEDBACK_TABLEPREFIX SS13_ ## ## Leave as is if you are using the standard schema file. -FEEDBACK_TABLEPREFIX +FEEDBACK_TABLEPREFIX ## Username/Login used to access the database. FEEDBACK_LOGIN username diff --git a/config/example/jobs_highpop.txt b/config/example/jobs_highpop.txt new file mode 100644 index 00000000000..962803ab886 --- /dev/null +++ b/config/example/jobs_highpop.txt @@ -0,0 +1,37 @@ +Captain=1 +Head of Personnel=1 +Head of Security=1 +Chief Engineer=1 +Research Director=1 +Chief Medical Officer=1 + +Station Engineer=5 +Roboticist=1 + +Medical Doctor=5 +Geneticist=2 +Virologist=1 + +Scientist=3 +Chemist=2 + +Bartender=1 +Botanist=2 +Chef=1 +Janitor=1 +Quartermaster=1 +Shaft Miner=3 + +Warden=1 +Detective=1 +Security Officer=7 + +Assistant=-1 +Atmospheric Technician=4 +Cargo Technician=3 +Chaplain=1 +Lawyer=2 +Librarian=1 + +AI=1 +Cyborg=1 \ No newline at end of file diff --git a/config/example/tos.txt b/config/example/tos.txt new file mode 100644 index 00000000000..eb43c50a083 --- /dev/null +++ b/config/example/tos.txt @@ -0,0 +1,3 @@ +

    Welcome to Space Station 13!

    + +Terms of service goes here. \ No newline at end of file diff --git a/config/names/diona.txt b/config/names/diona.txt deleted file mode 100644 index 3eb4b5f4498..00000000000 --- a/config/names/diona.txt +++ /dev/null @@ -1,13 +0,0 @@ -Blade of Grass Bent Before Wind -Glimmer Of The Stars -The Ripple Of the Waves -Colors Of Dusk -The Still Of Night -Silence Of The Wind -Gentle Breeze of the Summer Wind -Glistening Water under the Blazing Sun -Child of the Scorching Sun -Blessed Plant-ling of Eternal Fields -Grass-walker of the Soothing Plains -Element of the Undying Fiona -Spawn of Mother Nature's Busum \ No newline at end of file diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css index f3fe28315f6..234c5ac2274 100644 --- a/goon/browserassets/css/browserOutput.css +++ b/goon/browserassets/css/browserOutput.css @@ -342,7 +342,8 @@ h1.alert, h2.alert {color: #000000;} .clown {color: #ff0000;} .shadowling {color: #3b2769;} .vulpkanin {color: #B97A57;} -.abductor {color: #800080;} +.abductor {color: #800080; font-style: italic;} +.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;} .rough {font-family: 'Trebuchet MS', cursive, sans-serif;} .say_quote {font-family: Georgia, Verdana, sans-serif;} .cult {color: #800080; font-weight: bold; font-style: italic;} diff --git a/html/changelog.html b/html/changelog.html index 3857178b750..136469832f5 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,537 @@ -->
    +

    07 August 2018

    +

    Kyep updated:

    +
      +
    • Simple_animal mobs now get a HUD button that lets them switch between HELP and HARM intents.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Unathi can now tailwhip when they are supposed to be able to.
    • +
    • Tail whipping gets logged.
    • +
    + +

    06 August 2018

    +

    AffectedArc07 updated:

    +
      +
    • Barber no longer spawns with an extra pair of shoes in his bag
    • +
    +

    Tails2091 updated:

    +
      +
    • Fixed Therapy Dolls not working.
    • +
    • Made Prize Machine & Merch Sore readable.
    • +
    • Fixed capitalizations and typos in both lists.
    • +
    + +

    05 August 2018

    +

    Crazylemon64 updated:

    +
      +
    • Space ruins can no longer trap you upon border transition
    • +
    • There are now several levels of space ruins
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in medical hyposprays
    • +
    + +

    03 August 2018

    +

    Fox McCloud updated:

    +
      +
    • IPC Change monitor is now an action button
    • +
    • Slime Color change is now an action button
    • +
    • Fixes staff of change leaving behind unknowns
    • +
    • Fixes Shadowlings not having shock resistant and thermal vision
    • +
    • Fixes staff of change gibbing people
    • +
    +

    Shazbot updated:

    +
      +
    • Adds in the ability to unsaw sawn off riot shotguns. Change: Changes the riot shotgun icon.
    • +
    + +

    02 August 2018

    +

    variableundefined updated:

    +
      +
    • Nightmares now works. Sleep well.
    • +
    • Megaphone actually logs in say log now.
    • +
    + +

    01 August 2018

    +

    Citinited updated:

    +
      +
    • Heaters and freezers now have min and max buttons
    • +
    +

    CornMyCob updated:

    +
      +
    • The description for miniature energy guns is now accurate
    • +
    • The third person text of someone reinforcing an airlock is now accurate
    • +
    +

    Tails2091 updated:

    +
      +
    • Karma refund now uses switch statement.
    • +
    +

    datlo updated:

    +
      +
    • Updated syndicate hardsuit description.
    • +
    + +

    31 July 2018

    +

    Tails2091 updated:

    +
      +
    • Claw Game Prize Ball now drops more than one ticket like it should.
    • +
    +

    variableundefined updated:

    +
      +
    • fix a runtime error with bluespace projector
    • +
    + +

    30 July 2018

    +

    Tails2091 updated:

    +
      +
    • Changed wannabe for loop to a real for loop.
    • +
    + +

    28 July 2018

    +

    KasparoVy updated:

    +
      +
    • You can now safely augment the heads of pointy-snooted Unathi, although your mileage may vary.
    • +
    + +

    27 July 2018

    +

    AffectedArc07 updated:

    +
      +
    • You can no longer use embeds in NTSL
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Space hotel is back in business
    • +
    • Non-hotel SNPCs work again
    • +
    +

    Fox McCloud updated:

    +
      +
    • Extract posibrains should have the correct names now
    • +
    • Abductors can now purchase a mind device to speak into crewmembers minds or give directives to abductees
    • +
    • Abductors now have their own versions of the FixOVein, Bonesetter, and Bonegel. Credit to Triiodine for the sprites
    • +
    • Adds a new electric shock and chemical gland for abductors
    • +
    • viral gland generates random viruses and egg laying gland eggs now have random reagents in them
    • +
    +

    variableundefined updated:

    +
      +
    • Cyborg Analyzer no longer rounds off the damage number it displays.
    • +
    + +

    25 July 2018

    +

    variableundefined updated:

    +
      +
    • Fixes runtime error from medical kit change
    • +
    + +

    24 July 2018

    +

    Kyep updated:

    +
      +
    • Number of roundstart atmos suits in atmos increased from 2 to 4.
    • +
    + +

    22 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes monkeys not having their own HUD
    • +
    • Fixes monkey to human transformations missing their HUD
    • +
    • Fixes changing species unequipping items
    • +
    • Fixes organs not being rejuvinated properly by mitocholide
    • +
    • Fixes shadowlings not being forced to hatch
    • +
    • Having a robotic head will allow you to use buzz, ping, beep, and the likes
    • +
    • Claw sharpening now works
    • +
    • Abductors have their own headset instead of a syndicate one
    • +
    • Can put monkeys in the gibber
    • +
    • gibbing some species will now generate different types of hides (monkeys give monkey hides, unathi give lizard hides, the likes)
    • +
    • fixes Vox name generation based on the wrong syllables
    • +
    • consolidates diona name lists; you'll no longer be asked to rename your Diona when you start the shift
    • +
    • botany grown diona can no longer rename themselves (as is consistent with ghost roles)
    • +
    • Fixes DNA scrambler so it gives a proper randomized species name
    • +
    • Fixed an edge case were Vox would have a permanent nitrogen alert
    • +
    • Fixes operatives being bald most of the time
    • +
    • Adds beesplosion chemical reaction
    • +
    +

    and taukausanake updated:

    +
      +
    • Swarmers can no longer destroy active clone pods.
    • +
    + +

    17 July 2018

    +

    Citinited updated:

    +
      +
    • volume pumps can be dispensed by the RPD again
    • +
    +

    datlo updated:

    +
      +
    • Provided abductors with an infection free surgery table.
    • +
    + +

    16 July 2018

    +

    Citinited updated:

    +
      +
    • RPD behaviour has been slightly tweaked - for example you can now rotate / flip / delete individual pipes by clicking on them without affecting other pipes on that tile.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes hand labelers not being able to label storage objects
    • +
    • Cameras can now be destroyed with weapons that have a force of 12 or greater
    • +
    • Cameras have 2 wires as opposed to 6; camera focus and power wires still remain
    • +
    • You can use hand labelers on reagent containers now
    • +
    + +

    14 July 2018

    +

    Anasari updated:

    +
      +
    • Assuming there is heal left, bandages and ointments used on limbs now heal both the limb and the hand / foot. Bandages and ointments used on the torso now heal head, arms, and lower body. The one on lower body heals the legs too.
    • +
    +

    Aurorablade updated:

    +
      +
    • Adds Spess Koi and related event.
    • +
    +

    Citinited updated:

    +
      +
    • The tachyon-doppler array now has a logging interface, and can print off stored explosive logs. Brag to your friends about your bomb-making skills!
    • +
    +

    Fox McCloud updated:

    +
      +
    • Robotic brains have their own unique sprite and full flavortext's now
    • +
    • Fixed a bug where IRC's would have IPC names
    • +
    + +

    11 July 2018

    +

    Alffd updated:

    +
      +
    • Updates SM engine to modern standards
    • +
    • Ports SM monitoring system from Bay and TG
    • +
    • Adds station wide radiation alarm when crystal/shard goes critical
    • +
    • Tesla zapping
    • +
    +

    Citinited updated:

    +
      +
    • Fortune cookies now drop random fortunes if cooked with a blank piece of paper.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds constructable Integrated Robotic Chassis
    • +
    • Adds surgery to customize existing robotic limb appearances
    • +
    • Positronic brains renamed to robotic brains
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added a Harmonica to Perma Brig
    • +
    +

    datlo updated:

    +
      +
    • Replaced instances of "Human" in ion laws by "Crew".
    • +
    • Fixed the ability of Service Borgs to spawn items on floors. Dosh!
    • +
    + +

    10 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Can no longer take assisted organs at round-start (mechanical organs are still a go, but renamed to cybernetic organs)
    • +
    • Can now start the round with cybernetic lungs, liver, and kidneys
    • +
    • Can produce cybernetic eyes at R&D and mechfabs
    • +
    • Cybernetic internal organs no longer take reduced damage (this does not apply to augments)
    • +
    • Cybernetic internal organs can be rendered inoperable (this does not apply to augments)
    • +
    • Fixes mitocholide/oculine healing damage on cybernetic organs
    • +
    • Fixes being able to restart a dead heart in your hands or with a defib
    • +
    + +

    09 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Enabled augmentation of the head
    • +
    • Adds cybernetic heart, lungs, liver, and kidneys to R&D and Robotics; also adds cybernetic upgraded lungs
    • +
    • Heads are no longer vital organs, but brains still are
    • +
    + +

    07 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Stechkin pistols in maintenance no longer spawn with a broken magazine
    • +
    +

    Kyep updated:

    +
      +
    • Removed PDA chatrooms. NTNet Relay Chatrooms, part of modular computers, still exist.
    • +
    + +

    06 July 2018

    +

    Fox McCloud updated:

    +
      +
    • removes explosive lances
    • +
    +

    datlo updated:

    +
      +
    • Replaced duplicate labor shuttle console on the bridge by a mining shuttle console.
    • +
    + +

    04 July 2018

    +

    Citinited updated:

    +
      +
    • Spelling error in agent IDs
    • +
    + +

    03 July 2018

    +

    MINIMAN10000 updated:

    +
      +
    • Restrained spacepod passanger can now exit pending a 2 minute wait time without moving.
    • +
    + +

    02 July 2018

    +

    Citinited updated:

    +
      +
    • Canisters obey melee cooldown now
    • +
    +

    Crazylemon64 updated:

    +
      +
    • All MMI variants can now install an "MMI radio upgrade" in order to acquire radio capability when outside of any other chassis. It can be installed either directly on the MMI, or through an opened cyborg chassis. This radio can later be removed if desired by using a screwdriver on the MMI.
    • +
    • MMIs can now pull up the direct interface of the radio instead of a single-toggle verb
    • +
    • MMI radio control is now done via action button instead of via verb
    • +
    • The radio MMI no longer exists as a distinct item
    • +
    + +

    01 July 2018

    +

    Anasari updated:

    +
      +
    • Shuttle can be called at 30:00 instead of 25:00 during War Ops.
    • +
    +

    Citinited updated:

    +
      +
    • The chef can now process spaghetti into macaroni, and can make several derivative foodstuffs.
    • +
    +

    datlo updated:

    +
      +
    • Syndicate clowns can now purchase Clown Magboots. Keep honking through slips and atmos!
    • +
    +

    monster860 updated:

    +
      +
    • Adds the mining podbay (again)
    • +
    + +

    30 June 2018

    +

    Citinited updated:

    +
      +
    • Adds the conveyor belt placer and bluespace conveyor belt placer, allowing you to much more easily create conveyor belts. The former can be gotten at any autolathe, the latter must be researched first.
    • +
    • Use a conveyor belt lever on aforementioned item to link all belts inside the placer with that lever.
    • +
    + +

    27 June 2018

    +

    MINIMAN10000 updated:

    +
      +
    • Containment emitters
    • +
    • deferred processing of SMES
    • +
    + +

    26 June 2018

    +

    Alffd updated:

    +
      +
    • Additional logic to atmos throwing.
    • +
    + +

    23 June 2018

    +

    matt81093 updated:

    +
      +
    • death squid hitbox position
    • +
    + +

    19 June 2018

    +

    Anasari updated:

    +
      +
    • Gloves of the north star is now categorized under highly visible and dangerous weapon instead of pointless badassery. (Because it's actually good)
    • +
    +

    Fox McCloud updated:

    +
      +
    • Can cast spells on CentComm z-level during ragin' mages
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Cardboard drop counts
    • +
    + +

    17 June 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes wizards not spawning with their clothes and backpack
    • +
    • It no longer snows on away missions
    • +
    +

    variableundefined updated:

    +
      +
    • Nuclear challenge time limit now depends on round start time.
    • +
    + +

    13 June 2018

    +

    Aurorablade updated:

    +
      +
    • Fluff for Panzerskull
    • +
    +

    Fox McCloud updated:

    +
      +
    • Medibots now actually talk, like beepsky
    • +
    • Adds Plastic surgery; fix someone's face or give them a new identity!
    • +
    • Having more than 50 cloneloss will render you "Unknown"
    • +
    • head disfigurement requires you to have more than 50 combined brute and burn damage, rather than tracking it separately
    • +
    • Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric acid not causing disfigurement at proper thresholds
    • +
    • Fixes syndicate medibot not being constructable from tactical medkits
    • +
    • Syndicate medibot and the mysterious medibot are better at treating brute and burn damage
    • +
    • Radiation event reworked; graphics updated--effects may be a bit more deadly
    • +
    • Buffed DIY chainsaws damage slightly
    • +
    • You now flip about when you spin with a double e-sword
    • +
    • Adds surgical augment to R&D
    • +
    • Tools on surgical augment are slightly faster at surgery
    • +
    • Wishgranter grants "Avatar of the Wishgranter" instead of making you a superhero
    • +
    • Toxin damage is stealthier and will no longer cause stinging spam message
    • +
    +

    Kyep updated:

    +
      +
    • Additional job slots are now available at 80+ server population.
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Airlock electronics lock
    • +
    • Airlock electronics close button
    • +
    +

    Piccione updated:

    +
      +
    • Added Magboots to the Paramedic's EVA gear closet
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Shadowling dethrall has been shortened to scalpel, hemostat, retractor, shine light, cautery
    • +
    + +

    11 June 2018

    +

    FalseIncarnate updated:

    +
      +
    • Food on utensils now properly inherits the name of the source dish.
    • +
    • Joined Souls rune can now properly can summon restrained targets with 3+ invokers.
    • +
    + +

    09 June 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes holobarrier icons being missing
    • +
    + +

    08 June 2018

    +

    Alffd updated:

    +
      +
    • Adds an automated emergency var on air alarms for mappers
    • +
    +

    Anasari updated:

    +
      +
    • Fixes admin log for spray displaying (0,0,0) all the time.
    • +
    +

    Desolate updated:

    +
      +
    • ED-209 code corrected to work properly. Floorbot code corrected to work properly.
    • +
    +

    and Dumbdumb updated:

    +
      +
    • Unathi and Vox Sec Hardsuit update
    • +
    + +

    05 June 2018

    +

    Kyep updated:

    +
      +
    • The Terror Spider away mission now has spiders colonizing the west side of the map. Only the gateway room is safe.
    • +
    + +

    04 June 2018

    +

    Fox McCloud updated:

    +
      +
    • Hulk mutation no longer works at range (ie: punching/breaking windows/walls at range)
    • +
    • You must be on harm intent to damage things if you have hulk
    • +
    • Having hulk allows you to punch and damage just about anything
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can smelt titanium and glass together to form titanium glass for building shuttle windows
    • +
    • You can smelt titanium, plasma and glass together to form plastitanium glass for building plastitanium windows
    • +
    • Fulltile windows now smooth, windows crack as they get damaged and can be repaired with help intent welder
    • +
    • Windows have deconstruction hints and show whether they can be rotated or not
    • +
    • Plasma glass no longer gets auto-colored
    • +
    • RCDs can deconstruct airlocks again, they have no force now though
    • +
    • Wielded fireaxe does a lot of damage to windows and grilles instead of just deleting them
    • +
    • Glass stacks now use stack recipes instead of a custom menu
    • +
    + +

    31 May 2018

    +

    FalseIncarnate updated:

    +
      +
    • The singulo no longer feeds on attention.
    • +
    + +

    26 May 2018

    +

    Birdtalon updated:

    +
      +
    • Holoparasite guide updated to include newer models. Small tooltip added for charger models.
    • +
    • laser tag gun projectiles now play appropriate sound when striking.
    • +
    +

    Citinited updated:

    +
      +
    • Hopefully fixes all issues with disposals sending you to nullspace.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes not being able to propel yourself through space by farting if you possessed both superfart and toxic farts
    • +
    +

    Kyep and Bxil updated:

    +
      +
    • Prevents everyone and their mother from seeing through closed poddoors.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Most things will now use the correct pronouns.
    • +
    • Newscasters properly check for feed channel creation and wanted issue creation
    • +
    • ERT should deploy properly without admins now.
    • +
    + +

    19 May 2018

    +

    Aurorablade updated:

    +
      +
    • Vet Coat Fluff item.
    • +
    • Spacepod mod kit now uses kit blueprints and not KITE blueprints (spelling error).
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds gloves of the North Star; get them on the uplink for 8 TC
    • +
    • Unarmed attacks now have their own icons, as does disarming.
    • +
    • Various mobs have their own custom icon attacks
    • +
    • Monkies now bite!
    • +
    + +

    18 May 2018

    +

    Fox McCloud updated:

    +
      +
    • Removes engineering and police tape
    • +
    • Adds security, atmospheric, and engineering holoprojectors
    • +
    +

    tigercat2000 updated:

    +
      +
    • You can now lock a facing direction with shift+middle mouse button, or lock your direction towards an object by clicking on it with shift + ctrl + middle mouse button.
    • +
    + +

    15 May 2018

    +

    Tayyyyyyy updated:

    +
      +
    • Pun pun is back!
    • +
    + +

    11 May 2018

    +

    Kyep updated:

    +
      +
    • It is no longer possible to create an infinite number of monkeys from the same monkey cube.
    • +
    + +

    09 May 2018

    +

    RyanSmake updated:

    +
      +
    • You can now jump on fax machines without the UI lying to you.
    • +
    +

    07 May 2018

    qwertyquerty updated:

      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 4af2bbd98ef..ca4bf39f22e 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -6392,3 +6392,367 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. 2018-05-07: qwertyquerty: - rscadd: The window title is custom now! +2018-05-09: + RyanSmake: + - bugfix: You can now jump on fax machines without the UI lying to you. +2018-05-11: + Kyep: + - bugfix: It is no longer possible to create an infinite number of monkeys from + the same monkey cube. +2018-05-15: + Tayyyyyyy: + - bugfix: Pun pun is back! +2018-05-18: + Fox McCloud: + - rscdel: Removes engineering and police tape + - rscadd: Adds security, atmospheric, and engineering holoprojectors + tigercat2000: + - rscadd: You can now lock a facing direction with shift+middle mouse button, or + lock your direction towards an object by clicking on it with shift + ctrl + + middle mouse button. +2018-05-19: + Aurorablade: + - rscadd: Vet Coat Fluff item. + - tweak: Spacepod mod kit now uses kit blueprints and not KITE blueprints (spelling + error). + Fox McCloud: + - rscadd: Adds gloves of the North Star; get them on the uplink for 8 TC + - rscadd: Unarmed attacks now have their own icons, as does disarming. + - rscadd: Various mobs have their own custom icon attacks + - tweak: Monkies now bite! +2018-05-26: + Birdtalon: + - tweak: Holoparasite guide updated to include newer models. Small tooltip added + for charger models. + - bugfix: laser tag gun projectiles now play appropriate sound when striking. + Citinited: + - bugfix: Hopefully fixes all issues with disposals sending you to nullspace. + Fox McCloud: + - bugfix: Fixes not being able to propel yourself through space by farting if you + possessed both superfart and toxic farts + Kyep and Bxil: + - bugfix: Prevents everyone and their mother from seeing through closed poddoors. + Tayyyyyyy: + - rscadd: Most things will now use the correct pronouns. + - bugfix: Newscasters properly check for feed channel creation and wanted issue + creation + - bugfix: ERT should deploy properly without admins now. +2018-05-31: + FalseIncarnate: + - bugfix: The singulo no longer feeds on attention. +2018-06-04: + Fox McCloud: + - bugfix: 'Hulk mutation no longer works at range (ie: punching/breaking windows/walls + at range)' + - tweak: You must be on harm intent to damage things if you have hulk + - rscadd: Having hulk allows you to punch and damage just about anything + uraniummeltdown: + - rscadd: You can smelt titanium and glass together to form titanium glass for building + shuttle windows + - rscadd: You can smelt titanium, plasma and glass together to form plastitanium + glass for building plastitanium windows + - rscadd: Fulltile windows now smooth, windows crack as they get damaged and can + be repaired with help intent welder + - rscadd: Windows have deconstruction hints and show whether they can be rotated + or not + - bugfix: Plasma glass no longer gets auto-colored + - bugfix: RCDs can deconstruct airlocks again, they have no force now though + - tweak: Wielded fireaxe does a lot of damage to windows and grilles instead of + just deleting them + - tweak: Glass stacks now use stack recipes instead of a custom menu +2018-06-05: + Kyep: + - bugfix: The Terror Spider away mission now has spiders colonizing the west side + of the map. Only the gateway room is safe. +2018-06-08: + Alffd: + - rscadd: Adds an automated emergency var on air alarms for mappers + Anasari: + - bugfix: Fixes admin log for spray displaying (0,0,0) all the time. + Desolate: + - bugfix: ED-209 code corrected to work properly. Floorbot code corrected to work + properly. + and Dumbdumb: + - rscadd: Unathi and Vox Sec Hardsuit update +2018-06-09: + Fox McCloud: + - bugfix: Fixes holobarrier icons being missing +2018-06-11: + FalseIncarnate: + - bugfix: Food on utensils now properly inherits the name of the source dish. + - bugfix: Joined Souls rune can now properly can summon restrained targets with + 3+ invokers. +2018-06-13: + Aurorablade: + - rscadd: Fluff for Panzerskull + Fox McCloud: + - rscadd: Medibots now actually talk, like beepsky + - rscadd: Adds Plastic surgery; fix someone's face or give them a new identity! + - tweak: Having more than 50 cloneloss will render you "Unknown" + - tweak: head disfigurement requires you to have more than 50 combined brute and + burn damage, rather than tracking it separately + - bugfix: Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric + acid not causing disfigurement at proper thresholds + - bugfix: Fixes syndicate medibot not being constructable from tactical medkits + - tweak: Syndicate medibot and the mysterious medibot are better at treating brute + and burn damage + - tweak: Radiation event reworked; graphics updated--effects may be a bit more deadly + - tweak: Buffed DIY chainsaws damage slightly + - tweak: You now flip about when you spin with a double e-sword + - rscadd: Adds surgical augment to R&D + - tweak: Tools on surgical augment are slightly faster at surgery + - rscadd: Wishgranter grants "Avatar of the Wishgranter" instead of making you a + superhero + - tweak: Toxin damage is stealthier and will no longer cause stinging spam message + Kyep: + - rscadd: Additional job slots are now available at 80+ server population. + MINIMAN10000: + - rscdel: Airlock electronics lock + - bugfix: Airlock electronics close button + Piccione: + - rscadd: Added Magboots to the Paramedic's EVA gear closet + Tayyyyyyy: + - tweak: Shadowling dethrall has been shortened to scalpel, hemostat, retractor, + shine light, cautery +2018-06-17: + Fox McCloud: + - bugfix: Fixes wizards not spawning with their clothes and backpack + - bugfix: It no longer snows on away missions + variableundefined: + - tweak: Nuclear challenge time limit now depends on round start time. +2018-06-19: + Anasari: + - tweak: Gloves of the north star is now categorized under highly visible and dangerous + weapon instead of pointless badassery. (Because it's actually good) + Fox McCloud: + - tweak: Can cast spells on CentComm z-level during ragin' mages + MINIMAN10000: + - bugfix: Cardboard drop counts +2018-06-23: + matt81093: + - bugfix: death squid hitbox position +2018-06-26: + Alffd: + - rscadd: Additional logic to atmos throwing. +2018-06-27: + MINIMAN10000: + - bugfix: Containment emitters + - rscadd: deferred processing of SMES +2018-06-30: + Citinited: + - rscadd: Adds the conveyor belt placer and bluespace conveyor belt placer, allowing + you to much more easily create conveyor belts. The former can be gotten at any + autolathe, the latter must be researched first. + - rscadd: Use a conveyor belt lever on aforementioned item to link all belts inside + the placer with that lever. +2018-07-01: + Anasari: + - tweak: Shuttle can be called at 30:00 instead of 25:00 during War Ops. + Citinited: + - rscadd: The chef can now process spaghetti into macaroni, and can make several + derivative foodstuffs. + datlo: + - rscadd: Syndicate clowns can now purchase Clown Magboots. Keep honking through + slips and atmos! + monster860: + - rscadd: Adds the mining podbay (again) +2018-07-02: + Citinited: + - tweak: Canisters obey melee cooldown now + Crazylemon64: + - rscadd: All MMI variants can now install an "MMI radio upgrade" in order to acquire + radio capability when outside of any other chassis. It can be installed either + directly on the MMI, or through an opened cyborg chassis. This radio can later + be removed if desired by using a screwdriver on the MMI. + - rscadd: MMIs can now pull up the direct interface of the radio instead of a single-toggle + verb + - rscadd: MMI radio control is now done via action button instead of via verb + - rscdel: The radio MMI no longer exists as a distinct item +2018-07-03: + MINIMAN10000: + - tweak: Restrained spacepod passanger can now exit pending a 2 minute wait time + without moving. +2018-07-04: + Citinited: + - bugfix: Spelling error in agent IDs +2018-07-06: + Fox McCloud: + - rscdel: removes explosive lances + datlo: + - bugfix: Replaced duplicate labor shuttle console on the bridge by a mining shuttle + console. +2018-07-07: + Fox McCloud: + - tweak: Stechkin pistols in maintenance no longer spawn with a broken magazine + Kyep: + - rscdel: Removed PDA chatrooms. NTNet Relay Chatrooms, part of modular computers, + still exist. +2018-07-09: + Fox McCloud: + - tweak: Enabled augmentation of the head + - rscadd: Adds cybernetic heart, lungs, liver, and kidneys to R&D and Robotics; + also adds cybernetic upgraded lungs + - tweak: Heads are no longer vital organs, but brains still are +2018-07-10: + Fox McCloud: + - rscdel: Can no longer take assisted organs at round-start (mechanical organs are + still a go, but renamed to cybernetic organs) + - rscadd: Can now start the round with cybernetic lungs, liver, and kidneys + - rscadd: Can produce cybernetic eyes at R&D and mechfabs + - tweak: Cybernetic internal organs no longer take reduced damage (this does not + apply to augments) + - tweak: Cybernetic internal organs can be rendered inoperable (this does not apply + to augments) + - bugfix: Fixes mitocholide/oculine healing damage on cybernetic organs + - bugfix: Fixes being able to restart a dead heart in your hands or with a defib +2018-07-11: + Alffd: + - bugfix: Updates SM engine to modern standards + - rscadd: Ports SM monitoring system from Bay and TG + - rscadd: Adds station wide radiation alarm when crystal/shard goes critical + - rscadd: Tesla zapping + Citinited: + - rscadd: Fortune cookies now drop random fortunes if cooked with a blank piece + of paper. + Fox McCloud: + - rscadd: Adds constructable Integrated Robotic Chassis + - rscadd: Adds surgery to customize existing robotic limb appearances + - tweak: Positronic brains renamed to robotic brains + FreeStylaLT: + - rscadd: Added a Harmonica to Perma Brig + datlo: + - bugfix: Replaced instances of "Human" in ion laws by "Crew". + - bugfix: Fixed the ability of Service Borgs to spawn items on floors. Dosh! +2018-07-14: + Anasari: + - tweak: Assuming there is heal left, bandages and ointments used on limbs now heal + both the limb and the hand / foot. Bandages and ointments used on the torso + now heal head, arms, and lower body. The one on lower body heals the legs too. + Aurorablade: + - rscadd: Adds Spess Koi and related event. + Citinited: + - tweak: The tachyon-doppler array now has a logging interface, and can print off + stored explosive logs. Brag to your friends about your bomb-making skills! + Fox McCloud: + - tweak: Robotic brains have their own unique sprite and full flavortext's now + - bugfix: Fixed a bug where IRC's would have IPC names +2018-07-16: + Citinited: + - tweak: RPD behaviour has been slightly tweaked - for example you can now rotate + / flip / delete individual pipes by clicking on them without affecting other + pipes on that tile. + Fox McCloud: + - bugfix: Fixes hand labelers not being able to label storage objects + - rscadd: Cameras can now be destroyed with weapons that have a force of 12 or greater + - tweak: Cameras have 2 wires as opposed to 6; camera focus and power wires still + remain + - tweak: You can use hand labelers on reagent containers now +2018-07-17: + Citinited: + - bugfix: volume pumps can be dispensed by the RPD again + datlo: + - rscadd: Provided abductors with an infection free surgery table. +2018-07-22: + Fox McCloud: + - bugfix: Fixes monkeys not having their own HUD + - bugfix: Fixes monkey to human transformations missing their HUD + - bugfix: Fixes changing species unequipping items + - bugfix: Fixes organs not being rejuvinated properly by mitocholide + - bugfix: Fixes shadowlings not being forced to hatch + - rscadd: Having a robotic head will allow you to use buzz, ping, beep, and the + likes + - tweak: Claw sharpening now works + - rscadd: Abductors have their own headset instead of a syndicate one + - tweak: Can put monkeys in the gibber + - rscadd: gibbing some species will now generate different types of hides (monkeys + give monkey hides, unathi give lizard hides, the likes) + - bugfix: fixes Vox name generation based on the wrong syllables + - tweak: consolidates diona name lists; you'll no longer be asked to rename your + Diona when you start the shift + - rscdel: botany grown diona can no longer rename themselves (as is consistent with + ghost roles) + - bugfix: Fixes DNA scrambler so it gives a proper randomized species name + - bugfix: Fixed an edge case were Vox would have a permanent nitrogen alert + - bugfix: Fixes operatives being bald most of the time + - rscadd: Adds beesplosion chemical reaction + and taukausanake: + - tweak: Swarmers can no longer destroy active clone pods. +2018-07-24: + Kyep: + - tweak: Number of roundstart atmos suits in atmos increased from 2 to 4. +2018-07-25: + variableundefined: + - bugfix: Fixes runtime error from medical kit change +2018-07-27: + AffectedArc07: + - bugfix: You can no longer use embeds in NTSL + Crazylemon64: + - rscadd: Space hotel is back in business + - bugfix: Non-hotel SNPCs work again + Fox McCloud: + - bugfix: Extract posibrains should have the correct names now + - rscadd: Abductors can now purchase a mind device to speak into crewmembers minds + or give directives to abductees + - rscadd: Abductors now have their own versions of the FixOVein, Bonesetter, and + Bonegel. Credit to Triiodine for the sprites + - rscadd: Adds a new electric shock and chemical gland for abductors + - tweak: viral gland generates random viruses and egg laying gland eggs now have + random reagents in them + variableundefined: + - tweak: Cyborg Analyzer no longer rounds off the damage number it displays. +2018-07-28: + KasparoVy: + - bugfix: You can now safely augment the heads of pointy-snooted Unathi, although + your mileage may vary. +2018-07-30: + Tails2091: + - bugfix: Changed wannabe for loop to a real for loop. +2018-07-31: + Tails2091: + - bugfix: Claw Game Prize Ball now drops more than one ticket like it should. + variableundefined: + - bugfix: fix a runtime error with bluespace projector +2018-08-01: + Citinited: + - tweak: Heaters and freezers now have min and max buttons + CornMyCob: + - tweak: The description for miniature energy guns is now accurate + - tweak: The third person text of someone reinforcing an airlock is now accurate + Tails2091: + - bugfix: Karma refund now uses switch statement. + datlo: + - rscadd: Updated syndicate hardsuit description. +2018-08-02: + variableundefined: + - bugfix: Nightmares now works. Sleep well. + - tweak: Megaphone actually logs in say log now. +2018-08-03: + Fox McCloud: + - tweak: IPC Change monitor is now an action button + - tweak: Slime Color change is now an action button + - bugfix: Fixes staff of change leaving behind unknowns + - bugfix: Fixes Shadowlings not having shock resistant and thermal vision + - bugfix: Fixes staff of change gibbing people + Shazbot: + - rscadd: 'Adds in the ability to unsaw sawn off riot shotguns. Change: Changes + the riot shotgun icon.' +2018-08-05: + Crazylemon64: + - bugfix: Space ruins can no longer trap you upon border transition + - rscadd: There are now several levels of space ruins + Fox McCloud: + - rscadd: Adds in medical hyposprays +2018-08-06: + AffectedArc07: + - tweak: Barber no longer spawns with an extra pair of shoes in his bag + Tails2091: + - bugfix: Fixed Therapy Dolls not working. + - tweak: Made Prize Machine & Merch Sore readable. + - spellcheck: Fixed capitalizations and typos in both lists. +2018-08-07: + Kyep: + - rscadd: Simple_animal mobs now get a HUD button that lets them switch between + HELP and HARM intents. + MarsM0nd: + - bugfix: Unathi can now tailwhip when they are supposed to be able to. + - rscadd: Tail whipping gets logged. diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 2fdc968ebd6..a5195cc0167 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index ee05d5f450e..060d8b77a27 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/weather_effects.dmi b/icons/effects/weather_effects.dmi index 215cf53556f..da1523706e2 100644 Binary files a/icons/effects/weather_effects.dmi and b/icons/effects/weather_effects.dmi differ diff --git a/icons/mob/ears.dmi b/icons/mob/ears.dmi index 13d5981c458..597029a456c 100644 Binary files a/icons/mob/ears.dmi and b/icons/mob/ears.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index 7fc4aa0a9ba..b1a26763fbd 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 760e82458d8..b4dea0cfa36 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/inhands/fluff_lefthand.dmi b/icons/mob/inhands/fluff_lefthand.dmi index 645c04a9ac9..a5721f518ce 100644 Binary files a/icons/mob/inhands/fluff_lefthand.dmi and b/icons/mob/inhands/fluff_lefthand.dmi differ diff --git a/icons/mob/inhands/fluff_righthand.dmi b/icons/mob/inhands/fluff_righthand.dmi index f0656ef8e22..50435f90e0d 100644 Binary files a/icons/mob/inhands/fluff_righthand.dmi and b/icons/mob/inhands/fluff_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index bc282c185d8..1455fa9ab0e 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 8b41a0ec07d..e9d610d754d 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/screen_simplemob.dmi b/icons/mob/screen_simplemob.dmi new file mode 100644 index 00000000000..e3295a84438 Binary files /dev/null and b/icons/mob/screen_simplemob.dmi differ diff --git a/icons/mob/species/unathi/helmet.dmi b/icons/mob/species/unathi/helmet.dmi index f969705ec83..14b099f3f45 100644 Binary files a/icons/mob/species/unathi/helmet.dmi and b/icons/mob/species/unathi/helmet.dmi differ diff --git a/icons/mob/species/unathi/suit.dmi b/icons/mob/species/unathi/suit.dmi index ebbfa5f9c73..1d0bcf81f27 100644 Binary files a/icons/mob/species/unathi/suit.dmi and b/icons/mob/species/unathi/suit.dmi differ diff --git a/icons/mob/species/vox/collar.dmi b/icons/mob/species/vox/collar.dmi index c0b8c6ba936..6c442c62f77 100644 Binary files a/icons/mob/species/vox/collar.dmi and b/icons/mob/species/vox/collar.dmi differ diff --git a/icons/mob/species/vox/helmet.dmi b/icons/mob/species/vox/helmet.dmi index c9227ce2119..a7186d611b6 100644 Binary files a/icons/mob/species/vox/helmet.dmi and b/icons/mob/species/vox/helmet.dmi differ diff --git a/icons/mob/species/vox/suit.dmi b/icons/mob/species/vox/suit.dmi index ca8289a3ccb..3af770d719a 100644 Binary files a/icons/mob/species/vox/suit.dmi and b/icons/mob/species/vox/suit.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 781bc710af3..209e052895a 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi index b3f92a3b57f..db92d8c21a6 100644 Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi index 7bcd0607116..f556369cf69 100644 Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index a63ff4f5daa..d1aa0e9805a 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index 720fafd8847..8593012e528 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index c3942e015de..7143a55ab59 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/species/unathi/hats.dmi b/icons/obj/clothing/species/unathi/hats.dmi index be2fb4f62aa..1ee46571f66 100644 Binary files a/icons/obj/clothing/species/unathi/hats.dmi and b/icons/obj/clothing/species/unathi/hats.dmi differ diff --git a/icons/obj/clothing/species/unathi/suits.dmi b/icons/obj/clothing/species/unathi/suits.dmi index 34c3ea75105..30b590cc7ed 100644 Binary files a/icons/obj/clothing/species/unathi/suits.dmi and b/icons/obj/clothing/species/unathi/suits.dmi differ diff --git a/icons/obj/clothing/ties_overlay.dmi b/icons/obj/clothing/ties_overlay.dmi index a17fed4818c..37bbfbf5d25 100644 Binary files a/icons/obj/clothing/ties_overlay.dmi and b/icons/obj/clothing/ties_overlay.dmi differ diff --git a/icons/obj/custom_items.dmi b/icons/obj/custom_items.dmi index d11043875fc..c27c19ac3aa 100644 Binary files a/icons/obj/custom_items.dmi and b/icons/obj/custom_items.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index f1c8b87aaa4..042c10b2aed 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/doors/windoor.dmi b/icons/obj/doors/windoor.dmi index 8104686b483..9bf105faaf6 100644 Binary files a/icons/obj/doors/windoor.dmi and b/icons/obj/doors/windoor.dmi differ diff --git a/icons/obj/engicart.dmi b/icons/obj/engicart.dmi index 36d45cdf04b..0e665bff8df 100644 Binary files a/icons/obj/engicart.dmi and b/icons/obj/engicart.dmi differ diff --git a/icons/obj/fish_items.dmi b/icons/obj/fish_items.dmi index fd8eea36540..76a9486fee6 100644 Binary files a/icons/obj/fish_items.dmi and b/icons/obj/fish_items.dmi differ diff --git a/icons/obj/food/containers.dmi b/icons/obj/food/containers.dmi index 6825f6c652d..ff25b77ab45 100644 Binary files a/icons/obj/food/containers.dmi and b/icons/obj/food/containers.dmi differ diff --git a/icons/obj/food/custom.dmi b/icons/obj/food/custom.dmi new file mode 100644 index 00000000000..42d28790790 Binary files /dev/null and b/icons/obj/food/custom.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index 3395b112947..487b36d3e97 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/food/pasta.dmi b/icons/obj/food/pasta.dmi new file mode 100644 index 00000000000..0179c3f5cc7 Binary files /dev/null and b/icons/obj/food/pasta.dmi differ diff --git a/icons/obj/food/pizza.dmi b/icons/obj/food/pizza.dmi new file mode 100644 index 00000000000..c26e792f2a0 Binary files /dev/null and b/icons/obj/food/pizza.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index 22dc1384904..e86a39361da 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index d828f2ee9de..5714fcf4c9f 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi index 119f3df0e37..83cb94a5ca3 100644 Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ diff --git a/icons/obj/modular_console.dmi b/icons/obj/modular_console.dmi index 85d6026617f..fba8ad59431 100644 Binary files a/icons/obj/modular_console.dmi and b/icons/obj/modular_console.dmi differ diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_laptop.dmi index 2daeee0c7a4..d04e68c2041 100644 Binary files a/icons/obj/modular_laptop.dmi and b/icons/obj/modular_laptop.dmi differ diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi index 2438f375f65..a6e3223a8d0 100644 Binary files a/icons/obj/modular_tablet.dmi and b/icons/obj/modular_tablet.dmi differ diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index 0a269e0d8b7..ab76789a0f0 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/icons/obj/pipes/disposal.dmi b/icons/obj/pipes/disposal.dmi index 707a064dd94..83440fc1b52 100644 Binary files a/icons/obj/pipes/disposal.dmi and b/icons/obj/pipes/disposal.dmi differ diff --git a/icons/obj/smooth_structures/clockwork_window.dmi b/icons/obj/smooth_structures/clockwork_window.dmi new file mode 100644 index 00000000000..90309ac3d52 Binary files /dev/null and b/icons/obj/smooth_structures/clockwork_window.dmi differ diff --git a/icons/obj/smooth_structures/plasma_window.dmi b/icons/obj/smooth_structures/plasma_window.dmi new file mode 100644 index 00000000000..3d57d156f01 Binary files /dev/null and b/icons/obj/smooth_structures/plasma_window.dmi differ diff --git a/icons/obj/smooth_structures/plastitanium_window.dmi b/icons/obj/smooth_structures/plastitanium_window.dmi new file mode 100644 index 00000000000..82ac0306159 Binary files /dev/null and b/icons/obj/smooth_structures/plastitanium_window.dmi differ diff --git a/icons/obj/smooth_structures/pod_window.dmi b/icons/obj/smooth_structures/pod_window.dmi new file mode 100644 index 00000000000..0fe7501225c Binary files /dev/null and b/icons/obj/smooth_structures/pod_window.dmi differ diff --git a/icons/obj/smooth_structures/reinforced_window.dmi b/icons/obj/smooth_structures/reinforced_window.dmi index b5f24ebbd30..ed9a2a143e6 100644 Binary files a/icons/obj/smooth_structures/reinforced_window.dmi and b/icons/obj/smooth_structures/reinforced_window.dmi differ diff --git a/icons/obj/smooth_structures/rice_window.dmi b/icons/obj/smooth_structures/rice_window.dmi index e3a82935cf2..f5e7a6dd57a 100644 Binary files a/icons/obj/smooth_structures/rice_window.dmi and b/icons/obj/smooth_structures/rice_window.dmi differ diff --git a/icons/obj/smooth_structures/rplasma_window.dmi b/icons/obj/smooth_structures/rplasma_window.dmi new file mode 100644 index 00000000000..c64f42c7f5a Binary files /dev/null and b/icons/obj/smooth_structures/rplasma_window.dmi differ diff --git a/icons/obj/smooth_structures/shuttle_window.dmi b/icons/obj/smooth_structures/shuttle_window.dmi index 3db34cf1ba1..85924dc449b 100644 Binary files a/icons/obj/smooth_structures/shuttle_window.dmi and b/icons/obj/smooth_structures/shuttle_window.dmi differ diff --git a/icons/obj/smooth_structures/tinted_window.dmi b/icons/obj/smooth_structures/tinted_window.dmi index ab992353275..be9affafeea 100644 Binary files a/icons/obj/smooth_structures/tinted_window.dmi and b/icons/obj/smooth_structures/tinted_window.dmi differ diff --git a/icons/obj/smooth_structures/window.dmi b/icons/obj/smooth_structures/window.dmi index 0197f5b20a7..670713bcfe0 100644 Binary files a/icons/obj/smooth_structures/window.dmi and b/icons/obj/smooth_structures/window.dmi differ diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi index 997642dcf29..d4b8e837db6 100755 Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ diff --git a/icons/obj/status_display.dmi b/icons/obj/status_display.dmi index b131da89349..81ccc415de1 100644 Binary files a/icons/obj/status_display.dmi and b/icons/obj/status_display.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 39df3590359..f388b9384fb 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 0b17038ade5..838503bbda1 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index a47c56cba87..b3723f9a53d 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/policetape.dmi b/icons/policetape.dmi deleted file mode 100644 index 74a758335a9..00000000000 Binary files a/icons/policetape.dmi and /dev/null differ diff --git a/icons/program_icons/smmon_0.gif b/icons/program_icons/smmon_0.gif new file mode 100644 index 00000000000..7b716c4e1c5 Binary files /dev/null and b/icons/program_icons/smmon_0.gif differ diff --git a/icons/program_icons/smmon_1.gif b/icons/program_icons/smmon_1.gif new file mode 100644 index 00000000000..bbe319b820f Binary files /dev/null and b/icons/program_icons/smmon_1.gif differ diff --git a/icons/program_icons/smmon_2.gif b/icons/program_icons/smmon_2.gif new file mode 100644 index 00000000000..9c58edd340e Binary files /dev/null and b/icons/program_icons/smmon_2.gif differ diff --git a/icons/program_icons/smmon_3.gif b/icons/program_icons/smmon_3.gif new file mode 100644 index 00000000000..dc7c8734eed Binary files /dev/null and b/icons/program_icons/smmon_3.gif differ diff --git a/icons/program_icons/smmon_4.gif b/icons/program_icons/smmon_4.gif new file mode 100644 index 00000000000..8a75e6e1184 Binary files /dev/null and b/icons/program_icons/smmon_4.gif differ diff --git a/icons/program_icons/smmon_5.gif b/icons/program_icons/smmon_5.gif new file mode 100644 index 00000000000..59356beda0a Binary files /dev/null and b/icons/program_icons/smmon_5.gif differ diff --git a/icons/program_icons/smmon_6.gif b/icons/program_icons/smmon_6.gif new file mode 100644 index 00000000000..aea2f87921d Binary files /dev/null and b/icons/program_icons/smmon_6.gif differ diff --git a/nano/templates/doppler_array.tmpl b/nano/templates/doppler_array.tmpl new file mode 100644 index 00000000000..d3bb40744b2 --- /dev/null +++ b/nano/templates/doppler_array.tmpl @@ -0,0 +1,25 @@ +

      Logged explosions:

      +{{if data.explosion_data == 0}} +

      No explosions logged this shift.

      +{{else}} +
      + Time logged + Epicenter + Actual size + Theoretical size +
      +
      + {{for data.explosion_data}} +
      + + {{:value.logged_time}} + {{:value.epicenter}} + {{:value.actual_size_message}} + {{:value.theoretical_size_message}} + {{:helper.link("Delete", "trash", {"log_to_delete": value.unique_datum_id})}} + +
      + {{/for}} +
      + {{:helper.link("Print all logs", "print", {"print_logs": 'yes'}, data.printing ? 'disabled' : null)}} +{{/if}} diff --git a/nano/templates/freezer.tmpl b/nano/templates/freezer.tmpl index d21d625f017..582598e05c5 100644 --- a/nano/templates/freezer.tmpl +++ b/nano/templates/freezer.tmpl @@ -36,6 +36,7 @@
      {{:helper.displayBar(data.targetGasTemperature, data.minGasTemperature, data.maxGasTemperature)}}
      + {{:helper.link('Min', null, {'minimum' : 'yes'}, (data.targetGasTemperature > data.minGasTemperature) ? null : 'disabled')}} {{:helper.link('-', null, {'temp' : -100}, (data.targetGasTemperature > data.minGasTemperature) ? null : 'disabled')}} {{:helper.link('-', null, {'temp' : -10}, (data.targetGasTemperature > data.minGasTemperature) ? null : 'disabled')}} {{:helper.link('-', null, {'temp' : -1}, (data.targetGasTemperature > data.minGasTemperature) ? null : 'disabled')}} @@ -43,6 +44,7 @@ {{:helper.link('+', null, {'temp' : 1}, (data.targetGasTemperature < data.maxGasTemperature) ? null : 'disabled')}} {{:helper.link('+', null, {'temp' : 10}, (data.targetGasTemperature < data.maxGasTemperature) ? null : 'disabled')}} {{:helper.link('+', null, {'temp' : 100}, (data.targetGasTemperature < data.maxGasTemperature) ? null : 'disabled')}} + {{:helper.link('Max', null, {'maximum' : 'yes'}, (data.targetGasTemperature < data.maxGasTemperature) ? null : 'disabled')}}
    diff --git a/nano/templates/pda_chatroom.tmpl b/nano/templates/pda_chatroom.tmpl deleted file mode 100644 index ae0d8e7f35b..00000000000 --- a/nano/templates/pda_chatroom.tmpl +++ /dev/null @@ -1,85 +0,0 @@ - -
    -
    - Chat Functions: -
    -
    - {{:helper.link(data.silent == 1 ? 'Ringer: Off' : 'Ringer: On', data.silent == 1 ? 'volume-off' : 'volume-up', {'choice' : "Toggle Ringer"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link(data.toff == 1 ? 'Notifications: Off' : 'Notifications: On',data.toff == 1 ? 'close' : 'check', {'choice' : "Toggle Chatroom"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link('Set Ringtone', 'bell-o', {'choice' : "Ringtone"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link('New Room', 'plus', {'choice' : "New Room"}, null, 'pdalink fixedLeftWide')}} -
    -
    - -
    - {{if data.no_server}} -

    ERROR: Messaging server is not responding.

    - {{:helper.link('Reconnect', 'refresh', {'choice' : "Reconnect"}, null, 'pdalink fixedLeftWidest')}} - {{else data.room}} - {{if data.inviting}} -

    Invite whom to #{{:data.room}}?

    - {{for data.people}} - {{:helper.link(value.name, 'user-plus', {'choice': "Invite PDA", 'user': value.ref}, null, 'pdalink fixedLeftWidest')}} - {{empty}} - No other people found. - {{/for}} - {{else}} -

    #{{:data.room}} – {{:data.topic}}

    -
    -
    - Room Functions: -
    -
    - {{:helper.link('Invite', 'user-plus', {'choice' : "Invite"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link('Change Topic', 'tag', {'choice' : "Topic"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link('Leave Channel', 'user-times', {'choice' : "Leave"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link(data.auto_scroll ? 'Autoscroll: On' : 'Autoscroll: Off', 'level-down', {'choice' : "Autoscroll"}, null, 'pdalink fixedLeftWide')}} -
    -
    -
    -
    - {{var prevName = "";}} - {{for data.history}} -
    -
    {{:value.username!=prevName ? value.username : " "}}
    -
    - {{:value.message}} -
    -
    - {{prevName = value.username;}} - {{/for}} -
    -
    - {{:helper.link('Post', 'comment', {'choice' : "Post"}, null, 'pdalink fixedLeftWidest')}} -
    -
    -
    - {{for data.users}} -
    -
    {{:value}}
    -
    - {{/for}} -
    - - {{/if}} - {{else}} -

    Rooms

    - {{for data.rooms}} -
    - {{:helper.link(value.name, 'arrow-circle-down', {'choice' : "Join", 'room' : value.ref}, null, 'pdalink fixedLeftWidest')}} -
    - {{empty}} - No rooms located. - {{/for}} - {{/if}} -
    \ No newline at end of file diff --git a/nano/templates/rpd.tmpl b/nano/templates/rpd.tmpl index bd92b91c979..6a9c2ccb517 100644 --- a/nano/templates/rpd.tmpl +++ b/nano/templates/rpd.tmpl @@ -4,101 +4,104 @@ Used In File(s): /code/game/objects/items/weapons/rpd.dm

    Mode:

    {{for data.mainmenu}} - {{:helper.link(String(value.category), String(value.icon), {"mode": Number(value.mode)}, data.mode == Number(value.mode) ? "linkOn" : null)}} + {{:helper.link(value.category, value.icon, {mode: value.mode}, data.mode == value.mode ? "linkOn" : null)}} {{/for}}
    {{if data.mode == 1}}

    Pipe type:

    {{for data.pipemenu}} - {{:helper.link(String(value.pipecategory), null, {"pipetype": Number(value.pipemode)}, data.pipetype == Number(value.pipemode) ? "linkOn" : null)}} + {{:helper.link(value.category, null, {pipe_category: value.pipemode}, data.pipe_category == value.pipemode ? "linkOn" : null)}} {{/for}}

    Available pipes:

    {{for data.pipelist}} - {{if value.category == data.pipetype}} -
    {{:helper.link(String(value.pipename), "arrow-right", {"whatpipe": Number(value.id)}, data.whatpipe == Number(value.id) ? "linkOn" : null)}}
    + {{if value.pipe_type == 1 && value.pipe_category == data.pipe_category}} +
    {{:helper.link(value.pipe_name, "arrow-right", {whatpipe: value.pipe_id}, data.whatpipe == value.pipe_id ? "linkOn" : null)}}
    {{/if}} {{/for}}
    {{for data.pipelist}} + {{if value.pipe_type != 1 || value.pipe_id != data.whatpipe || value.orientations == 1}} + {{continue;}} + {{/if}}
    - {{if value.id == data.whatpipe && value.orientations != 1}} -
    - {{:helper.link("Orient automatically", null, {"iconrotation": 0}, data.iconrotation == 0 ? "linkOn" : null)}} -
    - {{/if}} - {{if value.id == data.whatpipe && value.orientations != 1 && value.bendy != 1}} +
    + {{:helper.link("Orient automatically", null, {iconrotation: 0}, data.iconrotation == 0 ? "linkOn" : null)}} +
    + {{if value.bendy}}
    - {{:helper.link("", "arrow-right", {"iconrotation": 1}, data.iconrotation == 1 ? "linkOn" : null)}} - + {{:helper.link("", "arrow-right", {iconrotation: 1}, data.iconrotation == 1 ? "linkOn" : null)}} +
    - {{:helper.link("", "arrow-right", {"iconrotation": 4}, data.iconrotation == 4 ? "linkOn" : null)}} - -
    - {{/if}} - {{if value.id == data.whatpipe && value.orientations == 4 && value.bendy != 1}} -
    - {{:helper.link("", "arrow-right", {"iconrotation": 2}, data.iconrotation == 2 ? "linkOn" : null)}} - + {{:helper.link("", "arrow-right", {iconrotation: 4}, data.iconrotation == 4 ? "linkOn" : null)}} +
    - {{:helper.link("", "arrow-right", {"iconrotation": 8}, data.iconrotation == 8 ? "linkOn" : null)}} - -
    - {{/if}} - {{if value.id == data.whatpipe && value.bendy == 1}} -
    - {{:helper.link("", "arrow-right", {"iconrotation": 1}, data.iconrotation == 1 ? "linkOn" : null)}} - + {{:helper.link("", "arrow-right", {iconrotation: 2}, data.iconrotation == 2 ? "linkOn" : null)}} +
    - {{:helper.link("", "arrow-right", {"iconrotation": 4}, data.iconrotation == 4 ? "linkOn" : null)}} - + {{:helper.link("", "arrow-right", {iconrotation: 8}, data.iconrotation == 8 ? "linkOn" : null)}} + +
    + {{else}} +
    + {{:helper.link("", "arrow-right", {iconrotation: 1}, data.iconrotation == 1 ? "linkOn" : null)}} +
    - {{:helper.link("", "arrow-right", {"iconrotation": 2}, data.iconrotation == 2 ? "linkOn" : null)}} - -
    -
    - {{:helper.link("", "arrow-right", {"iconrotation": 8}, data.iconrotation == 8 ? "linkOn" : null)}} - + {{:helper.link("", "arrow-right", {iconrotation: 4}, data.iconrotation == 4 ? "linkOn" : null)}} +
    + {{if value.orientations == 4}} +
    + {{:helper.link("", "arrow-right", {iconrotation: 2}, data.iconrotation == 2 ? "linkOn" : null)}} + +
    +
    + {{:helper.link("", "arrow-right", {iconrotation: 8}, data.iconrotation == 8 ? "linkOn" : null)}} + +
    + {{/if}} {{/if}}
    {{/for}} {{else data.mode == 2}}

    Available pipes:

    - {{for data.dpipelist}} -
    {{:helper.link(String(value.pipename), "arrow-right", {"whatdpipe": Number(value.id)}, data.whatdpipe == Number(value.id) ? "linkOn" : null)}}
    + {{for data.pipelist}} + {{if value.pipe_type == 2}} +
    {{:helper.link(value.pipe_name, "arrow-right", {whatdpipe: value.pipe_id}, data.whatdpipe == value.pipe_id ? "linkOn" : null)}}
    + {{/if}} {{/for}}
    - {{for data.dpipelist}} + {{for data.pipelist}} + {{if value.pipe_type != 2 || value.pipe_id != data.whatdpipe || value.orientations == 1}} + {{continue;}} + {{/if}}
    - {{if value.id == data.whatdpipe && value.orientations != 1}} -
    - {{:helper.link("Orient automatically", null, {"iconrotation": 0}, data.iconrotation == 0 ? "linkOn" : null)}} +
    + {{:helper.link("Orient automatically", null, {iconrotation: 0}, data.iconrotation == 0 ? "linkOn" : null)}} +
    +
    + {{:helper.link("", "arrow-right", {iconrotation: 1}, data.iconrotation == 1 ? "linkOn" : null)}} + +
    +
    + {{:helper.link("", "arrow-right", {iconrotation: 4}, data.iconrotation == 4 ? "linkOn" : null)}} + +
    + {{if value.orientations == 4}} +
    + {{:helper.link("", "arrow-right", {iconrotation: 2}, data.iconrotation == 2 ? "linkOn" : null)}} +
    - {{:helper.link("", "arrow-right", {"iconrotation": 1}, data.iconrotation == 1 ? "linkOn" : null)}} - -
    -
    - {{:helper.link("", "arrow-right", {"iconrotation": 4}, data.iconrotation == 4 ? "linkOn" : null)}} - -
    - {{/if}} - {{if value.id == data.whatdpipe && value.orientations == 4}} -
    - {{:helper.link("", "arrow-right", {"iconrotation": 2}, data.iconrotation == 2 ? "linkOn" : null)}} - -
    -
    - {{:helper.link("", "arrow-right", {"iconrotation": 8}, data.iconrotation == 8 ? "linkOn" : null)}} - + {{:helper.link("", "arrow-right", {iconrotation: 8}, data.iconrotation == 8 ? "linkOn" : null)}} +
    {{/if}}
    @@ -109,4 +112,4 @@ Used In File(s): /code/game/objects/items/weapons/rpd.dm

    Device ready to flip loose pipes...

    {{else data.mode == 5}}

    Device ready to eat loose pipes...

    -{{/if}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/supermatter_monitor.tmpl b/nano/templates/supermatter_monitor.tmpl new file mode 100644 index 00000000000..3bc87984d79 --- /dev/null +++ b/nano/templates/supermatter_monitor.tmpl @@ -0,0 +1,111 @@ +{{if data.active}} + {{:helper.link('Back to Menu', null, {'clear' : 1})}}
    +
    +
    + Core Integrity: +
    +
    + {{:helper.displayBar(data.SM_integrity, 0, 100, (data.SM_integrity == 100) ? 'good' : (data.SM_integrity >= 50) ? 'average' : 'bad')}} {{:data.SM_integrity}}% +
    +
    + Relative EER: +
    +
    + {{if data.SM_power > 300}} + {{:data.SM_power}} MeV/cm3 + {{else data.SM_power > 150}} + {{:data.SM_power}} MeV/cm3 + {{else}} + {{:data.SM_power}} MeV/cm3 + {{/if}} +
    +
    + Temperature: +
    +
    + {{if data.SM_ambienttemp > 5000}} + {{:data.SM_ambienttemp}} K + {{else data.SM_ambienttemp > 4000}} + {{:data.SM_ambienttemp}} K + {{else}} + {{:data.SM_ambienttemp}} K + {{/if}} +
    +
    + Pressure: +
    +
    + {{if data.SM_ambientpressure > 10000}} + {{:data.SM_ambientpressure}} kPa + {{else data.SM_ambientpressure > 5000}} + {{:data.SM_ambientpressure}} kPa + {{else}} + {{:data.SM_ambientpressure}} kPa + {{/if}} +
    +
    +

    +
    + Gas Composition: +
    +
    +
    +
    + O2: +
    +
    + {{:data.SM_gas_O2}} % +
    +
    + CO2: +
    +
    + {{:data.SM_gas_CO2}} % +
    +
    + N2: +
    +
    + {{:data.SM_gas_N2}} % +
    +
    + PL: +
    +
    + {{:data.SM_gas_PL}} % +
    +
    + OTHER: +
    +
    + {{:data.SM_gas_OTHER}} % +
    +
    +
    +
    +{{else}} + {{:helper.link('Refresh', null, {'refresh' : 1})}}
    + {{for data.supermatters}} +
    +
    + Area: +
    +
    + {{:value.area_name}} +
    +
    + Integrity: +
    +
    + {{:value.integrity}} % +
    +
    + Options: +
    +
    + {{:helper.link('View Details', null, {'set' : value.uid})}} +
    +
    + {{/for}} +{{/if}} diff --git a/paradise.dme b/paradise.dme index a1d7df60b95..0dbb53d572b 100644 --- a/paradise.dme +++ b/paradise.dme @@ -18,6 +18,7 @@ #include "code\__DEFINES\_globals.dm" #include "code\__DEFINES\_readme.dm" #include "code\__DEFINES\admin.dm" +#include "code\__DEFINES\antagonists.dm" #include "code\__DEFINES\atmospherics.dm" #include "code\__DEFINES\bots.dm" #include "code\__DEFINES\callbacks.dm" @@ -44,6 +45,7 @@ #include "code\__DEFINES\misc.dm" #include "code\__DEFINES\mobs.dm" #include "code\__DEFINES\pda.dm" +#include "code\__DEFINES\pipes.dm" #include "code\__DEFINES\preferences.dm" #include "code\__DEFINES\process_scheduler.dm" #include "code\__DEFINES\qdel.dm" @@ -76,6 +78,7 @@ #include "code\__HELPERS\matrices.dm" #include "code\__HELPERS\mobs.dm" #include "code\__HELPERS\names.dm" +#include "code\__HELPERS\pronouns.dm" #include "code\__HELPERS\qdel.dm" #include "code\__HELPERS\sanitize_values.dm" #include "code\__HELPERS\text.dm" @@ -88,8 +91,6 @@ #include "code\__HELPERS\sorts\MergeSort.dm" #include "code\__HELPERS\sorts\TimSort.dm" #include "code\_DATASTRUCTURES\heap.dm" -#include "code\_DATASTRUCTURES\linked_lists.dm" -#include "code\_DATASTRUCTURES\priority_queue.dm" #include "code\_DATASTRUCTURES\stacks.dm" #include "code\_globalvars\configuration.dm" #include "code\_globalvars\database.dm" @@ -101,6 +102,7 @@ #include "code\_globalvars\station.dm" #include "code\_globalvars\unused.dm" #include "code\_globalvars\lists\flavor_misc.dm" +#include "code\_globalvars\lists\fortunes.dm" #include "code\_globalvars\lists\misc.dm" #include "code\_globalvars\lists\mobs.dm" #include "code\_globalvars\lists\names.dm" @@ -198,7 +200,6 @@ #include "code\controllers\Processes\obj.dm" #include "code\controllers\Processes\shuttles.dm" #include "code\controllers\Processes\ticker.dm" -#include "code\controllers\Processes\weather.dm" #include "code\controllers\ProcessScheduler\core\process.dm" #include "code\controllers\ProcessScheduler\core\processScheduler.dm" #include "code\controllers\subsystem\air.dm" @@ -213,6 +214,7 @@ #include "code\controllers\subsystem\sun.dm" #include "code\controllers\subsystem\throwing.dm" #include "code\controllers\subsystem\timer.dm" +#include "code\controllers\subsystem\weather.dm" #include "code\controllers\subsystem\processing\processing.dm" #include "code\datums\action.dm" #include "code\datums\ai_law_sets.dm" @@ -220,17 +222,17 @@ #include "code\datums\beam.dm" #include "code\datums\browser.dm" #include "code\datums\callback.dm" -#include "code\datums\computerfiles.dm" #include "code\datums\datacore.dm" #include "code\datums\datum.dm" #include "code\datums\datumvars.dm" #include "code\datums\gas_mixture.dm" +#include "code\datums\holocall.dm" #include "code\datums\hud.dm" #include "code\datums\mind.dm" #include "code\datums\mixed.dm" -#include "code\datums\modules.dm" #include "code\datums\mutable_appearance.dm" #include "code\datums\periodic_news.dm" +#include "code\datums\pipe_datums.dm" #include "code\datums\progressbar.dm" #include "code\datums\recipe.dm" #include "code\datums\ruins.dm" @@ -314,6 +316,7 @@ #include "code\datums\helper_datums\topic_input.dm" #include "code\datums\looping_sounds\looping_sound.dm" #include "code\datums\looping_sounds\machinery_sounds.dm" +#include "code\datums\looping_sounds\weather.dm" #include "code\datums\outfits\outfit.dm" #include "code\datums\outfits\outfit_admin.dm" #include "code\datums\ruins\space.dm" @@ -353,7 +356,10 @@ #include "code\datums\status_effects\status_effect.dm" #include "code\datums\vr\level.dm" #include "code\datums\weather\weather.dm" -#include "code\datums\weather\weather_types.dm" +#include "code\datums\weather\weather_types\ash_storm.dm" +#include "code\datums\weather\weather_types\floor_is_lava.dm" +#include "code\datums\weather\weather_types\radiation_storm.dm" +#include "code\datums\weather\weather_types\snow_storm.dm" #include "code\datums\wires\airlock.dm" #include "code\datums\wires\alarm.dm" #include "code\datums\wires\apc.dm" @@ -385,7 +391,6 @@ #include "code\game\data_huds.dm" #include "code\game\response_team.dm" #include "code\game\shuttle_engines.dm" -#include "code\game\skincmd.dm" #include "code\game\sound.dm" #include "code\game\world.dm" #include "code\game\area\ai_monitored.dm" @@ -404,8 +409,6 @@ #include "code\game\dna\genes\powers.dm" #include "code\game\dna\genes\vg_disabilities.dm" #include "code\game\dna\genes\vg_powers.dm" -#include "code\game\gamemodes\antag_hud.dm" -#include "code\game\gamemodes\antag_spawner.dm" #include "code\game\gamemodes\factions.dm" #include "code\game\gamemodes\game_mode.dm" #include "code\game\gamemodes\gameticker.dm" @@ -469,8 +472,10 @@ #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\meteor\meteor.dm" #include "code\game\gamemodes\meteor\meteors.dm" +#include "code\game\gamemodes\miniantags\abduction\abductee_objectives.dm" #include "code\game\gamemodes\miniantags\abduction\abduction.dm" #include "code\game\gamemodes\miniantags\abduction\abduction_gear.dm" +#include "code\game\gamemodes\miniantags\abduction\abduction_outfits.dm" #include "code\game\gamemodes\miniantags\abduction\abduction_surgery.dm" #include "code\game\gamemodes\miniantags\abduction\gland.dm" #include "code\game\gamemodes\miniantags\abduction\machinery\camera.dm" @@ -529,6 +534,7 @@ #include "code\game\jobs\job_controller.dm" #include "code\game\jobs\job_exp.dm" #include "code\game\jobs\job_objective.dm" +#include "code\game\jobs\job_scaling.dm" #include "code\game\jobs\jobs.dm" #include "code\game\jobs\whitelist.dm" #include "code\game\jobs\job\central.dm" @@ -630,7 +636,6 @@ #include "code\game\machinery\computer\computer.dm" #include "code\game\machinery\computer\crew.dm" #include "code\game\machinery\computer\HolodeckControl.dm" -#include "code\game\machinery\computer\hologram.dm" #include "code\game\machinery\computer\honkputer.dm" #include "code\game\machinery\computer\law.dm" #include "code\game\machinery\computer\medical.dm" @@ -770,7 +775,6 @@ #include "code\game\objects\items\flag.dm" #include "code\game\objects\items\latexballoon.dm" #include "code\game\objects\items\misc.dm" -#include "code\game\objects\items\policetape.dm" #include "code\game\objects\items\random_items.dm" #include "code\game\objects\items\shooting_range.dm" #include "code\game\objects\items\toys.dm" @@ -867,7 +871,6 @@ #include "code\game\objects\items\weapons\paint.dm" #include "code\game\objects\items\weapons\paiwire.dm" #include "code\game\objects\items\weapons\pneumaticCannon.dm" -#include "code\game\objects\items\weapons\power_cells.dm" #include "code\game\objects\items\weapons\powerfist.dm" #include "code\game\objects\items\weapons\RCD.dm" #include "code\game\objects\items\weapons\RCL.dm" @@ -962,10 +965,10 @@ #include "code\game\objects\structures\false_walls.dm" #include "code\game\objects\structures\flora.dm" #include "code\game\objects\structures\foodcart.dm" -#include "code\game\objects\structures\fullwindow.dm" #include "code\game\objects\structures\girders.dm" #include "code\game\objects\structures\grille.dm" #include "code\game\objects\structures\guillotine.dm" +#include "code\game\objects\structures\holosign.dm" #include "code\game\objects\structures\inflatable.dm" #include "code\game\objects\structures\janicart.dm" #include "code\game\objects\structures\kitchen_spike.dm" @@ -1138,6 +1141,12 @@ #include "code\modules\alarm\fire_alarm.dm" #include "code\modules\alarm\motion_alarm.dm" #include "code\modules\alarm\power_alarm.dm" +#include "code\modules\antagonists\_common\antag_datum.dm" +#include "code\modules\antagonists\_common\antag_helpers.dm" +#include "code\modules\antagonists\_common\antag_hud.dm" +#include "code\modules\antagonists\_common\antag_spawner.dm" +#include "code\modules\antagonists\_common\antag_team.dm" +#include "code\modules\antagonists\wishgranter\wishgranter.dm" #include "code\modules\arcade\arcade_base.dm" #include "code\modules\arcade\arcade_prize.dm" #include "code\modules\arcade\claw_game.dm" @@ -1343,6 +1352,7 @@ #include "code\modules\events\immovable_rod.dm" #include "code\modules\events\infestation.dm" #include "code\modules\events\ion_storm.dm" +#include "code\modules\events\koi_mirgration.dm" #include "code\modules\events\mass_hallucination.dm" #include "code\modules\events\meaty_gore.dm" #include "code\modules\events\meaty_ops.dm" @@ -1394,12 +1404,24 @@ #include "code\modules\food_and_drinks\drinks\drinks\drinkingglass.dm" #include "code\modules\food_and_drinks\drinks\drinks\mugs.dm" #include "code\modules\food_and_drinks\drinks\drinks\shotglass.dm" -#include "code\modules\food_and_drinks\food\candy.dm" #include "code\modules\food_and_drinks\food\condiment.dm" #include "code\modules\food_and_drinks\food\customizables.dm" -#include "code\modules\food_and_drinks\food\meat.dm" -#include "code\modules\food_and_drinks\food\seafood.dm" #include "code\modules\food_and_drinks\food\snacks.dm" +#include "code\modules\food_and_drinks\food\foods\baked_goods.dm" +#include "code\modules\food_and_drinks\food\foods\bread.dm" +#include "code\modules\food_and_drinks\food\foods\candy.dm" +#include "code\modules\food_and_drinks\food\foods\desserts.dm" +#include "code\modules\food_and_drinks\food\foods\ethnic.dm" +#include "code\modules\food_and_drinks\food\foods\ingredients.dm" +#include "code\modules\food_and_drinks\food\foods\junkfood.dm" +#include "code\modules\food_and_drinks\food\foods\meat.dm" +#include "code\modules\food_and_drinks\food\foods\misc.dm" +#include "code\modules\food_and_drinks\food\foods\pasta.dm" +#include "code\modules\food_and_drinks\food\foods\pizza.dm" +#include "code\modules\food_and_drinks\food\foods\sandwiches.dm" +#include "code\modules\food_and_drinks\food\foods\seafood.dm" +#include "code\modules\food_and_drinks\food\foods\side_dishes.dm" +#include "code\modules\food_and_drinks\food\foods\soups.dm" #include "code\modules\food_and_drinks\kitchen_machinery\candy_maker.dm" #include "code\modules\food_and_drinks\kitchen_machinery\cereal_maker.dm" #include "code\modules\food_and_drinks\kitchen_machinery\cooker.dm" @@ -1617,7 +1639,8 @@ #include "code\modules\mob\living\carbon\brain\life.dm" #include "code\modules\mob\living\carbon\brain\login.dm" #include "code\modules\mob\living\carbon\brain\MMI.dm" -#include "code\modules\mob\living\carbon\brain\posibrain.dm" +#include "code\modules\mob\living\carbon\brain\MMI_radio.dm" +#include "code\modules\mob\living\carbon\brain\robotic_brain.dm" #include "code\modules\mob\living\carbon\brain\say.dm" #include "code\modules\mob\living\carbon\brain\update_status.dm" #include "code\modules\mob\living\carbon\human\appearance.dm" @@ -1643,15 +1666,28 @@ #include "code\modules\mob\living\carbon\human\interactive\functions.dm" #include "code\modules\mob\living\carbon\human\interactive\interactive.dm" #include "code\modules\mob\living\carbon\human\interactive\prefabs.dm" +#include "code\modules\mob\living\carbon\human\species\_species.dm" #include "code\modules\mob\living\carbon\human\species\abductor.dm" -#include "code\modules\mob\living\carbon\human\species\apollo.dm" +#include "code\modules\mob\living\carbon\human\species\diona.dm" +#include "code\modules\mob\living\carbon\human\species\drask.dm" #include "code\modules\mob\living\carbon\human\species\golem.dm" +#include "code\modules\mob\living\carbon\human\species\grey.dm" +#include "code\modules\mob\living\carbon\human\species\human.dm" +#include "code\modules\mob\living\carbon\human\species\kidan.dm" +#include "code\modules\mob\living\carbon\human\species\machine.dm" #include "code\modules\mob\living\carbon\human\species\monkey.dm" +#include "code\modules\mob\living\carbon\human\species\nucleation.dm" #include "code\modules\mob\living\carbon\human\species\plasmaman.dm" #include "code\modules\mob\living\carbon\human\species\shadow.dm" +#include "code\modules\mob\living\carbon\human\species\shadowling.dm" #include "code\modules\mob\living\carbon\human\species\skeleton.dm" -#include "code\modules\mob\living\carbon\human\species\species.dm" -#include "code\modules\mob\living\carbon\human\species\station.dm" +#include "code\modules\mob\living\carbon\human\species\skrell.dm" +#include "code\modules\mob\living\carbon\human\species\slime.dm" +#include "code\modules\mob\living\carbon\human\species\tajaran.dm" +#include "code\modules\mob\living\carbon\human\species\unathi.dm" +#include "code\modules\mob\living\carbon\human\species\vox.dm" +#include "code\modules\mob\living\carbon\human\species\vulpkanin.dm" +#include "code\modules\mob\living\carbon\human\species\wryn.dm" #include "code\modules\mob\living\carbon\slime\death.dm" #include "code\modules\mob\living\carbon\slime\emote.dm" #include "code\modules\mob\living\carbon\slime\examine.dm" @@ -1851,6 +1887,7 @@ #include "code\modules\modular_computers\file_system\programs\command\comms.dm" #include "code\modules\modular_computers\file_system\programs\engineering\alarm.dm" #include "code\modules\modular_computers\file_system\programs\engineering\power_monitor.dm" +#include "code\modules\modular_computers\file_system\programs\engineering\sm_monitor.dm" #include "code\modules\modular_computers\file_system\programs\generic\configurator.dm" #include "code\modules\modular_computers\file_system\programs\generic\file_browser.dm" #include "code\modules\modular_computers\file_system\programs\generic\ntdownloader.dm" @@ -1922,7 +1959,6 @@ #include "code\modules\pda\app.dm" #include "code\modules\pda\cart.dm" #include "code\modules\pda\cart_apps.dm" -#include "code\modules\pda\chatroom.dm" #include "code\modules\pda\core_apps.dm" #include "code\modules\pda\messenger.dm" #include "code\modules\pda\messenger_plugins.dm" @@ -2072,6 +2108,7 @@ #include "code\modules\reagents\reagent_containers\pill.dm" #include "code\modules\reagents\reagent_containers\spray.dm" #include "code\modules\reagents\reagent_containers\syringes.dm" +#include "code\modules\recycling\belt-placer.dm" #include "code\modules\recycling\conveyor2.dm" #include "code\modules\recycling\disposal-construction.dm" #include "code\modules\recycling\disposal.dm" @@ -2110,6 +2147,7 @@ #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" #include "code\modules\ruins\ruin_areas.dm" +#include "code\modules\scripting\__defines.dm" #include "code\modules\scripting\Errors.dm" #include "code\modules\scripting\Options.dm" #include "code\modules\scripting\AST\AST Nodes.dm" @@ -2160,7 +2198,6 @@ #include "code\modules\surgery\cavity_implant.dm" #include "code\modules\surgery\dental_implant.dm" #include "code\modules\surgery\encased.dm" -#include "code\modules\surgery\face.dm" #include "code\modules\surgery\generic.dm" #include "code\modules\surgery\helpers.dm" #include "code\modules\surgery\implant_removal.dm" @@ -2168,6 +2205,7 @@ #include "code\modules\surgery\limb_reattach.dm" #include "code\modules\surgery\organs_internal.dm" #include "code\modules\surgery\other.dm" +#include "code\modules\surgery\plastic_surgery.dm" #include "code\modules\surgery\remove_embedded_object.dm" #include "code\modules\surgery\rig_removal.dm" #include "code\modules\surgery\robotics.dm" @@ -2180,8 +2218,13 @@ #include "code\modules\surgery\organs\autoimplanter.dm" #include "code\modules\surgery\organs\blood.dm" #include "code\modules\surgery\organs\body_egg.dm" +#include "code\modules\surgery\organs\eyes.dm" +#include "code\modules\surgery\organs\heart.dm" #include "code\modules\surgery\organs\helpers.dm" +#include "code\modules\surgery\organs\kidneys.dm" +#include "code\modules\surgery\organs\liver.dm" #include "code\modules\surgery\organs\lungs.dm" +#include "code\modules\surgery\organs\mmi_holder.dm" #include "code\modules\surgery\organs\organ.dm" #include "code\modules\surgery\organs\organ_external.dm" #include "code\modules\surgery\organs\organ_icon.dm" diff --git a/sound/creatures/bee.ogg b/sound/creatures/bee.ogg new file mode 100644 index 00000000000..ea8dcc2b369 Binary files /dev/null and b/sound/creatures/bee.ogg differ diff --git a/sound/goonstation/items/hypo.ogg b/sound/goonstation/items/hypo.ogg new file mode 100644 index 00000000000..8525a1b43c7 Binary files /dev/null and b/sound/goonstation/items/hypo.ogg differ diff --git a/sound/lavaland/ash_storm_end.ogg b/sound/lavaland/ash_storm_end.ogg deleted file mode 100644 index f9b01453dda..00000000000 Binary files a/sound/lavaland/ash_storm_end.ogg and /dev/null differ diff --git a/sound/lavaland/ash_storm_start.ogg b/sound/lavaland/ash_storm_start.ogg deleted file mode 100644 index 4b9bebffd08..00000000000 Binary files a/sound/lavaland/ash_storm_start.ogg and /dev/null differ diff --git a/sound/lavaland/ash_storm_windup.ogg b/sound/lavaland/ash_storm_windup.ogg deleted file mode 100644 index a9f0fa3270e..00000000000 Binary files a/sound/lavaland/ash_storm_windup.ogg and /dev/null differ diff --git a/sound/machines/engine_alert2.ogg b/sound/machines/engine_alert2.ogg new file mode 100644 index 00000000000..83f693617a7 Binary files /dev/null and b/sound/machines/engine_alert2.ogg differ diff --git a/sound/voice/mapple.ogg b/sound/voice/mapple.ogg new file mode 100644 index 00000000000..21e26742ca1 Binary files /dev/null and b/sound/voice/mapple.ogg differ diff --git a/sound/voice/mcatch.ogg b/sound/voice/mcatch.ogg new file mode 100644 index 00000000000..07b8aaab75c Binary files /dev/null and b/sound/voice/mcatch.ogg differ diff --git a/sound/voice/mcoming.ogg b/sound/voice/mcoming.ogg new file mode 100644 index 00000000000..d3eb9e467f4 Binary files /dev/null and b/sound/voice/mcoming.ogg differ diff --git a/sound/voice/mdelicious.ogg b/sound/voice/mdelicious.ogg new file mode 100644 index 00000000000..5158538580e Binary files /dev/null and b/sound/voice/mdelicious.ogg differ diff --git a/sound/voice/mfeelbetter.ogg b/sound/voice/mfeelbetter.ogg new file mode 100644 index 00000000000..fdbe57fd2e9 Binary files /dev/null and b/sound/voice/mfeelbetter.ogg differ diff --git a/sound/voice/mflies.ogg b/sound/voice/mflies.ogg new file mode 100644 index 00000000000..831281ebbee Binary files /dev/null and b/sound/voice/mflies.ogg differ diff --git a/sound/voice/mhelp.ogg b/sound/voice/mhelp.ogg new file mode 100644 index 00000000000..516d5db068d Binary files /dev/null and b/sound/voice/mhelp.ogg differ diff --git a/sound/voice/minjured.ogg b/sound/voice/minjured.ogg new file mode 100644 index 00000000000..0e968b3980c Binary files /dev/null and b/sound/voice/minjured.ogg differ diff --git a/sound/voice/minsult.ogg b/sound/voice/minsult.ogg new file mode 100644 index 00000000000..017292977a1 Binary files /dev/null and b/sound/voice/minsult.ogg differ diff --git a/sound/voice/mlive.ogg b/sound/voice/mlive.ogg new file mode 100644 index 00000000000..ceb0dec9a34 Binary files /dev/null and b/sound/voice/mlive.ogg differ diff --git a/sound/voice/mlost.ogg b/sound/voice/mlost.ogg new file mode 100644 index 00000000000..7b332ac346a Binary files /dev/null and b/sound/voice/mlost.ogg differ diff --git a/sound/voice/mno.ogg b/sound/voice/mno.ogg new file mode 100644 index 00000000000..030e43a0109 Binary files /dev/null and b/sound/voice/mno.ogg differ diff --git a/sound/voice/mpatchedup.ogg b/sound/voice/mpatchedup.ogg new file mode 100644 index 00000000000..1314f6ee471 Binary files /dev/null and b/sound/voice/mpatchedup.ogg differ diff --git a/sound/voice/mradar.ogg b/sound/voice/mradar.ogg new file mode 100644 index 00000000000..ad347a6d891 Binary files /dev/null and b/sound/voice/mradar.ogg differ diff --git a/sound/voice/msurgeon.ogg b/sound/voice/msurgeon.ogg new file mode 100644 index 00000000000..a300ee57ef6 Binary files /dev/null and b/sound/voice/msurgeon.ogg differ diff --git a/sound/weather/ashstorm/inside/active_end.ogg b/sound/weather/ashstorm/inside/active_end.ogg new file mode 100644 index 00000000000..959bf5773eb Binary files /dev/null and b/sound/weather/ashstorm/inside/active_end.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid1.ogg b/sound/weather/ashstorm/inside/active_mid1.ogg new file mode 100644 index 00000000000..95244cd2b7c Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid1.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid2.ogg b/sound/weather/ashstorm/inside/active_mid2.ogg new file mode 100644 index 00000000000..a45584b9f31 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid2.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid3.ogg b/sound/weather/ashstorm/inside/active_mid3.ogg new file mode 100644 index 00000000000..be2e672fa0e Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid3.ogg differ diff --git a/sound/weather/ashstorm/inside/active_start.ogg b/sound/weather/ashstorm/inside/active_start.ogg new file mode 100644 index 00000000000..3efab12ef26 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_start.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_end.ogg b/sound/weather/ashstorm/inside/weak_end.ogg new file mode 100644 index 00000000000..416b75a9b84 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_end.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid1.ogg b/sound/weather/ashstorm/inside/weak_mid1.ogg new file mode 100644 index 00000000000..d3211c6b5fc Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid1.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid2.ogg b/sound/weather/ashstorm/inside/weak_mid2.ogg new file mode 100644 index 00000000000..b6491a7afb8 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid2.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid3.ogg b/sound/weather/ashstorm/inside/weak_mid3.ogg new file mode 100644 index 00000000000..95238c72d40 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid3.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_start.ogg b/sound/weather/ashstorm/inside/weak_start.ogg new file mode 100644 index 00000000000..59abf1937dc Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_start.ogg differ diff --git a/sound/weather/ashstorm/outside/active_end.ogg b/sound/weather/ashstorm/outside/active_end.ogg new file mode 100644 index 00000000000..95149d846cc Binary files /dev/null and b/sound/weather/ashstorm/outside/active_end.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid1.ogg b/sound/weather/ashstorm/outside/active_mid1.ogg new file mode 100644 index 00000000000..189528ab569 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid1.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid2.ogg b/sound/weather/ashstorm/outside/active_mid2.ogg new file mode 100644 index 00000000000..92317f2e0a7 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid2.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid3.ogg b/sound/weather/ashstorm/outside/active_mid3.ogg new file mode 100644 index 00000000000..34846bfd42c Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid3.ogg differ diff --git a/sound/weather/ashstorm/outside/active_start.ogg b/sound/weather/ashstorm/outside/active_start.ogg new file mode 100644 index 00000000000..8b3acf1a153 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_start.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_end.ogg b/sound/weather/ashstorm/outside/weak_end.ogg new file mode 100644 index 00000000000..55db2fc3565 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_end.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid1.ogg b/sound/weather/ashstorm/outside/weak_mid1.ogg new file mode 100644 index 00000000000..56faa9ad26c Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid1.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid2.ogg b/sound/weather/ashstorm/outside/weak_mid2.ogg new file mode 100644 index 00000000000..0c836ad220a Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid2.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid3.ogg b/sound/weather/ashstorm/outside/weak_mid3.ogg new file mode 100644 index 00000000000..f2cbfb0f4b9 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid3.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_start.ogg b/sound/weather/ashstorm/outside/weak_start.ogg new file mode 100644 index 00000000000..1ac59c36f05 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_start.ogg differ diff --git a/tgstation.dme b/tgstation.dme deleted file mode 120000 index abc8cf17220..00000000000 --- a/tgstation.dme +++ /dev/null @@ -1 +0,0 @@ -paradise.dme \ No newline at end of file