From 3f89a00415a7753c093d8274f6776d77d3844aaa Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 9 Jan 2020 17:59:34 +1100 Subject: [PATCH 01/61] Adds IPC plushie and toast, toast is made via IPC plushie. --- code/game/objects/items/toys.dm | 13 ++++++++++++ .../food_and_drinks/food/foods/bread.dm | 19 ++++++++++++++++++ icons/obj/food/food.dmi | Bin 97979 -> 98385 bytes icons/obj/toy.dmi | Bin 77735 -> 78263 bytes 4 files changed, 32 insertions(+) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 0ad64e24f23..66f5ebbf874 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1085,6 +1085,19 @@ obj/item/toy/cards/deck/syndicate/black return ..() +/obj/item/toy/plushie/ipcplushie + name = "ipc plushie" + desc = "An adorable ipc plushie, straight from New Canaan. Arguably more durable than the real deal. Toaster functionality included." + icon_state = "plushie_ipc" + item_state = "plushie_ipc" + +/obj/item/toy/plushie/ipcplushie/attackby(obj/item/B, mob/user, params) + if(istype(B, /obj/item/reagent_containers/food/snacks/breadslice)) + new /obj/item/reagent_containers/food/snacks/toast(get_turf(loc)) + to_chat(user, " You insert bread into the toaster. ") + playsound(loc, 'sound/machines/ding.ogg', 50, 1) + qdel(B) + //New generation TG plushies /obj/item/toy/plushie/lizardplushie diff --git a/code/modules/food_and_drinks/food/foods/bread.dm b/code/modules/food_and_drinks/food/foods/bread.dm index d888a532c01..e26a45ca88b 100644 --- a/code/modules/food_and_drinks/food/foods/bread.dm +++ b/code/modules/food_and_drinks/food/foods/bread.dm @@ -166,6 +166,23 @@ list_reagents = list("nutriment" = 2, "vitamin" = 2) tastes = list("bread" = 2) +/obj/item/reagent_containers/food/snacks/toast + name = "Toast" + desc = "Yeah! Toast!" + icon_state = "toast" + filling_color = "#B2580E" + bitesize = 3 + list_reagents = list("nutriment" = 3) + tastes = list("toast" = 2) + + /*name = "Toast" + desc = "Yeah! Toast!" + icon_state = "toast" + filling_color = "#b2580e" + bitesize = 3 + list_reagents = list("nutriment" = 3) + tastes = list("toast" = 2)*/ + /obj/item/reagent_containers/food/snacks/jelliedtoast name = "Jellied Toast" desc = "A slice of bread covered with delicious jam." @@ -198,3 +215,5 @@ trash = /obj/item/trash/waffles filling_color = "#E6DEB5" list_reagents = list("nutriment" = 8, "vitamin" = 1) + + diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index aea237f5bed3be518b1bbceef927798252caaf94..fdd520c1b145359ebde99d91706c5f0f3975d49a 100644 GIT binary patch delta 7915 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 UWAN_<(9NTx@mRf9)h6oy08Lt!bpQYW diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 511b578ad4a29b89a1ae13de6c8aeda120ee1540..1ef7016307de59d80f1054b932a070b35c98960f 100644 GIT binary patch delta 18760 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 delta 18228 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 e6ciem{|EdI;1Li(u~^Rl0000 Date: Fri, 10 Jan 2020 13:44:46 +1100 Subject: [PATCH 02/61] made IPC capital, added return statement, and deleted usless taost comment. --- code/game/objects/items/toys.dm | 4 +++- code/modules/food_and_drinks/food/foods/bread.dm | 8 -------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 66f5ebbf874..e414eb3d53c 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1086,7 +1086,7 @@ obj/item/toy/cards/deck/syndicate/black ..() /obj/item/toy/plushie/ipcplushie - name = "ipc plushie" + name = "IPC plushie" desc = "An adorable ipc plushie, straight from New Canaan. Arguably more durable than the real deal. Toaster functionality included." icon_state = "plushie_ipc" item_state = "plushie_ipc" @@ -1097,6 +1097,8 @@ obj/item/toy/cards/deck/syndicate/black to_chat(user, " You insert bread into the toaster. ") playsound(loc, 'sound/machines/ding.ogg', 50, 1) qdel(B) + else + return ..() //New generation TG plushies diff --git a/code/modules/food_and_drinks/food/foods/bread.dm b/code/modules/food_and_drinks/food/foods/bread.dm index e26a45ca88b..55255658233 100644 --- a/code/modules/food_and_drinks/food/foods/bread.dm +++ b/code/modules/food_and_drinks/food/foods/bread.dm @@ -174,14 +174,6 @@ bitesize = 3 list_reagents = list("nutriment" = 3) tastes = list("toast" = 2) - - /*name = "Toast" - desc = "Yeah! Toast!" - icon_state = "toast" - filling_color = "#b2580e" - bitesize = 3 - list_reagents = list("nutriment" = 3) - tastes = list("toast" = 2)*/ /obj/item/reagent_containers/food/snacks/jelliedtoast name = "Jellied Toast" From 934ef6dcd04e7a5cd2c682caa2abd26228c2527f Mon Sep 17 00:00:00 2001 From: SteelSlayer Date: Wed, 27 May 2020 18:11:40 -0500 Subject: [PATCH 03/61] guardian coms fix --- .../gamemodes/miniantags/guardian/guardian.dm | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index 126587a0c97..850c6ef57bd 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -182,15 +182,18 @@ input = stripped_input(src, "Please enter a message to tell your summoner.", "Guardian", "") else input = message - if(!input) return + if(!input) + return - for(var/mob/M in GLOB.mob_list) - if(M == summoner) - to_chat(M, "[src]: [input]") - log_say("(GUARDIAN to [key_name(M)]) [input]", src) - else if(M in GLOB.dead_mob_list && M.client && M.stat == DEAD && !isnewplayer(M)) - to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]") + // Show the message to the host and to the guardian. + to_chat(summoner, "[src]: [input]") to_chat(src, "[src]: [input]") + log_say("(GUARDIAN to [key_name(summoner)]) [input]", src) + + // Show the message to any ghosts/dead players. + for(var/mob/M in GLOB.dead_mob_list) + if(M && M.client && M.stat == DEAD && !isnewplayer(M)) + to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]") //override set to true if message should be passed through instead of going to host communication /mob/living/simple_animal/hostile/guardian/say(message, override = FALSE) @@ -208,18 +211,23 @@ set category = "Guardian" set desc = "Communicate telepathically with your guardian." var/input = stripped_input(src, "Please enter a message to tell your guardian.", "Message", "") - if(!input) return + if(!input) + return - for(var/mob/M in GLOB.mob_list) - if(istype(M, /mob/living/simple_animal/hostile/guardian)) - var/mob/living/simple_animal/hostile/guardian/G = M - if(G.summoner == src) - to_chat(G, "[src]: [input]") - log_say("(GUARDIAN to [key_name(G)]) [input]", src) + // Find the guardian in our host's contents. + var/mob/living/simple_animal/hostile/guardian/G = locate() in contents + if(!G) + return - else if(M in GLOB.dead_mob_list && M.client && M.stat == DEAD && !isnewplayer(M)) - to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]") + // Show the message to our guardian and to host. + to_chat(G, "[src]: [input]") to_chat(src, "[src]: [input]") + log_say("(GUARDIAN to [key_name(G)]) [input]", src) + + // Show the message to any ghosts/dead players. + for(var/mob/M in GLOB.dead_mob_list) + if(M && M.client && M.stat == DEAD && !isnewplayer(M)) + to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]") /mob/living/proc/guardian_recall() set name = "Recall Guardian" From dd3749f75ceca2ae909d924627f7e4aa44356003 Mon Sep 17 00:00:00 2001 From: SteelSlayer Date: Thu, 28 May 2020 13:34:58 -0500 Subject: [PATCH 04/61] say logs --- code/game/gamemodes/miniantags/guardian/guardian.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index 850c6ef57bd..7c7f7a9f694 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -189,6 +189,7 @@ to_chat(summoner, "[src]: [input]") to_chat(src, "[src]: [input]") log_say("(GUARDIAN to [key_name(summoner)]) [input]", src) + create_log(SAY_LOG, "GUARDIAN to HOST: [input]", summoner) // Show the message to any ghosts/dead players. for(var/mob/M in GLOB.dead_mob_list) @@ -223,6 +224,7 @@ to_chat(G, "[src]: [input]") to_chat(src, "[src]: [input]") log_say("(GUARDIAN to [key_name(G)]) [input]", src) + create_log(SAY_LOG, "HOST to GUARDIAN: [input]", G) // Show the message to any ghosts/dead players. for(var/mob/M in GLOB.dead_mob_list) From 645dfe20520bf7398fc8601a246f6a43be62466a Mon Sep 17 00:00:00 2001 From: trololiver112 <59520813+trololiver112@users.noreply.github.com> Date: Fri, 29 May 2020 23:52:19 +0200 Subject: [PATCH 05/61] Fixes the Changeling tentacle grab logging --- code/game/gamemodes/changeling/powers/mutations.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index d225ac6886a..707f3d57573 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -321,7 +321,7 @@ if(INTENT_GRAB) C.visible_message("[L] is grabbed by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!") - add_attack_logs(src, C, "[src] has grabbed [C] and pulled them towards [H] with a tentacle") + add_attack_logs(H, C, "[H] grabbed [C] with a changeling tentacle") C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(H, /mob/proc/tentacle_grab, C)) return 1 From f6ea3204fd925d7a9b15c2ef8d50ccf06a42124d Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Thu, 4 Jun 2020 22:00:05 -0400 Subject: [PATCH 06/61] Hierophant Buff--Staff Nerf --- code/modules/mining/lavaland/loot/hierophant_loot.dm | 2 +- .../mob/living/simple_animal/hostile/megafauna/hierophant.dm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/mining/lavaland/loot/hierophant_loot.dm b/code/modules/mining/lavaland/loot/hierophant_loot.dm index a3f6e738380..fc81e6399ae 100644 --- a/code/modules/mining/lavaland/loot/hierophant_loot.dm +++ b/code/modules/mining/lavaland/loot/hierophant_loot.dm @@ -93,7 +93,7 @@ blast_range = initial(blast_range) if(isliving(user)) var/mob/living/L = user - var/health_percent = L.health / L.maxHealth + var/health_percent = max(L.health / L.maxHealth, 0) // Don't go negative chaser_cooldown += round(health_percent * 20) //two tenths of a second for each missing 10% of health cooldown_time += round(health_percent * 10) //one tenth of a second for each missing 10% of health chaser_speed = max(chaser_speed + health_percent, 0.5) //one tenth of a second faster for each missing 10% of health diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 716f5436223..a4a3481d61b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -452,6 +452,7 @@ Difficulty: Hard else burst_range = 3 INVOKE_ASYNC(src, .proc/burst, get_turf(src), 0.25) //melee attacks on living mobs cause it to release a fast burst if on cooldown + OpenFire() else devour(L) else From 3b4bda996a431bb787e7675241f7e11f7847684c Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Sat, 6 Jun 2020 19:59:04 +0100 Subject: [PATCH 07/61] Re-adds NTTC filtering --- code/game/machinery/tcomms/_base.dm | 2 ++ code/game/machinery/tcomms/core.dm | 37 +++++++++++++++++++++++- code/game/machinery/tcomms/nttc.dm | 7 +++++ nano/templates/tcomms_core.tmpl | 44 +++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/tcomms/_base.dm b/code/game/machinery/tcomms/_base.dm index a857afcef89..7fc2ddae23b 100644 --- a/code/game/machinery/tcomms/_base.dm +++ b/code/game/machinery/tcomms/_base.dm @@ -171,6 +171,8 @@ GLOBAL_LIST_EMPTY(tcomms_machines) var/vname /// List of all channels this can be sent or recieved on var/list/zlevels = list() + /// Should this signal be re-broadcasted (Can be modified by NTTC, defaults to TRUE) + var/pass = TRUE /** * Destructor for the TCM datum. diff --git a/code/game/machinery/tcomms/core.dm b/code/game/machinery/tcomms/core.dm index 9e638913f9d..3fdae14746f 100644 --- a/code/game/machinery/tcomms/core.dm +++ b/code/game/machinery/tcomms/core.dm @@ -1,5 +1,6 @@ #define UI_TAB_CONFIG "CONFIG" #define UI_TAB_LINKS "LINKS" +#define UI_TAB_FILTER "FILTER" /** * # Telecommunications Core @@ -81,6 +82,11 @@ // Now we can run NTTC tcm = nttc.modify_message(tcm) + // If the signal shouldnt be broadcast, dont broadcast it + if(!tcm.pass) + // We still return TRUE here because the signal was handled, even though we didnt broadcast + return TRUE + // Now we generate the list of where that signal should go to tcm.zlevels = reachable_zlevels tcm.zlevels |= tcm.source_level @@ -168,6 +174,9 @@ data["entries"] += list(list("addr" = "\ref[R]", "net_id" = R.network_id, "sector" = R.loc.z, "status" = status, "status_color" = status_color)) // End the shit + if(ui_tab == UI_TAB_FILTER) + data["filtered_users"] = nttc.filtering + return data /obj/machinery/tcomms/core/Topic(href, href_list) @@ -177,7 +186,7 @@ if(href_list["tab"]) // Make sure its a valid tab - if(href_list["tab"] in list(UI_TAB_CONFIG, UI_TAB_LINKS)) + if(href_list["tab"] in list(UI_TAB_CONFIG, UI_TAB_LINKS, UI_TAB_FILTER)) ui_tab = href_list["tab"] // Check if they did a href, but only for that current tab @@ -257,9 +266,35 @@ to_chat(usr, "Successfully changed password from [link_password] to [new_password].") link_password = new_password + if(ui_tab == UI_TAB_FILTER) + if(href_list["add_filter"]) + // This is a stripped input because I did NOT come this far for this system to be abused by HTML injection + var/name_to_add = stripped_input(usr, "Enter a name to add to the filtering list", "Name Entry") + if(name_to_add == "") + return + if(name_to_add in nttc.filtering) + to_chat(usr, "ERROR: User already in filtering list.") + else + nttc.filtering |= name_to_add + log_action(usr, "has added [name_to_add] to the NTTC filter list on core with ID [network_id]", TRUE) + to_chat(usr, "Successfully added [name_to_add] to the NTTC filtering list.") + + + if(href_list["remove_filter"]) + var/name_to_remove = href_list["remove_filter"] + if(!(name_to_remove in nttc.filtering)) + to_chat(usr, "ERROR: Name does not exist in filter list. Please file an issue report.") + else + var/confirm = alert(usr, "Are you sure you want to remove [name_to_remove] from the filtering list?", "Confirm Removal", "Yes", "No") + if(confirm == "Yes") + nttc.filtering -= name_to_remove + log_action(usr, "has removed [name_to_remove] from the NTTC filter list on core with ID [network_id]", TRUE) + to_chat(usr, "Successfully removed [name_to_remove] from the NTTC filtering list.") + // Hack to speed update the nanoUI SSnanoui.update_uis(src) #undef UI_TAB_CONFIG #undef UI_TAB_LINKS +#undef UI_TAB_FILTER diff --git a/code/game/machinery/tcomms/nttc.dm b/code/game/machinery/tcomms/nttc.dm index 6ee158c6cc0..14e932dcf7f 100644 --- a/code/game/machinery/tcomms/nttc.dm +++ b/code/game/machinery/tcomms/nttc.dm @@ -153,6 +153,10 @@ var/list/job_card_styles = list( JOB_STYLE_1, JOB_STYLE_2, JOB_STYLE_3, JOB_STYLE_4 ) + + // List of people who will get blocked out of comms + var/list/filtering = list() + // Used to determine what languages are allowable for conversion. Generated during runtime. var/list/valid_languages = list("--DISABLE--") @@ -220,6 +224,9 @@ // Primary signal modification. This is where all of the variables behavior are actually implemented. /datum/nttc_configuration/proc/modify_message(datum/tcomms_message/tcm) + // Check if they should be blacklisted right off the bat. We can save CPU if the message wont even be processed + if(tcm.sender_name in filtering) + tcm.pass = FALSE // All job and coloring shit if(toggle_job_color || toggle_name_color) var/job = tcm.sender_job diff --git a/nano/templates/tcomms_core.tmpl b/nano/templates/tcomms_core.tmpl index 028f087aec8..bc083e657a7 100644 --- a/nano/templates/tcomms_core.tmpl +++ b/nano/templates/tcomms_core.tmpl @@ -1,5 +1,6 @@ {{:helper.link('Device Configuration', 'wrench', {'tab' : "CONFIG"}, data.tab == "CONFIG" ? 'selected' : '')}} {{:helper.link('Device Links', 'link', {'tab' : "LINKS"}, data.tab == "LINKS" ? 'selected' : '')}} +{{:helper.link('User Filtering', 'user-times', {'tab' : "FILTER"}, data.tab == "FILTER" ? 'selected' : '')}} {{if data.tab == "CONFIG"}}

Core Configuration

@@ -136,4 +137,47 @@ {{/for}} +{{else data.tab == "FILTER"}} + +

Filtering List

+
+
+ {{:helper.link('Add User', 'plus', {'add_filter': 1})}} +
+
+
+ + + + + + + + + + + + + {{for data.filtered_users}} + + + + + {{/for}} + +
NameRemove
{{:value}}{{:helper.link('Remove', 'times', {'remove_filter' : value}, null, 'infoButton')}}
{{/if}} From f6a3a44cb3cad69312b246fc438ad18b5697e482 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Mon, 8 Jun 2020 19:38:12 -0400 Subject: [PATCH 08/61] Adds Swarming Component --- code/datums/components/swarming.dm | 55 +++++++++++++++++++ code/game/atoms_movable.dm | 11 ++-- code/game/mecha/mecha.dm | 2 +- code/game/objects/effects/spiders.dm | 1 + .../carbon/alien/humanoid/humanoid_defense.dm | 2 +- .../carbon/alien/larva/larva_defense.dm | 2 +- code/modules/mob/living/living.dm | 6 +- .../living/simple_animal/animal_defense.dm | 2 +- .../mob/living/simple_animal/hostile/bees.dm | 1 + .../simple_animal/hostile/mining/hivelord.dm | 1 + .../simple_animal/hostile/spaceworms.dm | 2 +- .../living/simple_animal/hostile/syndicate.dm | 7 ++- .../living/simple_animal/posessed_object.dm | 2 +- paradise.dme | 1 + 14 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 code/datums/components/swarming.dm diff --git a/code/datums/components/swarming.dm b/code/datums/components/swarming.dm new file mode 100644 index 00000000000..c9d20f1f702 --- /dev/null +++ b/code/datums/components/swarming.dm @@ -0,0 +1,55 @@ +/datum/component/swarming + var/offset_x = 0 + var/offset_y = 0 + var/is_swarming = FALSE + var/list/swarm_members = list() + +/datum/component/swarming/Initialize(max_x = 24, max_y = 24) + if(!ismovableatom(parent)) + return COMPONENT_INCOMPATIBLE + offset_x = rand(-max_x, max_x) + offset_y = rand(-max_y, max_y) + + RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/join_swarm) + RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/leave_swarm) + +/datum/component/swarming/Destroy() + for(var/other in swarm_members) + var/datum/component/swarming/other_swarm = other + other_swarm.swarm_members -= src + if(!other_swarm.swarm_members.len) + other_swarm.unswarm() + swarm_members = null + return ..() + +/datum/component/swarming/proc/join_swarm(datum/source, atom/movable/AM) + var/datum/component/swarming/other_swarm = AM.GetComponent(/datum/component/swarming) + if(!other_swarm) + return + swarm() + swarm_members |= other_swarm + other_swarm.swarm() + other_swarm.swarm_members |= src + +/datum/component/swarming/proc/leave_swarm(datum/source, atom/movable/AM) + var/datum/component/swarming/other_swarm = AM.GetComponent(/datum/component/swarming) + if(!other_swarm || !(other_swarm in swarm_members)) + return + swarm_members -= other_swarm + if(!swarm_members.len) + unswarm() + other_swarm.swarm_members -= src + if(!other_swarm.swarm_members.len) + other_swarm.unswarm() + +/datum/component/swarming/proc/swarm() + var/atom/movable/owner = parent + if(!is_swarming) + is_swarming = TRUE + animate(owner, pixel_x = owner.pixel_x + offset_x, pixel_y = owner.pixel_y + offset_y, time = 2) + +/datum/component/swarming/proc/unswarm() + var/atom/movable/owner = parent + if(is_swarming) + animate(owner, pixel_x = owner.pixel_x - offset_x, pixel_y = owner.pixel_y - offset_y, time = 2) + is_swarming = FALSE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index ac77d3d4553..9f2a0e09aee 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -233,6 +233,9 @@ SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) SEND_SIGNAL(AM, COMSIG_CROSSED_MOVABLE, src) +/atom/movable/Uncrossed(atom/movable/AM) + SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM) + /atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump(). if(A && yes) SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A) @@ -501,7 +504,7 @@ 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) +/atom/movable/proc/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!no_effect && (visual_effect_icon || used_item)) do_item_attack_animation(A, visual_effect_icon, used_item) @@ -509,10 +512,6 @@ 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 @@ -525,7 +524,7 @@ 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) + animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, time = 2) /atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item) var/image/I diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 610436406d8..4234064874a 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1454,7 +1454,7 @@ ..() -/obj/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y) +/obj/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!no_effect) if(selected) used_item = selected diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index d97663759af..7af5d7a998f 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -98,6 +98,7 @@ pixel_x = rand(6,-6) pixel_y = rand(6,-6) START_PROCESSING(SSobj, src) + AddComponent(/datum/component/swarming) /obj/structure/spider/spiderling/Destroy() STOP_PROCESSING(SSobj, src) 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 e7f783acd72..3174879caac 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -55,7 +55,7 @@ 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) +/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!no_effect && !visual_effect_icon) visual_effect_icon = ATTACK_EFFECT_CLAW ..() 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 69e12b6ae19..d13dab884b2 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm @@ -31,7 +31,7 @@ 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) +/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!no_effect && !visual_effect_icon) visual_effect_icon = ATTACK_EFFECT_BITE ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index dfa4bb61c9d..9f768ffc76d 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -740,7 +740,8 @@ clear_alert("weightless") else throw_alert("weightless", /obj/screen/alert/weightless) - float(!has_gravity) + if(!flying) + float(!has_gravity) /mob/living/proc/float(on) if(throwing) @@ -825,8 +826,7 @@ spawn_dust() gib() -/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) +/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!used_item) used_item = get_active_hand() ..() diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 2cfc5e746dc..b42f3275997 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -118,7 +118,7 @@ /mob/living/simple_animal/blob_act(obj/structure/blob/B) adjustBruteLoss(20) -/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) +/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect) if(!no_effect && !visual_effect_icon && melee_damage_upper) if(melee_damage_upper < 10) visual_effect_icon = ATTACK_EFFECT_PUNCH diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index c1e7548d9a3..3276416fe7f 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -60,6 +60,7 @@ /mob/living/simple_animal/hostile/poison/bees/New() ..() generate_bee_visuals() + AddComponent(/datum/component/swarming) /mob/living/simple_animal/hostile/poison/bees/Destroy() beegent = null diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index ca9b632e06a..a5248e98bb6 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -90,6 +90,7 @@ /mob/living/simple_animal/hostile/asteroid/hivelordbrood/Initialize(mapload) . = ..() addtimer(CALLBACK(src, .proc/death), 100) + AddComponent(/datum/component/swarming) /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood diff --git a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm index fd569984920..07f26031ed5 100644 --- a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm +++ b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm @@ -335,7 +335,7 @@ //Jiggle the whole worm forwards towards the next segment -/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) +/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect) ..() if(previousWorm) previousWorm.do_attack_animation(src) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 23970e88826..6f40dfe2a3f 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -349,7 +349,8 @@ icon = 'icons/mob/critter.dmi' icon_state = "viscerator_attack" icon_living = "viscerator_attack" - pass_flags = PASSTABLE + pass_flags = PASSTABLE | PASSMOB + a_intent = INTENT_HARM health = 15 maxHealth = 15 obj_damage = 0 @@ -365,3 +366,7 @@ gold_core_spawnable = HOSTILE_SPAWN del_on_death = 1 deathmessage = "is smashed into pieces!" + +/mob/living/simple_animal/hostile/viscerator/Initialize(mapload) + . = ..() + AddComponent(/datum/component/swarming) diff --git a/code/modules/mob/living/simple_animal/posessed_object.dm b/code/modules/mob/living/simple_animal/posessed_object.dm index bde995d8edb..c3cb61d5970 100644 --- a/code/modules/mob/living/simple_animal/posessed_object.dm +++ b/code/modules/mob/living/simple_animal/posessed_object.dm @@ -27,7 +27,7 @@ . += "[src] appears to be having trouble staying afloat!" -/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) +/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect) ..() animate_ghostly_presence(src, -1, 20, 1) // Restart the floating animation after the attack animation, as it will be cancelled. diff --git a/paradise.dme b/paradise.dme index c137faf236f..7393d7c6bb7 100644 --- a/paradise.dme +++ b/paradise.dme @@ -302,6 +302,7 @@ #include "code\datums\components\paintable.dm" #include "code\datums\components\spawner.dm" #include "code\datums\components\squeak.dm" +#include "code\datums\components\swarming.dm" #include "code\datums\components\waddling.dm" #include "code\datums\diseases\_disease.dm" #include "code\datums\diseases\_MobProcs.dm" From 07f085a6c48b5ef94ac8d65154dbb6ddaf500b04 Mon Sep 17 00:00:00 2001 From: Moku Moku <66841525+Moku-Mok@users.noreply.github.com> Date: Sat, 13 Jun 2020 15:19:59 +0200 Subject: [PATCH 09/61] Correcting Welder Messages on the Field Generator. This simply swaps WELD and SLICE messages that were previously incorrect to instead reflect as to what they should actually do. Hopefully this can clear up some confusion for players, aswell as making it just look cleaner. --- code/modules/power/singularity/field_generator.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 62f2ed36065..b70a79106be 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -113,15 +113,15 @@ field_generator power level display if(!I.tool_use_check(user, 0)) return if(state == FG_SECURED) - WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE - else if(state == FG_WELDED) WELDER_ATTEMPT_FLOOR_WELD_MESSAGE + else if(state == FG_WELDED) + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE if(I.use_tool(src, user, 20, volume = I.tool_volume)) if(state == FG_SECURED) - WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + WELDER_FLOOR_WELD_SUCCESS_MESSAGE state = FG_WELDED else if(state == FG_WELDED) - WELDER_FLOOR_WELD_SUCCESS_MESSAGE + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE state = FG_SECURED /obj/machinery/field/generator/emp_act() From 960e6e3255b110a42c96ea9e7148ecba90ff8b13 Mon Sep 17 00:00:00 2001 From: Luca Date: Sun, 14 Jun 2020 02:56:49 +1000 Subject: [PATCH 10/61] Changed CRLF to LF in Toy.dmi --- code/game/objects/items/toys.dm | 3596 +++++++++++++++---------------- 1 file changed, 1798 insertions(+), 1798 deletions(-) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index cbfb61e0dde..85d664d4e08 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1,1798 +1,1798 @@ -/* Toys! - * Contains: - * Balloons - * Fake telebeacon - * Fake singularity - * Toy swords - * Toy mechs - * Snap pops - * Water flower - * Toy Nuke - * Card Deck - * Therapy dolls - * Toddler doll - * Inflatable duck - * Foam armblade - * Mini Gibber - * Toy xeno - * Toy chainsaws - * Action Figures - */ - - -/obj/item/toy - throwforce = 0 - throw_speed = 4 - throw_range = 20 - force = 0 - - -/* - * Balloons - */ -/obj/item/toy/balloon - name = "water balloon" - desc = "A translucent balloon. There's nothing in it." - icon = 'icons/obj/toy.dmi' - icon_state = "waterballoon-e" - item_state = "balloon-empty" - -/obj/item/toy/balloon/New() - ..() - create_reagents(10) - -/obj/item/toy/balloon/attack(mob/living/carbon/human/M as mob, mob/user as mob) - return - -/obj/item/toy/balloon/afterattack(atom/A, mob/user, proximity) - if(!proximity) - return - if(istype(A, /obj/structure/reagent_dispensers)) - var/obj/structure/reagent_dispensers/RD = A - if(RD.reagents.total_volume <= 0) - to_chat(user, "[RD] is empty.") - else if(reagents.total_volume >= 10) - to_chat(user, "[src] is full.") - else - A.reagents.trans_to(src, 10) - to_chat(user, "You fill the balloon with the contents of [A].") - desc = "A translucent balloon with some form of liquid sloshing around in it." - update_icon() - -/obj/item/toy/balloon/wash(mob/user, atom/source) - if(reagents.total_volume < 10) - reagents.add_reagent("water", min(10-reagents.total_volume, 10)) - to_chat(user, "You fill the balloon from the [source].") - desc = "A translucent balloon with some form of liquid sloshing around in it." - update_icon() - return - -/obj/item/toy/balloon/attackby(obj/O as obj, mob/user as mob, params) - if(istype(O, /obj/item/reagent_containers/glass) || istype(O, /obj/item/reagent_containers/food/drinks/drinkingglass)) - if(O.reagents) - if(O.reagents.total_volume < 1) - to_chat(user, "The [O] is empty.") - else if(O.reagents.total_volume >= 1) - if(O.reagents.has_reagent("facid", 1)) - to_chat(user, "The acid chews through the balloon!") - O.reagents.reaction(user) - qdel(src) - else - desc = "A translucent balloon with some form of liquid sloshing around in it." - to_chat(user, "You fill the balloon with the contents of [O].") - O.reagents.trans_to(src, 10) - update_icon() - return - -/obj/item/toy/balloon/throw_impact(atom/hit_atom) - if(reagents.total_volume >= 1) - visible_message("The [src] bursts!","You hear a pop and a splash.") - reagents.reaction(get_turf(hit_atom)) - for(var/atom/A in get_turf(hit_atom)) - reagents.reaction(A) - icon_state = "burst" - spawn(5) - if(src) - qdel(src) - return - -/obj/item/toy/balloon/update_icon() - if(src.reagents.total_volume >= 1) - icon_state = "waterballoon" - item_state = "balloon" - else - icon_state = "waterballoon-e" - item_state = "balloon-empty" - -/obj/item/toy/syndicateballoon - name = "syndicate balloon" - desc = "There is a tag on the back that reads \"FUK NT!11!\"." - throwforce = 0 - throw_speed = 4 - throw_range = 20 - force = 0 - icon_state = "syndballoon" - item_state = "syndballoon" - w_class = WEIGHT_CLASS_BULKY - var/lastused = null - -/obj/item/toy/syndicateballoon/attack_self(mob/user) - if(world.time - lastused < CLICK_CD_MELEE) - return - var/playverb = pick("bat [src]", "tug on [src]'s string", "play with [src]") - user.visible_message("[user] plays with [src].", "You [playverb].") - lastused = world.time - -/* - * Fake telebeacon - */ -/obj/item/toy/blink - name = "electronic blink toy game" - desc = "Blink. Blink. Blink. Ages 8 and up." - icon = 'icons/obj/radio.dmi' - icon_state = "beacon" - item_state = "signaler" - -/* - * Fake singularity - */ -/obj/item/toy/spinningtoy - name = "Gravitational Singularity" - desc = "\"Singulo\" brand spinning toy." - icon = 'icons/obj/singularity.dmi' - icon_state = "singularity_s1" - -/* - * Toy swords - */ -/obj/item/toy/sword - name = "toy sword" - desc = "A cheap, plastic replica of an energy sword. Realistic sounds! Ages 8 and up." - icon_state = "sword0" - item_state = "sword0" - var/active = FALSE - w_class = WEIGHT_CLASS_SMALL - attack_verb = list("attacked", "struck", "hit") - -/obj/item/toy/sword/attack_self(mob/user) - active = !active - if(active) - to_chat(user, "You extend the plastic blade with a quick flick of your wrist.") - playsound(user, 'sound/weapons/saberon.ogg', 20, 1) - icon_state = "swordblue" - item_state = "swordblue" - w_class = WEIGHT_CLASS_BULKY - else - to_chat(user, "You push the plastic blade back down into the handle.") - playsound(user, 'sound/weapons/saberoff.ogg', 20, 1) - icon_state = "sword0" - item_state = "sword0" - w_class = WEIGHT_CLASS_SMALL - - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_l_hand() - H.update_inv_r_hand() - add_fingerprint(user) - return - -// Copied from /obj/item/melee/energy/sword/attackby -/obj/item/toy/sword/attackby(obj/item/W, mob/living/user, params) - ..() - if(istype(W, /obj/item/toy/sword)) - if(W == src) - to_chat(user, "You try to attach the end of the plastic sword to... itself. You're not very smart, are you?") - if(ishuman(user)) - user.adjustBrainLoss(10) - else if((W.flags & NODROP) || (flags & NODROP)) - to_chat(user, "\the [flags & NODROP ? src : W] is stuck to your hand, you can't attach it to \the [flags & NODROP ? W : src]!") - else - to_chat(user, "You attach the ends of the two plastic swords, making a single double-bladed toy! You're fake-cool.") - new /obj/item/twohanded/dualsaber/toy(user.loc) - user.unEquip(W) - user.unEquip(src) - qdel(W) - qdel(src) - -/* - * Subtype of Double-Bladed Energy Swords - */ -/obj/item/twohanded/dualsaber/toy - name = "double-bladed toy sword" - desc = "A cheap, plastic replica of TWO energy swords. Double the fun!" - force = 0 - throwforce = 0 - throw_speed = 3 - throw_range = 5 - force_unwielded = 0 - force_wielded = 0 - origin_tech = null - attack_verb = list("attacked", "struck", "hit") - brightness_on = 0 - sharp_when_wielded = FALSE // It's a toy - -/obj/item/twohanded/dualsaber/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - return 0 - -/obj/item/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles - return 0 - -/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") - hitsound = 'sound/weapons/bladeslice.ogg' - -/obj/item/toy/katana/suicide_act(mob/user) - 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 - - -/* - * Snap pops viral shit - */ -/obj/item/toy/snappop/virus - name = "unstable goo" - desc = "Your palm is oozing this stuff!" - icon = 'icons/mob/slimes.dmi' - icon_state = "red slime extract" - throwforce = 5.0 - throw_speed = 10 - throw_range = 30 - w_class = WEIGHT_CLASS_TINY - - -/obj/item/toy/snappop/virus/throw_impact(atom/hit_atom) - ..() - do_sparks(3, 1, src) - new /obj/effect/decal/cleanable/ash(src.loc) - visible_message("The [name] explodes!","You hear a bang!") - playsound(src, 'sound/effects/snap.ogg', 50, 1) - qdel(src) - -/* - * Snap pops - */ -/obj/item/toy/snappop - name = "snap pop" - desc = "Wow!" - icon = 'icons/obj/toy.dmi' - icon_state = "snappop" - w_class = WEIGHT_CLASS_TINY - var/ash_type = /obj/effect/decal/cleanable/ash - -/obj/item/toy/snappop/proc/pop_burst(var/n=3, var/c=1) - do_sparks(n, c, src) - new ash_type(loc) - visible_message("[src] explodes!", - "You hear a snap!") - playsound(src, 'sound/effects/snap.ogg', 50, 1) - qdel(src) - -/obj/item/toy/snappop/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE) - ..() - pop_burst() - -/obj/item/toy/snappop/throw_impact(atom/hit_atom) - ..() - pop_burst() - -/obj/item/toy/snappop/Crossed(H as mob|obj, oldloc) - if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off - var/mob/living/carbon/M = H - if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN) - to_chat(M, "You step on the snap pop!") - pop_burst(2, 0) - -/obj/item/toy/snappop/phoenix - name = "phoenix snap pop" - desc = "Wow! And wow! And wow!" - ash_type = /obj/effect/decal/cleanable/ash/snappop_phoenix - -/obj/effect/decal/cleanable/ash/snappop_phoenix - var/respawn_time = 300 - -/obj/effect/decal/cleanable/ash/snappop_phoenix/Initialize(mapload) - . = ..() - addtimer(CALLBACK(src, .proc/respawn), respawn_time) - -/obj/effect/decal/cleanable/ash/snappop_phoenix/proc/respawn() - new /obj/item/toy/snappop/phoenix(get_turf(src)) - qdel(src) - - -/* - * Mech prizes - */ -/obj/item/toy/prize - icon = 'icons/obj/toy.dmi' - icon_state = "ripleytoy" - var/cooldown = 0 - -//all credit to skasi for toy mech fun ideas -/obj/item/toy/prize/attack_self(mob/user as mob) - if(cooldown < world.time - 8) - to_chat(user, "You play with [src].") - playsound(user, 'sound/mecha/mechstep.ogg', 20, 1) - cooldown = world.time - -/obj/item/toy/prize/attack_hand(mob/user as mob) - if(loc == user) - if(cooldown < world.time - 8) - to_chat(user, "You play with [src].") - playsound(user, 'sound/mecha/mechturn.ogg', 20, 1) - cooldown = world.time - return - ..() - -/obj/random/mech - name = "Random Mech Prize" - desc = "This is a random prize" - icon = 'icons/obj/toy.dmi' - icon_state = "ripleytoy" - -/obj/random/mech/item_to_spawn() - return pick(subtypesof(/obj/item/toy/prize)) //exclude the base type. - -/obj/item/toy/prize/ripley - name = "toy ripley" - desc = "Mini-Mecha action figure! Collect them all! 1/11." - -/obj/item/toy/prize/fireripley - name = "toy firefighting ripley" - desc = "Mini-Mecha action figure! Collect them all! 2/11." - icon_state = "fireripleytoy" - -/obj/item/toy/prize/deathripley - name = "toy deathsquad ripley" - desc = "Mini-Mecha action figure! Collect them all! 3/11." - icon_state = "deathripleytoy" - -/obj/item/toy/prize/gygax - name = "toy gygax" - 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." - icon_state = "durandprize" - -/obj/item/toy/prize/honk - name = "toy H.O.N.K." - desc = "Mini-Mecha action figure! Collect them all! 6/11." - icon_state = "honkprize" - -/obj/item/toy/prize/marauder - name = "toy marauder" - desc = "Mini-Mecha action figure! Collect them all! 7/11." - icon_state = "marauderprize" - -/obj/item/toy/prize/seraph - name = "toy seraph" - desc = "Mini-Mecha action figure! Collect them all! 8/11." - icon_state = "seraphprize" - -/obj/item/toy/prize/mauler - name = "toy mauler" - desc = "Mini-Mecha action figure! Collect them all! 9/11." - icon_state = "maulerprize" - -/obj/item/toy/prize/odysseus - name = "toy odysseus" - desc = "Mini-Mecha action figure! Collect them all! 10/11." - icon_state = "odysseusprize" - -/obj/item/toy/prize/phazon - name = "toy phazon" - desc = "Mini-Mecha action figure! Collect them all! 11/11." - icon_state = "phazonprize" - - - -/* -|| A Deck of Cards for playing various games of chance || -*/ - - - -obj/item/toy/cards - resistance_flags = FLAMMABLE - max_integrity = 50 - var/parentdeck = null - var/deckstyle = "nanotrasen" - var/card_hitsound = null - var/card_force = 0 - var/card_throwforce = 0 - var/card_throw_speed = 4 - var/card_throw_range = 20 - var/list/card_attack_verb = list("attacked") - -obj/item/toy/cards/New() - ..() - -obj/item/toy/cards/proc/apply_card_vars(obj/item/toy/cards/newobj, obj/item/toy/cards/sourceobj) // Applies variables for supporting multiple types of card deck - if(!istype(sourceobj)) - return - -obj/item/toy/cards/deck - name = "deck of cards" - desc = "A deck of space-grade playing cards." - icon = 'icons/obj/toy.dmi' - deckstyle = "nanotrasen" - icon_state = "deck_nanotrasen_full" - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - var/list/cards = list() - -obj/item/toy/cards/deck/New() - ..() - icon_state = "deck_[deckstyle]_full" - for(var/i in 2 to 10) - cards += "[i] of Hearts" - cards += "[i] of Spades" - cards += "[i] of Clubs" - cards += "[i] of Diamonds" - cards += "King of Hearts" - cards += "King of Spades" - cards += "King of Clubs" - cards += "King of Diamonds" - cards += "Queen of Hearts" - cards += "Queen of Spades" - cards += "Queen of Clubs" - cards += "Queen of Diamonds" - cards += "Jack of Hearts" - cards += "Jack of Spades" - cards += "Jack of Clubs" - cards += "Jack of Diamonds" - cards += "Ace of Hearts" - cards += "Ace of Spades" - 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) - icon_state = "deck_[deckstyle]_empty" - to_chat(user, "There are no more cards to draw.") - return - var/obj/item/toy/cards/singlecard/H = new/obj/item/toy/cards/singlecard(user.loc) - choice = cards[1] - H.cardname = choice - H.parentdeck = src - var/O = src - H.apply_card_vars(H,O) - cards -= choice - 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.") - update_icon() - -obj/item/toy/cards/deck/attack_self(mob/user as mob) - if(cooldown < world.time - 50) - cards = shuffle(cards) - playsound(user, 'sound/items/cardshuffle.ogg', 50, 1) - user.visible_message("[user] shuffles the deck.", "You shuffle the deck.") - cooldown = world.time - -obj/item/toy/cards/deck/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params) - ..() - if(istype(C)) - if(C.parentdeck == src) - if(!user.unEquip(C)) - to_chat(user, "The card is stuck to your hand, you can't add it to the deck!") - return - cards += C.cardname - user.visible_message("[user] adds a card to the bottom of the deck.","You add the card to the bottom of the deck.") - qdel(C) - else - to_chat(user, "You can't mix cards from other decks.") - update_icon() - - -obj/item/toy/cards/deck/attackby(obj/item/toy/cards/cardhand/C, mob/living/user, params) - ..() - if(istype(C)) - if(C.parentdeck == src) - if(!user.unEquip(C)) - 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 [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.") - update_icon() - -obj/item/toy/cards/deck/MouseDrop(atom/over_object) - var/mob/M = usr - if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) - return - if(Adjacent(usr)) - if(over_object == M && loc != M) - M.put_in_hands(src) - to_chat(usr, "You pick up the deck.") - - else if(istype(over_object, /obj/screen)) - switch(over_object.name) - if("l_hand") - if(!remove_item_from_storage(M)) - M.unEquip(src) - M.put_in_l_hand(src) - to_chat(usr, "You pick up the deck.") - if("r_hand") - if(!remove_item_from_storage(M)) - M.unEquip(src) - M.put_in_r_hand(src) - to_chat(usr, "You pick up the deck.") - 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" - desc = "A number of cards not in a deck, customarily held in ones hand." - icon = 'icons/obj/toy.dmi' - icon_state = "nanotrasen_hand2" - w_class = WEIGHT_CLASS_TINY - var/list/currenthand = list() - var/choice = null - - -obj/item/toy/cards/cardhand/attack_self(mob/user as mob) - user.set_machine(src) - interact(user) - -obj/item/toy/cards/cardhand/interact(mob/user) - var/dat = "You have:
" - for(var/t in currenthand) - dat += "A [t].
" - dat += "Which card will you remove next?" - var/datum/browser/popup = new(user, "cardhand", "Hand of Cards", 400, 240) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.set_content(dat) - popup.open() - - -obj/item/toy/cards/cardhand/Topic(href, href_list) - if(..()) - return - if(usr.stat || !ishuman(usr) || !usr.canmove) - return - var/mob/living/carbon/human/cardUser = usr - var/O = src - if(href_list["pick"]) - if(cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) - var/choice = href_list["pick"] - var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc) - currenthand -= choice - C.parentdeck = src.parentdeck - C.cardname = choice - 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 [cardUser.p_their()] hand.", "You take the [C.cardname] from your hand.") - - interact(cardUser) - 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 - N.cardname = src.currenthand[1] - N.apply_card_vars(N,O) - cardUser.unEquip(src) - N.pickup(cardUser) - cardUser.put_in_any_hand_if_possible(N) - to_chat(cardUser, "You also take [currenthand[1]] and hold it.") - cardUser << browse(null, "window=cardhand") - qdel(src) - return - -obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params) - if(istype(C)) - if(C.parentdeck == parentdeck) - currenthand += C.cardname - user.unEquip(C) - user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [C.cardname] to your hand.") - interact(user) - update_icon() - qdel(C) - else - to_chat(user, "You can't mix cards from other decks.") - -obj/item/toy/cards/cardhand/apply_card_vars(obj/item/toy/cards/newobj,obj/item/toy/cards/sourceobj) - ..() - newobj.deckstyle = sourceobj.deckstyle - newobj.icon_state = "[deckstyle]_hand2" // Another dumb hack, without this the hand is invisible (or has the default deckstyle) until another card is added. - newobj.card_hitsound = sourceobj.card_hitsound - newobj.card_force = sourceobj.card_force - newobj.card_throwforce = sourceobj.card_throwforce - newobj.card_throw_speed = sourceobj.card_throw_speed - newobj.card_throw_range = sourceobj.card_throw_range - newobj.card_attack_verb = sourceobj.card_attack_verb - newobj.resistance_flags = sourceobj.resistance_flags - - -obj/item/toy/cards/singlecard - name = "card" - desc = "a card" - icon = 'icons/obj/toy.dmi' - icon_state = "singlecard_nanotrasen_down" - w_class = WEIGHT_CLASS_TINY - var/cardname = null - var/flipped = 0 - pixel_x = -5 - - -obj/item/toy/cards/singlecard/examine(mob/user) - . = ..() - if(get_dist(user, src) <= 0) - 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 [cardUser.p_their()] card.", "The card reads: [src.cardname]") - else - . += "You need to have the card in your hand to check it." - - -obj/item/toy/cards/singlecard/verb/Flip() - set name = "Flip Card" - set category = "Object" - set src in range(1) - if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) - return - if(!flipped) - flipped = 1 - if(cardname) - icon_state = "sc_[cardname]_[deckstyle]" - name = cardname - else - icon_state = "sc_Ace of Spades_[deckstyle]" - name = "What Card" - pixel_x = 5 - else - flipped = 0 - icon_state = "singlecard_down_[deckstyle]" - name = "card" - pixel_x = -5 - -obj/item/toy/cards/singlecard/attackby(obj/item/I, mob/living/user, params) - if(istype(I, /obj/item/toy/cards/singlecard/)) - var/obj/item/toy/cards/singlecard/C = I - if(C.parentdeck == parentdeck) - var/obj/item/toy/cards/cardhand/H = new/obj/item/toy/cards/cardhand(user.loc) - H.currenthand += C.cardname - H.currenthand += cardname - H.parentdeck = C.parentdeck - H.apply_card_vars(H,C) - user.unEquip(C) - H.pickup(user) - user.put_in_active_hand(H) - to_chat(user, "You combine the [C.cardname] and the [cardname] into a hand.") - qdel(C) - qdel(src) - else - to_chat(user, "You can't mix cards from other decks.") - - if(istype(I, /obj/item/toy/cards/cardhand/)) - var/obj/item/toy/cards/cardhand/H = I - if(H.parentdeck == parentdeck) - H.currenthand += cardname - user.unEquip(src) - user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [cardname] to your hand.") - H.interact(user) - 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()) - return - Flip() - -obj/item/toy/cards/singlecard/apply_card_vars(obj/item/toy/cards/singlecard/newobj,obj/item/toy/cards/sourceobj) - ..() - newobj.deckstyle = sourceobj.deckstyle - newobj.icon_state = "singlecard_down_[deckstyle]" // Without this the card is invisible until flipped. It's an ugly hack, but it works. - newobj.card_hitsound = sourceobj.card_hitsound - newobj.hitsound = newobj.card_hitsound - newobj.card_force = sourceobj.card_force - newobj.force = newobj.card_force - newobj.card_throwforce = sourceobj.card_throwforce - newobj.throwforce = newobj.card_throwforce - newobj.card_throw_speed = sourceobj.card_throw_speed - newobj.throw_speed = newobj.card_throw_speed - newobj.card_throw_range = sourceobj.card_throw_range - newobj.throw_range = newobj.card_throw_range - newobj.card_attack_verb = sourceobj.card_attack_verb - newobj.attack_verb = newobj.card_attack_verb - - -/* -|| Syndicate playing cards, for pretending you're Gambit and playing poker for the nuke disk. || -*/ - -obj/item/toy/cards/deck/syndicate - name = "suspicious looking deck of cards" - desc = "A deck of space-grade playing cards. They seem unusually rigid." - deckstyle = "syndicate" - card_hitsound = 'sound/weapons/bladeslice.ogg' - card_force = 5 - card_throwforce = 10 - card_throw_speed = 3 - card_throw_range = 20 - card_attack_verb = list("attacked", "sliced", "diced", "slashed", "cut") - resistance_flags = NONE - -/* -|| Custom card decks || -*/ -obj/item/toy/cards/deck/black - deckstyle = "black" - -obj/item/toy/cards/deck/syndicate/black - deckstyle = "black" - -/obj/item/toy/nuke - name = "\improper Nuclear Fission Explosive toy" - desc = "A plastic model of a Nuclear Fission Explosive." - icon = 'icons/obj/toy.dmi' - icon_state = "nuketoyidle" - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - -/obj/item/toy/nuke/attack_self(mob/user) - if(cooldown < world.time) - cooldown = world.time + 1800 //3 minutes - user.visible_message("[user] presses a button on [src]", "You activate [src], it plays a loud noise!", "You hear the click of a button.") - spawn(5) //gia said so - icon_state = "nuketoy" - playsound(src, 'sound/machines/alarm.ogg', 100, 0, 0) - sleep(135) - icon_state = "nuketoycool" - sleep(cooldown - world.time) - icon_state = "nuketoyidle" - else - var/timeleft = (cooldown - world.time) - to_chat(user, "Nothing happens, and '[round(timeleft/10)]' appears on a small display.") - -/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 - resistance_flags = FLAMMABLE - -/obj/item/toy/therapy/New() - ..() - if(item_color) - name = "[item_color] therapy doll" - desc += " This one is [item_color]." - icon_state = "therapy[item_color]" - -/obj/item/toy/therapy/attack_self(mob/user) - if(cooldown < world.time - 8) - to_chat(user, "You relieve some stress with \the [src].") - playsound(user, 'sound/items/squeaktoy.ogg', 20, 1) - cooldown = world.time - -/obj/random/therapy - name = "Random Therapy Doll" - desc = "This is a random therapy doll." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyred" - -/obj/random/therapy/item_to_spawn() - return pick(subtypesof(/obj/item/toy/therapy)) //exclude the base type. - -/obj/item/toy/therapy/red - item_state = "egg4" // It's the red egg in items_left/righthand - item_color = "red" - -/obj/item/toy/therapy/purple - item_state = "egg1" // It's the magenta egg in items_left/righthand - item_color = "purple" - -/obj/item/toy/therapy/blue - item_state = "egg2" // It's the blue egg in items_left/righthand - item_color = "blue" - -/obj/item/toy/therapy/yellow - item_state = "egg5" // It's the yellow egg in items_left/righthand - item_color = "yellow" - -/obj/item/toy/therapy/orange - item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless - item_color = "orange" - -/obj/item/toy/therapy/green - item_state = "egg3" // It's the green egg in items_left/righthand - item_color = "green" - -/obj/item/toddler - icon_state = "toddler" - name = "toddler" - desc = "This baby looks almost real. Wait, did it just burp?" - force = 5 - w_class = WEIGHT_CLASS_BULKY - slot_flags = SLOT_BACK - - -//This should really be somewhere else but I don't know where. w/e - -/obj/item/inflatable_duck - name = "inflatable duck" - desc = "No bother to sink or swim when you can just float!" - icon_state = "inflatable" - item_state = "inflatable" - icon = 'icons/obj/clothing/belts.dmi' - slot_flags = SLOT_BELT - -/* - * Fake meteor - */ - -/obj/item/toy/minimeteor - name = "Mini-Meteor" - desc = "Relive the excitement of a meteor shower! SweetMeat-eor. Co is not responsible for any injuries, headaches or hearing loss caused by Mini-Meteor." - icon = 'icons/obj/toy.dmi' - icon_state = "minimeteor" - w_class = WEIGHT_CLASS_SMALL - -/obj/item/toy/minimeteor/throw_impact(atom/hit_atom) - ..() - playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) - for(var/mob/M in range(10, src)) - if(!M.stat && !istype(M, /mob/living/silicon/ai))\ - shake_camera(M, 3, 1) - qdel(src) - -/* - * Carp plushie - */ - -/obj/item/toy/carpplushie - name = "space carp plushie" - desc = "An adorable stuffed toy that resembles a space carp." - icon = 'icons/obj/toy.dmi' - icon_state = "carpplushie" - attack_verb = list("bitten", "eaten", "fin slapped") - var/bitesound = 'sound/weapons/bite.ogg' - resistance_flags = FLAMMABLE - -// Attack mob -/obj/item/toy/carpplushie/attack(mob/M as mob, mob/user as mob) - playsound(loc, bitesound, 20, 1) // Play bite sound in local area - return ..() - -// Attack self -/obj/item/toy/carpplushie/attack_self(mob/user as mob) - playsound(src.loc, bitesound, 20, 1) - return ..() - - -/obj/random/carp_plushie - name = "Random Carp Plushie" - desc = "This is a random plushie" - icon = 'icons/obj/toy.dmi' - icon_state = "carpplushie" - -/obj/random/carp_plushie/item_to_spawn() - return pick(typesof(/obj/item/toy/carpplushie)) //can pick any carp plushie, even the original. - -/obj/item/toy/carpplushie/ice - icon_state = "icecarp" - -/obj/item/toy/carpplushie/silent - icon_state = "silentcarp" - -/obj/item/toy/carpplushie/electric - icon_state = "electriccarp" - -/obj/item/toy/carpplushie/gold - icon_state = "goldcarp" - -/obj/item/toy/carpplushie/toxin - icon_state = "toxincarp" - -/obj/item/toy/carpplushie/dragon - icon_state = "dragoncarp" - -/obj/item/toy/carpplushie/pink - icon_state = "pinkcarp" - -/obj/item/toy/carpplushie/candy - icon_state = "candycarp" - -/obj/item/toy/carpplushie/nebula - icon_state = "nebulacarp" - -/obj/item/toy/carpplushie/void - icon_state = "voidcarp" - -/* - * Plushie - */ - - -/obj/item/toy/plushie - name = "plushie" - desc = "An adorable, soft, and cuddly plushie." - icon = 'icons/obj/toy.dmi' - var/poof_sound = 'sound/weapons/thudswoosh.ogg' - attack_verb = list("poofed", "bopped", "whapped","cuddled","fluffed") - resistance_flags = FLAMMABLE - -/obj/item/toy/plushie/attack(mob/M as mob, mob/user as mob) - playsound(loc, poof_sound, 20, 1) // Play the whoosh sound in local area - if(iscarbon(M)) - if(prob(10)) - M.reagents.add_reagent("hugs", 10) - return ..() - -/obj/item/toy/plushie/attack_self(mob/user as mob) - var/cuddle_verb = pick("hugs","cuddles","snugs") - user.visible_message("[user] [cuddle_verb] the [src].") - playsound(get_turf(src), poof_sound, 50, 1, -1) - return ..() - -/obj/random/plushie - name = "Random Plushie" - desc = "This is a random plushie" - icon = 'icons/obj/toy.dmi' - icon_state = "redfox" - -/obj/random/plushie/item_to_spawn() - return pick(subtypesof(/obj/item/toy/plushie) - typesof(/obj/item/toy/plushie/fluff)) //exclude the base type. - -/obj/item/toy/plushie/corgi - name = "corgi plushie" - icon_state = "corgi" - -/obj/item/toy/plushie/girly_corgi - name = "corgi plushie" - icon_state = "girlycorgi" - -/obj/item/toy/plushie/robo_corgi - name = "borgi plushie" - icon_state = "robotcorgi" - -/obj/item/toy/plushie/octopus - name = "octopus plushie" - icon_state = "loveable" - -/obj/item/toy/plushie/face_hugger - name = "facehugger plushie" - icon_state = "huggable" - -//foxes are basically the best - -/obj/item/toy/plushie/red_fox - name = "red fox plushie" - icon_state = "redfox" - -/obj/item/toy/plushie/black_fox - name = "black fox plushie" - icon_state = "blackfox" - -/obj/item/toy/plushie/marble_fox - name = "marble fox plushie" - icon_state = "marblefox" - -/obj/item/toy/plushie/blue_fox - name = "blue fox plushie" - icon_state = "bluefox" - -/obj/item/toy/plushie/orange_fox - name = "orange fox plushie" - icon_state = "orangefox" - -/obj/item/toy/plushie/coffee_fox - name = "coffee fox plushie" - icon_state = "coffeefox" - -/obj/item/toy/plushie/pink_fox - name = "pink fox plushie" - icon_state = "pinkfox" - -/obj/item/toy/plushie/purple_fox - name = "purple fox plushie" - icon_state = "purplefox" - -/obj/item/toy/plushie/crimson_fox - name = "crimson fox plushie" - icon_state = "crimsonfox" - -/obj/item/toy/plushie/deer - name = "deer plushie" - icon_state = "deer" - -/obj/item/toy/plushie/black_cat - name = "black cat plushie" - icon_state = "blackcat" - -/obj/item/toy/plushie/grey_cat - name = "grey cat plushie" - icon_state = "greycat" - -/obj/item/toy/plushie/white_cat - name = "white cat plushie" - icon_state = "whitecat" - -/obj/item/toy/plushie/orange_cat - name = "orange cat plushie" - icon_state = "orangecat" - -/obj/item/toy/plushie/siamese_cat - name = "siamese cat plushie" - icon_state = "siamesecat" - -/obj/item/toy/plushie/tabby_cat - name = "tabby cat plushie" - icon_state = "tabbycat" - -/obj/item/toy/plushie/tuxedo_cat - name = "tuxedo cat plushie" - icon_state = "tuxedocat" - -/obj/item/toy/plushie/voxplushie - name = "vox plushie" - desc = "A stitched-together vox, fresh from the skipjack. Press its belly to hear it skree!" - icon_state = "plushie_vox" - item_state = "plushie_vox" - var/cooldown = 0 - -/obj/item/toy/plushie/voxplushie/attack_self(mob/user) - if(!cooldown) - playsound(user, 'sound/voice/shriek1.ogg', 10, 0) - visible_message("Skreee!") - cooldown = 1 - spawn(30) cooldown = 0 - return - ..() - -/obj/item/toy/plushie/ipcplushie - name = "IPC plushie" - desc = "An adorable IPC plushie, straight from New Canaan. Arguably more durable than the real deal. Toaster functionality included." - icon_state = "plushie_ipc" - item_state = "plushie_ipc" - -/obj/item/toy/plushie/ipcplushie/attackby(obj/item/B, mob/user, params) - if(istype(B, /obj/item/reagent_containers/food/snacks/breadslice)) - new /obj/item/reagent_containers/food/snacks/toast(get_turf(loc)) - to_chat(user, " You insert bread into the toaster. ") - playsound(loc, 'sound/machines/ding.ogg', 50, 1) - qdel(B) - else - return ..() - -//New generation TG plushies - -/obj/item/toy/plushie/lizardplushie - name = "lizard plushie" - desc = "An adorable stuffed toy that resembles a lizardperson." - icon_state = "plushie_lizard" - item_state = "plushie_lizard" - -/obj/item/toy/plushie/snakeplushie - name = "snake plushie" - desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing." - icon_state = "plushie_snake" - item_state = "plushie_snake" - -/obj/item/toy/plushie/nukeplushie - name = "operative plushie" - desc = "An stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious." - icon_state = "plushie_nuke" - item_state = "plushie_nuke" - -/obj/item/toy/plushie/slimeplushie - name = "slime plushie" - desc = "An adorable stuffed toy that resembles a slime. It is practically just a hacky sack." - icon_state = "plushie_slime" - item_state = "plushie_slime" - -/* - * Foam Armblade - */ - - /obj/item/toy/foamblade - name = "foam armblade" - desc = "it says \"Sternside Changs #1 fan\" on it. " - icon = 'icons/obj/toy.dmi' - icon_state = "foamblade" - item_state = "arm_blade" - attack_verb = list("pricked", "absorbed", "gored") - w_class = WEIGHT_CLASS_SMALL - resistance_flags = FLAMMABLE - -/* - * Toy/fake flash - */ -/obj/item/toy/flash - name = "toy flash" - desc = "FOR THE REVOLU- Oh wait, that's just a toy." - icon = 'icons/obj/device.dmi' - icon_state = "flash" - item_state = "flashtool" - w_class = WEIGHT_CLASS_TINY - -/obj/item/toy/flash/attack(mob/living/M, mob/user) - playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) - flick("[initial(icon_state)]2", src) - user.visible_message("[user] blinds [M] with the flash!") - - -/* - * Toy big red button - */ -/obj/item/toy/redbutton - name = "big red button" - desc = "A big, plastic red button. Reads 'From HonkCo Pranks?' on the back." - icon = 'icons/obj/assemblies.dmi' - icon_state = "bigred" - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - -/obj/item/toy/redbutton/attack_self(mob/user) - if(cooldown < world.time) - cooldown = (world.time + 300) // Sets cooldown at 30 seconds - user.visible_message("[user] presses the big red button.", "You press the button, it plays a loud noise!", "The button clicks loudly.") - playsound(src, 'sound/effects/explosionfar.ogg', 50, 0, 0) - for(var/mob/M in range(10, src)) // Checks range - if(!M.stat && !istype(M, /mob/living/silicon/ai)) // Checks to make sure whoever's getting shaken is alive/not the AI - sleep(8) // Short delay to match up with the explosion sound - shake_camera(M, 2, 1) // Shakes player camera 2 squares for 1 second. - - else - to_chat(user, "Nothing happens.") - - -/* - * AI core prizes - */ -/obj/item/toy/AI - name = "toy AI" - desc = "A little toy model AI core with real law announcing action!" - icon = 'icons/obj/toy.dmi' - icon_state = "AI" - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - -/obj/item/toy/AI/attack_self(mob/user) - if(!cooldown) //for the sanity of everyone - var/message = generate_ion_law() - to_chat(user, "You press the button on [src].") - playsound(user, 'sound/machines/click.ogg', 20, 1) - visible_message("[bicon(src)] [message]") - cooldown = 1 - spawn(30) cooldown = 0 - return - ..() - -/obj/item/toy/codex_gigas - name = "Toy Codex Gigas" - desc = "A tool to help you write fictional devils!" - icon = 'icons/obj/library.dmi' - icon_state = "demonomicon" - w_class = WEIGHT_CLASS_SMALL - var/cooldown = FALSE - -/obj/item/toy/codex_gigas/attack_self(mob/user) - if(!cooldown) - user.visible_message( - "[user] presses the button on \the [src].", - "You press the button on \the [src].", - "You hear a soft click.") - var/list/messages = list() - var/datum/devilinfo/devil = randomDevilInfo() - messages += "Some fun facts about: [devil.truename]" - messages += "[GLOB.lawlorify[LORE][devil.bane]]" - messages += "[GLOB.lawlorify[LORE][devil.obligation]]" - messages += "[GLOB.lawlorify[LORE][devil.ban]]" - messages += "[GLOB.lawlorify[LORE][devil.banish]]" - playsound(loc, 'sound/machines/click.ogg', 20, 1) - cooldown = TRUE - for(var/message in messages) - user.loc.visible_message("[bicon(src)] [message]") - sleep(10) - spawn(20) - cooldown = FALSE - return - ..() - -/obj/item/toy/owl - name = "owl action figure" - desc = "An action figure modeled after 'The Owl', defender of justice." - icon = 'icons/obj/toy.dmi' - icon_state = "owlprize" - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - -/obj/item/toy/owl/attack_self(mob/user) - if(!cooldown) //for the sanity of everyone - var/message = pick("You won't get away this time, Griffin!", "Stop right there, criminal!", "Hoot! Hoot!", "I am the night!") - to_chat(user, "You pull the string on the [src].") - playsound(user, 'sound/creatures/hoot.ogg', 25, 1) - visible_message("[bicon(src)] [message]") - cooldown = 1 - spawn(30) cooldown = 0 - return - ..() - -/obj/item/toy/griffin - name = "griffin action figure" - desc = "An action figure modeled after 'The Griffin', criminal mastermind." - icon = 'icons/obj/toy.dmi' - icon_state = "griffinprize" - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - -/obj/item/toy/griffin/attack_self(mob/user) - if(!cooldown) //for the sanity of everyone - var/message = pick("You can't stop me, Owl!", "My plan is flawless! The vault is mine!", "Caaaawwww!", "You will never catch me!") - to_chat(user, "You pull the string on the [src].") - playsound(user, 'sound/creatures/caw.ogg', 25, 1) - visible_message("[bicon(src)] [message]") - cooldown = 1 - spawn(30) cooldown = 0 - return - ..() - -// DND Character minis. Use the naming convention (type)character for the icon states. -/obj/item/toy/character - icon = 'icons/obj/toy.dmi' - w_class = WEIGHT_CLASS_SMALL - pixel_z = 5 - -/obj/item/toy/character/alien - name = "Xenomorph Miniature" - desc = "A miniature xenomorph. Scary!" - icon_state = "aliencharacter" -/obj/item/toy/character/cleric - name = "Cleric Miniature" - desc = "A wee little cleric, with his wee little staff." - icon_state = "clericcharacter" -/obj/item/toy/character/warrior - name = "Warrior Miniature" - desc = "That sword would make a decent toothpick." - icon_state = "warriorcharacter" -/obj/item/toy/character/thief - name = "Thief Miniature" - desc = "Hey, where did my wallet go!?" - icon_state = "thiefcharacter" -/obj/item/toy/character/wizard - name = "Wizard Miniature" - desc = "MAGIC!" - icon_state = "wizardcharacter" -/obj/item/toy/character/cthulhu - name = "Cthulhu Miniature" - desc = "The dark lord has risen!" - icon_state = "darkmastercharacter" -/obj/item/toy/character/lich - name = "Lich Miniature" - desc = "Murderboner extraordinaire." - icon_state = "lichcharacter" -/obj/item/storage/box/characters - name = "Box of Miniatures" - desc = "The nerd's best friends." - icon_state = "box" -/obj/item/storage/box/characters/New() - ..() - new /obj/item/toy/character/alien(src) - new /obj/item/toy/character/cleric(src) - new /obj/item/toy/character/warrior(src) - new /obj/item/toy/character/thief(src) - new /obj/item/toy/character/wizard(src) - new /obj/item/toy/character/cthulhu(src) - new /obj/item/toy/character/lich(src) - - -//Pet Rocks, just like from the 70's! - -/obj/item/toy/pet_rock - name = "pet rock" - desc = "The perfect pet!" - icon = 'icons/obj/toy.dmi' - icon_state = "pet_rock" - w_class = WEIGHT_CLASS_SMALL - force = 5 - throwforce = 5 - attack_verb = list("attacked", "bashed", "smashed", "stoned") - hitsound = "swing_hit" - -/obj/item/toy/pet_rock/fred - name = "fred" - desc = "Fred, the bestest boy pet in the whole wide universe!" - icon_state = "fred" - -/obj/item/toy/pet_rock/roxie - name = "roxie" - desc = "Roxie, the bestest girl pet in the whole wide universe!" - icon_state = "roxie" - -//minigibber, so cute - -/obj/item/toy/minigibber - name = "miniature gibber" - desc = "A miniature recreation of Nanotrasen's famous meat grinder." - icon = 'icons/obj/toy.dmi' - icon_state = "minigibber" - attack_verb = list("grinded", "gibbed") - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - var/obj/stored_minature = null - -/obj/item/toy/minigibber/attack_self(var/mob/user) - - if(stored_minature) - to_chat(user, "\The [src] makes a violent grinding noise as it tears apart the miniature figure inside!") - QDEL_NULL(stored_minature) - playsound(user, 'sound/goonstation/effects/gib.ogg', 20, 1) - cooldown = world.time - - if(cooldown < world.time - 8) - to_chat(user, "You hit the gib button on \the [src].") - playsound(user, 'sound/goonstation/effects/gib.ogg', 20, 1) - cooldown = world.time - -/obj/item/toy/minigibber/attackby(var/obj/O, var/mob/user, params) - if(istype(O,/obj/item/toy/character) && O.loc == user) - to_chat(user, "You start feeding \the [O] [bicon(O)] into \the [src]'s mini-input.") - if(do_after(user, 10, target = src)) - if(O.loc != user) - to_chat(user, "\The [O] is too far away to feed into \the [src]!") - else - to_chat(user, "You feed \the [O] [bicon(O)] into \the [src]!") - user.unEquip(O) - O.forceMove(src) - stored_minature = O - else - to_chat(user, "You stop feeding \the [O] into \the [src]'s mini-input.") - else ..() - -/* - * Xenomorph action figure - */ - -/obj/item/toy/toy_xeno - icon = 'icons/obj/toy.dmi' - icon_state = "toy_xeno" - name = "xenomorph action figure" - desc = "MEGA presents the new Xenos Isolated action figure! Comes complete with realistic sounds! Pull back string to use." - w_class = WEIGHT_CLASS_SMALL - var/cooldown = 0 - -/obj/item/toy/toy_xeno/attack_self(mob/user) - if(cooldown <= world.time) - cooldown = (world.time + 50) //5 second cooldown - user.visible_message("[user] pulls back the string on [src].") - icon_state = "[initial(icon_state)]_used" - sleep(5) - audible_message("[bicon(src)] Hiss!") - var/list/possible_sounds = list('sound/voice/hiss1.ogg', 'sound/voice/hiss2.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg') - playsound(get_turf(src), pick(possible_sounds), 50, 1) - spawn(45) - if(src) - icon_state = "[initial(icon_state)]" - else - to_chat(user, "The string on [src] hasn't rewound all the way!") - return - -/obj/item/toy/russian_revolver - name = "russian revolver" - desc = "for fun and games!" - icon = 'icons/obj/guns/projectile.dmi' - icon_state = "detective_gold" - item_state = "gun" - lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/guns_righthand.dmi' - hitsound = "swing_hit" - flags = CONDUCT - slot_flags = SLOT_BELT - materials = list(MAT_METAL=2000) - w_class = WEIGHT_CLASS_NORMAL - throwforce = 5 - throw_speed = 4 - throw_range = 5 - force = 5 - origin_tech = "combat=1" - attack_verb = list("struck", "hit", "bashed") - var/bullets_left = 0 - var/max_shots = 6 - -/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 [user.p_their()] head before pulling the trigger! It looks like [user.p_theyre()] trying to commit suicide.") - playsound(loc, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1) - return BRUTELOSS - -/obj/item/toy/russian_revolver/New() - ..() - spin_cylinder() - -/obj/item/toy/russian_revolver/attack_self(mob/user) - if(!bullets_left) - user.visible_message("[user] loads a bullet into [src]'s cylinder before spinning it.") - spin_cylinder() - else - user.visible_message("[user] spins the cylinder on [src]!") - spin_cylinder() - -/obj/item/toy/russian_revolver/attack(mob/M, mob/living/user) - return - -/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, flag, params) - if(flag) - if(target in user.contents) - return - if(!ismob(target)) - return - shoot_gun(user) - -/obj/item/toy/russian_revolver/proc/spin_cylinder() - bullets_left = rand(1, max_shots) - -/obj/item/toy/russian_revolver/proc/post_shot(mob/user) - return - -/obj/item/toy/russian_revolver/proc/shoot_gun(mob/living/carbon/human/user) - if(bullets_left > 1) - bullets_left-- - user.visible_message("*click*") - playsound(src, 'sound/weapons/empty.ogg', 100, 1) - return FALSE - if(bullets_left == 1) - bullets_left = 0 - var/zone = "head" - if(!(user.has_organ(zone))) // If they somehow don't have a head. - zone = "chest" - playsound(src, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1) - user.visible_message("[src] goes off!") - post_shot(user) - user.apply_damage(300, BRUTE, zone, sharp = TRUE, used_weapon = "Self-inflicted gunshot wound to the [zone].") - user.bleed(BLOOD_VOLUME_NORMAL) - user.death() // Just in case - return TRUE - else - to_chat(user, "[src] needs to be reloaded.") - return FALSE - -/obj/item/toy/russian_revolver/trick_revolver - name = "\improper .357 revolver" - desc = "A suspicious revolver. Uses .357 ammo." - icon_state = "revolver" - max_shots = 1 - var/fake_bullets = 0 - -/obj/item/toy/russian_revolver/trick_revolver/New() - ..() - fake_bullets = rand(2, 7) - -/obj/item/toy/russian_revolver/trick_revolver/examine(mob/user) //Sneaky sneaky - . = ..() - . += "Has [fake_bullets] round\s remaining." - . += "[fake_bullets] of those are live rounds." - -/obj/item/toy/russian_revolver/trick_revolver/post_shot(user) - to_chat(user, "[src] did look pretty dodgey!") - SEND_SOUND(user, 'sound/misc/sadtrombone.ogg') //HONK -/* - * Rubber Chainsaw - */ -/obj/item/twohanded/toy/chainsaw - name = "Toy Chainsaw" - desc = "A toy chainsaw with a rubber edge. Ages 8 and up" - icon_state = "chainsaw0" - force = 0 - throwforce = 0 - throw_speed = 4 - throw_range = 20 - wieldsound = 'sound/weapons/chainsawstart.ogg' - attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered") - -/obj/item/twohanded/toy/chainsaw/update_icon() - if(wielded) - icon_state = "chainsaw[wielded]" - else - icon_state = "chainsaw0" - -/* - * Cat Toy - */ -/obj/item/toy/cattoy - name = "toy mouse" - desc = "A colorful toy mouse!" - icon = 'icons/obj/toy.dmi' - icon_state = "toy_mouse" - w_class = WEIGHT_CLASS_SMALL - resistance_flags = FLAMMABLE - var/cooldown = 0 - -/* - * Action Figures - */ - - -/obj/random/figure - name = "Random Action Figure" - desc = "This is a random toy action figure" - icon = 'icons/obj/toy.dmi' - icon_state = "nuketoy" - -/obj/random/figure/item_to_spawn() - return pick(subtypesof(/obj/item/toy/figure)) - - -/obj/item/toy/figure - name = "Non-Specific Action Figure action figure" - desc = "A \"Space Life\" brand... wait, what the hell is this thing?" - icon = 'icons/obj/toy.dmi' - icon_state = "nuketoy" - var/cooldown = 0 - var/toysay = "What the fuck did you do?" - -/obj/item/toy/figure/New() - ..() - desc = "A \"Space Life\" brand [name]" - -/obj/item/toy/figure/attack_self(mob/user as mob) - if(cooldown < world.time) - cooldown = (world.time + 30) //3 second cooldown - user.visible_message("[bicon(src)] The [src] says \"[toysay]\".") - playsound(user, 'sound/machines/click.ogg', 20, 1) - -/obj/item/toy/figure/cmo - name = "Chief Medical Officer action figure" - icon_state = "cmo" - toysay = "Suit sensors!" - -/obj/item/toy/figure/assistant - name = "Assistant action figure" - icon_state = "assistant" - toysay = "Grey tide station wide!" - -/obj/item/toy/figure/atmos - name = "Atmospheric Technician action figure" - icon_state = "atmos" - toysay = "Glory to Atmosia!" - -/obj/item/toy/figure/bartender - name = "Bartender action figure" - icon_state = "bartender" - toysay = "Wheres my monkey?" - -/obj/item/toy/figure/borg - name = "Cyborg action figure" - icon_state = "borg" - toysay = "I. LIVE. AGAIN." - -/obj/item/toy/figure/botanist - name = "Botanist action figure" - icon_state = "botanist" - toysay = "Dude, I see colors..." - -/obj/item/toy/figure/captain - name = "Captain action figure" - icon_state = "captain" - toysay = "Crew, the Nuke Disk is safely up my ass." - -/obj/item/toy/figure/cargotech - name = "Cargo Technician action figure" - icon_state = "cargotech" - toysay = "For Cargonia!" - -/obj/item/toy/figure/ce - name = "Chief Engineer action figure" - icon_state = "ce" - toysay = "Wire the solars!" - -/obj/item/toy/figure/chaplain - name = "Chaplain action figure" - icon_state = "chaplain" - toysay = "Gods make me a killing machine please!" - -/obj/item/toy/figure/chef - name = "Chef action figure" - icon_state = "chef" - toysay = "I swear it's not human meat." - -/obj/item/toy/figure/chemist - name = "Chemist action figure" - icon_state = "chemist" - toysay = "Get your pills!" - -/obj/item/toy/figure/clown - name = "Clown action figure" - icon_state = "clown" - toysay = "Honk!" - -/obj/item/toy/figure/ian - name = "Ian action figure" - icon_state = "ian" - toysay = "Arf!" - -/obj/item/toy/figure/detective - name = "Detective action figure" - icon_state = "detective" - toysay = "This airlock has grey jumpsuit and insulated glove fibers on it." - -/obj/item/toy/figure/dsquad - name = "Death Squad Officer action figure" - icon_state = "dsquad" - toysay = "Eliminate all threats!" - -/obj/item/toy/figure/engineer - name = "Engineer action figure" - icon_state = "engineer" - toysay = "Oh god, the singularity is loose!" - -/obj/item/toy/figure/geneticist - name = "Geneticist action figure" - icon_state = "geneticist" - toysay = "I'm not qualified for this job." - -/obj/item/toy/figure/hop - name = "Head of Personnel action figure" - icon_state = "hop" - toysay = "Giving out all access!" - -/obj/item/toy/figure/hos - name = "Head of Security action figure" - icon_state = "hos" - toysay = "I'm here to win, anything else is secondary." - -/obj/item/toy/figure/qm - name = "Quartermaster action figure" - icon_state = "qm" - toysay = "Hail Cargonia!" - -/obj/item/toy/figure/janitor - name = "Janitor action figure" - icon_state = "janitor" - toysay = "Look at the signs, you idiot." - -/obj/item/toy/figure/lawyer - name = "Internal Affairs Agent action figure" - icon_state = "lawyer" - toysay = "Standard Operating Procedure says they're guilty! Hacking is proof they're an Enemy of the Corporation!" - -/obj/item/toy/figure/librarian - name = "Librarian action figure" - icon_state = "librarian" - toysay = "One day while..." - -/obj/item/toy/figure/md - name = "Medical Doctor action figure" - icon_state = "md" - toysay = "The patient is already dead!" - -/obj/item/toy/figure/mime - name = "Mime action figure" - desc = "A \"Space Life\" brand Mime action figure." - icon_state = "mime" - toysay = "..." - -/obj/item/toy/figure/miner - name = "Shaft Miner action figure" - icon_state = "miner" - toysay = "Oh god it's eating my intestines!" - -/obj/item/toy/figure/ninja - name = "Ninja action figure" - icon_state = "ninja" - toysay = "Oh god! Stop shooting, I'm friendly!" - -/obj/item/toy/figure/wizard - name = "Wizard action figure" - icon_state = "wizard" - toysay = "Ei Nath!" - -/obj/item/toy/figure/rd - name = "Research Director action figure" - icon_state = "rd" - toysay = "Blowing all of the borgs!" - -/obj/item/toy/figure/roboticist - name = "Roboticist action figure" - icon_state = "roboticist" - toysay = "He asked to be borged!" - -/obj/item/toy/figure/scientist - name = "Scientist action figure" - icon_state = "scientist" - toysay = "Someone else must have made those bombs!" - -/obj/item/toy/figure/syndie - name = "Nuclear Operative action figure" - icon_state = "syndie" - toysay = "Get that fucking disk!" - -/obj/item/toy/figure/secofficer - name = "Security Officer action figure" - icon_state = "secofficer" - toysay = "I am the law!" - -/obj/item/toy/figure/virologist - name = "Virologist action figure" - icon_state = "virologist" - toysay = "The cure is potassium!" - -/obj/item/toy/figure/warden - name = "Warden action figure" - icon_state = "warden" - toysay = "Execute him for breaking in!" - -////////////////////////////////////////////////////// -// Magic 8-Ball / Conch // -////////////////////////////////////////////////////// - -/obj/item/toy/eight_ball - name = "Magic 8-Ball" - desc = "Mystical! Magical! Ages 8+!" - icon = 'icons/obj/toy.dmi' - icon_state = "eight-ball" - var/use_action = "shakes the ball" - var/cooldown = 0 - var/list/possible_answers = list("Definitely", "All signs point to yes.", "Most likely.", "Yes.", "Ask again later.", "Better not tell you now.", "Future Unclear.", "Maybe.", "Doubtful.", "No.", "Don't count on it.", "Never.") - -/obj/item/toy/eight_ball/attack_self(mob/user as mob) - if(!cooldown) - var/answer = pick(possible_answers) - 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 - return - -/obj/item/toy/eight_ball/conch - name = "Magic Conch Shell" - desc = "All hail the Magic Conch!" - icon_state = "conch" - use_action = "pulls the string" - possible_answers = list("Yes.", "No.", "Try asking again.", "Nothing.", "I don't think so.", "Neither.", "Maybe someday.") - -/* - *Fake cuffs (honk honk) - */ - -/obj/item/restraints/handcuffs/toy - desc = "Toy handcuffs. Plastic and extremely cheaply made." - throwforce = 0 - breakouttime = 0 - ignoresClumsy = TRUE +/* Toys! + * Contains: + * Balloons + * Fake telebeacon + * Fake singularity + * Toy swords + * Toy mechs + * Snap pops + * Water flower + * Toy Nuke + * Card Deck + * Therapy dolls + * Toddler doll + * Inflatable duck + * Foam armblade + * Mini Gibber + * Toy xeno + * Toy chainsaws + * Action Figures + */ + + +/obj/item/toy + throwforce = 0 + throw_speed = 4 + throw_range = 20 + force = 0 + + +/* + * Balloons + */ +/obj/item/toy/balloon + name = "water balloon" + desc = "A translucent balloon. There's nothing in it." + icon = 'icons/obj/toy.dmi' + icon_state = "waterballoon-e" + item_state = "balloon-empty" + +/obj/item/toy/balloon/New() + ..() + create_reagents(10) + +/obj/item/toy/balloon/attack(mob/living/carbon/human/M as mob, mob/user as mob) + return + +/obj/item/toy/balloon/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + if(istype(A, /obj/structure/reagent_dispensers)) + var/obj/structure/reagent_dispensers/RD = A + if(RD.reagents.total_volume <= 0) + to_chat(user, "[RD] is empty.") + else if(reagents.total_volume >= 10) + to_chat(user, "[src] is full.") + else + A.reagents.trans_to(src, 10) + to_chat(user, "You fill the balloon with the contents of [A].") + desc = "A translucent balloon with some form of liquid sloshing around in it." + update_icon() + +/obj/item/toy/balloon/wash(mob/user, atom/source) + if(reagents.total_volume < 10) + reagents.add_reagent("water", min(10-reagents.total_volume, 10)) + to_chat(user, "You fill the balloon from the [source].") + desc = "A translucent balloon with some form of liquid sloshing around in it." + update_icon() + return + +/obj/item/toy/balloon/attackby(obj/O as obj, mob/user as mob, params) + if(istype(O, /obj/item/reagent_containers/glass) || istype(O, /obj/item/reagent_containers/food/drinks/drinkingglass)) + if(O.reagents) + if(O.reagents.total_volume < 1) + to_chat(user, "The [O] is empty.") + else if(O.reagents.total_volume >= 1) + if(O.reagents.has_reagent("facid", 1)) + to_chat(user, "The acid chews through the balloon!") + O.reagents.reaction(user) + qdel(src) + else + desc = "A translucent balloon with some form of liquid sloshing around in it." + to_chat(user, "You fill the balloon with the contents of [O].") + O.reagents.trans_to(src, 10) + update_icon() + return + +/obj/item/toy/balloon/throw_impact(atom/hit_atom) + if(reagents.total_volume >= 1) + visible_message("The [src] bursts!","You hear a pop and a splash.") + reagents.reaction(get_turf(hit_atom)) + for(var/atom/A in get_turf(hit_atom)) + reagents.reaction(A) + icon_state = "burst" + spawn(5) + if(src) + qdel(src) + return + +/obj/item/toy/balloon/update_icon() + if(src.reagents.total_volume >= 1) + icon_state = "waterballoon" + item_state = "balloon" + else + icon_state = "waterballoon-e" + item_state = "balloon-empty" + +/obj/item/toy/syndicateballoon + name = "syndicate balloon" + desc = "There is a tag on the back that reads \"FUK NT!11!\"." + throwforce = 0 + throw_speed = 4 + throw_range = 20 + force = 0 + icon_state = "syndballoon" + item_state = "syndballoon" + w_class = WEIGHT_CLASS_BULKY + var/lastused = null + +/obj/item/toy/syndicateballoon/attack_self(mob/user) + if(world.time - lastused < CLICK_CD_MELEE) + return + var/playverb = pick("bat [src]", "tug on [src]'s string", "play with [src]") + user.visible_message("[user] plays with [src].", "You [playverb].") + lastused = world.time + +/* + * Fake telebeacon + */ +/obj/item/toy/blink + name = "electronic blink toy game" + desc = "Blink. Blink. Blink. Ages 8 and up." + icon = 'icons/obj/radio.dmi' + icon_state = "beacon" + item_state = "signaler" + +/* + * Fake singularity + */ +/obj/item/toy/spinningtoy + name = "Gravitational Singularity" + desc = "\"Singulo\" brand spinning toy." + icon = 'icons/obj/singularity.dmi' + icon_state = "singularity_s1" + +/* + * Toy swords + */ +/obj/item/toy/sword + name = "toy sword" + desc = "A cheap, plastic replica of an energy sword. Realistic sounds! Ages 8 and up." + icon_state = "sword0" + item_state = "sword0" + var/active = FALSE + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("attacked", "struck", "hit") + +/obj/item/toy/sword/attack_self(mob/user) + active = !active + if(active) + to_chat(user, "You extend the plastic blade with a quick flick of your wrist.") + playsound(user, 'sound/weapons/saberon.ogg', 20, 1) + icon_state = "swordblue" + item_state = "swordblue" + w_class = WEIGHT_CLASS_BULKY + else + to_chat(user, "You push the plastic blade back down into the handle.") + playsound(user, 'sound/weapons/saberoff.ogg', 20, 1) + icon_state = "sword0" + item_state = "sword0" + w_class = WEIGHT_CLASS_SMALL + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_l_hand() + H.update_inv_r_hand() + add_fingerprint(user) + return + +// Copied from /obj/item/melee/energy/sword/attackby +/obj/item/toy/sword/attackby(obj/item/W, mob/living/user, params) + ..() + if(istype(W, /obj/item/toy/sword)) + if(W == src) + to_chat(user, "You try to attach the end of the plastic sword to... itself. You're not very smart, are you?") + if(ishuman(user)) + user.adjustBrainLoss(10) + else if((W.flags & NODROP) || (flags & NODROP)) + to_chat(user, "\the [flags & NODROP ? src : W] is stuck to your hand, you can't attach it to \the [flags & NODROP ? W : src]!") + else + to_chat(user, "You attach the ends of the two plastic swords, making a single double-bladed toy! You're fake-cool.") + new /obj/item/twohanded/dualsaber/toy(user.loc) + user.unEquip(W) + user.unEquip(src) + qdel(W) + qdel(src) + +/* + * Subtype of Double-Bladed Energy Swords + */ +/obj/item/twohanded/dualsaber/toy + name = "double-bladed toy sword" + desc = "A cheap, plastic replica of TWO energy swords. Double the fun!" + force = 0 + throwforce = 0 + throw_speed = 3 + throw_range = 5 + force_unwielded = 0 + force_wielded = 0 + origin_tech = null + attack_verb = list("attacked", "struck", "hit") + brightness_on = 0 + sharp_when_wielded = FALSE // It's a toy + +/obj/item/twohanded/dualsaber/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + return 0 + +/obj/item/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles + return 0 + +/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") + hitsound = 'sound/weapons/bladeslice.ogg' + +/obj/item/toy/katana/suicide_act(mob/user) + 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 + + +/* + * Snap pops viral shit + */ +/obj/item/toy/snappop/virus + name = "unstable goo" + desc = "Your palm is oozing this stuff!" + icon = 'icons/mob/slimes.dmi' + icon_state = "red slime extract" + throwforce = 5.0 + throw_speed = 10 + throw_range = 30 + w_class = WEIGHT_CLASS_TINY + + +/obj/item/toy/snappop/virus/throw_impact(atom/hit_atom) + ..() + do_sparks(3, 1, src) + new /obj/effect/decal/cleanable/ash(src.loc) + visible_message("The [name] explodes!","You hear a bang!") + playsound(src, 'sound/effects/snap.ogg', 50, 1) + qdel(src) + +/* + * Snap pops + */ +/obj/item/toy/snappop + name = "snap pop" + desc = "Wow!" + icon = 'icons/obj/toy.dmi' + icon_state = "snappop" + w_class = WEIGHT_CLASS_TINY + var/ash_type = /obj/effect/decal/cleanable/ash + +/obj/item/toy/snappop/proc/pop_burst(var/n=3, var/c=1) + do_sparks(n, c, src) + new ash_type(loc) + visible_message("[src] explodes!", + "You hear a snap!") + playsound(src, 'sound/effects/snap.ogg', 50, 1) + qdel(src) + +/obj/item/toy/snappop/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE) + ..() + pop_burst() + +/obj/item/toy/snappop/throw_impact(atom/hit_atom) + ..() + pop_burst() + +/obj/item/toy/snappop/Crossed(H as mob|obj, oldloc) + if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off + var/mob/living/carbon/M = H + if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN) + to_chat(M, "You step on the snap pop!") + pop_burst(2, 0) + +/obj/item/toy/snappop/phoenix + name = "phoenix snap pop" + desc = "Wow! And wow! And wow!" + ash_type = /obj/effect/decal/cleanable/ash/snappop_phoenix + +/obj/effect/decal/cleanable/ash/snappop_phoenix + var/respawn_time = 300 + +/obj/effect/decal/cleanable/ash/snappop_phoenix/Initialize(mapload) + . = ..() + addtimer(CALLBACK(src, .proc/respawn), respawn_time) + +/obj/effect/decal/cleanable/ash/snappop_phoenix/proc/respawn() + new /obj/item/toy/snappop/phoenix(get_turf(src)) + qdel(src) + + +/* + * Mech prizes + */ +/obj/item/toy/prize + icon = 'icons/obj/toy.dmi' + icon_state = "ripleytoy" + var/cooldown = 0 + +//all credit to skasi for toy mech fun ideas +/obj/item/toy/prize/attack_self(mob/user as mob) + if(cooldown < world.time - 8) + to_chat(user, "You play with [src].") + playsound(user, 'sound/mecha/mechstep.ogg', 20, 1) + cooldown = world.time + +/obj/item/toy/prize/attack_hand(mob/user as mob) + if(loc == user) + if(cooldown < world.time - 8) + to_chat(user, "You play with [src].") + playsound(user, 'sound/mecha/mechturn.ogg', 20, 1) + cooldown = world.time + return + ..() + +/obj/random/mech + name = "Random Mech Prize" + desc = "This is a random prize" + icon = 'icons/obj/toy.dmi' + icon_state = "ripleytoy" + +/obj/random/mech/item_to_spawn() + return pick(subtypesof(/obj/item/toy/prize)) //exclude the base type. + +/obj/item/toy/prize/ripley + name = "toy ripley" + desc = "Mini-Mecha action figure! Collect them all! 1/11." + +/obj/item/toy/prize/fireripley + name = "toy firefighting ripley" + desc = "Mini-Mecha action figure! Collect them all! 2/11." + icon_state = "fireripleytoy" + +/obj/item/toy/prize/deathripley + name = "toy deathsquad ripley" + desc = "Mini-Mecha action figure! Collect them all! 3/11." + icon_state = "deathripleytoy" + +/obj/item/toy/prize/gygax + name = "toy gygax" + 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." + icon_state = "durandprize" + +/obj/item/toy/prize/honk + name = "toy H.O.N.K." + desc = "Mini-Mecha action figure! Collect them all! 6/11." + icon_state = "honkprize" + +/obj/item/toy/prize/marauder + name = "toy marauder" + desc = "Mini-Mecha action figure! Collect them all! 7/11." + icon_state = "marauderprize" + +/obj/item/toy/prize/seraph + name = "toy seraph" + desc = "Mini-Mecha action figure! Collect them all! 8/11." + icon_state = "seraphprize" + +/obj/item/toy/prize/mauler + name = "toy mauler" + desc = "Mini-Mecha action figure! Collect them all! 9/11." + icon_state = "maulerprize" + +/obj/item/toy/prize/odysseus + name = "toy odysseus" + desc = "Mini-Mecha action figure! Collect them all! 10/11." + icon_state = "odysseusprize" + +/obj/item/toy/prize/phazon + name = "toy phazon" + desc = "Mini-Mecha action figure! Collect them all! 11/11." + icon_state = "phazonprize" + + + +/* +|| A Deck of Cards for playing various games of chance || +*/ + + + +obj/item/toy/cards + resistance_flags = FLAMMABLE + max_integrity = 50 + var/parentdeck = null + var/deckstyle = "nanotrasen" + var/card_hitsound = null + var/card_force = 0 + var/card_throwforce = 0 + var/card_throw_speed = 4 + var/card_throw_range = 20 + var/list/card_attack_verb = list("attacked") + +obj/item/toy/cards/New() + ..() + +obj/item/toy/cards/proc/apply_card_vars(obj/item/toy/cards/newobj, obj/item/toy/cards/sourceobj) // Applies variables for supporting multiple types of card deck + if(!istype(sourceobj)) + return + +obj/item/toy/cards/deck + name = "deck of cards" + desc = "A deck of space-grade playing cards." + icon = 'icons/obj/toy.dmi' + deckstyle = "nanotrasen" + icon_state = "deck_nanotrasen_full" + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + var/list/cards = list() + +obj/item/toy/cards/deck/New() + ..() + icon_state = "deck_[deckstyle]_full" + for(var/i in 2 to 10) + cards += "[i] of Hearts" + cards += "[i] of Spades" + cards += "[i] of Clubs" + cards += "[i] of Diamonds" + cards += "King of Hearts" + cards += "King of Spades" + cards += "King of Clubs" + cards += "King of Diamonds" + cards += "Queen of Hearts" + cards += "Queen of Spades" + cards += "Queen of Clubs" + cards += "Queen of Diamonds" + cards += "Jack of Hearts" + cards += "Jack of Spades" + cards += "Jack of Clubs" + cards += "Jack of Diamonds" + cards += "Ace of Hearts" + cards += "Ace of Spades" + 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) + icon_state = "deck_[deckstyle]_empty" + to_chat(user, "There are no more cards to draw.") + return + var/obj/item/toy/cards/singlecard/H = new/obj/item/toy/cards/singlecard(user.loc) + choice = cards[1] + H.cardname = choice + H.parentdeck = src + var/O = src + H.apply_card_vars(H,O) + cards -= choice + 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.") + update_icon() + +obj/item/toy/cards/deck/attack_self(mob/user as mob) + if(cooldown < world.time - 50) + cards = shuffle(cards) + playsound(user, 'sound/items/cardshuffle.ogg', 50, 1) + user.visible_message("[user] shuffles the deck.", "You shuffle the deck.") + cooldown = world.time + +obj/item/toy/cards/deck/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params) + ..() + if(istype(C)) + if(C.parentdeck == src) + if(!user.unEquip(C)) + to_chat(user, "The card is stuck to your hand, you can't add it to the deck!") + return + cards += C.cardname + user.visible_message("[user] adds a card to the bottom of the deck.","You add the card to the bottom of the deck.") + qdel(C) + else + to_chat(user, "You can't mix cards from other decks.") + update_icon() + + +obj/item/toy/cards/deck/attackby(obj/item/toy/cards/cardhand/C, mob/living/user, params) + ..() + if(istype(C)) + if(C.parentdeck == src) + if(!user.unEquip(C)) + 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 [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.") + update_icon() + +obj/item/toy/cards/deck/MouseDrop(atom/over_object) + var/mob/M = usr + if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) + return + if(Adjacent(usr)) + if(over_object == M && loc != M) + M.put_in_hands(src) + to_chat(usr, "You pick up the deck.") + + else if(istype(over_object, /obj/screen)) + switch(over_object.name) + if("l_hand") + if(!remove_item_from_storage(M)) + M.unEquip(src) + M.put_in_l_hand(src) + to_chat(usr, "You pick up the deck.") + if("r_hand") + if(!remove_item_from_storage(M)) + M.unEquip(src) + M.put_in_r_hand(src) + to_chat(usr, "You pick up the deck.") + 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" + desc = "A number of cards not in a deck, customarily held in ones hand." + icon = 'icons/obj/toy.dmi' + icon_state = "nanotrasen_hand2" + w_class = WEIGHT_CLASS_TINY + var/list/currenthand = list() + var/choice = null + + +obj/item/toy/cards/cardhand/attack_self(mob/user as mob) + user.set_machine(src) + interact(user) + +obj/item/toy/cards/cardhand/interact(mob/user) + var/dat = "You have:
" + for(var/t in currenthand) + dat += "A [t].
" + dat += "Which card will you remove next?" + var/datum/browser/popup = new(user, "cardhand", "Hand of Cards", 400, 240) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.set_content(dat) + popup.open() + + +obj/item/toy/cards/cardhand/Topic(href, href_list) + if(..()) + return + if(usr.stat || !ishuman(usr) || !usr.canmove) + return + var/mob/living/carbon/human/cardUser = usr + var/O = src + if(href_list["pick"]) + if(cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) + var/choice = href_list["pick"] + var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc) + currenthand -= choice + C.parentdeck = src.parentdeck + C.cardname = choice + 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 [cardUser.p_their()] hand.", "You take the [C.cardname] from your hand.") + + interact(cardUser) + 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 + N.cardname = src.currenthand[1] + N.apply_card_vars(N,O) + cardUser.unEquip(src) + N.pickup(cardUser) + cardUser.put_in_any_hand_if_possible(N) + to_chat(cardUser, "You also take [currenthand[1]] and hold it.") + cardUser << browse(null, "window=cardhand") + qdel(src) + return + +obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params) + if(istype(C)) + if(C.parentdeck == parentdeck) + currenthand += C.cardname + user.unEquip(C) + user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [C.cardname] to your hand.") + interact(user) + update_icon() + qdel(C) + else + to_chat(user, "You can't mix cards from other decks.") + +obj/item/toy/cards/cardhand/apply_card_vars(obj/item/toy/cards/newobj,obj/item/toy/cards/sourceobj) + ..() + newobj.deckstyle = sourceobj.deckstyle + newobj.icon_state = "[deckstyle]_hand2" // Another dumb hack, without this the hand is invisible (or has the default deckstyle) until another card is added. + newobj.card_hitsound = sourceobj.card_hitsound + newobj.card_force = sourceobj.card_force + newobj.card_throwforce = sourceobj.card_throwforce + newobj.card_throw_speed = sourceobj.card_throw_speed + newobj.card_throw_range = sourceobj.card_throw_range + newobj.card_attack_verb = sourceobj.card_attack_verb + newobj.resistance_flags = sourceobj.resistance_flags + + +obj/item/toy/cards/singlecard + name = "card" + desc = "a card" + icon = 'icons/obj/toy.dmi' + icon_state = "singlecard_nanotrasen_down" + w_class = WEIGHT_CLASS_TINY + var/cardname = null + var/flipped = 0 + pixel_x = -5 + + +obj/item/toy/cards/singlecard/examine(mob/user) + . = ..() + if(get_dist(user, src) <= 0) + 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 [cardUser.p_their()] card.", "The card reads: [src.cardname]") + else + . += "You need to have the card in your hand to check it." + + +obj/item/toy/cards/singlecard/verb/Flip() + set name = "Flip Card" + set category = "Object" + set src in range(1) + if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) + return + if(!flipped) + flipped = 1 + if(cardname) + icon_state = "sc_[cardname]_[deckstyle]" + name = cardname + else + icon_state = "sc_Ace of Spades_[deckstyle]" + name = "What Card" + pixel_x = 5 + else + flipped = 0 + icon_state = "singlecard_down_[deckstyle]" + name = "card" + pixel_x = -5 + +obj/item/toy/cards/singlecard/attackby(obj/item/I, mob/living/user, params) + if(istype(I, /obj/item/toy/cards/singlecard/)) + var/obj/item/toy/cards/singlecard/C = I + if(C.parentdeck == parentdeck) + var/obj/item/toy/cards/cardhand/H = new/obj/item/toy/cards/cardhand(user.loc) + H.currenthand += C.cardname + H.currenthand += cardname + H.parentdeck = C.parentdeck + H.apply_card_vars(H,C) + user.unEquip(C) + H.pickup(user) + user.put_in_active_hand(H) + to_chat(user, "You combine the [C.cardname] and the [cardname] into a hand.") + qdel(C) + qdel(src) + else + to_chat(user, "You can't mix cards from other decks.") + + if(istype(I, /obj/item/toy/cards/cardhand/)) + var/obj/item/toy/cards/cardhand/H = I + if(H.parentdeck == parentdeck) + H.currenthand += cardname + user.unEquip(src) + user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [cardname] to your hand.") + H.interact(user) + 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()) + return + Flip() + +obj/item/toy/cards/singlecard/apply_card_vars(obj/item/toy/cards/singlecard/newobj,obj/item/toy/cards/sourceobj) + ..() + newobj.deckstyle = sourceobj.deckstyle + newobj.icon_state = "singlecard_down_[deckstyle]" // Without this the card is invisible until flipped. It's an ugly hack, but it works. + newobj.card_hitsound = sourceobj.card_hitsound + newobj.hitsound = newobj.card_hitsound + newobj.card_force = sourceobj.card_force + newobj.force = newobj.card_force + newobj.card_throwforce = sourceobj.card_throwforce + newobj.throwforce = newobj.card_throwforce + newobj.card_throw_speed = sourceobj.card_throw_speed + newobj.throw_speed = newobj.card_throw_speed + newobj.card_throw_range = sourceobj.card_throw_range + newobj.throw_range = newobj.card_throw_range + newobj.card_attack_verb = sourceobj.card_attack_verb + newobj.attack_verb = newobj.card_attack_verb + + +/* +|| Syndicate playing cards, for pretending you're Gambit and playing poker for the nuke disk. || +*/ + +obj/item/toy/cards/deck/syndicate + name = "suspicious looking deck of cards" + desc = "A deck of space-grade playing cards. They seem unusually rigid." + deckstyle = "syndicate" + card_hitsound = 'sound/weapons/bladeslice.ogg' + card_force = 5 + card_throwforce = 10 + card_throw_speed = 3 + card_throw_range = 20 + card_attack_verb = list("attacked", "sliced", "diced", "slashed", "cut") + resistance_flags = NONE + +/* +|| Custom card decks || +*/ +obj/item/toy/cards/deck/black + deckstyle = "black" + +obj/item/toy/cards/deck/syndicate/black + deckstyle = "black" + +/obj/item/toy/nuke + name = "\improper Nuclear Fission Explosive toy" + desc = "A plastic model of a Nuclear Fission Explosive." + icon = 'icons/obj/toy.dmi' + icon_state = "nuketoyidle" + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + +/obj/item/toy/nuke/attack_self(mob/user) + if(cooldown < world.time) + cooldown = world.time + 1800 //3 minutes + user.visible_message("[user] presses a button on [src]", "You activate [src], it plays a loud noise!", "You hear the click of a button.") + spawn(5) //gia said so + icon_state = "nuketoy" + playsound(src, 'sound/machines/alarm.ogg', 100, 0, 0) + sleep(135) + icon_state = "nuketoycool" + sleep(cooldown - world.time) + icon_state = "nuketoyidle" + else + var/timeleft = (cooldown - world.time) + to_chat(user, "Nothing happens, and '[round(timeleft/10)]' appears on a small display.") + +/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 + resistance_flags = FLAMMABLE + +/obj/item/toy/therapy/New() + ..() + if(item_color) + name = "[item_color] therapy doll" + desc += " This one is [item_color]." + icon_state = "therapy[item_color]" + +/obj/item/toy/therapy/attack_self(mob/user) + if(cooldown < world.time - 8) + to_chat(user, "You relieve some stress with \the [src].") + playsound(user, 'sound/items/squeaktoy.ogg', 20, 1) + cooldown = world.time + +/obj/random/therapy + name = "Random Therapy Doll" + desc = "This is a random therapy doll." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyred" + +/obj/random/therapy/item_to_spawn() + return pick(subtypesof(/obj/item/toy/therapy)) //exclude the base type. + +/obj/item/toy/therapy/red + item_state = "egg4" // It's the red egg in items_left/righthand + item_color = "red" + +/obj/item/toy/therapy/purple + item_state = "egg1" // It's the magenta egg in items_left/righthand + item_color = "purple" + +/obj/item/toy/therapy/blue + item_state = "egg2" // It's the blue egg in items_left/righthand + item_color = "blue" + +/obj/item/toy/therapy/yellow + item_state = "egg5" // It's the yellow egg in items_left/righthand + item_color = "yellow" + +/obj/item/toy/therapy/orange + item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless + item_color = "orange" + +/obj/item/toy/therapy/green + item_state = "egg3" // It's the green egg in items_left/righthand + item_color = "green" + +/obj/item/toddler + icon_state = "toddler" + name = "toddler" + desc = "This baby looks almost real. Wait, did it just burp?" + force = 5 + w_class = WEIGHT_CLASS_BULKY + slot_flags = SLOT_BACK + + +//This should really be somewhere else but I don't know where. w/e + +/obj/item/inflatable_duck + name = "inflatable duck" + desc = "No bother to sink or swim when you can just float!" + icon_state = "inflatable" + item_state = "inflatable" + icon = 'icons/obj/clothing/belts.dmi' + slot_flags = SLOT_BELT + +/* + * Fake meteor + */ + +/obj/item/toy/minimeteor + name = "Mini-Meteor" + desc = "Relive the excitement of a meteor shower! SweetMeat-eor. Co is not responsible for any injuries, headaches or hearing loss caused by Mini-Meteor." + icon = 'icons/obj/toy.dmi' + icon_state = "minimeteor" + w_class = WEIGHT_CLASS_SMALL + +/obj/item/toy/minimeteor/throw_impact(atom/hit_atom) + ..() + playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) + for(var/mob/M in range(10, src)) + if(!M.stat && !istype(M, /mob/living/silicon/ai))\ + shake_camera(M, 3, 1) + qdel(src) + +/* + * Carp plushie + */ + +/obj/item/toy/carpplushie + name = "space carp plushie" + desc = "An adorable stuffed toy that resembles a space carp." + icon = 'icons/obj/toy.dmi' + icon_state = "carpplushie" + attack_verb = list("bitten", "eaten", "fin slapped") + var/bitesound = 'sound/weapons/bite.ogg' + resistance_flags = FLAMMABLE + +// Attack mob +/obj/item/toy/carpplushie/attack(mob/M as mob, mob/user as mob) + playsound(loc, bitesound, 20, 1) // Play bite sound in local area + return ..() + +// Attack self +/obj/item/toy/carpplushie/attack_self(mob/user as mob) + playsound(src.loc, bitesound, 20, 1) + return ..() + + +/obj/random/carp_plushie + name = "Random Carp Plushie" + desc = "This is a random plushie" + icon = 'icons/obj/toy.dmi' + icon_state = "carpplushie" + +/obj/random/carp_plushie/item_to_spawn() + return pick(typesof(/obj/item/toy/carpplushie)) //can pick any carp plushie, even the original. + +/obj/item/toy/carpplushie/ice + icon_state = "icecarp" + +/obj/item/toy/carpplushie/silent + icon_state = "silentcarp" + +/obj/item/toy/carpplushie/electric + icon_state = "electriccarp" + +/obj/item/toy/carpplushie/gold + icon_state = "goldcarp" + +/obj/item/toy/carpplushie/toxin + icon_state = "toxincarp" + +/obj/item/toy/carpplushie/dragon + icon_state = "dragoncarp" + +/obj/item/toy/carpplushie/pink + icon_state = "pinkcarp" + +/obj/item/toy/carpplushie/candy + icon_state = "candycarp" + +/obj/item/toy/carpplushie/nebula + icon_state = "nebulacarp" + +/obj/item/toy/carpplushie/void + icon_state = "voidcarp" + +/* + * Plushie + */ + + +/obj/item/toy/plushie + name = "plushie" + desc = "An adorable, soft, and cuddly plushie." + icon = 'icons/obj/toy.dmi' + var/poof_sound = 'sound/weapons/thudswoosh.ogg' + attack_verb = list("poofed", "bopped", "whapped","cuddled","fluffed") + resistance_flags = FLAMMABLE + +/obj/item/toy/plushie/attack(mob/M as mob, mob/user as mob) + playsound(loc, poof_sound, 20, 1) // Play the whoosh sound in local area + if(iscarbon(M)) + if(prob(10)) + M.reagents.add_reagent("hugs", 10) + return ..() + +/obj/item/toy/plushie/attack_self(mob/user as mob) + var/cuddle_verb = pick("hugs","cuddles","snugs") + user.visible_message("[user] [cuddle_verb] the [src].") + playsound(get_turf(src), poof_sound, 50, 1, -1) + return ..() + +/obj/random/plushie + name = "Random Plushie" + desc = "This is a random plushie" + icon = 'icons/obj/toy.dmi' + icon_state = "redfox" + +/obj/random/plushie/item_to_spawn() + return pick(subtypesof(/obj/item/toy/plushie) - typesof(/obj/item/toy/plushie/fluff)) //exclude the base type. + +/obj/item/toy/plushie/corgi + name = "corgi plushie" + icon_state = "corgi" + +/obj/item/toy/plushie/girly_corgi + name = "corgi plushie" + icon_state = "girlycorgi" + +/obj/item/toy/plushie/robo_corgi + name = "borgi plushie" + icon_state = "robotcorgi" + +/obj/item/toy/plushie/octopus + name = "octopus plushie" + icon_state = "loveable" + +/obj/item/toy/plushie/face_hugger + name = "facehugger plushie" + icon_state = "huggable" + +//foxes are basically the best + +/obj/item/toy/plushie/red_fox + name = "red fox plushie" + icon_state = "redfox" + +/obj/item/toy/plushie/black_fox + name = "black fox plushie" + icon_state = "blackfox" + +/obj/item/toy/plushie/marble_fox + name = "marble fox plushie" + icon_state = "marblefox" + +/obj/item/toy/plushie/blue_fox + name = "blue fox plushie" + icon_state = "bluefox" + +/obj/item/toy/plushie/orange_fox + name = "orange fox plushie" + icon_state = "orangefox" + +/obj/item/toy/plushie/coffee_fox + name = "coffee fox plushie" + icon_state = "coffeefox" + +/obj/item/toy/plushie/pink_fox + name = "pink fox plushie" + icon_state = "pinkfox" + +/obj/item/toy/plushie/purple_fox + name = "purple fox plushie" + icon_state = "purplefox" + +/obj/item/toy/plushie/crimson_fox + name = "crimson fox plushie" + icon_state = "crimsonfox" + +/obj/item/toy/plushie/deer + name = "deer plushie" + icon_state = "deer" + +/obj/item/toy/plushie/black_cat + name = "black cat plushie" + icon_state = "blackcat" + +/obj/item/toy/plushie/grey_cat + name = "grey cat plushie" + icon_state = "greycat" + +/obj/item/toy/plushie/white_cat + name = "white cat plushie" + icon_state = "whitecat" + +/obj/item/toy/plushie/orange_cat + name = "orange cat plushie" + icon_state = "orangecat" + +/obj/item/toy/plushie/siamese_cat + name = "siamese cat plushie" + icon_state = "siamesecat" + +/obj/item/toy/plushie/tabby_cat + name = "tabby cat plushie" + icon_state = "tabbycat" + +/obj/item/toy/plushie/tuxedo_cat + name = "tuxedo cat plushie" + icon_state = "tuxedocat" + +/obj/item/toy/plushie/voxplushie + name = "vox plushie" + desc = "A stitched-together vox, fresh from the skipjack. Press its belly to hear it skree!" + icon_state = "plushie_vox" + item_state = "plushie_vox" + var/cooldown = 0 + +/obj/item/toy/plushie/voxplushie/attack_self(mob/user) + if(!cooldown) + playsound(user, 'sound/voice/shriek1.ogg', 10, 0) + visible_message("Skreee!") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + +/obj/item/toy/plushie/ipcplushie + name = "IPC plushie" + desc = "An adorable IPC plushie, straight from New Canaan. Arguably more durable than the real deal. Toaster functionality included." + icon_state = "plushie_ipc" + item_state = "plushie_ipc" + +/obj/item/toy/plushie/ipcplushie/attackby(obj/item/B, mob/user, params) + if(istype(B, /obj/item/reagent_containers/food/snacks/breadslice)) + new /obj/item/reagent_containers/food/snacks/toast(get_turf(loc)) + to_chat(user, " You insert bread into the toaster. ") + playsound(loc, 'sound/machines/ding.ogg', 50, 1) + qdel(B) + else + return ..() + +//New generation TG plushies + +/obj/item/toy/plushie/lizardplushie + name = "lizard plushie" + desc = "An adorable stuffed toy that resembles a lizardperson." + icon_state = "plushie_lizard" + item_state = "plushie_lizard" + +/obj/item/toy/plushie/snakeplushie + name = "snake plushie" + desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing." + icon_state = "plushie_snake" + item_state = "plushie_snake" + +/obj/item/toy/plushie/nukeplushie + name = "operative plushie" + desc = "An stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious." + icon_state = "plushie_nuke" + item_state = "plushie_nuke" + +/obj/item/toy/plushie/slimeplushie + name = "slime plushie" + desc = "An adorable stuffed toy that resembles a slime. It is practically just a hacky sack." + icon_state = "plushie_slime" + item_state = "plushie_slime" + +/* + * Foam Armblade + */ + + /obj/item/toy/foamblade + name = "foam armblade" + desc = "it says \"Sternside Changs #1 fan\" on it. " + icon = 'icons/obj/toy.dmi' + icon_state = "foamblade" + item_state = "arm_blade" + attack_verb = list("pricked", "absorbed", "gored") + w_class = WEIGHT_CLASS_SMALL + resistance_flags = FLAMMABLE + +/* + * Toy/fake flash + */ +/obj/item/toy/flash + name = "toy flash" + desc = "FOR THE REVOLU- Oh wait, that's just a toy." + icon = 'icons/obj/device.dmi' + icon_state = "flash" + item_state = "flashtool" + w_class = WEIGHT_CLASS_TINY + +/obj/item/toy/flash/attack(mob/living/M, mob/user) + playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) + flick("[initial(icon_state)]2", src) + user.visible_message("[user] blinds [M] with the flash!") + + +/* + * Toy big red button + */ +/obj/item/toy/redbutton + name = "big red button" + desc = "A big, plastic red button. Reads 'From HonkCo Pranks?' on the back." + icon = 'icons/obj/assemblies.dmi' + icon_state = "bigred" + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + +/obj/item/toy/redbutton/attack_self(mob/user) + if(cooldown < world.time) + cooldown = (world.time + 300) // Sets cooldown at 30 seconds + user.visible_message("[user] presses the big red button.", "You press the button, it plays a loud noise!", "The button clicks loudly.") + playsound(src, 'sound/effects/explosionfar.ogg', 50, 0, 0) + for(var/mob/M in range(10, src)) // Checks range + if(!M.stat && !istype(M, /mob/living/silicon/ai)) // Checks to make sure whoever's getting shaken is alive/not the AI + sleep(8) // Short delay to match up with the explosion sound + shake_camera(M, 2, 1) // Shakes player camera 2 squares for 1 second. + + else + to_chat(user, "Nothing happens.") + + +/* + * AI core prizes + */ +/obj/item/toy/AI + name = "toy AI" + desc = "A little toy model AI core with real law announcing action!" + icon = 'icons/obj/toy.dmi' + icon_state = "AI" + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + +/obj/item/toy/AI/attack_self(mob/user) + if(!cooldown) //for the sanity of everyone + var/message = generate_ion_law() + to_chat(user, "You press the button on [src].") + playsound(user, 'sound/machines/click.ogg', 20, 1) + visible_message("[bicon(src)] [message]") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + +/obj/item/toy/codex_gigas + name = "Toy Codex Gigas" + desc = "A tool to help you write fictional devils!" + icon = 'icons/obj/library.dmi' + icon_state = "demonomicon" + w_class = WEIGHT_CLASS_SMALL + var/cooldown = FALSE + +/obj/item/toy/codex_gigas/attack_self(mob/user) + if(!cooldown) + user.visible_message( + "[user] presses the button on \the [src].", + "You press the button on \the [src].", + "You hear a soft click.") + var/list/messages = list() + var/datum/devilinfo/devil = randomDevilInfo() + messages += "Some fun facts about: [devil.truename]" + messages += "[GLOB.lawlorify[LORE][devil.bane]]" + messages += "[GLOB.lawlorify[LORE][devil.obligation]]" + messages += "[GLOB.lawlorify[LORE][devil.ban]]" + messages += "[GLOB.lawlorify[LORE][devil.banish]]" + playsound(loc, 'sound/machines/click.ogg', 20, 1) + cooldown = TRUE + for(var/message in messages) + user.loc.visible_message("[bicon(src)] [message]") + sleep(10) + spawn(20) + cooldown = FALSE + return + ..() + +/obj/item/toy/owl + name = "owl action figure" + desc = "An action figure modeled after 'The Owl', defender of justice." + icon = 'icons/obj/toy.dmi' + icon_state = "owlprize" + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + +/obj/item/toy/owl/attack_self(mob/user) + if(!cooldown) //for the sanity of everyone + var/message = pick("You won't get away this time, Griffin!", "Stop right there, criminal!", "Hoot! Hoot!", "I am the night!") + to_chat(user, "You pull the string on the [src].") + playsound(user, 'sound/creatures/hoot.ogg', 25, 1) + visible_message("[bicon(src)] [message]") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + +/obj/item/toy/griffin + name = "griffin action figure" + desc = "An action figure modeled after 'The Griffin', criminal mastermind." + icon = 'icons/obj/toy.dmi' + icon_state = "griffinprize" + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + +/obj/item/toy/griffin/attack_self(mob/user) + if(!cooldown) //for the sanity of everyone + var/message = pick("You can't stop me, Owl!", "My plan is flawless! The vault is mine!", "Caaaawwww!", "You will never catch me!") + to_chat(user, "You pull the string on the [src].") + playsound(user, 'sound/creatures/caw.ogg', 25, 1) + visible_message("[bicon(src)] [message]") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + +// DND Character minis. Use the naming convention (type)character for the icon states. +/obj/item/toy/character + icon = 'icons/obj/toy.dmi' + w_class = WEIGHT_CLASS_SMALL + pixel_z = 5 + +/obj/item/toy/character/alien + name = "Xenomorph Miniature" + desc = "A miniature xenomorph. Scary!" + icon_state = "aliencharacter" +/obj/item/toy/character/cleric + name = "Cleric Miniature" + desc = "A wee little cleric, with his wee little staff." + icon_state = "clericcharacter" +/obj/item/toy/character/warrior + name = "Warrior Miniature" + desc = "That sword would make a decent toothpick." + icon_state = "warriorcharacter" +/obj/item/toy/character/thief + name = "Thief Miniature" + desc = "Hey, where did my wallet go!?" + icon_state = "thiefcharacter" +/obj/item/toy/character/wizard + name = "Wizard Miniature" + desc = "MAGIC!" + icon_state = "wizardcharacter" +/obj/item/toy/character/cthulhu + name = "Cthulhu Miniature" + desc = "The dark lord has risen!" + icon_state = "darkmastercharacter" +/obj/item/toy/character/lich + name = "Lich Miniature" + desc = "Murderboner extraordinaire." + icon_state = "lichcharacter" +/obj/item/storage/box/characters + name = "Box of Miniatures" + desc = "The nerd's best friends." + icon_state = "box" +/obj/item/storage/box/characters/New() + ..() + new /obj/item/toy/character/alien(src) + new /obj/item/toy/character/cleric(src) + new /obj/item/toy/character/warrior(src) + new /obj/item/toy/character/thief(src) + new /obj/item/toy/character/wizard(src) + new /obj/item/toy/character/cthulhu(src) + new /obj/item/toy/character/lich(src) + + +//Pet Rocks, just like from the 70's! + +/obj/item/toy/pet_rock + name = "pet rock" + desc = "The perfect pet!" + icon = 'icons/obj/toy.dmi' + icon_state = "pet_rock" + w_class = WEIGHT_CLASS_SMALL + force = 5 + throwforce = 5 + attack_verb = list("attacked", "bashed", "smashed", "stoned") + hitsound = "swing_hit" + +/obj/item/toy/pet_rock/fred + name = "fred" + desc = "Fred, the bestest boy pet in the whole wide universe!" + icon_state = "fred" + +/obj/item/toy/pet_rock/roxie + name = "roxie" + desc = "Roxie, the bestest girl pet in the whole wide universe!" + icon_state = "roxie" + +//minigibber, so cute + +/obj/item/toy/minigibber + name = "miniature gibber" + desc = "A miniature recreation of Nanotrasen's famous meat grinder." + icon = 'icons/obj/toy.dmi' + icon_state = "minigibber" + attack_verb = list("grinded", "gibbed") + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + var/obj/stored_minature = null + +/obj/item/toy/minigibber/attack_self(var/mob/user) + + if(stored_minature) + to_chat(user, "\The [src] makes a violent grinding noise as it tears apart the miniature figure inside!") + QDEL_NULL(stored_minature) + playsound(user, 'sound/goonstation/effects/gib.ogg', 20, 1) + cooldown = world.time + + if(cooldown < world.time - 8) + to_chat(user, "You hit the gib button on \the [src].") + playsound(user, 'sound/goonstation/effects/gib.ogg', 20, 1) + cooldown = world.time + +/obj/item/toy/minigibber/attackby(var/obj/O, var/mob/user, params) + if(istype(O,/obj/item/toy/character) && O.loc == user) + to_chat(user, "You start feeding \the [O] [bicon(O)] into \the [src]'s mini-input.") + if(do_after(user, 10, target = src)) + if(O.loc != user) + to_chat(user, "\The [O] is too far away to feed into \the [src]!") + else + to_chat(user, "You feed \the [O] [bicon(O)] into \the [src]!") + user.unEquip(O) + O.forceMove(src) + stored_minature = O + else + to_chat(user, "You stop feeding \the [O] into \the [src]'s mini-input.") + else ..() + +/* + * Xenomorph action figure + */ + +/obj/item/toy/toy_xeno + icon = 'icons/obj/toy.dmi' + icon_state = "toy_xeno" + name = "xenomorph action figure" + desc = "MEGA presents the new Xenos Isolated action figure! Comes complete with realistic sounds! Pull back string to use." + w_class = WEIGHT_CLASS_SMALL + var/cooldown = 0 + +/obj/item/toy/toy_xeno/attack_self(mob/user) + if(cooldown <= world.time) + cooldown = (world.time + 50) //5 second cooldown + user.visible_message("[user] pulls back the string on [src].") + icon_state = "[initial(icon_state)]_used" + sleep(5) + audible_message("[bicon(src)] Hiss!") + var/list/possible_sounds = list('sound/voice/hiss1.ogg', 'sound/voice/hiss2.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg') + playsound(get_turf(src), pick(possible_sounds), 50, 1) + spawn(45) + if(src) + icon_state = "[initial(icon_state)]" + else + to_chat(user, "The string on [src] hasn't rewound all the way!") + return + +/obj/item/toy/russian_revolver + name = "russian revolver" + desc = "for fun and games!" + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "detective_gold" + item_state = "gun" + lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/guns_righthand.dmi' + hitsound = "swing_hit" + flags = CONDUCT + slot_flags = SLOT_BELT + materials = list(MAT_METAL=2000) + w_class = WEIGHT_CLASS_NORMAL + throwforce = 5 + throw_speed = 4 + throw_range = 5 + force = 5 + origin_tech = "combat=1" + attack_verb = list("struck", "hit", "bashed") + var/bullets_left = 0 + var/max_shots = 6 + +/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 [user.p_their()] head before pulling the trigger! It looks like [user.p_theyre()] trying to commit suicide.") + playsound(loc, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1) + return BRUTELOSS + +/obj/item/toy/russian_revolver/New() + ..() + spin_cylinder() + +/obj/item/toy/russian_revolver/attack_self(mob/user) + if(!bullets_left) + user.visible_message("[user] loads a bullet into [src]'s cylinder before spinning it.") + spin_cylinder() + else + user.visible_message("[user] spins the cylinder on [src]!") + spin_cylinder() + +/obj/item/toy/russian_revolver/attack(mob/M, mob/living/user) + return + +/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, flag, params) + if(flag) + if(target in user.contents) + return + if(!ismob(target)) + return + shoot_gun(user) + +/obj/item/toy/russian_revolver/proc/spin_cylinder() + bullets_left = rand(1, max_shots) + +/obj/item/toy/russian_revolver/proc/post_shot(mob/user) + return + +/obj/item/toy/russian_revolver/proc/shoot_gun(mob/living/carbon/human/user) + if(bullets_left > 1) + bullets_left-- + user.visible_message("*click*") + playsound(src, 'sound/weapons/empty.ogg', 100, 1) + return FALSE + if(bullets_left == 1) + bullets_left = 0 + var/zone = "head" + if(!(user.has_organ(zone))) // If they somehow don't have a head. + zone = "chest" + playsound(src, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1) + user.visible_message("[src] goes off!") + post_shot(user) + user.apply_damage(300, BRUTE, zone, sharp = TRUE, used_weapon = "Self-inflicted gunshot wound to the [zone].") + user.bleed(BLOOD_VOLUME_NORMAL) + user.death() // Just in case + return TRUE + else + to_chat(user, "[src] needs to be reloaded.") + return FALSE + +/obj/item/toy/russian_revolver/trick_revolver + name = "\improper .357 revolver" + desc = "A suspicious revolver. Uses .357 ammo." + icon_state = "revolver" + max_shots = 1 + var/fake_bullets = 0 + +/obj/item/toy/russian_revolver/trick_revolver/New() + ..() + fake_bullets = rand(2, 7) + +/obj/item/toy/russian_revolver/trick_revolver/examine(mob/user) //Sneaky sneaky + . = ..() + . += "Has [fake_bullets] round\s remaining." + . += "[fake_bullets] of those are live rounds." + +/obj/item/toy/russian_revolver/trick_revolver/post_shot(user) + to_chat(user, "[src] did look pretty dodgey!") + SEND_SOUND(user, 'sound/misc/sadtrombone.ogg') //HONK +/* + * Rubber Chainsaw + */ +/obj/item/twohanded/toy/chainsaw + name = "Toy Chainsaw" + desc = "A toy chainsaw with a rubber edge. Ages 8 and up" + icon_state = "chainsaw0" + force = 0 + throwforce = 0 + throw_speed = 4 + throw_range = 20 + wieldsound = 'sound/weapons/chainsawstart.ogg' + attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered") + +/obj/item/twohanded/toy/chainsaw/update_icon() + if(wielded) + icon_state = "chainsaw[wielded]" + else + icon_state = "chainsaw0" + +/* + * Cat Toy + */ +/obj/item/toy/cattoy + name = "toy mouse" + desc = "A colorful toy mouse!" + icon = 'icons/obj/toy.dmi' + icon_state = "toy_mouse" + w_class = WEIGHT_CLASS_SMALL + resistance_flags = FLAMMABLE + var/cooldown = 0 + +/* + * Action Figures + */ + + +/obj/random/figure + name = "Random Action Figure" + desc = "This is a random toy action figure" + icon = 'icons/obj/toy.dmi' + icon_state = "nuketoy" + +/obj/random/figure/item_to_spawn() + return pick(subtypesof(/obj/item/toy/figure)) + + +/obj/item/toy/figure + name = "Non-Specific Action Figure action figure" + desc = "A \"Space Life\" brand... wait, what the hell is this thing?" + icon = 'icons/obj/toy.dmi' + icon_state = "nuketoy" + var/cooldown = 0 + var/toysay = "What the fuck did you do?" + +/obj/item/toy/figure/New() + ..() + desc = "A \"Space Life\" brand [name]" + +/obj/item/toy/figure/attack_self(mob/user as mob) + if(cooldown < world.time) + cooldown = (world.time + 30) //3 second cooldown + user.visible_message("[bicon(src)] The [src] says \"[toysay]\".") + playsound(user, 'sound/machines/click.ogg', 20, 1) + +/obj/item/toy/figure/cmo + name = "Chief Medical Officer action figure" + icon_state = "cmo" + toysay = "Suit sensors!" + +/obj/item/toy/figure/assistant + name = "Assistant action figure" + icon_state = "assistant" + toysay = "Grey tide station wide!" + +/obj/item/toy/figure/atmos + name = "Atmospheric Technician action figure" + icon_state = "atmos" + toysay = "Glory to Atmosia!" + +/obj/item/toy/figure/bartender + name = "Bartender action figure" + icon_state = "bartender" + toysay = "Wheres my monkey?" + +/obj/item/toy/figure/borg + name = "Cyborg action figure" + icon_state = "borg" + toysay = "I. LIVE. AGAIN." + +/obj/item/toy/figure/botanist + name = "Botanist action figure" + icon_state = "botanist" + toysay = "Dude, I see colors..." + +/obj/item/toy/figure/captain + name = "Captain action figure" + icon_state = "captain" + toysay = "Crew, the Nuke Disk is safely up my ass." + +/obj/item/toy/figure/cargotech + name = "Cargo Technician action figure" + icon_state = "cargotech" + toysay = "For Cargonia!" + +/obj/item/toy/figure/ce + name = "Chief Engineer action figure" + icon_state = "ce" + toysay = "Wire the solars!" + +/obj/item/toy/figure/chaplain + name = "Chaplain action figure" + icon_state = "chaplain" + toysay = "Gods make me a killing machine please!" + +/obj/item/toy/figure/chef + name = "Chef action figure" + icon_state = "chef" + toysay = "I swear it's not human meat." + +/obj/item/toy/figure/chemist + name = "Chemist action figure" + icon_state = "chemist" + toysay = "Get your pills!" + +/obj/item/toy/figure/clown + name = "Clown action figure" + icon_state = "clown" + toysay = "Honk!" + +/obj/item/toy/figure/ian + name = "Ian action figure" + icon_state = "ian" + toysay = "Arf!" + +/obj/item/toy/figure/detective + name = "Detective action figure" + icon_state = "detective" + toysay = "This airlock has grey jumpsuit and insulated glove fibers on it." + +/obj/item/toy/figure/dsquad + name = "Death Squad Officer action figure" + icon_state = "dsquad" + toysay = "Eliminate all threats!" + +/obj/item/toy/figure/engineer + name = "Engineer action figure" + icon_state = "engineer" + toysay = "Oh god, the singularity is loose!" + +/obj/item/toy/figure/geneticist + name = "Geneticist action figure" + icon_state = "geneticist" + toysay = "I'm not qualified for this job." + +/obj/item/toy/figure/hop + name = "Head of Personnel action figure" + icon_state = "hop" + toysay = "Giving out all access!" + +/obj/item/toy/figure/hos + name = "Head of Security action figure" + icon_state = "hos" + toysay = "I'm here to win, anything else is secondary." + +/obj/item/toy/figure/qm + name = "Quartermaster action figure" + icon_state = "qm" + toysay = "Hail Cargonia!" + +/obj/item/toy/figure/janitor + name = "Janitor action figure" + icon_state = "janitor" + toysay = "Look at the signs, you idiot." + +/obj/item/toy/figure/lawyer + name = "Internal Affairs Agent action figure" + icon_state = "lawyer" + toysay = "Standard Operating Procedure says they're guilty! Hacking is proof they're an Enemy of the Corporation!" + +/obj/item/toy/figure/librarian + name = "Librarian action figure" + icon_state = "librarian" + toysay = "One day while..." + +/obj/item/toy/figure/md + name = "Medical Doctor action figure" + icon_state = "md" + toysay = "The patient is already dead!" + +/obj/item/toy/figure/mime + name = "Mime action figure" + desc = "A \"Space Life\" brand Mime action figure." + icon_state = "mime" + toysay = "..." + +/obj/item/toy/figure/miner + name = "Shaft Miner action figure" + icon_state = "miner" + toysay = "Oh god it's eating my intestines!" + +/obj/item/toy/figure/ninja + name = "Ninja action figure" + icon_state = "ninja" + toysay = "Oh god! Stop shooting, I'm friendly!" + +/obj/item/toy/figure/wizard + name = "Wizard action figure" + icon_state = "wizard" + toysay = "Ei Nath!" + +/obj/item/toy/figure/rd + name = "Research Director action figure" + icon_state = "rd" + toysay = "Blowing all of the borgs!" + +/obj/item/toy/figure/roboticist + name = "Roboticist action figure" + icon_state = "roboticist" + toysay = "He asked to be borged!" + +/obj/item/toy/figure/scientist + name = "Scientist action figure" + icon_state = "scientist" + toysay = "Someone else must have made those bombs!" + +/obj/item/toy/figure/syndie + name = "Nuclear Operative action figure" + icon_state = "syndie" + toysay = "Get that fucking disk!" + +/obj/item/toy/figure/secofficer + name = "Security Officer action figure" + icon_state = "secofficer" + toysay = "I am the law!" + +/obj/item/toy/figure/virologist + name = "Virologist action figure" + icon_state = "virologist" + toysay = "The cure is potassium!" + +/obj/item/toy/figure/warden + name = "Warden action figure" + icon_state = "warden" + toysay = "Execute him for breaking in!" + +////////////////////////////////////////////////////// +// Magic 8-Ball / Conch // +////////////////////////////////////////////////////// + +/obj/item/toy/eight_ball + name = "Magic 8-Ball" + desc = "Mystical! Magical! Ages 8+!" + icon = 'icons/obj/toy.dmi' + icon_state = "eight-ball" + var/use_action = "shakes the ball" + var/cooldown = 0 + var/list/possible_answers = list("Definitely", "All signs point to yes.", "Most likely.", "Yes.", "Ask again later.", "Better not tell you now.", "Future Unclear.", "Maybe.", "Doubtful.", "No.", "Don't count on it.", "Never.") + +/obj/item/toy/eight_ball/attack_self(mob/user as mob) + if(!cooldown) + var/answer = pick(possible_answers) + 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 + return + +/obj/item/toy/eight_ball/conch + name = "Magic Conch Shell" + desc = "All hail the Magic Conch!" + icon_state = "conch" + use_action = "pulls the string" + possible_answers = list("Yes.", "No.", "Try asking again.", "Nothing.", "I don't think so.", "Neither.", "Maybe someday.") + +/* + *Fake cuffs (honk honk) + */ + +/obj/item/restraints/handcuffs/toy + desc = "Toy handcuffs. Plastic and extremely cheaply made." + throwforce = 0 + breakouttime = 0 + ignoresClumsy = TRUE From 4ab914da43c5081aec2aa4e58fc18cf79402b584 Mon Sep 17 00:00:00 2001 From: SteelSlayer Date: Sat, 13 Jun 2020 13:31:56 -0500 Subject: [PATCH 11/61] removes references to console screens --- code/game/machinery/constructable_frame.dm | 68 ++++++++++++++-------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 92db2f4a419..9ee9f5df959 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -218,7 +218,7 @@ //Machine Frame Circuit Boards /*Common Parts: Parts List: Ignitor, Timer, Infra-red laser, Infra-red sensor, t_scanner, Capacitor, Valve, sensor unit, -micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. +micro-manipulator, glass sheets, beaker, Microlaser, matter bin, power cells. Note: Once everything is added to the public areas, will add MAT_METAL and MAT_GLASS to circuit boards since autolathe won't be able to destroy them and players will be able to make replacements. */ @@ -293,6 +293,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/emitter board_type = "machine" origin_tech = "programming=3;powerstorage=4;engineering=4" + frame_desc = "Requires 1 Micro Laser and 1 Manipulator." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stock_parts/manipulator = 1) @@ -302,6 +303,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/compressor board_type = "machine" origin_tech = "programming=4;powerstorage=4;engineering=4" + frame_desc = "Requires 5 pieces of cable and 6 Manipulators." req_components = list( /obj/item/stack/cable_coil = 5, /obj/item/stock_parts/manipulator = 6) @@ -311,6 +313,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/turbine board_type = "machine" origin_tech = "programming=4;powerstorage=4;engineering=4" + frame_desc = "Requires 5 pieces of cable and 6 Manipulators." req_components = list( /obj/item/stack/cable_coil = 5, /obj/item/stock_parts/capacitor = 6) @@ -321,7 +324,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/atmospherics/unary/cold_sink/freezer board_type = "machine" origin_tech = "programming=3;plasmatech=3" - frame_desc = "Requires 2 Matter Bins, 2 Micro Lasers, 1 piece of cable and 1 Console Screen." + frame_desc = "Requires 2 Matter Bins, 2 Micro Lasers, 1 piece of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/micro_laser = 2, @@ -364,7 +367,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/biogenerator board_type = "machine" origin_tech = "programming=2;biotech=3;materials=3" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 1 Console Screen." + frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -376,7 +379,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/plantgenes board_type = "machine" origin_tech = "programming=3;biotech=3" - frame_desc = "Requires 1 Manipulator, 1 Micro Laser, 1 Console Screen, and 1 Scanning Module." + frame_desc = "Requires 1 Manipulator, 1 Micro Laser, 1 Sheet of glass, and 1 Scanning Module." req_components = list( /obj/item/stock_parts/manipulator = 1, /obj/item/stock_parts/micro_laser = 1, @@ -400,7 +403,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/hydroponics/constructable board_type = "machine" origin_tech = "programming=1;biotech=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulator, and 1 Console Screen." + frame_desc = "Requires 2 Matter Bins, 1 Manipulator, and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -411,7 +414,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/microwave board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 1 Micro Laser, 2 pieces of cable and 1 Console Screen." + frame_desc = "Requires 1 Micro Laser, 2 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/cable_coil = 2, @@ -422,7 +425,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/oven board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Console Screen." + frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5, @@ -433,7 +436,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/grill board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Console Screen." + frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5, @@ -444,7 +447,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/candy_maker board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 1 Manipulator, 5 pieces of cable and 1 Console Screen." + frame_desc = "Requires 1 Manipulator, 5 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/manipulator = 1, /obj/item/stack/cable_coil = 5, @@ -455,7 +458,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/cooker/deepfryer board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 2 Micro Lasers and 5 pieces of cable." + frame_desc = "Requires 2 Micro Laser and 5 pieces of cable." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5) @@ -465,6 +468,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/gibber board_type = "machine" origin_tech = "programming=2;engineering=2" + frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -474,6 +478,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/tesla_coil board_type = "machine" origin_tech = "programming=3;magnets=3;powerstorage=3" + frame_desc = "Requires 1 Capacitor." req_components = list( /obj/item/stock_parts/capacitor = 1) @@ -482,6 +487,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/grounding_rod board_type = "machine" origin_tech = "programming=3;powerstorage=3;magnets=3;plasmatech=2" + frame_desc = "Requires 1 Capacitor." req_components = list( /obj/item/stock_parts/capacitor = 1) @@ -490,6 +496,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/processor board_type = "machine" origin_tech = "programming=1" + frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -499,6 +506,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/recycler board_type = "machine" origin_tech = "programming=2;engineering=2" + frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -508,6 +516,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/smartfridge board_type = "machine" origin_tech = "programming=1" + frame_desc = "Requires 1 Matter bin." req_components = list( /obj/item/stock_parts/matter_bin = 1) var/list/fridge_names_paths = list( @@ -551,6 +560,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/monkey_recycler board_type = "machine" origin_tech = "programming=1;biotech=2" + frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -560,6 +570,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/hologram/holopad board_type = "machine" origin_tech = "programming=1" + frame_desc = "Requires 1 Capacitor." req_components = list( /obj/item/stock_parts/capacitor = 1) @@ -568,7 +579,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_dispenser board_type = "machine" origin_tech = "materials=4;programming=4;plasmatech=4;biotech=3" - frame_desc = "Requires 2 Matter Bins, 1 Capacitor, 1 Manipulator, 1 Console Screen, and 1 Power Cell." + frame_desc = "Requires 2 Matter Bins, 1 Capacitor, 1 Manipulator, 1 Sheet of glass, and 1 Power Cell." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/capacitor = 1, /obj/item/stock_parts/manipulator = 1, @@ -580,6 +591,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_master board_type = "machine" origin_tech = "materials=3;programming=2;biotech=3" + frame_desc = "Requires 1 Manipulator, 2 Beakers and 1 Sheet of glass." req_components = list( /obj/item/reagent_containers/glass/beaker = 2, /obj/item/stock_parts/manipulator = 1, @@ -609,7 +621,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_heater board_type = "machine" origin_tech = "programming=2;engineering=2;biotech=2" - frame_desc = "Requires 1 Micro Laser and 1 Console Screen." + frame_desc = "Requires 1 Micro Laser and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/sheet/glass = 1) @@ -630,6 +642,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/experimentor board_type = "machine" origin_tech = "magnets=1;engineering=1;programming=1;biotech=1;bluespace=2" + frame_desc = "Requires 2 Micro Lasers, 2 Manipulators and 1 Scanning Module." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 2, @@ -640,7 +653,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/destructive_analyzer board_type = "machine" origin_tech = "magnets=2;engineering=2;programming=2" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, and 1 Micro-Laser." + frame_desc = "Requires 1 Scanning Module, 1 Manipulator, and 1 Micro Laser." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 1, @@ -651,7 +664,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/autolathe board_type = "machine" origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 3 Matter Bins, 1 Manipulator, and 1 Console Screen." + frame_desc = "Requires 3 Matter Bins, 1 Manipulator, and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 3, /obj/item/stock_parts/manipulator = 1, @@ -692,7 +705,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/port_gen/pacman board_type = "machine" origin_tech = "programming=2;powerstorage=3;plasmatech=3;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Micro-Laser, 2 Pieces of Cable, and 1 Capacitor." + frame_desc = "Requires 1 Matter Bin, 1 Micro Laser, 2 Pieces of Cable, and 1 Capacitor." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/micro_laser = 1, @@ -724,7 +737,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mecha_part_fabricator board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulator, 1 Micro-Laser and 1 Console Screen." + frame_desc = "Requires 2 Matter Bins, 1 Manipulator, 1 Micro Laser and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -736,7 +749,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mecha_part_fabricator/spacepod board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulators, 1 Micro-Lasers, and 1 Console Screen." + frame_desc = "Requires 2 Matter Bins, 1 Manipulators, 1 Micro Laser, and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -749,7 +762,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/clonepod board_type = "machine" origin_tech = "programming=2;biotech=2" - frame_desc = "Requires 2 Manipulator, 2 Scanning Module, 2 pieces of cable and 1 Console Screen." + frame_desc = "Requires 2 Manipulator, 2 Scanning Module, 2 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stack/cable_coil = 2, /obj/item/stock_parts/scanning_module = 2, @@ -761,7 +774,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/dna_scannernew board_type = "machine" origin_tech = "programming=2;biotech=2" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, 1 Micro-Laser, 2 pieces of cable and 1 Console Screen." + frame_desc = "Requires 1 Scanning Module, 1 Manipulator, 1 Micro Laser, 2 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 1, @@ -794,7 +807,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/teleport/station board_type = "machine" origin_tech = "programming=4;engineering=4;bluespace=4;plasmatech=3" - frame_desc = "Requires 2 Bluespace Crystals, 2 Capacitors and 1 Console Screen." + frame_desc = "Requires 2 Bluespace Crystals, 2 Capacitors and 1 Sheet of glass." req_components = list( /obj/item/stack/ore/bluespace_crystal = 2, /obj/item/stock_parts/capacitor = 2, @@ -825,7 +838,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/telepad board_type = "machine" origin_tech = "programming=4;engineering=3;plasmatech=4;bluespace=4" - frame_desc = "Requires 2 Bluespace Crystals, 1 Capacitor, 1 piece of cable and 1 Console Screen." + frame_desc = "Requires 2 Bluespace Crystals, 1 Capacitor, 1 piece of cable and 1 Sheet of glass." req_components = list( /obj/item/stack/ore/bluespace_crystal = 2, /obj/item/stock_parts/capacitor = 1, @@ -849,7 +862,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/sleeper board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 2 Console Screens." + frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 2 Sheets of glasss." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -870,7 +883,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/bodyscanner board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Scanning Module, 2 pieces of cable and 2 Console Screens." + frame_desc = "Requires 1 Scanning Module, 2 pieces of cable and 2 Sheets of glasss." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stack/cable_coil = 2, @@ -881,7 +894,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/atmospherics/unary/cryo_cell board_type = "machine" origin_tech = "programming=4;biotech=3;engineering=4;plasmatech=3" - frame_desc = "Requires 1 Matter Bin, 1 piece of cable and 4 Console Screens." + frame_desc = "Requires 1 Matter Bin, 1 piece of cable and 4 Sheets of glasss." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stack/cable_coil = 1, @@ -920,6 +933,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mineral/ore_redemption board_type = "machine" origin_tech = "programming=1;engineering=2" + frame_desc = "Requires 1 Matter Bin, 1 Micro-manipulator, 1 Micro Laser, 1 Igniter and 1 Sheets of glasss." req_components = list( /obj/item/stack/sheet/glass = 1, /obj/item/stock_parts/matter_bin = 1, @@ -936,6 +950,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mineral/equipment_vendor board_type = "machine" origin_tech = "programming=1;engineering=3" + frame_desc = "Requires 3 Matter bins and 1 Sheet of glass." req_components = list( /obj/item/stack/sheet/glass = 1, /obj/item/stock_parts/matter_bin = 3) @@ -949,6 +964,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/arcade/claw board_type = "machine" origin_tech = "programming=1" + frame_desc = "Requires 1 Matter bin, 1 Manipulator, 5 pieces of cable coil and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -960,6 +976,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/prize_counter board_type = "machine" origin_tech = "programming=1" + frame_desc = "Requires 1 Matter bin, 1 Manipulator, 1 piece of cable coil and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -971,6 +988,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/gameboard board_type = "machine" origin_tech = "programming=1" + frame_desc = "Requires 1 Micro Laser, 3 pieces of cable coil and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/cable_coil = 3, @@ -982,8 +1000,8 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/logic_gate board_type = "machine" origin_tech = "programming=1" //This stuff is pretty much the absolute basis of programming, so it's mostly useless for research + frame_desc = "Requires 1 piece of cable coil." req_components = list(/obj/item/stack/cable_coil = 1) - var/list/names_paths = list( "NOT Gate" = /obj/machinery/logic_gate/not, "OR Gate" = /obj/machinery/logic_gate/or, From e368309557f53790eee5850bf896ba16b5f01980 Mon Sep 17 00:00:00 2001 From: SteelSlayer Date: Sat, 13 Jun 2020 13:56:38 -0500 Subject: [PATCH 12/61] no more triple s --- code/game/machinery/constructable_frame.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 9ee9f5df959..2927e5dea3a 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -862,7 +862,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/sleeper board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 2 Sheets of glasss." + frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 2 Sheets of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -883,7 +883,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/bodyscanner board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Scanning Module, 2 pieces of cable and 2 Sheets of glasss." + frame_desc = "Requires 1 Scanning Module, 2 pieces of cable and 2 Sheets of glass." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stack/cable_coil = 2, @@ -894,7 +894,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/atmospherics/unary/cryo_cell board_type = "machine" origin_tech = "programming=4;biotech=3;engineering=4;plasmatech=3" - frame_desc = "Requires 1 Matter Bin, 1 piece of cable and 4 Sheets of glasss." + frame_desc = "Requires 1 Matter Bin, 1 piece of cable and 4 Sheets of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stack/cable_coil = 1, @@ -933,7 +933,7 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mineral/ore_redemption board_type = "machine" origin_tech = "programming=1;engineering=2" - frame_desc = "Requires 1 Matter Bin, 1 Micro-manipulator, 1 Micro Laser, 1 Igniter and 1 Sheets of glasss." + frame_desc = "Requires 1 Matter Bin, 1 Micro-manipulator, 1 Micro Laser, 1 Igniter and 1 Sheets of glass." req_components = list( /obj/item/stack/sheet/glass = 1, /obj/item/stock_parts/matter_bin = 1, From 4330fde443d78ab3f084ccb6a59f61675cde372f Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Sun, 14 Jun 2020 10:20:09 +0100 Subject: [PATCH 13/61] Removes Non-existent docking port from Delta --- _maps/map_files/Delta/delta.dmm | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/_maps/map_files/Delta/delta.dmm b/_maps/map_files/Delta/delta.dmm index 171e1ffde1a..a8fefed799d 100644 --- a/_maps/map_files/Delta/delta.dmm +++ b/_maps/map_files/Delta/delta.dmm @@ -112194,17 +112194,6 @@ /obj/effect/decal/warning_stripes/west, /turf/simulated/floor/plasteel, /area/shuttle/escape) -"dTU" = ( -/obj/docking_port/stationary{ - dir = 8; - dwidth = 3; - height = 5; - id = "sit_scimaint"; - name = "Cyberiad Science Maint"; - width = 11 - }, -/turf/space, -/area/space/nearstation) "dTV" = ( /obj/machinery/power/solar{ name = "Aft Starboard Solar Panel" @@ -170544,7 +170533,7 @@ aaa aaa aaa aaa -dTU +aaa aaa aaa aaa From 46aea3f0dcf29be7120861024eef11d85400feb1 Mon Sep 17 00:00:00 2001 From: mochi Date: Sun, 14 Jun 2020 21:00:29 +0200 Subject: [PATCH 14/61] Fix HUDs taking parent atom's color/alpha --- code/modules/mob/mob.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 235996e571f..7d9aa6e7fb1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -42,6 +42,7 @@ hud_list[hud] = list() else var/image/I = image('icons/mob/hud.dmi', src, "") + I.appearance_flags = RESET_COLOR | RESET_ALPHA hud_list[hud] = I /mob/proc/generate_name() From abb25ba76073742a414c1b9aa25b25abf3ab1c18 Mon Sep 17 00:00:00 2001 From: mochi Date: Sun, 14 Jun 2020 21:16:48 +0200 Subject: [PATCH 15/61] HUDs gotta take their atom's alpha after all --- code/modules/mob/mob.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 7d9aa6e7fb1..62037219eeb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -42,7 +42,7 @@ hud_list[hud] = list() else var/image/I = image('icons/mob/hud.dmi', src, "") - I.appearance_flags = RESET_COLOR | RESET_ALPHA + I.appearance_flags = RESET_COLOR hud_list[hud] = I /mob/proc/generate_name() From aa65e6b0222c4019c44e94d142f1066984f91b36 Mon Sep 17 00:00:00 2001 From: joep van der velden Date: Sun, 14 Jun 2020 23:33:30 +0200 Subject: [PATCH 16/61] Ports TGs way of handling bullet_act on shooting targets --- code/game/objects/items/shooting_range.dm | 134 ++++++---------------- 1 file changed, 34 insertions(+), 100 deletions(-) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 8b85d8821d9..bffb9e449f7 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -4,24 +4,23 @@ desc = "A shooting target." icon = 'icons/obj/objects.dmi' icon_state = "target_h" - density = 0 + density = FALSE var/hp = 1800 - var/icon/virtualIcon - var/list/bulletholes = list() /obj/item/target/Destroy() + cut_overlays() // if a target is deleted and associated with a stake, force stake to forget - for(var/obj/structure/target_stake/T in view(3,src)) + for(var/obj/structure/target_stake/T in view(3, src)) if(T.pinned_target == src) T.pinned_target = null - T.density = 1 + T.density = TRUE break return ..() // delete target /obj/item/target/Move() ..() // After target moves, check for nearby stakes. If associated, move to target - for(var/obj/structure/target_stake/M in view(3,src)) + for(var/obj/structure/target_stake/M in view(3, src)) if(M.density == 0 && M.pinned_target == src) M.loc = loc @@ -33,12 +32,12 @@ /obj/item/target/welder_act(mob/user, obj/item/I) . = TRUE - if(!use_tool(src, user, 0,, volume = I.tool_volume)) + if(!use_tool(src, user, 0, volume = I.tool_volume)) return overlays.Cut() - to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") + to_chat(user, "You slice off [src]'s uneven chunks of aluminium and scorch marks.") -/obj/item/target/attack_hand(mob/user as mob) +/obj/item/target/attack_hand(mob/user) // taking pinned targets off! var/obj/structure/target_stake/stake for(var/obj/structure/target_stake/T in view(3,src)) @@ -48,8 +47,8 @@ if(stake) if(stake.pinned_target) - stake.density = 1 - density = 0 + stake.density = TRUE + density = FALSE layer = OBJ_LAYER loc = user.loc @@ -77,101 +76,36 @@ desc = "A shooting target that looks like a xenomorphic alien." hp = 2350 // alium onest too kinda -/obj/item/target/bullet_act(var/obj/item/projectile/Proj) - var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!" - var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1) - var/decaltype = 1 // 1 - scorch, 2 - bullet +#define DECALTYPE_SCORCH 1 +#define DECALTYPE_BULLET 2 - if(istype(/obj/item/projectile/bullet, Proj)) - decaltype = 2 - - - virtualIcon = new(icon, icon_state) - - if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null) - - hp -= Proj.damage +/obj/item/target/bullet_act(obj/item/projectile/P) + var/p_x = P.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset P.p_x!" + var/p_y = P.p_y + pick(0,0,0,0,0,-1,1) + var/decaltype = DECALTYPE_SCORCH + if(istype(P, /obj/item/projectile/bullet)) + decaltype = DECALTYPE_BULLET + var/icon/C = icon(icon, icon_state) + if(C.GetPixel(p_x, p_y) && LAZYLEN(overlays) <= 35) // if the located pixel isn't blank (null) + hp -= P.damage if(hp <= 0) - visible_message("[src] breaks into tiny pieces and collapses!") + visible_message("[src] breaks into tiny pieces and collapses!") qdel(src) - - // Create a temporary object to represent the damage - var/obj/bmark = new - bmark.pixel_x = p_x - bmark.pixel_y = p_y - bmark.icon = 'icons/effects/effects.dmi' - bmark.layer = 3.5 - bmark.icon_state = "scorch" - - if(decaltype == 1) - // Energy weapons are hot. they scorch! - - // offset correction - bmark.pixel_x-- - bmark.pixel_y-- - - if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice)) - bmark.icon_state = "scorch" - bmark.dir = pick(NORTH,SOUTH,EAST,WEST) // random scorch design - - + return + var/image/bullet_hole = image('icons/effects/effects.dmi', "scorch", OBJ_LAYER + 0.5) + bullet_hole.pixel_x = p_x - 1 //offset correction + bullet_hole.pixel_y = p_y - 1 + if(decaltype == DECALTYPE_SCORCH) + if(P.damage >= 20 || istype(P, /obj/item/projectile/beam/practice)) + bullet_hole.setDir(pick(NORTH,SOUTH,EAST,WEST))// random scorch design. light_scorch does not have different directions else - bmark.icon_state = "light_scorch" + bullet_hole.icon_state = "light_scorch" else - - // Bullets are hard. They make dents! - bmark.icon_state = "dent" - - if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes - if(decaltype == 2) // bullet - if(prob(Proj.damage+30)) // bullets make holes more commonly! - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole - else // Lasers! - if(prob(Proj.damage-10)) // lasers make holes less commonly - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole - - // draw bullet holes - for(var/datum/bullethole/B in bulletholes) - - virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right - virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom - - overlays += bmark // add the decal - - icon = virtualIcon // apply bulletholes over decals - + bullet_hole.icon_state = "dent" + add_overlay(bullet_hole) return return -1 // the bullet/projectile goes through the target! Ie, you missed - -// Small memory holder entity for transparent bullet holes -/datum/bullethole - // First box - var/b1x1 = 0 - var/b1x2 = 0 - var/b1y = 0 - - // Second box - var/b2x = 0 - var/b2y1 = 0 - var/b2y2 = 0 - -/datum/bullethole/New(obj/item/target/Target, pixel_x = 0, pixel_y = 0) - if(!Target) return - - // Randomize the first box - b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4) - b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4) - b1y = pixel_y - if(prob(35)) - b1y += rand(-4,4) - - // Randomize the second box - b2x = pixel_x - if(prob(35)) - b2x += rand(-4,4) - b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4) - b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4) - - Target.bulletholes.Add(src) +#undef DECALTYPE_SCORCH +#undef DECALTYPE_BULLET From 92d143e4ab42c86231d783ccc4ec5d6ca0927789 Mon Sep 17 00:00:00 2001 From: joep van der velden Date: Mon, 15 Jun 2020 07:36:31 +0200 Subject: [PATCH 17/61] small optimization --- code/game/objects/items/shooting_range.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index bffb9e449f7..41b546a0b52 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -85,8 +85,7 @@ var/decaltype = DECALTYPE_SCORCH if(istype(P, /obj/item/projectile/bullet)) decaltype = DECALTYPE_BULLET - var/icon/C = icon(icon, icon_state) - if(C.GetPixel(p_x, p_y) && LAZYLEN(overlays) <= 35) // if the located pixel isn't blank (null) + if(LAZYLEN(overlays) <= 35 && icon(icon, icon_state).GetPixel(p_x, p_y)) // if the located pixel isn't blank (null) hp -= P.damage if(hp <= 0) visible_message("[src] breaks into tiny pieces and collapses!") From c70b5a2f05703eb715277f0b5b539040dacf5c2c Mon Sep 17 00:00:00 2001 From: joep van der velden Date: Mon, 15 Jun 2020 09:14:56 +0200 Subject: [PATCH 18/61] sure travis --- code/game/objects/items/shooting_range.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 41b546a0b52..9b24b1efce6 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -85,7 +85,9 @@ var/decaltype = DECALTYPE_SCORCH if(istype(P, /obj/item/projectile/bullet)) decaltype = DECALTYPE_BULLET - if(LAZYLEN(overlays) <= 35 && icon(icon, icon_state).GetPixel(p_x, p_y)) // if the located pixel isn't blank (null) + + var/icon/C = icon(icon, icon_state) + if(LAZYLEN(overlays) <= 35 && C.GetPixel(p_x, p_y)) // if the located pixel isn't blank (null) hp -= P.damage if(hp <= 0) visible_message("[src] breaks into tiny pieces and collapses!") From 559f907e9ca6a1f9c9c6245ffad72ab45e8d98fe Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Mon, 15 Jun 2020 10:21:48 +0100 Subject: [PATCH 19/61] Fixes shuttle exploit --- code/modules/shuttle/shuttle.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 0f872b599a1..fd4bb0b6ad5 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -809,7 +809,8 @@ if(href_list["move"]) if(!options.Find(href_list["move"])) //I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. // Seriously, though, NEVER trust a Topic with something like this. Ever. - message_admins("move HREF ([src] attempted to move to: [href_list["move"]]) exploit attempted by [key_name_admin(usr)] on [src] (JMP)") + // Sidenote for whoever did this last. Why did you set it to echo whatever the user entered to admin chat? You solved one exploit and created another. + message_admins("EXPLOIT: [ADMIN_LOOKUPFLW(usr)] attempted to move [src] to an invalid location! [ADMIN_COORDJMP(src)]") return switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1, usr)) if(0) From 15ca95df972a679163465320c57d993ea7c40820 Mon Sep 17 00:00:00 2001 From: trololiver112 <59520813+trololiver112@users.noreply.github.com> Date: Mon, 15 Jun 2020 16:19:46 +0200 Subject: [PATCH 20/61] Fixes shadowling darksight not toggling nightvision --- code/game/gamemodes/shadowling/shadowling_abilities.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index 2cafb1bc219..276b03defdf 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -186,9 +186,12 @@ if(!H.vision_type) to_chat(H, "You shift the nerves in your eyes, allowing you to see in the dark.") H.vision_type = new vision_path + H.update_sight() + else to_chat(H, "You return your vision to normal.") H.vision_type = null + H.update_sight() /obj/effect/proc_holder/spell/targeted/shadow_vision/thrall desc = "Thrall Darksight" From 6cdce262e990c3d0b00d02f22e4fd2e661d7a3cc Mon Sep 17 00:00:00 2001 From: trololiver112 <59520813+trololiver112@users.noreply.github.com> Date: Mon, 15 Jun 2020 16:20:52 +0200 Subject: [PATCH 21/61] removed spacing issue BEFORE FARIE COMMENTED IT THIS TIME --- code/game/gamemodes/shadowling/shadowling_abilities.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index 276b03defdf..98812c8cb53 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -187,7 +187,6 @@ to_chat(H, "You shift the nerves in your eyes, allowing you to see in the dark.") H.vision_type = new vision_path H.update_sight() - else to_chat(H, "You return your vision to normal.") H.vision_type = null From f95556d835023e4022133d492f80911d1dc6775a Mon Sep 17 00:00:00 2001 From: TDSSS <32099540+TDSSS@users.noreply.github.com> Date: Mon, 15 Jun 2020 16:23:42 +0200 Subject: [PATCH 22/61] minor fix --- code/game/objects/items/toys.dm | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 85d664d4e08..9ec6e010f44 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1086,7 +1086,7 @@ obj/item/toy/cards/deck/syndicate/black spawn(30) cooldown = 0 return ..() - + /obj/item/toy/plushie/ipcplushie name = "IPC plushie" desc = "An adorable IPC plushie, straight from New Canaan. Arguably more durable than the real deal. Toaster functionality included." @@ -1099,7 +1099,7 @@ obj/item/toy/cards/deck/syndicate/black to_chat(user, " You insert bread into the toaster. ") playsound(loc, 'sound/machines/ding.ogg', 50, 1) qdel(B) - else + else return ..() //New generation TG plushies @@ -1132,15 +1132,15 @@ obj/item/toy/cards/deck/syndicate/black * Foam Armblade */ - /obj/item/toy/foamblade - name = "foam armblade" - desc = "it says \"Sternside Changs #1 fan\" on it. " - icon = 'icons/obj/toy.dmi' - icon_state = "foamblade" - item_state = "arm_blade" - attack_verb = list("pricked", "absorbed", "gored") - w_class = WEIGHT_CLASS_SMALL - resistance_flags = FLAMMABLE +/obj/item/toy/foamblade + name = "foam armblade" + desc = "it says \"Sternside Changs #1 fan\" on it. " + icon = 'icons/obj/toy.dmi' + icon_state = "foamblade" + item_state = "arm_blade" + attack_verb = list("pricked", "absorbed", "gored") + w_class = WEIGHT_CLASS_SMALL + resistance_flags = FLAMMABLE /* * Toy/fake flash From a843221617fb969906d55d50851c70ae6fde0fc2 Mon Sep 17 00:00:00 2001 From: trololiver112 <59520813+trololiver112@users.noreply.github.com> Date: Mon, 15 Jun 2020 19:25:23 +0200 Subject: [PATCH 23/61] Procced --- code/game/gamemodes/shadowling/shadowling_abilities.dm | 7 ++----- code/modules/mob/living/carbon/human/species/shadow.dm | 4 ++-- code/modules/mob/mob.dm | 4 ++++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index 98812c8cb53..e763d3ec6e9 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -175,7 +175,6 @@ range = -1 include_user = 1 clothes_req = 0 - var/datum/vision_override/vision_path = /datum/vision_override/nightvision action_icon_state = "darksight" /obj/effect/proc_holder/spell/targeted/shadow_vision/cast(list/targets, mob/user = usr) @@ -185,12 +184,10 @@ var/mob/living/carbon/human/H = target if(!H.vision_type) to_chat(H, "You shift the nerves in your eyes, allowing you to see in the dark.") - H.vision_type = new vision_path - H.update_sight() + H.set_sight(new /datum/vision_override/nightvision) else to_chat(H, "You return your vision to normal.") - H.vision_type = null - H.update_sight() + H.set_sight() /obj/effect/proc_holder/spell/targeted/shadow_vision/thrall desc = "Thrall Darksight" diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index 63f062b8bc8..2a850f56494 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -39,10 +39,10 @@ /datum/action/innate/shadow/darkvision/Activate() var/mob/living/carbon/human/H = owner if(!H.vision_type) - H.vision_type = new /datum/vision_override/nightvision + H.set_sight(new /datum/vision_override/nightvision) to_chat(H, "You adjust your vision to pierce the darkness.") else - H.vision_type = null + H.set_sight() to_chat(H, "You adjust your vision to recognize the shadows.") /datum/species/shadow/on_species_gain(mob/living/carbon/human/H) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 235996e571f..b2d24818d43 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1356,6 +1356,10 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \ SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT) sync_lighting_plane_alpha() +/mob/proc/set_sight(datum/vision_override/O) + vision_type = O + update_sight() + /mob/proc/sync_lighting_plane_alpha() if(hud_used) var/obj/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"] From 52d6fde04bb9c38ded5eed7d14cbbaa62d68ab5a Mon Sep 17 00:00:00 2001 From: SteelSlayer Date: Mon, 15 Jun 2020 12:40:59 -0500 Subject: [PATCH 24/61] removes frame_desc --- .../game/machinery/computer/buildandrepair.dm | 3 +- code/game/machinery/constructable_frame.dm | 58 ------------------- 2 files changed, 1 insertion(+), 60 deletions(-) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index adc4175a45d..993a1c5cbaa 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -45,7 +45,6 @@ var/list/req_components = null var/powernet = null var/list/records = null - var/frame_desc = null var/contain_parts = 1 toolspeed = 1 usesound = 'sound/items/deconstruct.ogg' @@ -64,7 +63,7 @@ var/atom/A = B if(!ispath(A)) continue - nice_list += list("[req_components[A]] [initial(A.name)]") + nice_list += list("[req_components[A]] [initial(A.name)]\s") . += "Required components: [english_list(nice_list)]." /obj/item/circuitboard/message_monitor diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 2927e5dea3a..96863c3e54d 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -226,7 +226,6 @@ to destroy them and players will be able to make replacements. name = "circuit board (Booze-O-Mat Vendor)" board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Resupply Canister." build_path = /obj/machinery/vending/boozeomat req_components = list(/obj/item/vending_refill/boozeomat = 1) @@ -282,7 +281,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/smes board_type = "machine" origin_tech = "programming=3;powerstorage=3;engineering=3" - frame_desc = "Requires 5 pieces of cable, 5 Power Cells and 1 Capacitor." req_components = list( /obj/item/stack/cable_coil = 5, /obj/item/stock_parts/cell = 5, @@ -293,7 +291,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/emitter board_type = "machine" origin_tech = "programming=3;powerstorage=4;engineering=4" - frame_desc = "Requires 1 Micro Laser and 1 Manipulator." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stock_parts/manipulator = 1) @@ -303,7 +300,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/compressor board_type = "machine" origin_tech = "programming=4;powerstorage=4;engineering=4" - frame_desc = "Requires 5 pieces of cable and 6 Manipulators." req_components = list( /obj/item/stack/cable_coil = 5, /obj/item/stock_parts/manipulator = 6) @@ -313,7 +309,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/turbine board_type = "machine" origin_tech = "programming=4;powerstorage=4;engineering=4" - frame_desc = "Requires 5 pieces of cable and 6 Manipulators." req_components = list( /obj/item/stack/cable_coil = 5, /obj/item/stock_parts/capacitor = 6) @@ -324,7 +319,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/atmospherics/unary/cold_sink/freezer board_type = "machine" origin_tech = "programming=3;plasmatech=3" - frame_desc = "Requires 2 Matter Bins, 2 Micro Lasers, 1 piece of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/micro_laser = 2, @@ -349,7 +343,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/recharger board_type = "machine" origin_tech = "powerstorage=3;materials=2" - frame_desc = "Requires 1 Capacitor" req_components = list(/obj/item/stock_parts/capacitor = 1) /obj/item/circuitboard/snow_machine @@ -357,7 +350,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/snow_machine board_type = "machine" origin_tech = "programming=2;materials=2" - frame_desc = "Requires 1 Matter Bin and 1 Micro Laser." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/micro_laser = 1) @@ -367,7 +359,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/biogenerator board_type = "machine" origin_tech = "programming=2;biotech=3;materials=3" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -379,7 +370,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/plantgenes board_type = "machine" origin_tech = "programming=3;biotech=3" - frame_desc = "Requires 1 Manipulator, 1 Micro Laser, 1 Sheet of glass, and 1 Scanning Module." req_components = list( /obj/item/stock_parts/manipulator = 1, /obj/item/stock_parts/micro_laser = 1, @@ -393,7 +383,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/seed_extractor board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Matter Bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -403,7 +392,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/hydroponics/constructable board_type = "machine" origin_tech = "programming=1;biotech=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulator, and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -414,7 +402,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/microwave board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 1 Micro Laser, 2 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/cable_coil = 2, @@ -425,7 +412,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/oven board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5, @@ -436,7 +422,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/grill board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5, @@ -447,7 +432,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/candy_maker board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 1 Manipulator, 5 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/manipulator = 1, /obj/item/stack/cable_coil = 5, @@ -458,7 +442,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/cooker/deepfryer board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 2 Micro Laser and 5 pieces of cable." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5) @@ -468,7 +451,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/gibber board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -478,7 +460,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/tesla_coil board_type = "machine" origin_tech = "programming=3;magnets=3;powerstorage=3" - frame_desc = "Requires 1 Capacitor." req_components = list( /obj/item/stock_parts/capacitor = 1) @@ -487,7 +468,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/grounding_rod board_type = "machine" origin_tech = "programming=3;powerstorage=3;magnets=3;plasmatech=2" - frame_desc = "Requires 1 Capacitor." req_components = list( /obj/item/stock_parts/capacitor = 1) @@ -496,7 +476,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/processor board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -506,7 +485,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/recycler board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -516,7 +494,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/smartfridge board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Matter bin." req_components = list( /obj/item/stock_parts/matter_bin = 1) var/list/fridge_names_paths = list( @@ -560,7 +537,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/monkey_recycler board_type = "machine" origin_tech = "programming=1;biotech=2" - frame_desc = "Requires 1 Matter bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -570,7 +546,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/hologram/holopad board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Capacitor." req_components = list( /obj/item/stock_parts/capacitor = 1) @@ -579,7 +554,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_dispenser board_type = "machine" origin_tech = "materials=4;programming=4;plasmatech=4;biotech=3" - frame_desc = "Requires 2 Matter Bins, 1 Capacitor, 1 Manipulator, 1 Sheet of glass, and 1 Power Cell." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/capacitor = 1, /obj/item/stock_parts/manipulator = 1, @@ -591,7 +565,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_master board_type = "machine" origin_tech = "materials=3;programming=2;biotech=3" - frame_desc = "Requires 1 Manipulator, 2 Beakers and 1 Sheet of glass." req_components = list( /obj/item/reagent_containers/glass/beaker = 2, /obj/item/stock_parts/manipulator = 1, @@ -621,7 +594,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_heater board_type = "machine" origin_tech = "programming=2;engineering=2;biotech=2" - frame_desc = "Requires 1 Micro Laser and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/sheet/glass = 1) @@ -631,7 +603,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/reagentgrinder/empty board_type = "machine" origin_tech = "materials=2;engineering=2;biotech=2" - frame_desc = "Requires 2 Manipulators and 1 Matter Bin." req_components = list( /obj/item/stock_parts/manipulator = 2, /obj/item/stock_parts/matter_bin = 1) @@ -642,7 +613,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/experimentor board_type = "machine" origin_tech = "magnets=1;engineering=1;programming=1;biotech=1;bluespace=2" - frame_desc = "Requires 2 Micro Lasers, 2 Manipulators and 1 Scanning Module." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 2, @@ -653,7 +623,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/destructive_analyzer board_type = "machine" origin_tech = "magnets=2;engineering=2;programming=2" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, and 1 Micro Laser." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 1, @@ -664,7 +633,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/autolathe board_type = "machine" origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 3 Matter Bins, 1 Manipulator, and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 3, /obj/item/stock_parts/manipulator = 1, @@ -675,7 +643,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/protolathe board_type = "machine" origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 2 Matter Bins, 2 Manipulators, and 2 Beakers." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 2, @@ -694,7 +661,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/circuit_imprinter board_type = "machine" origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, and 2 Beakers." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -705,7 +671,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/port_gen/pacman board_type = "machine" origin_tech = "programming=2;powerstorage=3;plasmatech=3;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Micro Laser, 2 Pieces of Cable, and 1 Capacitor." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/micro_laser = 1, @@ -727,7 +692,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/server board_type = "machine" origin_tech = "programming=3" - frame_desc = "Requires 2 pieces of cable, and 1 Scanning Module." req_components = list( /obj/item/stack/cable_coil = 2, /obj/item/stock_parts/scanning_module = 1) @@ -737,7 +701,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mecha_part_fabricator board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulator, 1 Micro Laser and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -749,7 +712,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mecha_part_fabricator/spacepod board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulators, 1 Micro Laser, and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -762,7 +724,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/clonepod board_type = "machine" origin_tech = "programming=2;biotech=2" - frame_desc = "Requires 2 Manipulator, 2 Scanning Module, 2 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stack/cable_coil = 2, /obj/item/stock_parts/scanning_module = 2, @@ -774,7 +735,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/dna_scannernew board_type = "machine" origin_tech = "programming=2;biotech=2" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, 1 Micro Laser, 2 pieces of cable and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 1, @@ -787,7 +747,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mech_bay_recharge_port board_type = "machine" origin_tech = "programming=3;powerstorage=3;engineering=3" - frame_desc = "Requires 1 piece of cable and 5 Capacitors." req_components = list( /obj/item/stack/cable_coil = 1, /obj/item/stock_parts/capacitor = 5) @@ -797,7 +756,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/teleport/hub board_type = "machine" origin_tech = "programming=3;engineering=4;bluespace=4;materials=4" - frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin." req_components = list( /obj/item/stack/ore/bluespace_crystal = 3, /obj/item/stock_parts/matter_bin = 1) @@ -807,7 +765,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/teleport/station board_type = "machine" origin_tech = "programming=4;engineering=4;bluespace=4;plasmatech=3" - frame_desc = "Requires 2 Bluespace Crystals, 2 Capacitors and 1 Sheet of glass." req_components = list( /obj/item/stack/ore/bluespace_crystal = 2, /obj/item/stock_parts/capacitor = 2, @@ -818,7 +775,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/teleport/perma board_type = "machine" origin_tech = "programming=3;engineering=4;bluespace=4;materials=4" - frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin." req_components = list( /obj/item/stack/ore/bluespace_crystal = 3, /obj/item/stock_parts/matter_bin = 1) @@ -838,7 +794,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/telepad board_type = "machine" origin_tech = "programming=4;engineering=3;plasmatech=4;bluespace=4" - frame_desc = "Requires 2 Bluespace Crystals, 1 Capacitor, 1 piece of cable and 1 Sheet of glass." req_components = list( /obj/item/stack/ore/bluespace_crystal = 2, /obj/item/stock_parts/capacitor = 1, @@ -850,7 +805,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/quantumpad board_type = "machine" origin_tech = "programming=3;engineering=3;plasmatech=3;bluespace=4" - frame_desc = "Requires 1 Bluespace Crystal, 1 Capacitor, 1 piece of cable and 1 Manipulator." req_components = list( /obj/item/stack/ore/bluespace_crystal = 1, /obj/item/stock_parts/capacitor = 1, @@ -862,7 +816,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/sleeper board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 2 Sheets of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -883,7 +836,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/bodyscanner board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Scanning Module, 2 pieces of cable and 2 Sheets of glass." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stack/cable_coil = 2, @@ -894,7 +846,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/atmospherics/unary/cryo_cell board_type = "machine" origin_tech = "programming=4;biotech=3;engineering=4;plasmatech=3" - frame_desc = "Requires 1 Matter Bin, 1 piece of cable and 4 Sheets of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stack/cable_coil = 1, @@ -905,7 +856,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/recharge_station board_type = "machine" origin_tech = "powerstorage=3;engineering=3" - frame_desc = "Requires 2 Capacitors, 1 Power Cell and 1 Manipulator." req_components = list( /obj/item/stock_parts/capacitor = 2, /obj/item/stock_parts/cell = 1, @@ -917,7 +867,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/tcomms/relay board_type = "machine" origin_tech = "programming=2;engineering=2;bluespace=2" - frame_desc = "Requires 2 Manipulators and 2 Cable Coil." req_components = list(/obj/item/stock_parts/manipulator = 2, /obj/item/stack/cable_coil = 2) /obj/item/circuitboard/tcomms/core @@ -925,7 +874,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/tcomms/core board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Manipulators and 2 Cable Coil." req_components = list(/obj/item/stock_parts/manipulator = 2, /obj/item/stack/cable_coil = 2) // End telecomms circuit boards /obj/item/circuitboard/ore_redemption @@ -933,7 +881,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mineral/ore_redemption board_type = "machine" origin_tech = "programming=1;engineering=2" - frame_desc = "Requires 1 Matter Bin, 1 Micro-manipulator, 1 Micro Laser, 1 Igniter and 1 Sheets of glass." req_components = list( /obj/item/stack/sheet/glass = 1, /obj/item/stock_parts/matter_bin = 1, @@ -950,7 +897,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mineral/equipment_vendor board_type = "machine" origin_tech = "programming=1;engineering=3" - frame_desc = "Requires 3 Matter bins and 1 Sheet of glass." req_components = list( /obj/item/stack/sheet/glass = 1, /obj/item/stock_parts/matter_bin = 3) @@ -964,7 +910,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/arcade/claw board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Matter bin, 1 Manipulator, 5 pieces of cable coil and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -976,7 +921,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/prize_counter board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Matter bin, 1 Manipulator, 1 piece of cable coil and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -988,7 +932,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/gameboard board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Micro Laser, 3 pieces of cable coil and 1 Sheet of glass." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/cable_coil = 3, @@ -1000,7 +943,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/logic_gate board_type = "machine" origin_tech = "programming=1" //This stuff is pretty much the absolute basis of programming, so it's mostly useless for research - frame_desc = "Requires 1 piece of cable coil." req_components = list(/obj/item/stack/cable_coil = 1) var/list/names_paths = list( "NOT Gate" = /obj/machinery/logic_gate/not, From e770103b72879516a0cd16f01163169f7cdbb509 Mon Sep 17 00:00:00 2001 From: trololiver112 <59520813+trololiver112@users.noreply.github.com> Date: Mon, 15 Jun 2020 22:17:22 +0200 Subject: [PATCH 25/61] commented --- code/game/gamemodes/changeling/powers/augmented_eyesight.dm | 4 ++-- code/game/gamemodes/shadowling/shadowling_abilities.dm | 2 +- code/modules/mob/living/carbon/human/species/shadow.dm | 2 +- code/modules/mob/mob.dm | 2 ++ code/modules/surgery/other.dm | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm index 34a2d67b58b..bd06954a505 100644 --- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm +++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm @@ -76,11 +76,11 @@ var/mob/living/carbon/human/H = owner H.weakeyes = 1 if(!H.vision_type) - H.vision_type = new /datum/vision_override/nightvision + H.set_sight(new /datum/vision_override/nightvision) /obj/item/organ/internal/cyberimp/eyes/thermals/ling/remove(mob/living/carbon/M, special = 0) if(ishuman(owner)) var/mob/living/carbon/human/H = owner H.weakeyes = 0 - H.vision_type = null + H.set_sight(null) ..() diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index e763d3ec6e9..e210fb61fda 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -187,7 +187,7 @@ H.set_sight(new /datum/vision_override/nightvision) else to_chat(H, "You return your vision to normal.") - H.set_sight() + H.set_sight(null) /obj/effect/proc_holder/spell/targeted/shadow_vision/thrall desc = "Thrall Darksight" diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index 2a850f56494..25d3c853368 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -42,7 +42,7 @@ H.set_sight(new /datum/vision_override/nightvision) to_chat(H, "You adjust your vision to pierce the darkness.") else - H.set_sight() + H.set_sight(null) to_chat(H, "You adjust your vision to recognize the shadows.") /datum/species/shadow/on_species_gain(mob/living/carbon/human/H) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index b2d24818d43..370c1fae76e 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1357,6 +1357,8 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \ sync_lighting_plane_alpha() /mob/proc/set_sight(datum/vision_override/O) + if(vision_type) + qdel(vision_type) //qdel the old vision_type unless it is null. vision_type = O update_sight() diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index b2bd8e6acd8..59274fb0c19 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -327,7 +327,7 @@ user.visible_message("[user] shines light onto the tumor in [target]'s [E]!", "You cleanse the contamination from [target]'s brain!") if(target.vision_type) //Turns off their darksight if it's still active. to_chat(target, "Your eyes are suddenly wrought with immense pain as your darksight is forcibly dismissed!") - target.vision_type = null + target.set_sight(null) SSticker.mode.remove_thrall(target.mind, 0) target.visible_message("A strange black mass falls from [target]'s [E]!") var/obj/item/organ/thing = new /obj/item/organ/internal/shadowtumor(get_turf(target)) From 75a8efa65c33a2be8cef2f308ec17c00193f03f5 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Mon, 15 Jun 2020 20:18:07 -0400 Subject: [PATCH 26/61] Updates Components (#13594) * Updates Components * signal documentation too * minor fixes --- code/__DEFINES/components.dm | 291 ------- code/__DEFINES/dcs/flags.dm | 41 + code/__DEFINES/dcs/helpers.dm | 15 + code/__DEFINES/dcs/signals.dm | 728 ++++++++++++++++++ code/__HELPERS/traits.dm | 1 + code/__HELPERS/unsorted.dm | 4 + code/controllers/subsystem/dcs.dm | 53 ++ code/datums/action.dm | 2 +- code/datums/components/README.md | 132 +--- code/datums/components/_component.dm | 312 ++++++-- code/datums/components/decal.dm | 2 +- code/datums/components/edit_complainer.dm | 23 + code/datums/components/jestosterone.dm | 5 - code/datums/components/label.dm | 4 +- code/datums/components/waddling.dm | 15 - code/datums/elements/_element.dm | 55 ++ code/datums/elements/waddling.dm | 25 + code/game/machinery/autolathe.dm | 18 +- code/game/machinery/recycler.dm | 7 +- code/game/mecha/mech_fabricator.dm | 16 +- code/game/objects/items/toys.dm | 12 + code/modules/admin/verbs/modifyvariables.dm | 1 + code/modules/clothing/shoes/magboots.dm | 5 +- code/modules/clothing/shoes/miscellaneous.dm | 5 +- code/modules/mining/machine_processing.dm | 12 +- code/modules/mining/machine_redemption.dm | 12 +- code/modules/mining/mint.dm | 6 +- code/modules/mob/living/carbon/human/say.dm | 2 +- .../mob/living/carbon/human/species/golem.dm | 5 +- .../living/simple_animal/friendly/penguin.dm | 2 +- .../reagents/chemistry/reagents/misc.dm | 21 +- code/modules/research/experimentor.dm | 2 +- code/modules/research/rdmachines.dm | 4 +- .../space_management/zlevel_manager.dm | 1 + code/modules/surgery/organs/organ_internal.dm | 5 +- paradise.dme | 10 +- 36 files changed, 1294 insertions(+), 560 deletions(-) delete mode 100644 code/__DEFINES/components.dm create mode 100644 code/__DEFINES/dcs/flags.dm create mode 100644 code/__DEFINES/dcs/helpers.dm create mode 100644 code/__DEFINES/dcs/signals.dm create mode 100644 code/controllers/subsystem/dcs.dm create mode 100644 code/datums/components/edit_complainer.dm delete mode 100644 code/datums/components/jestosterone.dm delete mode 100644 code/datums/components/waddling.dm create mode 100644 code/datums/elements/_element.dm create mode 100644 code/datums/elements/waddling.dm diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm deleted file mode 100644 index c9691c195b8..00000000000 --- a/code/__DEFINES/components.dm +++ /dev/null @@ -1,291 +0,0 @@ -#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) ) - -#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) - -//shorthand -#define GET_COMPONENT_FROM(varname, path, target) var##path/##varname = ##target.GetComponent(##path) -#define GET_COMPONENT(varname, path) GET_COMPONENT_FROM(varname, path, src) - -#define COMPONENT_INCOMPATIBLE 1 - -// How multiple components of the exact same type are handled in the same datum - -#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default) -#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed -#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted -#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new - -// All signals. Format: -// When the signal is called: (signal arguments) -// All signals send the source datum of the signal as the first argument - -// global signals -// These are signals which can be listened to by any component on any parent -// start global signals with "!", this used to be necessary but now it's just a formatting choice -#define COMSIG_GLOB_NEW_Z "!new_z" //from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args) -#define COMSIG_GLOB_VAR_EDIT "!var_edit" //called after a successful var edit somewhere in the world: (list/args) -#define COMSIG_GLOB_MOB_CREATED "!mob_created" //mob was created somewhere : (mob) -#define COMSIG_GLOB_MOB_DEATH "!mob_death" //mob died somewhere : (mob , gibbed) - -////////////////////////////////////////////////////////////////// - -// /datum signals -#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component) -#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component) -#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation -#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called -#define COMSIG_TOPIC "handle_topic" //generic topic handler (usr, href_list) - -// /atom signals -#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) - #define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called -#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human) -#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob, result) -#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //from base of atom/get_examine_name(): (/mob, list/overrides) - //Positions for overrides list - #define EXAMINE_POSITION_ARTICLE 1 - #define EXAMINE_POSITION_BEFORE 2 - //End positions - #define COMPONENT_EXNAME_CHANGED 1 -#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom) -#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc) -#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc) - #define COMPONENT_ATOM_BLOCK_EXIT 1 -#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target) -#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity) -#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume) -#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone) -#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob) -#define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume) -#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): () -#define COMSIG_ATOM_RAD_ACT "atom_rad_act" //from base of atom/rad_act(intensity) -#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): () -#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): () -#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode) -#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size) -#define COMSIG_ATOM_SET_LIGHT "atom_set_light" //from base of atom/set_light(): (l_range, l_power, l_color) -#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" //from base of atom/setDir(): (old_dir, new_dir) -#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" //from base of atom/handle_atom_del(): (atom/deleted) -#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" //from base of atom/has_gravity(): (turf/location, list/forced_gravities) -#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" //from proc/get_rad_contents(): () - #define COMPONENT_BLOCK_RADIATION 1 -#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" //from base of datum/radiation_wave/radiate(): (strength) - #define COMPONENT_BLOCK_CONTAMINATION 1 -#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" //from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width) - #define COMPONENT_RAD_WAVE_HANDLED 1 -#define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next) - #define COMPONENT_BLOCK_REACH 1 -#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I) -///////////////// -#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" //from base of atom/attack_ghost(): (mob/dead/observer/ghost) -#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" //from base of atom/attack_hand(): (mob/user) -#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw" //from base of atom/attack_paw(): (mob/user) - #define COMPONENT_NO_ATTACK_HAND 1 //works on all 3. -///////////////// - -#define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area) -#define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area) - -#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user) -#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob) -#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob) -#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob) -#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob) -#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto" //from base of atom/MouseDrop(): (/atom/over, /mob/user) - #define COMPONENT_NO_MOUSEDROP 1 -#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto" //from base of atom/MouseDrop_T: (/atom/from, /mob/user) - -// /area signals -#define COMSIG_AREA_ENTERED "area_entered" //from base of area/Entered(): (atom/movable/M) -#define COMSIG_AREA_EXITED "area_exited" //from base of area/Exited(): (atom/movable/M) - -// /turf signals -#define COMSIG_TURF_CHANGE "turf_change" //from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps) -#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity" //from base of atom/has_gravity(): (atom/asker, list/forced_gravities) - -// /atom/movable signals -#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) -#define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable) -#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) -#define COMSIG_CROSSED_MOVABLE "crossed_movable" //when we cross over something (calling Crossed() on that atom) -#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable) -#define COMSIG_MOVABLE_UNCROSS "movable_uncross" //from base of atom/movable/Uncross(): (/atom/movable) - #define COMPONENT_MOVABLE_BLOCK_UNCROSS 1 -#define COMSIG_MOVABLE_BUMP "movable_bump" //from base of atom/movable/Bump(): (/atom) -#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum) -#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" //from base of mob/living/hitby(): (mob/living/target, hit_zone) -#define COMSIG_MOVABLE_BUCKLE "buckle" //from base of atom/movable/buckle_mob(): (mob, force) -#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" //from base of atom/movable/unbuckle_mob(): (mob, force) -#define COMSIG_MOVABLE_PRE_THROW "movable_pre_throw" //from base of atom/movable/throw_at(): (list/args) - #define COMPONENT_CANCEL_THROW 1 -#define COMSIG_MOVABLE_POST_THROW "movable_post_throw" //from base of atom/movable/throw_at(): (datum/thrownthing, spin) -#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" //from base of atom/movable/onTransitZ(): (old_z, new_z) -#define COMSIG_MOVABLE_HEAR "movable_hear" //from base of atom/movable/Hear(): (message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) -#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source) - -// /mob signals -#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed) -#define COMSIG_MOB_CLICKON "mob_clickon" //from base of mob/clickon(): (atom/A, params) - #define COMSIG_MOB_CANCEL_CLICKON 1 -#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj -#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (magic, holy, protection_sources) - #define COMPONENT_BLOCK_MAGIC 1 -#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //from base of mob/create_mob_hud(): () -#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //from base of -#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" //from base of /obj/item/attack(): (mob/M, mob/user) -#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters) -#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params) -#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target) -#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): () - -// /mob/living signals -#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living) -#define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living) -#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living) -#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage) -#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: () - -//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! -#define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" //from base of mob/living/Paralyze() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" //from base of mob/living/Immobilize() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" //from base of mob/living/Unconscious() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" //from base of mob/living/Sleeping() (amount, update, ignore) - #define COMPONENT_NO_STUN 1 //For all of them - -// /mob/living/carbon signals -#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) - -// /mob/living/simple_animal/hostile signals -#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" - #define COMPONENT_HOSTILE_NO_ATTACK 1 - -// /obj signals -#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled) -#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value) -#define COMSIG_OBJ_UPDATE_ICON "obj_update_icon" //called in /obj/update_icon() - - -// /obj/item signals -#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user) -#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob) - #define COMPONENT_NO_INTERACT 1 -#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob) - #define COMPONENT_NO_ATTACK_OBJ 1 -#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" //from base of obj/item/pre_attack(): (atom/target, mob/user, params) - #define COMPONENT_NO_ATTACK 1 -#define COMSIG_ITEM_AFTERATTACK "item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, params) -#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot) -#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (mob/user) -#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker) -#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) -#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) -#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args) - -// /obj/item/clothing signals -#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () - -// /obj/item/implant signals -#define COMSIG_IMPLANT_ACTIVATED "implant_activated" //from base of /obj/item/implant/proc/activate(): () -#define COMSIG_IMPLANT_IMPLANTING "implant_implanting" //from base of /obj/item/implant/proc/implant(): (list/args) - #define COMPONENT_STOP_IMPLANTING 1 -#define COMSIG_IMPLANT_OTHER "implant_other" //called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant) - //#define COMPONENT_STOP_IMPLANTING 1 //The name makes sense for both - #define COMPONENT_DELETE_NEW_IMPLANT 2 - #define COMPONENT_DELETE_OLD_IMPLANT 4 -#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists" //called on implants being implanted into someone with an uplink implant: (datum/component/uplink) - //This uses all return values of COMSIG_IMPLANT_OTHER - -// /obj/item/pda signals -#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone" //called on pda when the user changes the ringtone: (mob/living/user, new_ringtone) - #define COMPONENT_STOP_RINGTONE_CHANGE 1 - -// /obj/item/radio signals -#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency" //called from base of /obj/item/radio/proc/set_frequency(): (list/args) - -// /obj/item/pen signals -#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) - - -// /mob/living/carbon/human signals -#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target) -#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) -#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted) - -// /datum/species signals -#define COMSIG_SPECIES_GAIN "species_gain" //from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) -#define COMSIG_SPECIES_LOSS "species_loss" //from datum/species/on_species_loss(): (datum/species/lost_species) - -/*******Component Specific Signals*******/ -//Janitor -#define COMSIG_TURF_IS_WET "check_turf_wet" //(): Returns bitflags of wet values. -#define COMSIG_TURF_MAKE_DRY "make_turf_try" //(max_strength, immediate, duration_decrease = INFINITY): Returns bool. -#define COMSIG_COMPONENT_CLEAN_ACT "clean_act" //called on an object to clean it of cleanables. Usualy with soap: (num/strength) - -//Food -#define COMSIG_FOOD_EATEN "food_eaten" //from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder) - -//Mood -#define COMSIG_ADD_MOOD_EVENT "add_mood" //Called when you send a mood event from anywhere in the code. -#define COMSIG_CLEAR_MOOD_EVENT "clear_mood" //Called when you clear a mood event from anywhere in the code. - -//NTnet -#define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" //called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata)) - -//Nanites -#define COMSIG_HAS_NANITES "has_nanites" //() returns TRUE if nanites are found -#define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs" //(list/nanite_programs) - makes the input list a copy the nanites' program list -#define COMSIG_NANITE_SET_VOLUME "nanite_set_volume" //(amount) Sets current nanite volume to the given amount -#define COMSIG_NANITE_ADJUST_VOLUME "nanite_adjust" //(amount) Adjusts nanite volume by the given amount -#define COMSIG_NANITE_SET_MAX_VOLUME "nanite_set_max_volume" //(amount) Sets maximum nanite volume to the given amount -#define COMSIG_NANITE_SET_CLOUD "nanite_set_cloud" //(amount(0-100)) Sets cloud ID to the given amount -#define COMSIG_NANITE_SET_SAFETY "nanite_set_safety" //(amount) Sets safety threshold to the given amount -#define COMSIG_NANITE_SET_REGEN "nanite_set_regen" //(amount) Sets regeneration rate to the given amount -#define COMSIG_NANITE_SIGNAL "nanite_signal" //(code(1-9999)) Called when sending a nanite signal to a mob. -#define COMSIG_NANITE_SCAN "nanite_scan" //(mob/user, full_scan) - sends to chat a scan of the nanites to the user, returns TRUE if nanites are detected -#define COMSIG_NANITE_UI_DATA "nanite_ui_data" //(list/data, scan_level) - adds nanite data to the given data list - made for ui_data procs -#define COMSIG_NANITE_ADD_PROGRAM "nanite_add_program" //(datum/nanite_program/new_program, datum/nanite_program/source_program) Called when adding a program to a nanite component - #define COMPONENT_PROGRAM_INSTALLED 1 //Installation successful - #define COMPONENT_PROGRAM_NOT_INSTALLED 2 //Installation failed, but there are still nanites -#define COMSIG_NANITE_SYNC "nanite_sync" //(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component - -// /datum/component/storage signals -#define COMSIG_CONTAINS_STORAGE "is_storage" //() - returns bool. -#define COMSIG_TRY_STORAGE_INSERT "storage_try_insert" //(obj/item/inserting, mob/user, silent, force) - returns bool -#define COMSIG_TRY_STORAGE_SHOW "storage_show_to" //(mob/show_to, force) - returns bool. -#define COMSIG_TRY_STORAGE_HIDE_FROM "storage_hide_from" //(mob/hide_from) - returns bool -#define COMSIG_TRY_STORAGE_HIDE_ALL "storage_hide_all" //returns bool -#define COMSIG_TRY_STORAGE_SET_LOCKSTATE "storage_lock_set_state" //(newstate) -#define COMSIG_IS_STORAGE_LOCKED "storage_get_lockstate" //() - returns bool. MUST CHECK IF STORAGE IS THERE FIRST! -#define COMSIG_TRY_STORAGE_TAKE_TYPE "storage_take_type" //(type, atom/destination, amount = INFINITY, check_adjacent, force, mob/user, list/inserted) - returns bool - type can be a list of types. -#define COMSIG_TRY_STORAGE_FILL_TYPE "storage_fill_type" //(type, amount = INFINITY, force = FALSE) //don't fuck this up. Force will ignore max_items, and amount is normally clamped to max_items. -#define COMSIG_TRY_STORAGE_TAKE "storage_take_obj" //(obj, new_loc, force = FALSE) - returns bool -#define COMSIG_TRY_STORAGE_QUICK_EMPTY "storage_quick_empty" //(loc) - returns bool - if loc is null it will dump at parent location. -#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" //(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE) -#define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip" //(obj/item/insertion_candidate, mob/user, silent) - returns bool - -// /datum/action signals -#define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action) - #define COMPONENT_ACTION_BLOCK_TRIGGER 1 - -/*******Non-Signal Component Related Defines*******/ - -//Redirection component init flags -#define REDIRECT_TRANSFER_WITH_TURF 1 - -//Arch -#define ARCH_PROB "probability" //Probability for each item -#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount - -//Ouch my toes! -#define CALTROP_BYPASS_SHOES 1 -#define CALTROP_IGNORE_WALKERS 2 - -//Xenobio hotkeys -#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob) -#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" //from slime AltClickOn(): (/mob) -#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" //from slime ShiftClickOn(): (/mob) -#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" //from turf ShiftClickOn(): (/mob) -#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob) -#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob) diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm new file mode 100644 index 00000000000..128c9f19387 --- /dev/null +++ b/code/__DEFINES/dcs/flags.dm @@ -0,0 +1,41 @@ +/// Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. +/// `parent` must not be modified if this is to be returned. +/// This will be noted in the runtime logs +#define COMPONENT_INCOMPATIBLE 1 +/// Returned in PostTransfer to prevent transfer, similar to `COMPONENT_INCOMPATIBLE` +#define COMPONENT_NOTRANSFER 2 + +/// Return value to cancel attaching +#define ELEMENT_INCOMPATIBLE 1 + +// /datum/element flags +/// Causes the detach proc to be called when the host object is being deleted +#define ELEMENT_DETACH (1 << 0) +/** + * Only elements created with the same arguments given after `id_arg_index` share an element instance + * The arguments are the same when the text and number values are the same and all other values have the same ref + */ +#define ELEMENT_BESPOKE (1 << 1) + +// How multiple components of the exact same type are handled in the same datum +/// old component is deleted (default) +#define COMPONENT_DUPE_HIGHLANDER 0 +/// duplicates allowed +#define COMPONENT_DUPE_ALLOWED 1 +/// new component is deleted +#define COMPONENT_DUPE_UNIQUE 2 +/// old component is given the initialization args of the new +#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 +/// each component of the same type is consulted as to whether the duplicate should be allowed +#define COMPONENT_DUPE_SELECTIVE 5 + +//Redirection component init flags +#define REDIRECT_TRANSFER_WITH_TURF 1 + +//Arch +#define ARCH_PROB "probability" //Probability for each item +#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount + +//Ouch my toes! +#define CALTROP_BYPASS_SHOES 1 +#define CALTROP_IGNORE_WALKERS 2 diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm new file mode 100644 index 00000000000..144e94f1fe0 --- /dev/null +++ b/code/__DEFINES/dcs/helpers.dm @@ -0,0 +1,15 @@ +/// Used to trigger signals and call procs registered for that signal +/// The datum hosting the signal is automaticaly added as the first argument +/// Returns a bitfield gathered from all registered procs +/// Arguments given here are packaged in a list and given to _SendSignal +#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) ) + +#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) + +/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments +#define AddElement(arguments...) _AddElement(list(##arguments)) +/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments +#define RemoveElement(arguments...) _RemoveElement(list(##arguments)) + +/// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments +#define AddComponent(arguments...) _AddComponent(list(##arguments)) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm new file mode 100644 index 00000000000..10aa1718dda --- /dev/null +++ b/code/__DEFINES/dcs/signals.dm @@ -0,0 +1,728 @@ +// All signals. Format: +// When the signal is called: (signal arguments) +// All signals send the source datum of the signal as the first argument + +// global signals +// These are signals which can be listened to by any component on any parent +// start global signals with "!", this used to be necessary but now it's just a formatting choice + +///from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args) +#define COMSIG_GLOB_NEW_Z "!new_z" +/// called after a successful var edit somewhere in the world: (list/args) +#define COMSIG_GLOB_VAR_EDIT "!var_edit" +/// called after an explosion happened : (epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range) +#define COMSIG_GLOB_EXPLOSION "!explosion" +/// mob was created somewhere : (mob) +#define COMSIG_GLOB_MOB_CREATED "!mob_created" +/// mob died somewhere : (mob , gibbed) +#define COMSIG_GLOB_MOB_DEATH "!mob_death" +/// global living say plug - use sparingly: (mob/speaker , message) +#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special" +/// called by datum/cinematic/play() : (datum/cinematic/new_cinematic) +#define COMSIG_GLOB_PLAY_CINEMATIC "!play_cinematic" + #define COMPONENT_GLOB_BLOCK_CINEMATIC (1<<0) +/// ingame button pressed (/obj/machinery/button/button) +#define COMSIG_GLOB_BUTTON_PRESSED "!button_pressed" + +/// signals from globally accessible objects + +///from SSsun when the sun changes position : (azimuth) +#define COMSIG_SUN_MOVED "sun_moved" + +////////////////////////////////////////////////////////////////// + +// /datum signals +/// when a component is added to a datum: (/datum/component) +#define COMSIG_COMPONENT_ADDED "component_added" +/// before a component is removed from a datum because of RemoveComponent: (/datum/component) +#define COMSIG_COMPONENT_REMOVING "component_removing" +/// before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation +#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" +/// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called +#define COMSIG_PARENT_QDELETING "parent_qdeleting" +/// generic topic handler (usr, href_list) +#define COMSIG_TOPIC "handle_topic" + +/// fires on the target datum when an element is attached to it (/datum/element) +#define COMSIG_ELEMENT_ATTACH "element_attach" +/// fires on the target datum when an element is attached to it (/datum/element) +#define COMSIG_ELEMENT_DETACH "element_detach" + +// /atom signals +///from base of atom/proc/Initialize(): sent any time a new atom is created +#define COMSIG_ATOM_CREATED "atom_created" +//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization +#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success" +///from base of atom/attackby(): (/obj/item, /mob/living, params) +#define COMSIG_PARENT_ATTACKBY "atom_attackby" +///Return this in response if you don't want afterattack to be called + #define COMPONENT_NO_AFTERATTACK (1<<0) +///from base of atom/attack_hulk(): (/mob/living/carbon/human) +#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" +///from base of atom/animal_attack(): (/mob/user) +#define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal" +///from base of atom/examine(): (/mob) +#define COMSIG_PARENT_EXAMINE "atom_examine" +///from base of atom/get_examine_name(): (/mob, list/overrides) +#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" + //Positions for overrides list + #define EXAMINE_POSITION_ARTICLE (1<<0) + #define EXAMINE_POSITION_BEFORE (1<<1) + //End positions + #define COMPONENT_EXNAME_CHANGED (1<<0) +///from base of atom/update_icon(): () +#define COMSIG_ATOM_UPDATE_ICON "atom_update_icon" + #define COMSIG_ATOM_NO_UPDATE_ICON_STATE (1<<0) + #define COMSIG_ATOM_NO_UPDATE_OVERLAYS (1<<1) +///from base of atom/update_overlays(): (list/new_overlays) +#define COMSIG_ATOM_UPDATE_OVERLAYS "atom_update_overlays" +///from base of atom/update_icon(): (signalOut, did_anything) +#define COMSIG_ATOM_UPDATED_ICON "atom_updated_icon" +///from base of atom/Entered(): (atom/movable/entering, /atom) +#define COMSIG_ATOM_ENTERED "atom_entered" +///from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc) +#define COMSIG_ATOM_EXIT "atom_exit" + #define COMPONENT_ATOM_BLOCK_EXIT (1<<0) +///from base of atom/Exited(): (atom/movable/exiting, atom/newloc) +#define COMSIG_ATOM_EXITED "atom_exited" +///from base of atom/Bumped(): (/atom/movable) +#define COMSIG_ATOM_BUMPED "atom_bumped" +///from base of atom/ex_act(): (severity, target) +#define COMSIG_ATOM_EX_ACT "atom_ex_act" +///from base of atom/emp_act(): (severity) +#define COMSIG_ATOM_EMP_ACT "atom_emp_act" +///from base of atom/fire_act(): (exposed_temperature, exposed_volume) +#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" +///from base of atom/bullet_act(): (/obj/projectile, def_zone) +#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" +///from base of atom/blob_act(): (/obj/structure/blob) +#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" +///from base of atom/acid_act(): (acidpwr, acid_volume) +#define COMSIG_ATOM_ACID_ACT "atom_acid_act" +///from base of atom/emag_act(): (/mob/user) +#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" +///from base of atom/rad_act(intensity) +#define COMSIG_ATOM_RAD_ACT "atom_rad_act" +///from base of atom/narsie_act(): () +#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" +///from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode) +#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" +///from base of atom/singularity_pull(): (S, current_size) +#define COMSIG_ATOM_SING_PULL "atom_sing_pull" +///from obj/machinery/bsa/full/proc/fire(): () +#define COMSIG_ATOM_BSA_BEAM "atom_bsa_beam_pass" + #define COMSIG_ATOM_BLOCKS_BSA_BEAM (1<<0) +///from base of atom/set_light(): (l_range, l_power, l_color) +#define COMSIG_ATOM_SET_LIGHT "atom_set_light" +///from base of atom/setDir(): (old_dir, new_dir) +#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" +///from base of atom/handle_atom_del(): (atom/deleted) +#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" +///from base of atom/has_gravity(): (turf/location, list/forced_gravities) +#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" +///from proc/get_rad_contents(): () +#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" + #define COMPONENT_BLOCK_RADIATION (1<<0) +///from base of datum/radiation_wave/radiate(): (strength) +#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" + #define COMPONENT_BLOCK_CONTAMINATION (1<<0) +///from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width) +#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" + #define COMPONENT_RAD_WAVE_HANDLED (1<<0) +///from internal loop in atom/movable/proc/CanReach(): (list/next) +#define COMSIG_ATOM_CANREACH "atom_can_reach" + #define COMPONENT_BLOCK_REACH (1<<0) +///from base of atom/screwdriver_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" +///from base of atom/wrench_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_WRENCH_ACT "atom_wrench_act" +///from base of atom/multitool_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_MULTITOOL_ACT "atom_multitool_act" +///from base of atom/welder_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_WELDER_ACT "atom_welder_act" +///from base of atom/wirecutter_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_WIRECUTTER_ACT "atom_wirecutter_act" +///from base of atom/crowbar_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_CROWBAR_ACT "atom_crowbar_act" +///from base of atom/analyser_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_ANALYSER_ACT "atom_analyser_act" + #define COMPONENT_BLOCK_TOOL_ATTACK (1<<0) +///called when teleporting into a protected turf: (channel, turf/origin) +#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" + #define COMPONENT_BLOCK_TELEPORT (1<<0) +///called when an atom is added to the hearers on get_hearers_in_view(): (list/processing_list, list/hearers) +#define COMSIG_ATOM_HEARER_IN_VIEW "atom_hearer_in_view" +///called when an atom starts orbiting another atom: (atom) +#define COMSIG_ATOM_ORBIT_BEGIN "atom_orbit_begin" +///called when an atom stops orbiting another atom: (atom) +#define COMSIG_ATOM_ORBIT_STOP "atom_orbit_stop" +///////////////// +///from base of atom/attack_ghost(): (mob/dead/observer/ghost) +#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" +///from base of atom/attack_hand(): (mob/user) +#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" +///from base of atom/attack_paw(): (mob/user) +#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw" + #define COMPONENT_NO_ATTACK_HAND (1<<0) //works on all 3. +//This signal return value bitflags can be found in __DEFINES/misc.dm + +///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels) +#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact" +///called on a movable (NOT living) when someone starts pulling it (atom/movable/puller, state, force) +#define COMSIG_ATOM_START_PULL "movable_start_pull" +///called on /living when someone starts pulling it (atom/movable/puller, state, force) +#define COMSIG_LIVING_START_PULL "living_start_pull" + +///////////////// + +///from base of area/Entered(): (/area) +#define COMSIG_ENTER_AREA "enter_area" +///from base of area/Exited(): (/area) +#define COMSIG_EXIT_AREA "exit_area" +///from base of atom/Click(): (location, control, params, mob/user) +#define COMSIG_CLICK "atom_click" +///from base of atom/ShiftClick(): (/mob) +#define COMSIG_CLICK_SHIFT "shift_click" + #define COMPONENT_ALLOW_EXAMINATE (1<<0) //Allows the user to examinate regardless of client.eye. +///from base of atom/CtrlClickOn(): (/mob) +#define COMSIG_CLICK_CTRL "ctrl_click" +///from base of atom/AltClick(): (/mob) +#define COMSIG_CLICK_ALT "alt_click" +///from base of atom/CtrlShiftClick(/mob) +#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" +///from base of atom/MouseDrop(): (/atom/over, /mob/user) +#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto" + #define COMPONENT_NO_MOUSEDROP (1<<0) +///from base of atom/MouseDrop_T: (/atom/from, /mob/user) +#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto" + +// /area signals + +///from base of area/Entered(): (atom/movable/M) +#define COMSIG_AREA_ENTERED "area_entered" +///from base of area/Exited(): (atom/movable/M) +#define COMSIG_AREA_EXITED "area_exited" + +// /turf signals + +///from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps) +#define COMSIG_TURF_CHANGE "turf_change" +///from base of atom/has_gravity(): (atom/asker, list/forced_gravities) +#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity" +///from base of turf/New(): (turf/source, direction) +#define COMSIG_TURF_MULTIZ_NEW "turf_multiz_new" + +// /atom/movable signals + +///from base of atom/movable/Moved(): (/atom) +#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" + #define COMPONENT_MOVABLE_BLOCK_PRE_MOVE (1<<0) +///from base of atom/movable/Moved(): (/atom, dir) +#define COMSIG_MOVABLE_MOVED "movable_moved" +///from base of atom/movable/Cross(): (/atom/movable) +#define COMSIG_MOVABLE_CROSS "movable_cross" +///from base of atom/movable/Crossed(): (/atom/movable) +#define COMSIG_MOVABLE_CROSSED "movable_crossed" +///when we cross over something (calling Crossed() on that atom) +#define COMSIG_CROSSED_MOVABLE "crossed_movable" +///from base of atom/movable/Uncross(): (/atom/movable) +#define COMSIG_MOVABLE_UNCROSS "movable_uncross" + #define COMPONENT_MOVABLE_BLOCK_UNCROSS (1<<0) +///from base of atom/movable/Uncrossed(): (/atom/movable) +#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" +///from base of atom/movable/Bump(): (/atom) +#define COMSIG_MOVABLE_BUMP "movable_bump" +///from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum) +#define COMSIG_MOVABLE_IMPACT "movable_impact" + #define COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH (1<<0) //if true, flip if the impact will push what it hits + #define COMPONENT_MOVABLE_IMPACT_NEVERMIND (1<<1) //return true if you destroyed whatever it was you're impacting and there won't be anything for hitby() to run on +///from base of mob/living/hitby(): (mob/living/target, hit_zone) +#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" +///from base of atom/movable/buckle_mob(): (mob, force) +#define COMSIG_MOVABLE_BUCKLE "buckle" +///from base of atom/movable/unbuckle_mob(): (mob, force) +#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" +///from base of atom/movable/throw_at(): (list/args) +#define COMSIG_MOVABLE_PRE_THROW "movable_pre_throw" + #define COMPONENT_CANCEL_THROW (1<<0) +///from base of atom/movable/throw_at(): (datum/thrownthing, spin) +#define COMSIG_MOVABLE_POST_THROW "movable_post_throw" +///from base of atom/movable/onTransitZ(): (old_z, new_z) +#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" +///called when the movable is placed in an unaccessible area, used for stationloving: () +#define COMSIG_MOVABLE_SECLUDED_LOCATION "movable_secluded" +///from base of atom/movable/Hear(): (proc args list(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)) +#define COMSIG_MOVABLE_HEAR "movable_hear" + #define HEARING_MESSAGE 1 + #define HEARING_SPEAKER 2 +// #define HEARING_LANGUAGE 3 + #define HEARING_RAW_MESSAGE 4 + /* #define HEARING_RADIO_FREQ 5 + #define HEARING_SPANS 6 + #define HEARING_MESSAGE_MODE 7 */ + +///called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source) +#define COMSIG_MOVABLE_DISPOSING "movable_disposing" + +// /mob signals + +///from base of /mob/Login(): () +#define COMSIG_MOB_LOGIN "mob_login" +///from base of /mob/Logout(): () +#define COMSIG_MOB_LOGOUT "mob_logout" +///from base of mob/death(): (gibbed) +#define COMSIG_MOB_DEATH "mob_death" +///from base of mob/set_stat(): (new_stat) +#define COMSIG_MOB_STATCHANGE "mob_statchange" +///from base of mob/clickon(): (atom/A, params) +#define COMSIG_MOB_CLICKON "mob_clickon" +///from base of mob/MiddleClickOn(): (atom/A) +#define COMSIG_MOB_MIDDLECLICKON "mob_middleclickon" +///from base of mob/AltClickOn(): (atom/A) +#define COMSIG_MOB_ALTCLICKON "mob_altclickon" + #define COMSIG_MOB_CANCEL_CLICKON (1<<0) + +///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj +#define COMSIG_MOB_ALLOWED "mob_allowed" +///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources) +#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" + #define COMPONENT_BLOCK_MAGIC (1<<0) +///from base of mob/create_mob_hud(): () +#define COMSIG_MOB_HUD_CREATED "mob_hud_created" +///from base of atom/attack_hand(): (mob/user) +#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" +///from base of /obj/item/attack(): (mob/M, mob/user) +#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" + #define COMPONENT_ITEM_NO_ATTACK (1<<0) +///from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone) +#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage" +///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters) +#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" +///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, proxiumity_flag, click_parameters) +#define COMSIG_MOB_ITEM_ATTACK_QDELETED "mob_item_attack_qdeleted" +///from base of mob/RangedAttack(): (atom/A, params) +#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" +///from base of /mob/throw_item(): (atom/target) +#define COMSIG_MOB_THROW "mob_throw" +///from base of /mob/verb/examinate(): (atom/target) +#define COMSIG_MOB_EXAMINATE "mob_examinate" +///from base of /mob/update_sight(): () +#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" +////from /mob/living/say(): () +#define COMSIG_MOB_SAY "mob_say" + #define COMPONENT_UPPERCASE_SPEECH (1<<0) + // used to access COMSIG_MOB_SAY argslist + #define SPEECH_MESSAGE 1 + // #define SPEECH_BUBBLE_TYPE 2 + #define SPEECH_SPANS 3 + /* #define SPEECH_SANITIZE 4 + #define SPEECH_LANGUAGE 5 + #define SPEECH_IGNORE_SPAM 6 + #define SPEECH_FORCED 7 */ + +///from /mob/say_dead(): (mob/speaker, message) +#define COMSIG_MOB_DEADSAY "mob_deadsay" + #define MOB_DEADSAY_SIGNAL_INTERCEPT (1<<0) +///from /mob/living/emote(): () +#define COMSIG_MOB_EMOTE "mob_emote" +///from base of mob/swap_hand(): (obj/item) +#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" + #define COMPONENT_BLOCK_SWAP (1<<0) + +// /mob/living signals + +///from base of mob/living/resist() (/mob/living) +#define COMSIG_LIVING_RESIST "living_resist" +///from base of mob/living/IgniteMob() (/mob/living) +#define COMSIG_LIVING_IGNITED "living_ignite" +///from base of mob/living/ExtinguishMob() (/mob/living) +#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" +///from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags) +#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" +///sent when items with siemen coeff. of 0 block a shock: (power_source, source, siemens_coeff, dist_check) +#define COMSIG_LIVING_SHOCK_PREVENTED "living_shock_prevented" +///sent by stuff like stunbatons and tasers: () +#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" +///from base of mob/living/revive() (full_heal, admin_revive) +#define COMSIG_LIVING_REVIVE "living_revive" +///from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) +#define COMSIG_LIVING_REGENERATE_LIMBS "living_regen_limbs" +///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment +#define COMSIG_LIVING_ATTACH_LIMB "living_attach_limb" + #define COMPONENT_NO_ATTACH (1<<0) +///sent from borg recharge stations: (amount, repairs) +#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge" +///sent when a mob/login() finishes: (client) +#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" +///sent from borg mobs to itself, for tools to catch an upcoming destroy() due to safe decon (rather than detonation) +#define COMSIG_BORG_SAFE_DECONSTRUCT "borg_safe_decon" + +//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! + +///from base of mob/living/Stun() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_STUN "living_stun" +///from base of mob/living/Knockdown() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" +///from base of mob/living/Paralyze() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" +///from base of mob/living/Immobilize() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" +///from base of mob/living/Unconscious() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" +///from base of mob/living/Sleeping() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" + #define COMPONENT_NO_STUN (1<<0) //For all of them +///from base of /mob/living/can_track(): (mob/user) +#define COMSIG_LIVING_CAN_TRACK "mob_cantrack" + #define COMPONENT_CANT_TRACK (1<<0) + +// /mob/living/carbon signals + +///from base of mob/living/carbon/soundbang_act(): (list(intensity)) +#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" +///from /item/organ/proc/Insert() (/obj/item/organ/) +#define COMSIG_CARBON_GAIN_ORGAN "carbon_gain_organ" +///from /item/organ/proc/Remove() (/obj/item/organ/) +#define COMSIG_CARBON_LOSE_ORGAN "carbon_lose_organ" +///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent) +#define COMSIG_CARBON_EQUIP_HAT "carbon_equip_hat" +///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent) +#define COMSIG_CARBON_UNEQUIP_HAT "carbon_unequip_hat" +///defined twice, in carbon and human's topics, fired when interacting with a valid embedded_object to pull it out (mob/living/carbon/target, /obj/item, /obj/item/bodypart/L) +#define COMSIG_CARBON_EMBED_RIP "item_embed_start_rip" +///called when removing a given item from a mob, from mob/living/carbon/remove_embedded_object(mob/living/carbon/target, /obj/item) +#define COMSIG_CARBON_EMBED_REMOVAL "item_embed_remove_safe" + +// /mob/living/simple_animal/hostile signals +#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" + #define COMPONENT_HOSTILE_NO_ATTACK (1<<0) + +// /obj signals + +///from base of obj/deconstruct(): (disassembled) +#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" +///called in /obj/structure/setAnchored(): (value) +#define COMSIG_OBJ_SETANCHORED "obj_setanchored" +///from base of code/game/machinery +#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" +///from base of /turf/proc/levelupdate(). (intact) true to hide and false to unhide +#define COMSIG_OBJ_HIDE "obj_hide" +///called in /obj/update_icon() +#define COMSIG_OBJ_UPDATE_ICON "obj_update_icon" + +// /obj/machinery signals + +///from /obj/machinery/obj_break(damage_flag): (damage_flag) +#define COMSIG_MACHINERY_BROKEN "machinery_broken" +///from base power_change() when power is lost +#define COMSIG_MACHINERY_POWER_LOST "machinery_power_lost" +///from base power_change() when power is restored +#define COMSIG_MACHINERY_POWER_RESTORED "machinery_power_restored" + +// /obj/item signals + +///from base of obj/item/attack(): (/mob/living/target, /mob/living/user) +#define COMSIG_ITEM_ATTACK "item_attack" +///from base of obj/item/attack_self(): (/mob) +#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" + #define COMPONENT_NO_INTERACT (1<<0) +///from base of obj/item/attack_obj(): (/obj, /mob) +#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" + #define COMPONENT_NO_ATTACK_OBJ (1<<0) +///from base of obj/item/pre_attack(): (atom/target, mob/user, params) +#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" + #define COMPONENT_NO_ATTACK (1<<0) +///from base of obj/item/afterattack(): (atom/target, mob/user, params) +#define COMSIG_ITEM_AFTERATTACK "item_afterattack" +///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, params) +#define COMSIG_ITEM_ATTACK_QDELETED "item_attack_qdeleted" +///from base of obj/item/equipped(): (/mob/equipper, slot) +#define COMSIG_ITEM_EQUIPPED "item_equip" +///from base of obj/item/dropped(): (mob/user) +#define COMSIG_ITEM_DROPPED "item_drop" +///from base of obj/item/pickup(): (/mob/taker) +#define COMSIG_ITEM_PICKUP "item_pickup" +///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) +#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" +///return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) +#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" +///called before marking an object for retrieval, checked in /obj/effect/proc_holder/spell/targeted/summonitem/cast() : (mob/user) +#define COMSIG_ITEM_MARK_RETRIEVAL "item_mark_retrieval" + #define COMPONENT_BLOCK_MARK_RETRIEVAL (1<<0) +///from base of obj/item/hit_reaction(): (list/args) +#define COMSIG_ITEM_HIT_REACT "item_hit_react" +///called on item when crossed by something (): (/atom/movable, mob/living/crossed) +#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" +///called on item when microwaved (): (obj/machinery/microwave/M) +#define COMSIG_ITEM_MICROWAVE_ACT "microwave_act" +///from base of item/sharpener/attackby(): (amount, max) +#define COMSIG_ITEM_SHARPEN_ACT "sharpen_act" + #define COMPONENT_BLOCK_SHARPEN_APPLIED (1<<0) + #define COMPONENT_BLOCK_SHARPEN_BLOCKED (1<<1) + #define COMPONENT_BLOCK_SHARPEN_ALREADY (1<<2) + #define COMPONENT_BLOCK_SHARPEN_MAXED (1<<3) +///from base of [/obj/item/proc/tool_check_callback]: (mob/living/user) +#define COMSIG_TOOL_IN_USE "tool_in_use" +///from base of [/obj/item/proc/tool_start_check]: (mob/living/user) +#define COMSIG_TOOL_START_USE "tool_start_use" +///from [/obj/item/proc/disableEmbedding]: +#define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed" +///from [/obj/effect/mine/proc/triggermine]: +#define COMSIG_MINE_TRIGGERED "minegoboom" + +// /obj/item signals for economy +///called when an item is sold by the exports subsystem +#define COMSIG_ITEM_SOLD "item_sold" +///called when a wrapped up structure is opened by hand +#define COMSIG_STRUCTURE_UNWRAPPED "structure_unwrapped" +#define COMSIG_ITEM_UNWRAPPED "item_unwrapped" +///called when a wrapped up item is opened by hand + #define COMSIG_ITEM_SPLIT_VALUE (1<<0) +///called when getting the item's exact ratio for cargo's profit. +#define COMSIG_ITEM_SPLIT_PROFIT "item_split_profits" +///called when getting the item's exact ratio for cargo's profit, without selling the item. +#define COMSIG_ITEM_SPLIT_PROFIT_DRY "item_split_profits_dry" + +// /obj/item/clothing signals + +///from base of obj/item/clothing/shoes/proc/step_action(): () +#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" +///from base of /obj/item/clothing/suit/space/proc/toggle_spacesuit(): (obj/item/clothing/suit/space/suit) +#define COMSIG_SUIT_SPACE_TOGGLE "suit_space_toggle" + +// /obj/item/implant signals +///from base of /obj/item/implant/proc/activate(): () +#define COMSIG_IMPLANT_ACTIVATED "implant_activated" +///from base of /obj/item/implant/proc/implant(): (list/args) +#define COMSIG_IMPLANT_IMPLANTING "implant_implanting" + #define COMPONENT_STOP_IMPLANTING (1<<0) +///called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant) +#define COMSIG_IMPLANT_OTHER "implant_other" + //#define COMPONENT_STOP_IMPLANTING (1<<0) //The name makes sense for both + #define COMPONENT_DELETE_NEW_IMPLANT (1<<1) + #define COMPONENT_DELETE_OLD_IMPLANT (1<<2) +///called on implants being implanted into someone with an uplink implant: (datum/component/uplink) +#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists" + //This uses all return values of COMSIG_IMPLANT_OTHER + +// /obj/item/pda signals + +///called on pda when the user changes the ringtone: (mob/living/user, new_ringtone) +#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone" + #define COMPONENT_STOP_RINGTONE_CHANGE (1<<0) +#define COMSIG_PDA_CHECK_DETONATE "pda_check_detonate" + #define COMPONENT_PDA_NO_DETONATE (1<<0) + +// /obj/item/radio signals + +///called from base of /obj/item/radio/proc/set_frequency(): (list/args) +#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency" + +// /obj/item/pen signals + +///called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) +#define COMSIG_PEN_ROTATED "pen_rotated" + +// /obj/item/gun signals + +///called in /obj/item/gun/process_fire (user, target, params, zone_override) +#define COMSIG_MOB_FIRED_GUN "mob_fired_gun" + +// /obj/item/grenade signals + +///called in /obj/item/gun/process_fire (user, target, params, zone_override) +#define COMSIG_GRENADE_PRIME "grenade_prime" +///called in /obj/item/gun/process_fire (user, target, params, zone_override) +#define COMSIG_GRENADE_ARMED "grenade_armed" + +// /obj/projectile signals (sent to the firer) + +///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) +#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" +///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) +#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" +///from base of /obj/projectile/proc/fire(): (obj/projectile, atom/original_target) +#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" +///from the base of /obj/projectile/proc/fire(): () +#define COMSIG_PROJECTILE_FIRE "projectile_fire" +///sent to targets during the process_hit proc of projectiles +#define COMSIG_PROJECTILE_PREHIT "com_proj_prehit" +///sent to targets during the process_hit proc of projectiles +#define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out" +///sent when trying to force an embed (mainly for projectiles, only used in the embed element) +#define COMSIG_EMBED_TRY_FORCE "item_try_embed" + +///sent to targets during the process_hit proc of projectiles +#define COMSIG_PELLET_CLOUD_INIT "pellet_cloud_init" + +// /obj/mecha signals + +///sent from mecha action buttons to the mecha they're linked to +#define COMSIG_MECHA_ACTION_ACTIVATE "mecha_action_activate" + +// /mob/living/carbon/human signals + +///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity) +#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack" +///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity) +#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" +///from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) +#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" +///Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted) +#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" +///Whenever EquipRanked is called, called after job is set +#define COMSIG_JOB_RECEIVED "job_received" + +// /datum/species signals + +///from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) +#define COMSIG_SPECIES_GAIN "species_gain" +///from datum/species/on_species_loss(): (datum/species/lost_species) +#define COMSIG_SPECIES_LOSS "species_loss" + +// /datum/song signals + +///sent to the instrument when a song starts playing +#define COMSIG_SONG_START "song_start" +///sent to the instrument when a song stops playing +#define COMSIG_SONG_END "song_end" + +/*******Component Specific Signals*******/ +//Janitor + +///(): Returns bitflags of wet values. +#define COMSIG_TURF_IS_WET "check_turf_wet" +///(max_strength, immediate, duration_decrease = INFINITY): Returns bool. +#define COMSIG_TURF_MAKE_DRY "make_turf_try" +///called on an object to clean it of cleanables. Usualy with soap: (num/strength) +#define COMSIG_COMPONENT_CLEAN_ACT "clean_act" + +//Creamed + +///called when you wash your face at a sink: (num/strength) +#define COMSIG_COMPONENT_CLEAN_FACE_ACT "clean_face_act" + +//Food + +///from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder) +#define COMSIG_FOOD_EATEN "food_eaten" + +//Gibs + +///from base of /obj/effect/decal/cleanable/blood/gibs/streak(): (list/directions, list/diseases) +#define COMSIG_GIBS_STREAK "gibs_streak" + +//Mood + +///called when you send a mood event from anywhere in the code. +#define COMSIG_ADD_MOOD_EVENT "add_mood" +///Mood event that only RnD members listen for +#define COMSIG_ADD_MOOD_EVENT_RND "RND_add_mood" +///called when you clear a mood event from anywhere in the code. +#define COMSIG_CLEAR_MOOD_EVENT "clear_mood" + +//NTnet + +///called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata)) +#define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" + +//Nanites + +///() returns TRUE if nanites are found +#define COMSIG_HAS_NANITES "has_nanites" +///() returns TRUE if nanites have stealth +#define COMSIG_NANITE_IS_STEALTHY "nanite_is_stealthy" +///() deletes the nanite component +#define COMSIG_NANITE_DELETE "nanite_delete" +///(list/nanite_programs) - makes the input list a copy the nanites' program list +#define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs" +///(amount) Returns nanite amount +#define COMSIG_NANITE_GET_VOLUME "nanite_get_volume" +///(amount) Sets current nanite volume to the given amount +#define COMSIG_NANITE_SET_VOLUME "nanite_set_volume" +///(amount) Adjusts nanite volume by the given amount +#define COMSIG_NANITE_ADJUST_VOLUME "nanite_adjust" +///(amount) Sets maximum nanite volume to the given amount +#define COMSIG_NANITE_SET_MAX_VOLUME "nanite_set_max_volume" +///(amount(0-100)) Sets cloud ID to the given amount +#define COMSIG_NANITE_SET_CLOUD "nanite_set_cloud" +///(method) Modify cloud sync status. Method can be toggle, enable or disable +#define COMSIG_NANITE_SET_CLOUD_SYNC "nanite_set_cloud_sync" +///(amount) Sets safety threshold to the given amount +#define COMSIG_NANITE_SET_SAFETY "nanite_set_safety" +///(amount) Sets regeneration rate to the given amount +#define COMSIG_NANITE_SET_REGEN "nanite_set_regen" +///(code(1-9999)) Called when sending a nanite signal to a mob. +#define COMSIG_NANITE_SIGNAL "nanite_signal" +///(comm_code(1-9999), comm_message) Called when sending a nanite comm signal to a mob. +#define COMSIG_NANITE_COMM_SIGNAL "nanite_comm_signal" +///(mob/user, full_scan) - sends to chat a scan of the nanites to the user, returns TRUE if nanites are detected +#define COMSIG_NANITE_SCAN "nanite_scan" +///(list/data, scan_level) - adds nanite data to the given data list - made for ui_data procs +#define COMSIG_NANITE_UI_DATA "nanite_ui_data" +///(datum/nanite_program/new_program, datum/nanite_program/source_program) Called when adding a program to a nanite component +#define COMSIG_NANITE_ADD_PROGRAM "nanite_add_program" + ///Installation successful + #define COMPONENT_PROGRAM_INSTALLED (1<<0) + ///Installation failed, but there are still nanites + #define COMPONENT_PROGRAM_NOT_INSTALLED (1<<1) +///(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component +#define COMSIG_NANITE_SYNC "nanite_sync" + +// /datum/component/storage signals + +///() - returns bool. +#define COMSIG_CONTAINS_STORAGE "is_storage" +///(obj/item/inserting, mob/user, silent, force) - returns bool +#define COMSIG_TRY_STORAGE_INSERT "storage_try_insert" +///(mob/show_to, force) - returns bool. +#define COMSIG_TRY_STORAGE_SHOW "storage_show_to" +///(mob/hide_from) - returns bool +#define COMSIG_TRY_STORAGE_HIDE_FROM "storage_hide_from" +///returns bool +#define COMSIG_TRY_STORAGE_HIDE_ALL "storage_hide_all" +///(newstate) +#define COMSIG_TRY_STORAGE_SET_LOCKSTATE "storage_lock_set_state" +///() - returns bool. MUST CHECK IF STORAGE IS THERE FIRST! +#define COMSIG_IS_STORAGE_LOCKED "storage_get_lockstate" +///(type, atom/destination, amount = INFINITY, check_adjacent, force, mob/user, list/inserted) - returns bool - type can be a list of types. +#define COMSIG_TRY_STORAGE_TAKE_TYPE "storage_take_type" +///(type, amount = INFINITY, force = FALSE). Force will ignore max_items, and amount is normally clamped to max_items. +#define COMSIG_TRY_STORAGE_FILL_TYPE "storage_fill_type" +///(obj, new_loc, force = FALSE) - returns bool +#define COMSIG_TRY_STORAGE_TAKE "storage_take_obj" +///(loc) - returns bool - if loc is null it will dump at parent location. +#define COMSIG_TRY_STORAGE_QUICK_EMPTY "storage_quick_empty" +///(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE) +#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" +///(obj/item/insertion_candidate, mob/user, silent) - returns bool +#define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip" + +// /datum/component/two_handed signals + +///from base of datum/component/two_handed/proc/wield(mob/living/carbon/user): (/mob/user) +#define COMSIG_TWOHANDED_WIELD "twohanded_wield" + #define COMPONENT_TWOHANDED_BLOCK_WIELD (1<<0) +///from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user) +#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield" + +// /datum/action signals + +///from base of datum/action/proc/Trigger(): (datum/action) +#define COMSIG_ACTION_TRIGGER "action_trigger" + #define COMPONENT_ACTION_BLOCK_TRIGGER (1<<0) + +//Xenobio hotkeys + +///from slime CtrlClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" +///from slime AltClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" +///from slime ShiftClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" +///from turf ShiftClickOn(): (/mob) +#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" +///from turf AltClickOn(): (/mob) +#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" +///from monkey CtrlClickOn(): (/mob) +#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm index ee6c5d10fe0..352a6fa3680 100644 --- a/code/__HELPERS/traits.dm +++ b/code/__HELPERS/traits.dm @@ -65,6 +65,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_WATERBREATH "waterbreathing" #define TRAIT_BLOODCRAWL "bloodcrawl" #define TRAIT_BLOODCRAWL_EAT "bloodcrawl_eat" +#define TRAIT_JESTER "jester" // common trait sources #define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index aa130bb3ca9..80852f25c3f 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -2038,3 +2038,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) tX = Clamp(origin.x + text2num(tX) - round(actual_view[1] / 2) - 1, 1, world.maxx) tY = Clamp(origin.y + text2num(tY) - round(actual_view[2] / 2) - 1, 1, world.maxy) return locate(tX, tY, tZ) + +/proc/CallAsync(datum/source, proctype, list/arguments) + set waitfor = FALSE + return call(source, proctype)(arglist(arguments)) diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm new file mode 100644 index 00000000000..09dea24071f --- /dev/null +++ b/code/controllers/subsystem/dcs.dm @@ -0,0 +1,53 @@ +PROCESSING_SUBSYSTEM_DEF(dcs) + name = "Datum Component System" + flags = SS_NO_INIT + + var/list/elements_by_type = list() + +/datum/controller/subsystem/processing/dcs/Recover() + comp_lookup = SSdcs.comp_lookup + +/datum/controller/subsystem/processing/dcs/proc/GetElement(list/arguments) + var/datum/element/eletype = arguments[1] + var/element_id = eletype + + if(!ispath(eletype, /datum/element)) + CRASH("Attempted to instantiate [eletype] as a /datum/element") + + if(initial(eletype.element_flags) & ELEMENT_BESPOKE) + element_id = GetIdFromArguments(arguments) + + . = elements_by_type[element_id] + if(.) + return + . = elements_by_type[element_id] = new eletype + +/**** + * Generates an id for bespoke elements when given the argument list + * Generating the id here is a bit complex because we need to support named arguments + * Named arguments can appear in any order and we need them to appear after ordered arguments + * We assume that no one will pass in a named argument with a value of null + **/ +/datum/controller/subsystem/processing/dcs/proc/GetIdFromArguments(list/arguments) + var/datum/element/eletype = arguments[1] + var/list/fullid = list("[eletype]") + var/list/named_arguments = list() + for(var/i in initial(eletype.id_arg_index) to length(arguments)) + var/key = arguments[i] + var/value + if(istext(key)) + value = arguments[key] + if(!(istext(key) || isnum(key))) + key = "\ref[key]" + key = "[key]" // Key is stringified so numbers dont break things + if(!isnull(value)) + if(!(istext(value) || isnum(value))) + value = "\ref[value]" + named_arguments["[key]"] = value + else + fullid += "[key]" + + if(length(named_arguments)) + named_arguments = sortList(named_arguments) + fullid += named_arguments + return list2params(fullid) diff --git a/code/datums/action.dm b/code/datums/action.dm index b7af84e9ddf..c1802da47c1 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -339,7 +339,7 @@ /datum/action/item_action/remove_tape/Trigger(attack_self = FALSE) if(..()) - GET_COMPONENT_FROM(DT, /datum/component/ducttape, target) + var/datum/component/ducttape/DT = target.GetComponent(/datum/component/ducttape) DT.remove_tape(target, usr) /datum/action/item_action/toggle_jetpack diff --git a/code/datums/components/README.md b/code/datums/components/README.md index 9d06a255dd7..3080f7e7b44 100644 --- a/code/datums/components/README.md +++ b/code/datums/components/README.md @@ -2,134 +2,8 @@ ## Concept -Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SEND_SIGNAL` call. Now every component that want's to can also know about this happening. +Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SendSignal()` call. Now every component that want's to can also know about this happening. -### In the code +See [this thread](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) for an introduction to the system as a whole. -#### Slippery things - -At the time of this writing, every object that is slippery overrides atom/Crossed does some checks, then slips the mob. Instead of all those Crossed overrides they could add a slippery component to all these objects. And have the checks in one proc that is run by the Crossed event - -#### Powercells - -A lot of objects have powercells. The `get_cell()` proc was added to give generic access to the cell var if it had one. This is just a specific use case of `GetComponent()` - -#### Radios - -The radio object as it is should not exist, given that more things use the _concept_ of radios rather than the object itself. The actual function of the radio can exist in a component which all the things that use it (Request consoles, actual radios, the SM shard) can add to themselves. - -#### Standos - -Stands have a lot of procs which mimic mob procs. Rather than inserting hooks for all these procs in overrides, the same can be accomplished with signals - -## API - -### Defines - -1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. This will be noted in the runtime logs - -### Vars - -1. `/datum/var/list/datum_components` (private) - * Lazy associated list of type -> component/list of components. -1. `/datum/var/list/comp_lookup` (private) - * Lazy associated list of signal -> registree/list of registrees -1. `/datum/var/list/signal_procs` (private) - * Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal -1. `/datum/var/signal_enabled` (protected, boolean) - * If the datum is signal enabled. If not, it will not react to signals - * `FALSE` by default, set to `TRUE` when a signal is registered -1. `/datum/component/var/dupe_mode` (protected, enum) - * How duplicate component types are handled when added to the datum. - * `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it - * `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added - * `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it - * `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component. -1. `/datum/component/var/dupe_type` (protected, type) - * Definition of a duplicate component type - * `null` means exact match on `type` (default) - * Any other type means that and all subtypes -1. `/datum/component/var/datum/parent` (protected, read-only) - * The datum this component belongs to - * Never `null` in child procs -1. `report_signal_origin` (protected, boolean) - * If `TRUE`, will invoke the callback when signalled with the signal type as the first argument. - * `FALSE` by default. - -### Procs - -1. `/datum/proc/GetComponent(component_type(type)) -> datum/component?` (public, final) - * Returns a reference to a component of component_type if it exists in the datum, null otherwise -1. `/datum/proc/GetComponents(component_type(type)) -> list` (public, final) - * Returns a list of references to all components of component_type that exist in the datum -1. `/datum/proc/GetExactComponent(component_type(type)) -> datum/component?` (public, final) - * Returns a reference to a component whose type MATCHES component_type if that component exists in the datum, null otherwise -1. `GET_COMPONENT(varname, component_type)` OR `GET_COMPONENT_FROM(varname, component_type, src)` - * Shorthand for `var/component_type/varname = src.GetComponent(component_type)` -1. `SEND_SIGNAL(target, sigtype, ...)` (public, final) - * Use to send signals to target datum - * Extra arguments are to be specified in the signal definition - * Returns a bitflag with signal specific information assembled from all activated components - * Arguments are packaged in a list and handed off to _SendSignal() -1. `/datum/proc/AddComponent(component_type(type), ...) -> datum/component` (public, final) - * Creates an instance of `component_type` in the datum and passes `...` to its `Initialize()` call - * Sends the `COMSIG_COMPONENT_ADDED` signal to the datum - * All components a datum owns are deleted with the datum - * Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set - * If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it - * Properly handles duplicate situations based on the `dupe_mode` var -1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final) - * Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead -1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async) - * Called on a component's `parent` after a signal received causes it to activate. `src` is the parameter - * Will only be called if a component's callback returns `TRUE` -1. `/datum/proc/TakeComponent(datum/component/C)` (public, final) - * Properly transfers ownership of a component from one datum to another - * Signals `COMSIG_COMPONENT_REMOVING` on the parent - * Called on the datum you want to own the component with another datum's component -1. `/datum/proc/_SendSignal(signal, list/arguments)` (private, final) - * Handles most of the actual signaling procedure - * Will runtime if used on datums with an empty component list -1. `/datum/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) - * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments - * Makes the datum listen for the specified `signal` on it's `parent` datum. - * When that signal is received `proc_ref` will be called on the component, along with associated arguments - * Example proc ref: `.proc/OnEvent` - * If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this - * These callbacks run asyncronously - * Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it -1. `/datum/component/New(datum/parent, ...)` (private, final) - * Runs internal setup for the component - * Extra arguments are passed to `Initialize()` -1. `/datum/component/Initialize(...)` (abstract, no-sleep) - * Called by `New()` with the same argments excluding `parent` - * Component does not exist in `parent`'s `datum_components` list yet, although `parent` is set and may be used - * Signals will not be received while this function is running - * Component may be deleted after this function completes without being attached - * Do not call `qdel(src)` from this function -1. `/datum/component/Destroy(force(bool), silent(bool))` (virtual, no-sleep) - * Sends the `COMSIG_COMPONENT_REMOVING` signal to the parent datum if the `parent` isn't being qdeleted - * Properly removes the component from `parent` and cleans up references - * Setting `force` makes it not check for and remove the component from the parent - * Setting `silent` deletes the component without sending a `COMSIG_COMPONENT_REMOVING` signal -1. `/datum/component/proc/InheritComponent(datum/component/C, i_am_original(boolean))` (abstract, no-sleep) - * Called on a component when a component of the same type was added to the same parent - * See `/datum/component/var/dupe_mode` - * `C`'s type will always be the same of the called component -1. `/datum/component/proc/AfterComponentActivated()` (abstract, async) - * Called on a component that was activated after it's `parent`'s `ComponentActivated()` is called -1. `/datum/component/proc/OnTransfer(datum/new_parent)` (abstract, no-sleep) - * Called before `new_parent` is assigned to `parent` in `TakeComponent()` - * Allows the component to react to ownership transfers -1. `/datum/component/proc/_RemoveFromParent()` (private, final) - * Clears `parent` and removes the component from it's component list -1. `/datum/component/proc/_JoinParent` (private, final) - * Tries to add the component to it's `parent`s `datum_components` list -1. `/datum/component/proc/RegisterWithParent` (abstract, no-sleep) - * Used to register the signals that should be on the `parent` object - * Use this if you plan on the component transfering between parents -1. `/datum/component/proc/UnregisterFromParent` (abstract, no-sleep) - * Counterpart to `RegisterWithParent()` - * Used to unregister the signals that should only be on the `parent` object - -### See/Define signals and their arguments in __DEFINES\components.dm +### See/Define signals and their arguments in [__DEFINES\components.dm](../../__DEFINES/components.dm) diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index e733ca78d2b..f895b8d81b1 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -1,21 +1,87 @@ +/** + * # Component + * + * The component datum + * + * A component should be a single standalone unit + * of functionality, that works by receiving signals from it's parent + * object to provide some single functionality (i.e a slippery component) + * that makes the object it's attached to cause people to slip over. + * Useful when you want shared behaviour independent of type inheritance + */ /datum/component + /** + * Defines how duplicate existing components are handled when added to a datum + * + * See [COMPONENT_DUPE_*][COMPONENT_DUPE_ALLOWED] definitions for available options + */ var/dupe_mode = COMPONENT_DUPE_HIGHLANDER + + /** + * The type to check for duplication + * + * `null` means exact match on `type` (default) + * + * Any other type means that and all subtypes + */ var/dupe_type + + /// The datum this components belongs to var/datum/parent - //only set to true if you are able to properly transfer this component - //At a minimum RegisterWithParent and UnregisterFromParent should be used - //Make sure you also implement PostTransfer for any post transfer handling + + /** + * Only set to true if you are able to properly transfer this component + * + * At a minimum [RegisterWithParent][/datum/component/proc/RegisterWithParent] and [UnregisterFromParent][/datum/component/proc/UnregisterFromParent] should be used + * + * Make sure you also implement [PostTransfer][/datum/component/proc/PostTransfer] for any post transfer handling + */ var/can_transfer = FALSE -/datum/component/New(datum/P, ...) - parent = P - var/list/arguments = args.Copy(2) +/** + * Create a new component. + * + * Additional arguments are passed to [Initialize()][/datum/component/proc/Initialize] + * + * Arguments: + * * datum/P the parent datum this component reacts to signals from + */ +/datum/component/New(list/raw_args) + parent = raw_args[1] + var/list/arguments = raw_args.Copy(2) if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) + stack_trace("Incompatible [type] assigned to a [parent.type]! args: [json_encode(arguments)]") qdel(src, TRUE, TRUE) - CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]") + return - _JoinParent(P) + _JoinParent(parent) +/** + * Called during component creation with the same arguments as in new excluding parent. + * + * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead + */ +/datum/component/proc/Initialize(...) + return + +/** + * Properly removes the component from `parent` and cleans up references + * + * Arguments: + * * force - makes it not check for and remove the component from the parent + * * silent - deletes the component without sending a [COMSIG_COMPONENT_REMOVING] signal + */ +/datum/component/Destroy(force=FALSE, silent=FALSE) + if(!force && parent) + _RemoveFromParent() + if(!silent) + SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src) + parent = null + return ..() + +/** + * Internal proc to handle behaviour of components when joining a parent + */ /datum/component/proc/_JoinParent() var/datum/P = parent //lazy init the parent's dc list @@ -51,21 +117,9 @@ RegisterWithParent() -// If you want/expect to be moving the component around between parents, use this to register on the parent for signals -/datum/component/proc/RegisterWithParent() - return - -/datum/component/proc/Initialize(...) - return - -/datum/component/Destroy(force=FALSE, silent=FALSE) - if(!force && parent) - _RemoveFromParent() - if(!silent) - SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src) - parent = null - return ..() - +/** + * Internal proc to handle behaviour when being removed from a parent + */ /datum/component/proc/_RemoveFromParent() var/datum/P = parent var/list/dc = P.datum_components @@ -84,10 +138,41 @@ UnregisterFromParent() +/** + * Register the component with the parent object + * + * Use this proc to register with your parent object + * + * Overridable proc that's called when added to a new parent + */ +/datum/component/proc/RegisterWithParent() + return + +/** + * Unregister from our parent object + * + * Use this proc to unregister from your parent object + * + * Overridable proc that's called when removed from a parent + * * + */ /datum/component/proc/UnregisterFromParent() return -/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE) +/** + * Register to listen for a signal from the passed in target + * + * This sets up a listening relationship such that when the target object emits a signal + * the source datum this proc is called upon, will recieve a callback to the given proctype + * Return values from procs registered must be a bitfield + * + * Arguments: + * * datum/target The target to listen for signals from + * * sig_type_or_types Either a string signal name, or a list of signal names (strings) + * * proctype The proc to call back when the signal is emitted + * * override If a previous registration exists you must explicitly set this + */ +/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE) if(QDELETED(src) || QDELETED(target)) return @@ -100,15 +185,12 @@ if(!lookup) target.comp_lookup = lookup = list() - if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now - proc_or_callback = CALLBACK(src, proc_or_callback) - var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types) for(var/sig_type in sig_types) if(!override && procs[target][sig_type]) stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning") - procs[target][sig_type] = proc_or_callback + procs[target][sig_type] = proctype if(!lookup[sig_type]) // Nothing has registered here yet lookup[sig_type] = src @@ -122,6 +204,17 @@ signal_enabled = TRUE +/** + * Stop listening to a given signal from target + * + * Breaks the relationship between target and source datum, removing the callback when the signal fires + * + * Doesn't care if a registration exists or not + * + * Arguments: + * * datum/target Datum to stop listening to signals from + * * sig_typeor_types Signal string key or list of signal keys to stop listening to specifically + */ /datum/proc/UnregisterSignal(datum/target, sig_type_or_types) var/list/lookup = target.comp_lookup if(!signal_procs || !signal_procs[target] || !lookup) @@ -129,6 +222,8 @@ if(!islist(sig_type_or_types)) sig_type_or_types = list(sig_type_or_types) for(var/sig in sig_type_or_types) + if(!signal_procs[target][sig]) + continue switch(length(lookup[sig])) if(2) lookup[sig] = (lookup[sig]-src)[1] @@ -151,41 +246,96 @@ if(!signal_procs[target].len) signal_procs -= target +/** + * Called on a component when a component of the same type was added to the same parent + * + * See [/datum/component/var/dupe_mode] + * + * `C`'s type will always be the same of the called component + */ /datum/component/proc/InheritComponent(datum/component/C, i_am_original) return + +/** + * Called on a component when a component of the same type was added to the same parent with [COMPONENT_DUPE_SELECTIVE] + * + * See [/datum/component/var/dupe_mode] + * + * `C`'s type will always be the same of the called component + * + * return TRUE if you are absorbing the component, otherwise FALSE if you are fine having it exist as a duplicate component + */ +/datum/component/proc/CheckDupeComponent(datum/component/C, ...) + return + + +/** + * Callback Just before this component is transferred + * + * Use this to do any special cleanup you might need to do before being deregged from an object + */ /datum/component/proc/PreTransfer() return +/** + * Callback Just after a component is transferred + * + * Use this to do any special setup you need to do after being moved to a new object + * + * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead + */ /datum/component/proc/PostTransfer() return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it +/** + * Internal proc to create a list of our type and all parent types + */ /datum/component/proc/_GetInverseTypeList(our_type = type) //we can do this one simple trick var/current_type = parent_type . = list(our_type, current_type) //and since most components are root level + 1, this won't even have to run - while(current_type != /datum/component) + while (current_type != /datum/component) current_type = type2parent(current_type) . += current_type +/** + * Internal proc to handle most all of the signaling procedure + * + * Will runtime if used on datums with an empty component list + * + * Use the [SEND_SIGNAL] define instead + */ /datum/proc/_SendSignal(sigtype, list/arguments) var/target = comp_lookup[sigtype] if(!length(target)) var/datum/C = target if(!C.signal_enabled) return NONE - var/datum/callback/CB = C.signal_procs[src][sigtype] - return CB.InvokeAsync(arglist(arguments)) + var/proctype = C.signal_procs[src][sigtype] + return NONE | CallAsync(C, proctype, arguments) . = NONE for(var/I in target) var/datum/C = I if(!C.signal_enabled) continue - var/datum/callback/CB = C.signal_procs[src][sigtype] - . |= CB.InvokeAsync(arglist(arguments)) + var/proctype = C.signal_procs[src][sigtype] + . |= CallAsync(C, proctype, arguments) -/datum/proc/GetComponent(c_type) +// The type arg is casted so initial works, you shouldn't be passing a real instance into this +/** + * Return any component assigned to this datum of the given type + * + * This will throw an error if it's possible to have more than one component of that type on the parent + * + * Arguments: + * * datum/component/c_type The typepath of the component you want to get a reference to + */ +/datum/proc/GetComponent(datum/component/c_type) + RETURN_TYPE(c_type) + if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE) + stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]") var/list/dc = datum_components if(!dc) return null @@ -193,7 +343,19 @@ if(length(.)) return .[1] -/datum/proc/GetExactComponent(c_type) +// The type arg is casted so initial works, you shouldn't be passing a real instance into this +/** + * Return any component assigned to this datum of the exact given type + * + * This will throw an error if it's possible to have more than one component of that type on the parent + * + * Arguments: + * * datum/component/c_type The typepath of the component you want to get a reference to + */ +/datum/proc/GetExactComponent(datum/component/c_type) + RETURN_TYPE(c_type) + if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE) + stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]") var/list/dc = datum_components if(!dc) return null @@ -205,6 +367,12 @@ return C return null +/** + * Get all components of a given type that are attached to this datum + * + * Arguments: + * * c_type The component type path + */ /datum/proc/GetComponents(c_type) var/list/dc = datum_components if(!dc) @@ -213,7 +381,19 @@ if(!length(.)) return list(.) -/datum/proc/AddComponent(new_type, ...) +/** + * Creates an instance of `new_type` in the datum and attaches to it as parent + * + * Sends the [COMSIG_COMPONENT_ADDED] signal to the datum + * + * Returns the component that was created. Or the old component in a dupe situation where [COMPONENT_DUPE_UNIQUE] was set + * + * If this tries to add a component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it + * + * Properly handles duplicate situations based on the `dupe_mode` var + */ +/datum/proc/_AddComponent(list/raw_args) + var/new_type = raw_args[1] var/datum/component/nt = new_type var/dm = initial(nt.dupe_mode) var/dt = initial(nt.dupe_type) @@ -228,7 +408,7 @@ new_comp = nt nt = new_comp.type - args[1] = src + raw_args[1] = src if(dm != COMPONENT_DUPE_ALLOWED) if(!dt) @@ -239,37 +419,62 @@ switch(dm) if(COMPONENT_DUPE_UNIQUE) if(!new_comp) - new_comp = new nt(arglist(args)) + new_comp = new nt(raw_args) if(!QDELETED(new_comp)) old_comp.InheritComponent(new_comp, TRUE) QDEL_NULL(new_comp) if(COMPONENT_DUPE_HIGHLANDER) if(!new_comp) - new_comp = new nt(arglist(args)) + new_comp = new nt(raw_args) if(!QDELETED(new_comp)) new_comp.InheritComponent(old_comp, FALSE) QDEL_NULL(old_comp) if(COMPONENT_DUPE_UNIQUE_PASSARGS) if(!new_comp) - var/list/arguments = args.Copy(2) - old_comp.InheritComponent(null, TRUE, arguments) + var/list/arguments = raw_args.Copy(2) + arguments.Insert(1, null, TRUE) + old_comp.InheritComponent(arglist(arguments)) else old_comp.InheritComponent(new_comp, TRUE) + if(COMPONENT_DUPE_SELECTIVE) + var/list/arguments = raw_args.Copy() + arguments[1] = new_comp + var/make_new_component = TRUE + for(var/i in GetComponents(new_type)) + var/datum/component/C = i + if(C.CheckDupeComponent(arglist(arguments))) + make_new_component = FALSE + QDEL_NULL(new_comp) + break + if(!new_comp && make_new_component) + new_comp = new nt(raw_args) else if(!new_comp) - new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal + new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal else if(!new_comp) - new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal + new_comp = new nt(raw_args) // Dupes are allowed, act like normal if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_comp) return new_comp return old_comp +/** + * Get existing component of type, or create it and return a reference to it + * + * Use this if the item needs to exist at the time of this call, but may not have been created before now + * + * Arguments: + * * component_type The typepath of the component to create or return + * * ... additional arguments to be passed when creating the component if it does not exist + */ /datum/proc/LoadComponent(component_type, ...) . = GetComponent(component_type) if(!.) - return AddComponent(arglist(args)) + return _AddComponent(args) +/** + * Removes the component from parent, ends up with a null parent + */ /datum/component/proc/RemoveComponent() if(!parent) return @@ -279,6 +484,14 @@ parent = null SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src) +/** + * Transfer this component to another parent + * + * Component is taken from source datum + * + * Arguments: + * * datum/component/target Target datum to transfer to + */ /datum/proc/TakeComponent(datum/component/target) if(!target || target.parent == src) return @@ -295,6 +508,14 @@ if(target == AddComponent(target)) target._JoinParent() +/** + * Transfer all components to target + * + * All components from source datum are taken + * + * Arguments: + * * /datum/target the target to move the components to + */ /datum/proc/TransferComponents(datum/target) var/list/dc = datum_components if(!dc) @@ -309,5 +530,8 @@ if(C.can_transfer) target.TakeComponent(comps) +/** + * Return the object that is the host of any UI's that this component has + */ /datum/component/nano_host() return parent diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm index 6a0f686b13a..876cf0c0507 100644 --- a/code/datums/components/decal.dm +++ b/code/datums/components/decal.dm @@ -7,7 +7,7 @@ var/first_dir // This only stores the dir arg from init -/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255) +/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable = CLEAN_GOD, _color, _layer = TURF_LAYER, _description, _alpha = 255) if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)) return COMPONENT_INCOMPATIBLE first_dir = _dir diff --git a/code/datums/components/edit_complainer.dm b/code/datums/components/edit_complainer.dm new file mode 100644 index 00000000000..35bb05ca791 --- /dev/null +++ b/code/datums/components/edit_complainer.dm @@ -0,0 +1,23 @@ +// This is just a bit of fun while making an example for global signal +/datum/component/edit_complainer + var/list/say_lines + +/datum/component/edit_complainer/Initialize(list/text) + if(!ismovableatom(parent)) + return COMPONENT_INCOMPATIBLE + + var/static/list/default_lines = list( + "CentComm's profligacy frays another thread.", + "Another tug at the weave.", + "Who knows when the stresses will finally shatter the form?", + "Even now a light shines through the cracks.", + "CentComm once more twists knowledge beyond its authority.", + "There is an uncertain air in the mansus.", + ) + say_lines = text || default_lines + + RegisterSignal(SSdcs, COMSIG_GLOB_VAR_EDIT, .proc/var_edit_react) + +/datum/component/edit_complainer/proc/var_edit_react(datum/source, list/arguments) + var/atom/movable/master = parent + master.atom_say(pick(say_lines)) diff --git a/code/datums/components/jestosterone.dm b/code/datums/components/jestosterone.dm deleted file mode 100644 index f37f1f03efb..00000000000 --- a/code/datums/components/jestosterone.dm +++ /dev/null @@ -1,5 +0,0 @@ -/datum/component/jestosterone - var/mind_type //Is the affected mob a clown / mime? - -/datum/component/jestosterone/Initialize(mind_type_arg) - mind_type = mind_type_arg diff --git a/code/datums/components/label.dm b/code/datums/components/label.dm index 26cb99c7e3c..c6d0c595ebb 100644 --- a/code/datums/components/label.dm +++ b/code/datums/components/label.dm @@ -32,12 +32,12 @@ This proc will fire after the parent is hit by a hand labeler which is trying to apply another label. Since the parent already has a label, it will remove the old one from the parent's name, and apply the new one. */ -/datum/component/label/InheritComponent(datum/component/label/new_comp , i_am_original, list/arguments) +/datum/component/label/InheritComponent(datum/component/label/new_comp , i_am_original, _label_name) remove_label() if(new_comp) label_name = new_comp.label_name else - label_name = arguments[1] + label_name = _label_name apply_label() /** diff --git a/code/datums/components/waddling.dm b/code/datums/components/waddling.dm deleted file mode 100644 index a1f538e4dd7..00000000000 --- a/code/datums/components/waddling.dm +++ /dev/null @@ -1,15 +0,0 @@ -/datum/component/waddling - dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS - -/datum/component/waddling/Initialize() - if(!isliving(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle) - -/datum/component/waddling/proc/Waddle() - var/mob/living/L = parent - if(L.incapacitated() || L.lying) - return - animate(L, pixel_z = 4, time = 0) - animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2) - animate(pixel_z = 0, transform = matrix(), time = 0) diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm new file mode 100644 index 00000000000..46a295f90be --- /dev/null +++ b/code/datums/elements/_element.dm @@ -0,0 +1,55 @@ +/** + * A holder for simple behaviour that can be attached to many different types + * + * Only one element of each type is instanced during game init. + * Otherwise acts basically like a lightweight component. + */ +/datum/element + /// Option flags for element behaviour + var/element_flags = NONE + /** + * The index of the first attach argument to consider for duplicate elements + * + * Is only used when flags contains [ELEMENT_BESPOKE] + * + * This is infinity so you must explicitly set this + */ + var/id_arg_index = INFINITY + +/// Activates the functionality defined by the element on the given target datum +/datum/element/proc/Attach(datum/target) + SHOULD_CALL_PARENT(1) + if(type == /datum/element) + return ELEMENT_INCOMPATIBLE + SEND_SIGNAL(target, COMSIG_ELEMENT_ATTACH, src) + if(element_flags & ELEMENT_DETACH) + RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE) + +/// Deactivates the functionality defines by the element on the given datum +/datum/element/proc/Detach(datum/source, force) + SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src) + SHOULD_CALL_PARENT(1) + UnregisterSignal(source, COMSIG_PARENT_QDELETING) + +/datum/element/Destroy(force) + if(!force) + return QDEL_HINT_LETMELIVE + SSdcs.elements_by_type -= type + return ..() + +//DATUM PROCS + +/// Finds the singleton for the element type given and attaches it to src +/datum/proc/_AddElement(list/arguments) + var/datum/element/ele = SSdcs.GetElement(arguments) + arguments[1] = src + if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE) + CRASH("Incompatible [arguments[1]] assigned to a [type]! args: [json_encode(args)]") + +/** + * Finds the singleton for the element type given and detaches it from src + * You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE] + */ +/datum/proc/_RemoveElement(list/arguments) + var/datum/element/ele = SSdcs.GetElement(arguments) + ele.Detach(src) diff --git a/code/datums/elements/waddling.dm b/code/datums/elements/waddling.dm new file mode 100644 index 00000000000..6abe75b3923 --- /dev/null +++ b/code/datums/elements/waddling.dm @@ -0,0 +1,25 @@ +/datum/element/waddling + +/datum/element/waddling/Attach(datum/target) + . = ..() + if(!ismovableatom(target)) + return ELEMENT_INCOMPATIBLE + if(isliving(target)) + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/LivingWaddle) + else + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/Waddle) + +/datum/element/waddling/Detach(datum/source, force) + . = ..() + UnregisterSignal(source, COMSIG_MOVABLE_MOVED) + +/datum/element/waddling/proc/LivingWaddle(mob/living/target) + if(target.incapacitated() || target.lying) + return + Waddle(target) + +/datum/element/waddling/proc/Waddle(atom/movable/target) + animate(target, pixel_z = 4, time = 0) + var/prev_trans = matrix(target.transform) + animate(pixel_z = 0, transform = turn(target.transform, pick(-12, 0, 12)), time = 2) + animate(pixel_z = 0, transform = prev_trans, time = 0) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 78367327a0c..7a0c2483b40 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -38,7 +38,7 @@ var/list/categories = list("Tools", "Electronics", "Construction", "Communication", "Security", "Machinery", "Medical", "Miscellaneous", "Dinnerware", "Imported") /obj/machinery/autolathe/New() - AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert)) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert)) ..() component_parts = list() component_parts += new /obj/item/circuitboard/autolathe(null) @@ -66,7 +66,7 @@ /obj/machinery/autolathe/Destroy() QDEL_NULL(wires) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -87,7 +87,7 @@ ui.open() /obj/machinery/autolathe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/data[0] data["screen"] = screen data["total_amount"] = materials.total_amount @@ -138,7 +138,7 @@ /obj/machinery/autolathe/proc/design_cost_data(datum/design/D) var/list/data = list() var/coeff = get_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/has_metal = 1 if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] / coeff))) has_metal = 0 @@ -152,7 +152,7 @@ return data /obj/machinery/autolathe/proc/queue_data(list/data) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/temp_metal = materials.amount(MAT_METAL) var/temp_glass = materials.amount(MAT_GLASS) data["processing"] = being_built.len ? get_processing_line() : null @@ -288,7 +288,7 @@ //multiplier checks : only stacks can have one and its value is 1, 10 ,25 or max_multiplier var/multiplier = text2num(href_list["multiplier"]) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/max_multiplier = min(design_last_ordered.maxstack, design_last_ordered.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/design_last_ordered.materials[MAT_METAL]):INFINITY,design_last_ordered.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/design_last_ordered.materials[MAT_GLASS]):INFINITY) var/is_stack = ispath(design_last_ordered.build_path, /obj/item/stack) @@ -342,7 +342,7 @@ for(var/obj/item/stock_parts/matter_bin/MB in component_parts) tot_rating += MB.rating tot_rating *= 25000 - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.max_amount = tot_rating * 3 for(var/obj/item/stock_parts/manipulator/M in component_parts) prod_coeff += M.rating - 1 @@ -355,7 +355,7 @@ desc = initial(desc)+"\nIt's building \a [initial(D.name)]." var/is_stack = ispath(D.build_path, /obj/item/stack) var/coeff = get_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/metal_cost = D.materials[MAT_METAL] var/glass_cost = D.materials[MAT_GLASS] var/power = max(2000, (metal_cost+glass_cost)*multiplier/5) @@ -387,7 +387,7 @@ return 0 var/coeff = get_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/metal_amount = materials.amount(MAT_METAL) if(custom_metal) metal_amount = custom_metal diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 081a48c3da1..e4e37ae1bcb 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -19,8 +19,7 @@ var/item_recycle_sound = 'sound/machines/recycler.ogg' /obj/machinery/recycler/New() - AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_PLASTIC, MAT_BLUESPACE), 0, - TRUE, null, null, null, TRUE) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_PLASTIC, MAT_BLUESPACE), 0, TRUE, null, null, null, TRUE) ..() component_parts = list() component_parts += new /obj/item/circuitboard/recycler(null) @@ -37,7 +36,7 @@ mat_mod *= 50000 for(var/obj/item/stock_parts/manipulator/M in component_parts) amt_made = 25 * M.rating //% of materials salvaged - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.max_amount = mat_mod amount_produced = min(100, amt_made) @@ -135,7 +134,7 @@ /obj/machinery/recycler/proc/recycle_item(obj/item/I) I.forceMove(loc) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/material_amount = materials.get_item_material_amount(I) if(!material_amount) qdel(I) diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 90256fe5d2a..7d8537c7910 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -38,9 +38,7 @@ ) /obj/machinery/mecha_part_fabricator/New() - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, - list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), 0, - FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), 0, FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE ..() component_parts = list() @@ -65,7 +63,7 @@ RefreshParts() /obj/machinery/mecha_part_fabricator/Destroy() - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -75,7 +73,7 @@ //maximum stocking amount (default 300000, 600000 at T4) for(var/obj/item/stock_parts/matter_bin/M in component_parts) T += M.rating - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.max_amount = (200000 + (T*50000)) //resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55) @@ -118,7 +116,7 @@ /obj/machinery/mecha_part_fabricator/proc/output_available_resources() var/output - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] output += "[M.name]: [M.amount] cm³" @@ -139,7 +137,7 @@ /obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) if(D.reagents_list.len) // No reagents storage - no reagent designs. return FALSE - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(materials.has_materials(get_resources_w_coeff(D))) return TRUE return FALSE @@ -149,7 +147,7 @@ desc = "It's building \a [initial(D.name)]." var/list/res_coef = get_resources_w_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.use_amount(res_coef) overlays += "fab-active" use_power = ACTIVE_POWER_USE @@ -414,7 +412,7 @@ break if(href_list["remove_mat"] && href_list["material"]) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"]) updateUsrDialog() diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 9ec6e010f44..eafd57cd21f 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1023,6 +1023,18 @@ obj/item/toy/cards/deck/syndicate/black name = "orange fox plushie" icon_state = "orangefox" +/obj/item/toy/plushie/orange_fox/grump + name = "grumpy fox" + desc = "An ancient plushie that seems particularly grumpy." + +/obj/item/toy/plushie/orange_fox/grump/ComponentInitialize() + . = ..() + var/static/list/grumps = list("Ahh, yes, you're so clever, var editing that.", "Really?", "If you make a runtime with var edits, it's your own damn fault.", + "Don't you dare post issues on the git when you don't even know how this works.", "Was that necessary?", "Ohhh, setting admin edited var must be your faovrite pastime!", + "Oh, so you have time to var edit, but you don't have time to ban that greytider?", "Oh boy, is this another one of those 'events'?", "Seriously, just stop.", "You do realize this is incurring proc call overhead.", + "Congrats, you just left a reference with your dirty client and now that thing you edited will never garbage collect properly.", "Is it that time of day, again, for unecessary adminbus?") + AddComponent(/datum/component/edit_complainer, grumps) + /obj/item/toy/plushie/coffee_fox name = "coffee fox plushie" icon_state = "coffeefox" diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index 0474629dea0..079446b0994 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -627,6 +627,7 @@ GLOBAL_LIST_INIT(VVpixelmovement, list("step_x", "step_y", "step_size", "bound_h if(!O.vv_edit_var(variable, var_new)) to_chat(src, "Your edit was rejected by the object.") return + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_VAR_EDIT, args) log_world("### VarEdit by [src]: [O.type] [variable]=[html_encode("[var_new]")]") log_admin("[key_name(src)] modified [original_name]'s [variable] to [var_new]") var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] to [var_new]" diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 916cb8e89d4..129b07af36e 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -73,16 +73,15 @@ obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team shoe_sound = "clownstep" origin_tech = "magnets=4;syndicate=2" var/enabled_waddle = TRUE - var/datum/component/waddle /obj/item/clothing/shoes/magboots/clown/equipped(mob/user, slot) . = ..() if(slot == slot_shoes && enabled_waddle) - waddle = user.AddComponent(/datum/component/waddling) + user.AddElement(/datum/element/waddling) /obj/item/clothing/shoes/magboots/clown/dropped(mob/user) . = ..() - QDEL_NULL(waddle) + user.RemoveElement(/datum/element/waddling) /obj/item/clothing/shoes/magboots/clown/CtrlClick(mob/living/user) if(!isliving(user)) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 6858355f876..962cfed80c5 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -71,16 +71,15 @@ var/footstep = 1 //used for squeeks whilst walking shoe_sound = "clownstep" var/enabled_waddle = TRUE - var/datum/component/waddle /obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot) . = ..() if(slot == slot_shoes && enabled_waddle) - waddle = user.AddComponent(/datum/component/waddling) + user.AddElement(/datum/element/waddling) /obj/item/clothing/shoes/clown_shoes/dropped(mob/user) . = ..() - QDEL_NULL(waddle) + user.RemoveElement(/datum/element/waddling) /obj/item/clothing/shoes/clown_shoes/CtrlClick(mob/living/user) if(!isliving(user)) diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 50cb7d09801..579df861c19 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -98,7 +98,7 @@ /obj/machinery/mineral/processing_unit/Destroy() CONSOLE = null QDEL_NULL(files) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -120,7 +120,7 @@ CONSOLE.updateUsrDialog() /obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!materials.has_space(material_amount)) unload_mineral(O) @@ -132,7 +132,7 @@ /obj/machinery/mineral/processing_unit/proc/get_machine_data() var/dat = "Smelter control console

" - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] dat += "[M.name]: [M.amount] cm³" @@ -165,7 +165,7 @@ return dat /obj/machinery/mineral/processing_unit/proc/smelt_ore() - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/datum/material/mat = materials.materials[selected_material] if(mat) var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT) @@ -187,7 +187,7 @@ on = FALSE return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.use_amount(alloy.materials, amount) generate_mineral(alloy.build_path) @@ -198,7 +198,7 @@ var/build_amount = SMELT_AMOUNT - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index ed955efda2c..7f1b520e7f8 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -67,7 +67,7 @@ /obj/machinery/mineral/ore_redemption/Destroy() QDEL_NULL(files) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -92,7 +92,7 @@ if(O && O.refined_type) points += O.points * point_upgrade * O.amount - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!material_amount) @@ -111,7 +111,7 @@ var/build_amount = 0 - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] var/datum/material/redemption_mat = materials.materials[mat_id] @@ -147,7 +147,7 @@ var/has_minerals = FALSE var/mineral_name = null - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT @@ -251,7 +251,7 @@ else dat += "No ID inserted. Insert ID.

" - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] if(M.amount) @@ -302,7 +302,7 @@ /obj/machinery/mineral/ore_redemption/Topic(href, href_list) if(..()) return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(href_list["eject_id"]) usr.put_in_hands(inserted_id) inserted_id = null diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index 9fb73229ba7..c6d23a1bbde 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -23,7 +23,7 @@ if(!T) return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/obj/item/stack/sheet/O in T) materials.insert_stack(O, O.amount) @@ -32,7 +32,7 @@ return var/dat = "Coin Press
" - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] if(!M.amount && chosen != mat_id) @@ -65,7 +65,7 @@ if(processing == 1) to_chat(usr, "The machine is processing.") return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(href_list["choose"]) if(materials.materials[href_list["choose"]]) chosen = href_list["choose"] diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 98edb60c6bf..65b4585ff6b 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -138,7 +138,7 @@ span = mind.speech_span if((COMIC in mutations) \ || (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \ - || GetComponent(/datum/component/jestosterone)) + || HAS_TRAIT(src, TRAIT_JESTER)) span = "sans" if(WINGDINGS in mutations) diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index 9f4a27a3c41..7ff32e38644 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -636,12 +636,11 @@ H.mutations.Add(COMIC) H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store) H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store) - H.AddComponent(/datum/component/waddling) + H.AddElement(/datum/element/waddling) /datum/species/golem/bananium/on_species_loss(mob/living/carbon/C) . = ..() - GET_COMPONENT_FROM(waddling, /datum/component/waddling, C) - waddling.Destroy() + C.RemoveElement(/datum/element/waddling) /datum/species/golem/bananium/get_random_name() var/clown_name = pick(GLOB.clown_names) diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm index dc00e252661..08321b1bb5a 100644 --- a/code/modules/mob/living/simple_animal/friendly/penguin.dm +++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm @@ -18,7 +18,7 @@ /mob/living/simple_animal/pet/penguin/Initialize(mapload) . = ..() - AddComponent(/datum/component/waddling) + AddElement(/datum/element/waddling) /mob/living/simple_animal/pet/penguin/emperor name = "Emperor penguin" diff --git a/code/modules/reagents/chemistry/reagents/misc.dm b/code/modules/reagents/chemistry/reagents/misc.dm index d84ed59e6de..f9a6f974dcf 100644 --- a/code/modules/reagents/chemistry/reagents/misc.dm +++ b/code/modules/reagents/chemistry/reagents/misc.dm @@ -450,21 +450,18 @@ var/mob/living/carbon/C = holder.my_atom if(!istype(C)) return - var/mind_type = FALSE if(C.mind) if(C.mind.assigned_role == "Clown" || C.mind.assigned_role == SPECIAL_ROLE_HONKSQUAD) - mind_type = "Clown" to_chat(C, "Whatever that was, it feels great!") else if(C.mind.assigned_role == "Mime") - mind_type = "Mime" to_chat(C, "You feel nauseous.") C.AdjustDizzy(volume) else to_chat(C, "Something doesn't feel right...") C.AdjustDizzy(volume) - C.AddComponent(/datum/component/jestosterone, mind_type) + ADD_TRAIT(C, TRAIT_JESTER, id) C.AddComponent(/datum/component/squeak, null, null, null, null, null, TRUE) - C.AddComponent(/datum/component/waddling) + C.AddElement(/datum/element/waddling) /datum/reagent/jestosterone/on_mob_life(mob/living/carbon/M) if(!istype(M)) @@ -472,8 +469,7 @@ var/update_flags = STATUS_UPDATE_NONE if(prob(10)) M.emote("giggle") - GET_COMPONENT_FROM(jestosterone_component, /datum/component/jestosterone, M) - if(jestosterone_component.mind_type == "Clown") + if(M?.mind.assigned_role == "Clown" || M?.mind.assigned_role == SPECIAL_ROLE_HONKSQUAD) update_flags |= M.adjustBruteLoss(-1.5 * REAGENTS_EFFECT_MULTIPLIER) //Screw those pesky clown beatings! else M.AdjustDizzy(10, 0, 500) @@ -493,18 +489,15 @@ "Your legs feel like jelly.", "You feel like telling a pun.") to_chat(M, "[pick(clown_message)]") - if(jestosterone_component.mind_type == "Mime") + if(M?.mind.assigned_role == "Mime") update_flags |= M.adjustToxLoss(1.5 * REAGENTS_EFFECT_MULTIPLIER) return ..() | update_flags /datum/reagent/jestosterone/on_mob_delete(mob/living/M) ..() - GET_COMPONENT_FROM(remove_fun, /datum/component/jestosterone, M) - GET_COMPONENT_FROM(squeaking, /datum/component/squeak, M) - GET_COMPONENT_FROM(waddling, /datum/component/waddling, M) - remove_fun.Destroy() - squeaking.Destroy() - waddling.Destroy() + REMOVE_TRAIT(M, TRAIT_JESTER, id) + qdel(M.GetComponent(/datum/component/squeak)) + M.RemoveElement(/datum/element/waddling) /datum/reagent/royal_bee_jelly name = "royal bee jelly" diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 95cee124076..caa273594de 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -449,7 +449,7 @@ visible_message("[src]'s crushing mechanism slowly and smoothly descends, flattening the [exp_on]!") new /obj/item/stack/sheet/plasteel(get_turf(pick(oview(1,src)))) if(linked_console.linked_lathe) - GET_COMPONENT_FROM(linked_materials, /datum/component/material_container, linked_console.linked_lathe) + var/datum/component/material_container/linked_materials = linked_console.linked_lathe.GetComponent(/datum/component/material_container) for(var/material in exp_on.materials) linked_materials.insert_amount( min((linked_materials.max_amount - linked_materials.total_amount), (exp_on.materials[material])), material) if(prob(EFFECT_PROB_VERYLOW-badThingCoeff)) diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index 7acdc53ce3d..bd4e5528a9b 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -20,9 +20,7 @@ var/datum/component/material_container/materials //Store for hyper speed! /obj/machinery/r_n_d/New() - materials = AddComponent(/datum/component/material_container, - list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), 0, - TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) + materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE ..() wires["Red"] = 0 diff --git a/code/modules/space_management/zlevel_manager.dm b/code/modules/space_management/zlevel_manager.dm index eb84206eea3..5582288a813 100644 --- a/code/modules/space_management/zlevel_manager.dm +++ b/code/modules/space_management/zlevel_manager.dm @@ -107,6 +107,7 @@ GLOBAL_DATUM_INIT(space_manager, /datum/zlev_manager, new()) // Increments the max z-level by one // For convenience's sake returns the z-level added /datum/zlev_manager/proc/add_new_zlevel(name, linkage = SELFLOOPING, traits = list(BLOCK_TELEPORT)) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, args) if(name in levels_by_name) throw EXCEPTION("Name already in use: [name]") world.maxz++ diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 5cab4dfafd8..53283ada95e 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -225,7 +225,6 @@ slot = "brain_tumor" var/organhonked = 0 var/suffering_delay = 900 - var/datum/component/waddle var/datum/component/squeak /obj/item/organ/internal/honktumor/insert(mob/living/carbon/M, special = 0) @@ -237,7 +236,7 @@ genemutcheck(M,GLOB.clumsyblock,null,MUTCHK_FORCED) genemutcheck(M,GLOB.comicblock,null,MUTCHK_FORCED) organhonked = world.time - waddle = M.AddComponent(/datum/component/waddling) + M.AddElement(/datum/element/waddling) squeak = M.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg' = 1), 50) /obj/item/organ/internal/honktumor/remove(mob/living/carbon/M, special = 0) @@ -249,7 +248,7 @@ M.dna.SetSEState(GLOB.comicblock,0) genemutcheck(M,GLOB.clumsyblock,null,MUTCHK_FORCED) genemutcheck(M,GLOB.comicblock,null,MUTCHK_FORCED) - QDEL_NULL(waddle) + M.RemoveElement(/datum/element/waddling) QDEL_NULL(squeak) qdel(src) diff --git a/paradise.dme b/paradise.dme index 1e60c68b509..b83ea6be6df 100644 --- a/paradise.dme +++ b/paradise.dme @@ -28,7 +28,6 @@ #include "code\__DEFINES\clothing.dm" #include "code\__DEFINES\colors.dm" #include "code\__DEFINES\combat.dm" -#include "code\__DEFINES\components.dm" #include "code\__DEFINES\construction.dm" #include "code\__DEFINES\contracts.dm" #include "code\__DEFINES\crafting.dm" @@ -76,6 +75,9 @@ #include "code\__DEFINES\typeids.dm" #include "code\__DEFINES\vv.dm" #include "code\__DEFINES\zlevel.dm" +#include "code\__DEFINES\dcs\flags.dm" +#include "code\__DEFINES\dcs\helpers.dm" +#include "code\__DEFINES\dcs\signals.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" #include "code\__HELPERS\AnimationLibrary.dm" @@ -219,6 +221,7 @@ #include "code\controllers\subsystem\atoms.dm" #include "code\controllers\subsystem\changelog.dm" #include "code\controllers\subsystem\chat.dm" +#include "code\controllers\subsystem\dcs.dm" #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\fires.dm" #include "code\controllers\subsystem\garbage.dm" @@ -296,14 +299,13 @@ #include "code\datums\components\caltrop.dm" #include "code\datums\components\decal.dm" #include "code\datums\components\ducttape.dm" -#include "code\datums\components\jestosterone.dm" +#include "code\datums\components\edit_complainer.dm" #include "code\datums\components\label.dm" #include "code\datums\components\material_container.dm" #include "code\datums\components\paintable.dm" #include "code\datums\components\slippery.dm" #include "code\datums\components\spawner.dm" #include "code\datums\components\squeak.dm" -#include "code\datums\components\waddling.dm" #include "code\datums\diseases\_disease.dm" #include "code\datums\diseases\_MobProcs.dm" #include "code\datums\diseases\anxiety.dm" @@ -360,6 +362,8 @@ #include "code\datums\diseases\advance\symptoms\weakness.dm" #include "code\datums\diseases\advance\symptoms\weight.dm" #include "code\datums\diseases\advance\symptoms\youth.dm" +#include "code\datums\elements\_element.dm" +#include "code\datums\elements\waddling.dm" #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\icon_snapshot.dm" From b3fb5c8ec0536a060f626c0cd18737fd92495d1e Mon Sep 17 00:00:00 2001 From: Kyep <16434066+Kyep@users.noreply.github.com> Date: Tue, 16 Jun 2020 00:20:01 +0000 Subject: [PATCH 27/61] Explorer Transfers (#13384) * v1, explorer as job transfer option for HOPs * move to support.dm * spacing * recategorize as support * ACCESS_EXTERNAL_AIRLOCKS * corrected access line * Updated explorer HUD icon Co-authored-by: Kyep --- code/__DEFINES/job.dm | 2 +- code/game/jobs/job/job.dm | 1 + code/game/jobs/job/support.dm | 21 ++++++++++++++++++ code/game/jobs/jobs.dm | 3 ++- code/game/machinery/computer/card.dm | 3 ++- code/modules/client/preference/preferences.dm | 3 +++ .../file_system/programs/command/card.dm | 3 ++- icons/mob/hud.dmi | Bin 15184 -> 15257 bytes 8 files changed, 32 insertions(+), 4 deletions(-) diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm index d72628e2cb7..349d1b246be 100644 --- a/code/__DEFINES/job.dm +++ b/code/__DEFINES/job.dm @@ -51,7 +51,7 @@ #define JOB_CLOWN (1<<11) #define JOB_MIME (1<<12) #define JOB_CIVILIAN (1<<13) - +#define JOB_EXPLORER (1<<14) #define JOBCAT_KARMA (1<<3) diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index a30799f08b9..d5c5089c8af 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -51,6 +51,7 @@ var/disabilities_allowed = 1 var/transfer_allowed = TRUE // If false, ID computer will always discourage transfers to this job, even if player is eligible + var/hidden_from_job_prefs = FALSE // if true, job preferences screen never shows this job. var/admin_only = 0 var/spawn_ert = 0 diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index d0064300b62..f2b8cf31671 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -450,3 +450,24 @@ /obj/item/storage/box/lip_stick = 1, /obj/item/storage/box/barber = 1 ) + +/datum/job/explorer + title = "Explorer" + flag = JOB_EXPLORER + department_flag = JOBCAT_SUPPORT + total_positions = 0 + spawn_positions = 0 + supervisors = "the head of personnel" + selection_color = "#dddddd" + access = list(ACCESS_MAINT_TUNNELS, ACCESS_GATEWAY, ACCESS_EVA, ACCESS_EXTERNAL_AIRLOCKS) + minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_GATEWAY, ACCESS_EVA, ACCESS_EXTERNAL_AIRLOCKS) + outfit = /datum/outfit/job/explorer + hidden_from_job_prefs = TRUE + +/datum/outfit/job/explorer + // This outfit is never used, because there are no slots for this job. + // To get it, you have to go to the HOP and ask for a transfer to it. + name = "Explorer" + jobtype = /datum/job/explorer + uniform = /obj/item/clothing/under/color/random + shoes = /obj/item/clothing/shoes/black diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index 8ff6b58e5c4..81cc54aa3c3 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -58,7 +58,8 @@ GLOBAL_LIST_INIT(support_positions, list( "Barber", "Magistrate", "Nanotrasen Representative", - "Blueshield" + "Blueshield", + "Explorer" )) GLOBAL_LIST_INIT(supply_positions, list( diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 40005f8fd12..978ba25b8d3 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -25,7 +25,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) /datum/job/ntnavyofficer, /datum/job/ntspecops, /datum/job/civilian, - /datum/job/syndicateofficer + /datum/job/syndicateofficer, + /datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work ) // Jobs that appear in the list, and you can prioritize, but not open/close slots for var/list/blacklisted_partial = list( diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 569ecd3e3ff..7b3133c0103 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -624,6 +624,9 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts if(job.admin_only) continue + if(job.hidden_from_job_prefs) + continue + index += 1 if((index >= limit) || (job.title in splitJobs)) if((index < limit) && (lastJob != null)) 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 9067a345d4e..b85fb710e38 100644 --- a/code/modules/modular_computers/file_system/programs/command/card.dm +++ b/code/modules/modular_computers/file_system/programs/command/card.dm @@ -35,7 +35,8 @@ /datum/job/ntnavyofficer, /datum/job/ntspecops, /datum/job/civilian, - /datum/job/syndicateofficer + /datum/job/syndicateofficer, + /datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work ) //The scaling factor of max total positions in relation to the total amount of people on board the station in % diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index bbe41ddbe22e6f7d6e4630871cd1724d27fb1a2b..df6b8f4de1f4c2009297501a43172eb18511a5cb 100644 GIT binary patch literal 15257 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 Date: Mon, 15 Jun 2020 23:59:47 -0400 Subject: [PATCH 28/61] Fixes a Couple of Components Things (#13629) --- code/datums/components/README.md | 2 +- code/game/objects/items/toys.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/components/README.md b/code/datums/components/README.md index 3080f7e7b44..03f7d3a5875 100644 --- a/code/datums/components/README.md +++ b/code/datums/components/README.md @@ -6,4 +6,4 @@ Loosely adapted from /vg/. This is an entity component system for adding behavio See [this thread](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) for an introduction to the system as a whole. -### See/Define signals and their arguments in [__DEFINES\components.dm](../../__DEFINES/components.dm) +### See/Define signals and their arguments in [__DEFINES\dcs\signals.dm](../../__DEFINES/dcs/signals.dm) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index eafd57cd21f..21795fb738c 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1030,7 +1030,7 @@ obj/item/toy/cards/deck/syndicate/black /obj/item/toy/plushie/orange_fox/grump/ComponentInitialize() . = ..() var/static/list/grumps = list("Ahh, yes, you're so clever, var editing that.", "Really?", "If you make a runtime with var edits, it's your own damn fault.", - "Don't you dare post issues on the git when you don't even know how this works.", "Was that necessary?", "Ohhh, setting admin edited var must be your faovrite pastime!", + "Don't you dare post issues on the git when you don't even know how this works.", "Was that necessary?", "Ohhh, setting admin edited var must be your favorite pastime!", "Oh, so you have time to var edit, but you don't have time to ban that greytider?", "Oh boy, is this another one of those 'events'?", "Seriously, just stop.", "You do realize this is incurring proc call overhead.", "Congrats, you just left a reference with your dirty client and now that thing you edited will never garbage collect properly.", "Is it that time of day, again, for unecessary adminbus?") AddComponent(/datum/component/edit_complainer, grumps) From 12f798390f31802141a5648c951377f1b0ec321b Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Tue, 16 Jun 2020 07:26:09 +0100 Subject: [PATCH 29/61] Minor refactor to wireless eguns --- code/game/atoms_movable.dm | 1 + .../mission_code/UO71-terrorspiders.dm | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 70926d7ba2b..908fa397c06 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -278,6 +278,7 @@ return 1 /atom/movable/proc/onTransitZ(old_z,new_z) + SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z) for(var/item in src) // Notify contents of Z-transition. This can be overridden if we know the items contents do not care. var/atom/movable/AM = item AM.onTransitZ(old_z,new_z) diff --git a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm index b41ec901573..92aa6e61770 100644 --- a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm +++ b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm @@ -191,26 +191,28 @@ origin_tech = null selfcharge = 1 can_charge = 0 - var/inawaymission = 1 + var/inawaymission = TRUE -/obj/item/gun/energy/laser/awaymission_aeg/process() +/obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload) + RegisterSignal(src, list(COMSIG_MOVABLE_Z_CHANGED), .proc/updateZ) + // Force update it incase it spawns outside an away mission and shouldnt be charged + updateZ() + return ..() + +/obj/item/gun/energy/laser/awaymission_aeg/proc/updateZ() var/turf/my_loc = get_turf(src) if(is_away_level(my_loc.z)) - if(inawaymission) - return ..() if(ismob(loc)) to_chat(loc, "Your [src] activates, starting to draw power from a nearby wireless power source.") - inawaymission = 1 + inawaymission = TRUE else if(inawaymission) if(ismob(loc)) to_chat(loc, "Your [src] deactivates, as it is out of range from its power source.") cell.charge = 0 - inawaymission = 0 + inawaymission = FALSE update_icon() - - /obj/item/reagent_containers/glass/beaker/terror_black_toxin name = "beaker 'Black Terror Venom'" From f11b5f7d7af3ce0aa58579617544653f86d65941 Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Tue, 16 Jun 2020 07:48:26 +0100 Subject: [PATCH 30/61] Farie change --- code/modules/awaymissions/mission_code/UO71-terrorspiders.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm index 92aa6e61770..08989d1716e 100644 --- a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm +++ b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm @@ -194,10 +194,10 @@ var/inawaymission = TRUE /obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload) + . = ..() RegisterSignal(src, list(COMSIG_MOVABLE_Z_CHANGED), .proc/updateZ) // Force update it incase it spawns outside an away mission and shouldnt be charged updateZ() - return ..() /obj/item/gun/energy/laser/awaymission_aeg/proc/updateZ() var/turf/my_loc = get_turf(src) From 5095c2a0e5e942e12900d64493bcba1d9b809154 Mon Sep 17 00:00:00 2001 From: mochi Date: Tue, 16 Jun 2020 09:18:06 +0200 Subject: [PATCH 31/61] Reset transform on HUDs as well --- code/modules/mob/mob.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 62037219eeb..46f80bc1919 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -42,7 +42,7 @@ hud_list[hud] = list() else var/image/I = image('icons/mob/hud.dmi', src, "") - I.appearance_flags = RESET_COLOR + I.appearance_flags = RESET_COLOR | RESET_TRANSFORM hud_list[hud] = I /mob/proc/generate_name() From 0b72f4eb8001eb780b1b1c7296fc9637e8f7f630 Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Tue, 16 Jun 2020 08:45:10 +0100 Subject: [PATCH 32/61] Forgot this --- code/modules/awaymissions/mission_code/UO71-terrorspiders.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm index 08989d1716e..f396b57e3ee 100644 --- a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm +++ b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm @@ -199,6 +199,11 @@ // Force update it incase it spawns outside an away mission and shouldnt be charged updateZ() +/obj/item/gun/energy/laser/awaymission_aeg/process() + // Only call the self-recharge proc if inside an away mission + if(inawaymission) + ..() + /obj/item/gun/energy/laser/awaymission_aeg/proc/updateZ() var/turf/my_loc = get_turf(src) if(is_away_level(my_loc.z)) From 6c465c84dc779cb6d94691eba2156f2e24feb840 Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Tue, 16 Jun 2020 14:39:58 +0100 Subject: [PATCH 33/61] Use onTransitZ --- code/game/atoms_movable.dm | 1 - .../mission_code/UO71-terrorspiders.dm | 22 +++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 908fa397c06..70926d7ba2b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -278,7 +278,6 @@ return 1 /atom/movable/proc/onTransitZ(old_z,new_z) - SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z) for(var/item in src) // Notify contents of Z-transition. This can be overridden if we know the items contents do not care. var/atom/movable/AM = item AM.onTransitZ(old_z,new_z) diff --git a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm index f396b57e3ee..8f562846e87 100644 --- a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm +++ b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm @@ -191,31 +191,25 @@ origin_tech = null selfcharge = 1 can_charge = 0 - var/inawaymission = TRUE + // Selfcharge is enabled and disabled, and used as the away mission tracker + selfcharge = TRUE /obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload) . = ..() - RegisterSignal(src, list(COMSIG_MOVABLE_Z_CHANGED), .proc/updateZ) // Force update it incase it spawns outside an away mission and shouldnt be charged - updateZ() + onTransitZ(new_z=loc.z) -/obj/item/gun/energy/laser/awaymission_aeg/process() - // Only call the self-recharge proc if inside an away mission - if(inawaymission) - ..() - -/obj/item/gun/energy/laser/awaymission_aeg/proc/updateZ() - var/turf/my_loc = get_turf(src) - if(is_away_level(my_loc.z)) +/obj/item/gun/energy/laser/awaymission_aeg/onTransitZ(old_z, new_z) + if(is_away_level(new_z)) if(ismob(loc)) to_chat(loc, "Your [src] activates, starting to draw power from a nearby wireless power source.") - inawaymission = TRUE + selfcharge = TRUE else - if(inawaymission) + if(selfcharge) if(ismob(loc)) to_chat(loc, "Your [src] deactivates, as it is out of range from its power source.") cell.charge = 0 - inawaymission = FALSE + selfcharge = FALSE update_icon() /obj/item/reagent_containers/glass/beaker/terror_black_toxin From fd209c5bc4f42338a11d14b0402d1131cea4b592 Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Tue, 16 Jun 2020 20:51:17 +0100 Subject: [PATCH 34/61] Gamebreaking bug must be fixed --- code/modules/awaymissions/mission_code/UO71-terrorspiders.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm index 8f562846e87..f06a9a37f9c 100644 --- a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm +++ b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm @@ -197,7 +197,7 @@ /obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload) . = ..() // Force update it incase it spawns outside an away mission and shouldnt be charged - onTransitZ(new_z=loc.z) + onTransitZ(new_z = loc.z) /obj/item/gun/energy/laser/awaymission_aeg/onTransitZ(old_z, new_z) if(is_away_level(new_z)) From e2ae488147c369e4313f29e464fa188613dd8f68 Mon Sep 17 00:00:00 2001 From: trololiver112 <59520813+trololiver112@users.noreply.github.com> Date: Wed, 17 Jun 2020 23:52:20 +0200 Subject: [PATCH 35/61] suggested changes --- code/game/gamemodes/changeling/powers/augmented_eyesight.dm | 2 +- code/game/gamemodes/shadowling/shadowling_abilities.dm | 2 +- code/modules/mob/living/carbon/human/species/shadow.dm | 2 +- code/modules/mob/mob.dm | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm index bd06954a505..d6062a02c5d 100644 --- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm +++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm @@ -76,7 +76,7 @@ var/mob/living/carbon/human/H = owner H.weakeyes = 1 if(!H.vision_type) - H.set_sight(new /datum/vision_override/nightvision) + H.set_sight(/datum/vision_override/nightvision) /obj/item/organ/internal/cyberimp/eyes/thermals/ling/remove(mob/living/carbon/M, special = 0) if(ishuman(owner)) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index e210fb61fda..27267d2ec02 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -184,7 +184,7 @@ var/mob/living/carbon/human/H = target if(!H.vision_type) to_chat(H, "You shift the nerves in your eyes, allowing you to see in the dark.") - H.set_sight(new /datum/vision_override/nightvision) + H.set_sight(/datum/vision_override/nightvision) else to_chat(H, "You return your vision to normal.") H.set_sight(null) diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index 25d3c853368..be2a7f44229 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -39,7 +39,7 @@ /datum/action/innate/shadow/darkvision/Activate() var/mob/living/carbon/human/H = owner if(!H.vision_type) - H.set_sight(new /datum/vision_override/nightvision) + H.set_sight(/datum/vision_override/nightvision) to_chat(H, "You adjust your vision to pierce the darkness.") else H.set_sight(null) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 370c1fae76e..90d574ba764 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1357,9 +1357,9 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \ sync_lighting_plane_alpha() /mob/proc/set_sight(datum/vision_override/O) - if(vision_type) - qdel(vision_type) //qdel the old vision_type unless it is null. - vision_type = O + QDEL_NULL(vision_type) + if(O) //in case of null + vision_type = new O update_sight() /mob/proc/sync_lighting_plane_alpha() From fb7d598fe09bbabbd784d5b1fe31ac0878e0a815 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Thu, 18 Jun 2020 15:59:06 -0400 Subject: [PATCH 36/61] Fixes No Slip Shoes (#13627) --- code/datums/components/slippery.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index 3e505eb0a8a..88e51209afb 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -20,12 +20,12 @@ var/slip_tiles /// TRUE If this slip can be avoided by walking. var/walking_is_safe - /// TRUE if having no slip shoes makes you immune to this slip. - var/noslip_is_immune + /// FALSE if you want no slip shoes to make you immune to the slip + var/slip_always /// The verb that players will see when someone slips on the parent. In the form of "You [slip_verb]ped on". var/slip_verb -/datum/component/slippery/Initialize(_description, _stun = 0, _weaken = 0, _slip_chance = 100, _slip_tiles = 0, _walking_is_safe = TRUE, _noslip_is_immune = TRUE, _slip_verb = "slip") +/datum/component/slippery/Initialize(_description, _stun = 0, _weaken = 0, _slip_chance = 100, _slip_tiles = 0, _walking_is_safe = TRUE, _slip_always = FALSE, _slip_verb = "slip") if(!isatom(parent)) return COMPONENT_INCOMPATIBLE @@ -35,7 +35,7 @@ slip_chance = max(0, _slip_chance) slip_tiles = max(0, _slip_tiles) walking_is_safe = _walking_is_safe - noslip_is_immune = _noslip_is_immune + slip_always = _slip_always slip_verb = _slip_verb /datum/component/slippery/RegisterWithParent() @@ -51,6 +51,6 @@ Additionally calls the parent's `after_slip()` proc on the `victim`. */ /datum/component/slippery/proc/Slip(datum/source, mob/living/carbon/human/victim) - if(istype(victim) && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, noslip_is_immune, slip_verb)) + if(istype(victim) && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, slip_always, slip_verb)) var/atom/movable/owner = parent owner.after_slip(victim) From 1a1e5641241a4d68ad1611452b63a32cff2d0912 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Thu, 18 Jun 2020 15:59:17 -0400 Subject: [PATCH 37/61] Fixes Unhackable Smartfridges (#13620) --- code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 756d2cf77ef..346b78e5b26 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -602,7 +602,7 @@ if(stat & (NOPOWER|BROKEN)) return 0 if(usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) - if(!allowed(usr) && !emagged && locked != -1 && href_list["vend"]) + if(!allowed(usr) && !emagged && locked != -1 && scan_id && href_list["vend"]) to_chat(usr, "Access denied.") SSnanoui.update_uis(src) return 0 From e3fa9658a8540f19e48d03ae76565d7a4198158d Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Thu, 18 Jun 2020 16:14:41 -0400 Subject: [PATCH 38/61] Resolves some Reagent Runtimes (#13591) * Resolves some Reagent Runtimes * preserve functionality * spans --- .../modules/reagents/chemistry/reagents/alcohol.dm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/code/modules/reagents/chemistry/reagents/alcohol.dm b/code/modules/reagents/chemistry/reagents/alcohol.dm index 2dde295a70a..6e33184f2d0 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol.dm @@ -18,18 +18,18 @@ /datum/reagent/consumable/ethanol/reaction_obj(obj/O, volume) if(istype(O,/obj/item/paper)) if(istype(O,/obj/item/paper/contract/infernal)) - to_chat(usr, "The solution ignites on contact with the [O].") + O.visible_message("The solution ignites on contact with [O].") else var/obj/item/paper/paperaffected = O paperaffected.clearpaper() - to_chat(usr, "The solution melts away the ink on the paper.") + paperaffected.visible_message("The solution melts away the ink on the paper.") if(istype(O,/obj/item/book)) if(volume >= 5) var/obj/item/book/affectedbook = O affectedbook.dat = null - to_chat(usr, "The solution melts away the ink on the book.") + affectedbook.visible_message("The solution melts away the ink on the book.") else - to_chat(usr, "It wasn't enough...") + O.visible_message("It wasn't enough...") /datum/reagent/consumable/ethanol/reaction_mob(mob/living/M, method=REAGENT_TOUCH, volume)//Splashing people with ethanol isn't quite as good as fuel. if(method == REAGENT_TOUCH) @@ -1190,12 +1190,12 @@ taste_description = "motor oil" /datum/reagent/consumable/ethanol/synthanol/on_mob_life(mob/living/M) + metabolization_rate = REAGENTS_METABOLISM if(!(M.dna.species.reagent_tag & PROCESS_SYN)) - holder.remove_reagent(id, 3.6) //gets removed from organics very fast + metabolization_rate += 3.6 //gets removed from organics very fast if(prob(25)) - holder.remove_reagent(id, 15) + metabolization_rate += 15 M.fakevomit() - return ..() /datum/reagent/consumable/ethanol/synthanol/reaction_mob(mob/living/M, method=REAGENT_TOUCH, volume) From 88f71cc151b78b8a00f8d1e7449d9881cac5d5db Mon Sep 17 00:00:00 2001 From: AffectedArc07 Date: Sat, 20 Jun 2020 10:51:26 +0100 Subject: [PATCH 39/61] Bumps to DreamChecker 1.4 --- _build_dependencies.sh | 2 +- code/__HELPERS/unsorted.dm | 3 --- code/controllers/subsystem/timer.dm | 4 ++-- code/controllers/subsystem/weather.dm | 2 -- code/datums/diseases/advance/advance.dm | 1 - code/datums/wires/wires.dm | 1 - code/game/data_huds.dm | 4 ---- .../abduction/machinery/experiment.dm | 1 - code/game/jobs/access.dm | 2 -- code/game/machinery/camera/camera.dm | 3 --- .../computer/syndicate_specops_shuttle.dm | 5 ++--- code/game/machinery/machinery.dm | 1 - code/game/machinery/vending.dm | 1 - code/game/objects/items/devices/uplinks.dm | 1 - code/game/objects/items/mixing_bowl.dm | 2 +- code/game/objects/items/toys.dm | 1 - code/modules/buildmode/bm_mode.dm | 2 +- code/modules/client/preference/preferences.dm | 1 - .../food_and_drinks/drinks/bottler/bottler.dm | 1 - .../kitchen_machinery/processor.dm | 2 +- code/modules/martial_arts/martial.dm | 1 - code/modules/mob/dead/observer/observer.dm | 1 - .../carbon/alien/humanoid/alien_powers.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 1 - .../simple_animal/friendly/spiderbot.dm | 2 -- .../computers/item/processor.dm | 1 - .../programs/generic/ntnrc_client.dm | 1 - .../hardware/battery_module.dm | 1 - code/modules/nano/interaction/default.dm | 2 +- code/modules/power/smes.dm | 2 -- code/modules/shuttle/navigation_computer.dm | 4 ++-- dreamchecker.exe | Bin 3306075 -> 3462482 bytes 32 files changed, 12 insertions(+), 46 deletions(-) diff --git a/_build_dependencies.sh b/_build_dependencies.sh index 24a33ed3644..b96b83d5fe3 100644 --- a/_build_dependencies.sh +++ b/_build_dependencies.sh @@ -1,6 +1,6 @@ # This file has all the information on what versions of libraries are thrown into the code # For dreamchecker -export SPACEMANDMM_TAG=suite-1.2 +export SPACEMANDMM_TAG=suite-1.4 # For NanoUI export NODE_VERSION=9 # For the scripts in tools diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 80852f25c3f..0958d758f55 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -25,11 +25,9 @@ if(!( istext(HTMLstring) )) CRASH("Given non-text argument!") - return else if(length(HTMLstring) != 7) CRASH("Given non-HTML argument!") - return var/textr = copytext(HTMLstring, 2, 4) var/textg = copytext(HTMLstring, 4, 6) var/textb = copytext(HTMLstring, 6, 8) @@ -46,7 +44,6 @@ if(length(textb) < 2) textr = text("0[]", textb) return text("#[][][]", textr, textg, textb) - return //Returns the middle-most value /proc/dd_range(var/low, var/high, var/num) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 7bb6a496274..53d77e8fad6 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -160,7 +160,7 @@ SUBSYSTEM_DEF(timer) if(timer.timeToRun < head_offset) bucket_resolution = null //force bucket recreation - CRASH("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") + stack_trace("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") if(timer.callBack && !timer.spent) timer.callBack.InvokeAsync() @@ -172,7 +172,7 @@ SUBSYSTEM_DEF(timer) if(timer.timeToRun < head_offset + TICKS2DS(practical_offset-1)) bucket_resolution = null //force bucket recreation - CRASH("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") + stack_trace("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") if(timer.callBack && !timer.spent) timer.callBack.InvokeAsync() spent += timer diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm index bf405444110..30186f80ad1 100644 --- a/code/controllers/subsystem/weather.dm +++ b/code/controllers/subsystem/weather.dm @@ -57,7 +57,6 @@ SUBSYSTEM_DEF(weather) break if(!ispath(weather_datum_type, /datum/weather)) CRASH("run_weather called with invalid weather_datum_type: [weather_datum_type || "null"]") - return if(isnull(z_levels)) z_levels = levels_by_trait(initial(weather_datum_type.target_trait)) @@ -65,7 +64,6 @@ SUBSYSTEM_DEF(weather) z_levels = list(z_levels) else if(!islist(z_levels)) CRASH("run_weather called with invalid z_levels: [z_levels || "null"]") - return var/datum/weather/W = new weather_datum_type(z_levels) W.telegraph() diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index 9aeade59a1d..cfd276dca48 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -171,7 +171,6 @@ GLOBAL_LIST_INIT(advance_cures, list( if(!symptoms || !symptoms.len) CRASH("We did not have any symptoms before generating properties.") - return var/list/properties = list("resistance" = 1, "stealth" = 0, "stage_rate" = 1, "transmittable" = 1, "severity" = 0) diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm index 907e6a695e1..09c874ce8a8 100644 --- a/code/datums/wires/wires.dm +++ b/code/datums/wires/wires.dm @@ -31,7 +31,6 @@ GLOBAL_LIST_INIT(wireColours, list("red", "blue", "green", "black", "orange", "b src.holder = holder if(!istype(holder, holder_type)) CRASH("Our holder is null/the wrong type!") - return // Generate new wires if(random) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 08a7b77daff..6bd00d286fe 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -135,8 +135,6 @@ return "health-90" else return "health-100" //past this point, you're just in trouble - return "0" - ///HOOKS @@ -270,7 +268,6 @@ return "crit" else return "dead" - return "dead" //Sillycone hooks /mob/living/silicon/proc/diag_hud_set_health() @@ -400,7 +397,6 @@ return "max" else return "zero" - return "zero" /obj/machinery/hydroponics/proc/plant_hud_set_nutrient() var/image/holder = hud_list[PLANT_NUTRIENT_HUD] diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 6e1b4a39d3a..d7354b87c5c 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -166,7 +166,6 @@ eject_abductee() SendBack(H) return "Specimen braindead - disposed." - return "ERROR" /obj/machinery/abductor/experiment/proc/SendBack(mob/living/carbon/human/H) diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 7f93fd9fef6..d5a59a36872 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -20,8 +20,6 @@ else return check_access_list(acc) - return 0 - /obj/item/proc/GetAccess() return list() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 24ffb494422..b66cad8d328 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -360,15 +360,12 @@ 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(mob/M) for(var/obj/machinery/camera/C in range(4, M)) if(C.can_use()) // check if camera disabled return C - break - return null /obj/machinery/camera/proc/Togglelight(on = FALSE) diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm index 0a65b6be408..4a701e2c960 100644 --- a/code/game/machinery/computer/syndicate_specops_shuttle.dm +++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm @@ -23,7 +23,7 @@ GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0) /proc/syndicate_elite_process() var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work. - var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located? + //var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located? var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky. var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. @@ -63,7 +63,6 @@ GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0) to_chat(usr, "The Syndicate Elite shuttle is unable to leave.") return - sleep(600) /* //Begin Marauder launchpad. spawn(0)//So it parallel processes it. @@ -129,8 +128,8 @@ GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0) if("ASSAULT3") spawn(0) M.close() - */ elite_squad.readyreset()//Reset firealarm after the team launched. + */ //End Marauder launchpad. for(var/obj/effect/landmark/L in GLOB.landmarks_list) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 19dc80f9a40..d318302500f 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -369,7 +369,6 @@ Class Procs: /obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames. return - return 0 /obj/machinery/proc/assign_uid() uid = gl_uid diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 1487256c712..7aa5661febe 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -190,7 +190,6 @@ var/obj/item/vending_refill/R = locate() in component_parts if(!R) CRASH("Constructible vending machine did not have a refill canister") - return R.products = unbuild_inventory(product_records) R.contraband = unbuild_inventory(hidden_records) diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index c5c8f67e34d..77e9eacc6a1 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -131,7 +131,6 @@ GLOBAL_LIST_EMPTY(world_uplinks) else var/datum/uplink_item/UI = ItemsReference[href_list["buy_item"]] return buy(UI, UI ? UI.reference : "") - return 0 /obj/item/uplink/proc/buy(var/datum/uplink_item/UI, var/reference) if(!UI) diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm index da851437fd5..1e1a39d49d0 100644 --- a/code/game/objects/items/mixing_bowl.dm +++ b/code/game/objects/items/mixing_bowl.dm @@ -118,7 +118,7 @@ /obj/item/mixing_bowl/Topic(href, href_list) if(..()) return - if("dispose") + if(href_list["dispose"]) dispose() return diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 21795fb738c..40d659ccf6b 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1247,7 +1247,6 @@ obj/item/toy/cards/deck/syndicate/black spawn(20) cooldown = FALSE return - ..() /obj/item/toy/owl name = "owl action figure" diff --git a/code/modules/buildmode/bm_mode.dm b/code/modules/buildmode/bm_mode.dm index 0169df7cd62..bf3b52a20ce 100644 --- a/code/modules/buildmode/bm_mode.dm +++ b/code/modules/buildmode/bm_mode.dm @@ -28,8 +28,8 @@ return "buildmode_[key]" /datum/buildmode_mode/proc/show_help(mob/user) - CRASH("No help defined, yell at a coder") to_chat(user, "There is no help defined for this mode, this is a bug.") + CRASH("No help defined, yell at a coder") /datum/buildmode_mode/proc/change_settings(mob/user) to_chat(user, "There is no configuration available for this mode") diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 7b3133c0103..0b74b7132fd 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -54,7 +54,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts return C.player_age else return max(0, days - C.player_age) - return 0 #define MAX_SAVE_SLOTS 30 // Save slots for regular players #define MAX_SAVE_SLOTS_MEMBER 30 // Save slots for BYOND members diff --git a/code/modules/food_and_drinks/drinks/bottler/bottler.dm b/code/modules/food_and_drinks/drinks/bottler/bottler.dm index b1667fc6a00..d7f1736bb4a 100644 --- a/code/modules/food_and_drinks/drinks/bottler/bottler.dm +++ b/code/modules/food_and_drinks/drinks/bottler/bottler.dm @@ -82,7 +82,6 @@ else //If it doesn't qualify in the above checks, we don't want it. Inform the person so they (ideally) stop trying to put the nuke disc in. to_chat(user, "You aren't sure this is able to be processed by the machine.") return 0 - return ..() /obj/machinery/bottler/wrench_act(mob/user, obj/item/I) . = TRUE diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm index 61f887e44bc..6891ab578bc 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm @@ -175,7 +175,7 @@ if(default_unfasten_wrench(user, O)) return - default_deconstruction_crowbar(user, O) + default_deconstruction_crowbar(user, O) var/obj/item/what = O diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm index 478438c47cb..882da0a9387 100644 --- a/code/modules/martial_arts/martial.dm +++ b/code/modules/martial_arts/martial.dm @@ -275,7 +275,6 @@ return else return ..() - return ..() /obj/item/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) if(wielded) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index dc7c2b4439e..8bff776c176 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -616,7 +616,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/Topic(href, href_list) if(usr != src) return - ..() if(href_list["track"]) var/atom/target = locate(href_list["track"]) 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 1ea256357e9..fec3012529e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -167,4 +167,4 @@ Doesn't work on other aliens/AI.*/ adjustPlasma(-amount) return 1 - return 0 + return 0 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 4b6d6c68603..0466c1c0be0 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -870,7 +870,6 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven unEquip(I) I.dropped() return - return 1 else to_chat(src, "You fail to remove [I]!") diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm index 7a1227960f4..877d542fa2b 100644 --- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm @@ -123,8 +123,6 @@ if(health >= maxHealth) to_chat(user, "[src] does not need repairing!") return - to_chat(user, "Unable to repair with the maintenance panel closed!") - return . = TRUE if(!I.use_tool(src, user, volume = I.tool_volume)) return diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm index 7bd5be3cf81..3095e0af876 100644 --- a/code/modules/modular_computers/computers/item/processor.dm +++ b/code/modules/modular_computers/computers/item/processor.dm @@ -19,7 +19,6 @@ /obj/item/modular_computer/processor/New(comp) if(!comp || !istype(comp, /obj/machinery/modular_computer)) CRASH("Inapropriate type passed to obj/item/modular_computer/processor/New()! Aborting.") - return // Obtain reference to machinery computer all_components = list() idle_threads = list() diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm index 517c8f99ebe..ca208c22b02 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm @@ -195,7 +195,6 @@ if(!computer) // This program shouldn't even be runnable without computer. CRASH("Var computer is null!") - return 1 if(!hard_drive) computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.") else // In 99.9% cases this will mean our HDD is full diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm index 7cec597dc13..1a48110006a 100644 --- a/code/modules/modular_computers/hardware/battery_module.dm +++ b/code/modules/modular_computers/hardware/battery_module.dm @@ -67,7 +67,6 @@ holder.shutdown_computer() return TRUE - return FALSE // Stock parts diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm index ca42220204d..fed18f989f5 100644 --- a/code/modules/nano/interaction/default.dm +++ b/code/modules/nano/interaction/default.dm @@ -85,7 +85,7 @@ GLOBAL_DATUM_INIT(default_state, /datum/topic_state/default, new()) if(. != STATUS_CLOSE) if(loc) . = min(., loc.contents_nano_distance(src_object, src)) - if(STATUS_INTERACTIVE) + if(. == STATUS_INTERACTIVE) return STATUS_UPDATE /mob/living/carbon/brain/default_can_use_topic(var/src_object) diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index f88128ab974..59ce091b170 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -248,8 +248,6 @@ disconnect_terminal() return ..() - return round(5.5*charge/(capacity ? capacity : 5e6)) - /obj/machinery/power/smes/proc/chargedisplay() return round(5.5*charge/(capacity ? capacity : 5e6)) diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index c57cea9216e..18db87f6eb7 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -32,9 +32,9 @@ jumpto_ports += list("nav_z1" = 1) if(access_tcomms) jumpto_ports += list("nav_z3" = 1) - if(ACCESS_CONSTRUCTION) + if(access_construction) jumpto_ports += list("nav_z4" = 1) - if(ACCESS_MINING) + if(access_mining) jumpto_ports += list("nav_z5" = 1) if(access_derelict) jumpto_ports += list("nav_z6" = 1) diff --git a/dreamchecker.exe b/dreamchecker.exe index 068a9f58a0c15fa7b711d6d26983d9562f2984e6..abe378640c5b789cafd9f254aa46762138fcf7c7 100644 GIT binary patch literal 3462482 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

W=1qnFrLD9(il*i8Vuy~GAPS#?* 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