diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index ddd7838b2c..aa86e7b308 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -50,7 +50,7 @@ // Chemistry lists. var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglycerin", "thirteenloko", "nicotine") // Increase heart rate. var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "bliss", "stoxin", "ambrosia_extract") // Decrease heart rate. -var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart. +var/list/heartstopper = list("potassium_chlorophoride", "zombiepowder") // This stops the heart. var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional #define MAX_PILL_SPRITE 24 //max icon state of the pill sprites diff --git a/code/game/antagonist/station/highlander.dm b/code/game/antagonist/station/highlander.dm index 9b54383278..2e4885fd76 100644 --- a/code/game/antagonist/station/highlander.dm +++ b/code/game/antagonist/station/highlander.dm @@ -12,6 +12,8 @@ var/datum/antagonist/highlander/highlanders initial_spawn_req = 3 initial_spawn_target = 5 + id_type = /obj/item/weapon/card/id/centcom/ERT + /datum/antagonist/highlander/New() ..() highlanders = src @@ -32,26 +34,28 @@ var/datum/antagonist/highlander/highlanders if(!..()) return - for (var/obj/item/I in player) - if (istype(I, /obj/item/weapon/implant)) - continue - qdel(I) - + // drop original items! It used to be a loop that just Qdeled everything including your organs! + // Dropping because of non-oxy breathers... That would suck wouldn't it? + player.drop_from_inventory(player.get_equipped_item(slot_wear_id)) + player.drop_from_inventory(player.get_equipped_item(slot_wear_suit)) + player.drop_from_inventory(player.get_equipped_item(slot_w_uniform)) + player.drop_from_inventory(player.get_equipped_item(slot_l_ear)) + player.drop_from_inventory(player.get_equipped_item(slot_head)) + player.drop_from_inventory(player.get_equipped_item(slot_l_hand)) + player.drop_from_inventory(player.get_equipped_item(slot_shoes)) + player.drop_from_inventory(player.get_equipped_item(slot_l_store)) + // highlanders! player.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(player), slot_w_uniform) - player.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(player), slot_l_ear) player.equip_to_slot_or_del(new /obj/item/clothing/head/beret(player), slot_head) player.equip_to_slot_or_del(new /obj/item/weapon/material/sword(player), slot_l_hand) player.equip_to_slot_or_del(new /obj/item/clothing/shoes/boots/combat(player), slot_shoes) player.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(get_turf(player)), slot_l_store) - var/obj/item/weapon/card/id/W = new(player) - W.name = "[player.real_name]'s ID Card" - W.icon_state = "centcom" - W.access = get_all_station_access().Copy() - W.access |= get_all_centcom_access() - W.assignment = "Highlander" - W.registered_name = player.real_name - player.equip_to_slot_or_del(W, slot_wear_id) + var/obj/item/weapon/card/id/id = create_id("Highlander", player) + if(id) + id.access |= get_all_station_access() + id.icon_state = "centcom" + create_radio(DTH_FREQ, player) /proc/only_one() diff --git a/code/game/objects/items/weapons/material/material_weapons.dm b/code/game/objects/items/weapons/material/material_weapons.dm index f300cb068e..2bd785d369 100644 --- a/code/game/objects/items/weapons/material/material_weapons.dm +++ b/code/game/objects/items/weapons/material/material_weapons.dm @@ -142,7 +142,7 @@ return /obj/item/weapon/material/proc/sharpen(var/material, var/sharpen_time, var/kit, mob/living/M) - if(!fragile) + if(!fragile && src.material.can_sharpen) if(health < initial(health)) to_chat(M, "You should repair [src] first. Try using [kit] on it.") return FALSE diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm index 9f0b05d914..80c2dd1fce 100644 --- a/code/game/turfs/flooring/flooring.dm +++ b/code/game/turfs/flooring/flooring.dm @@ -210,6 +210,17 @@ var/list/flooring_types 'sound/effects/footstep/mud3.ogg', 'sound/effects/footstep/mud4.ogg')) +/decl/flooring/rock + name = "rocks" + desc = "Hard as a rock." + icon = 'icons/turf/outdoors.dmi' + icon_base = "rock" + footstep_sounds = list("human" = list( + 'sound/effects/footstep/LightStone1.ogg', + 'sound/effects/footstep/LightStone2.ogg', + 'sound/effects/footstep/LightStone3.ogg', + 'sound/effects/footstep/LightStone4.ogg')) + /decl/flooring/asteroid name = "coarse sand" desc = "You got a pebble in your shoe just looking at it." diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm index e55196aea6..98d195001c 100644 --- a/code/game/turfs/simulated/outdoors/outdoors.dm +++ b/code/game/turfs/simulated/outdoors/outdoors.dm @@ -123,6 +123,7 @@ var/list/turf_edge_cache = list() desc = "Hard as a rock." icon_state = "rock" edge_blending_priority = 1 + initial_flooring = /decl/flooring/rock /turf/simulated/floor/outdoors/rocks/caves outdoors = OUTDOORS_NO @@ -185,4 +186,4 @@ var/list/turf_edge_cache = list() icon = 'icons/turf/concrete.dmi' icon_state = "concrete_dark" desc = "Some sort of material composite road." - edge_blending_priority = -1 \ No newline at end of file + edge_blending_priority = -1 diff --git a/code/modules/lore_codex/codex.dm b/code/modules/lore_codex/codex.dm index e93f10638f..008cf429ed 100644 --- a/code/modules/lore_codex/codex.dm +++ b/code/modules/lore_codex/codex.dm @@ -9,21 +9,21 @@ var/datum/codex_tree/tree = null var/root_type = /datum/lore/codex/category/main_borealis_lore //YW EDIT - var/static/list/codex_tree_keys = list() // CHOMPedit: static list linking codexes to the correct codex_tree. + var/static/list/codex_tree_keys = list() // static list linking codexes to the correct codex_tree. /obj/item/weapon/book/codex/Initialize() - tree = codex_tree_keys["[root_type]"] // CHOMPedit start + tree = codex_tree_keys["[root_type]"] if(!tree) tree = new(src, root_type) - codex_tree_keys["[root_type]"] = tree // CHOMPedit end + codex_tree_keys["[root_type]"] = tree . = ..() /obj/item/weapon/book/codex/attack_self(mob/user) - if(!tree) // CHOMPedit start + if(!tree) tree = codex_tree_keys["[root_type]"] if(!tree) tree = new(src, root_type) - codex_tree_keys["[root_type]"] = tree // CHOMPedit end + codex_tree_keys["[root_type]"] = tree icon_state = "[initial(icon_state)]-open" tree.display(user) diff --git a/code/modules/lore_codex/codex_tree.dm b/code/modules/lore_codex/codex_tree.dm index 71aa80b087..200a1ec4f0 100644 --- a/code/modules/lore_codex/codex_tree.dm +++ b/code/modules/lore_codex/codex_tree.dm @@ -4,9 +4,9 @@ var/atom/movable/holder = null var/root_type = null var/datum/lore/codex/home = null // Top-most page. - var/datum/lore/codex/current_page = null // Current page or category to display to the user. + var/list/current_page = list() // Current page or category to display to the user. // converted to list to track multiple players. var/list/indexed_pages = list() // Assoc list with search terms pointing to a ref of the page. It's created on New(). - var/list/history = list() // List of pages we previously visited. + var/list/history = list() // List of pages we previously visited. // now a 2D list /datum/codex_tree/New(var/new_holder, var/new_root_type) holder = new_holder @@ -16,25 +16,31 @@ /datum/codex_tree/proc/generate_pages() home = new root_type(src) // This will also generate the others. - current_page = home - indexed_pages = current_page.index_page() + //current_page = home + indexed_pages = home.index_page() // changed from current_page to home. // Changes current_page to its parent, assuming one exists. -/datum/codex_tree/proc/go_to_parent() - if(current_page && current_page.parent) - current_page = current_page.parent +/datum/codex_tree/proc/go_to_parent(var/mob/user) + var/datum/lore/codex/D = current_page["[user]"] + if(istype(D) && D.parent) + current_page["[user]"] = D.parent // Changes current_page to a specific page or category. -/datum/codex_tree/proc/go_to_page(var/datum/lore/codex/new_page, var/dont_record_history = FALSE) - if(new_page) // Make sure we're not going to a null page for whatever reason. - current_page = new_page +/datum/codex_tree/proc/go_to_page(var/datum/lore/codex/new_page, var/dont_record_history = FALSE, var/mob/user) + var/datum/lore/codex/D = current_page["[user]"] + if(new_page && istype(D)) // Make sure we're not going to a null page for whatever reason. + current_page["[user]"] = new_page if(!dont_record_history) - history.Add(new_page) + var/list/H = history["[user]"] + if(!H) + H = list() + H.Add(new_page) + history["[user]"] = H -/datum/codex_tree/proc/quick_link(var/search_word) +/datum/codex_tree/proc/quick_link(var/search_word, var/mob/user) for(var/word in indexed_pages) if(lowertext(search_word) == lowertext(word)) // Exact matches unfortunately limit our ability to perform SEOs. - go_to_page(indexed_pages[word]) + go_to_page(indexed_pages[word], FALSE, user) return /datum/codex_tree/proc/get_page_from_type(var/desired_type) @@ -45,16 +51,26 @@ return null // Returns to the last visited page, based on the history list. -/datum/codex_tree/proc/go_back() - if((history.len - 1) > 0) - if(history[history.len] == current_page) - history.len-- // This gets rid of the current page in the history. - go_to_page(pop(history), dont_record_history = TRUE) // Where as this will get us the previous page that we want to go to. +/datum/codex_tree/proc/go_back(var/mob/user) + var/list/H = history["[user]"] + var/datum/lore/codex/D = current_page["[user]"] + if(!LAZYLEN(H) || !istype(D)) + return + if((H.len) > 1) + if(H[H.len] == D) + H.len-- // This gets rid of the current page in the history. + history["[user]"] = H + if(H.len == 1) + go_to_page(H[H.len], TRUE, user) + return + go_to_page(pop(history["[user]"]), TRUE, user) // Where as this will get us the previous page that we want to go to. + else + go_to_page(H[H.len], TRUE, user) -/datum/codex_tree/proc/get_tree_position() - if(current_page) +/datum/codex_tree/proc/get_tree_position(var/mob/user) + var/datum/lore/codex/checked = current_page["[user]"] + if(istype(checked)) var/output = "" - var/datum/lore/codex/checked = current_page output = "[checked.name]" while(checked.parent) output = "[checked.parent.name] \> [output]" @@ -75,38 +91,53 @@ /datum/codex_tree/proc/display(mob/user) // icon_state = "[initial(icon_state)]-open" - if(!current_page) + if(!home) generate_pages() + if(!user) + return + var/datum/lore/codex/D = current_page["[user]"] + if(!istype(D)) // Initialize current_page and history + current_page["[user]"] = home + D = current_page["[user]"] + if(!istype(D)) + log_debug("Codex_tree failed to failed to load for [user].") + return + var/list/H_init = list() + H_init.Add(home) + history["[user]"] = H_init + //if(!current_page) + //generate_pages() user << browse_rsc('html/browser/codex.css', "codex.css") var/dat dat = "" - dat += "[holder.name] ([current_page.name])" + dat += "[holder.name] ([D.name])" dat += "" dat += "" dat += "" - dat += "[get_tree_position()]
" + dat += "[get_tree_position(user)]
" dat += "[make_search_bar()]
" dat += "
" - dat += "

[current_page.name]

" + dat += "

[D.name]

" dat += "
" - if(current_page.data) - dat += "[current_page.data]
" + if(D.data) + dat += "[D.data]
" dat += "
" - if(istype(current_page, /datum/lore/codex/category)) + if(istype(D, /datum/lore/codex/category)) dat += "
" - var/datum/lore/codex/category/C = current_page + var/datum/lore/codex/category/C = D for(var/datum/lore/codex/child in C.children) dat += "[child.name]" dat += "
" dat += "
" - if(history.len - 1) + var/list/H = history["[user]"] + if(LAZYLEN(H)) dat += "
\[Go Back\]" - if(current_page.parent) + if(D.parent) dat += "
\[Go Up\]" - if(current_page != home) + if(D != home) dat += "
\[Go To Home\]" dat += "
" user << browse(dat, "window=the_empress_protects;size=600x550") @@ -120,21 +151,21 @@ if(href_list["target"]) // Direct link, using a ref var/datum/lore/codex/new_page = locate(href_list["target"]) - go_to_page(new_page) + go_to_page(new_page, FALSE, usr) else if(href_list["search_query"]) - quick_link(href_list["search_query"]) + quick_link(href_list["search_query"], usr) else if(href_list["go_to_parent"]) - go_to_parent() + go_to_parent(usr) else if(href_list["go_back"]) - go_back() + go_back(usr) else if(href_list["go_to_home"]) - go_to_page(home) + go_to_page(home, FALSE, usr) else if(href_list["quick_link"]) // Indirect link, using a (hopefully) indexed word. - quick_link(href_list["quick_link"]) + quick_link(href_list["quick_link"], usr) else if(href_list["close"]) // Close the book, if our holder is actually a book. - if(istype(holder, /obj/item/weapon/book/codex)) - holder.icon_state = initial(holder.icon_state) + //if(istype(holder, /obj/item/weapon/book/codex)) + //holder.icon_state = initial(holder.icon_state) usr << browse(null, "window=the_empress_protects") return - display(usr) \ No newline at end of file + display(usr) diff --git a/code/modules/maps/tg/map_template.dm b/code/modules/maps/tg/map_template.dm index 3e530206a4..17f43d1029 100644 --- a/code/modules/maps/tg/map_template.dm +++ b/code/modules/maps/tg/map_template.dm @@ -9,8 +9,8 @@ var/annihilate = FALSE // If true, all (movable) atoms at the location where the map is loaded will be deleted before the map is loaded in. var/fixed_orientation = FALSE // If true, the submap will not be rotated randomly when loaded. - var/cost = null /* The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until - it runs out. The cost of a submap should roughly corrispond with several factors such as size, loot, difficulty, desired scarcity, etc. + var/cost = null /* The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until + it runs out. The cost of a submap should roughly corrispond with several factors such as size, loot, difficulty, desired scarcity, etc. Set to -1 to force the submap to always be made. */ var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually. var/discard_prob = 0 // If non-zero, there is a chance that the map seeding algorithm will skip this template when selecting potential templates to use. @@ -74,7 +74,7 @@ A.power_change() if(machinery_was_awake) - SSmachines.wake() // Wake only if it was awake before we tried to suspended it. + SSmachines.wake() // Wake only if it was awake before we tried to suspended it. SSshuttles.block_init_queue = prev_shuttle_queue_state SSshuttles.process_init_queues() // We will flush the queue unless there were other blockers, in which case they will do it. @@ -214,6 +214,12 @@ potential_submaps -= chosen_template continue + // Is single use template already placed + if(!chosen_template.allow_duplicates && chosen_template.loaded) + priority_submaps -= chosen_template + potential_submaps -= chosen_template + continue + // Did we already place down a very similar submap? if(chosen_template.template_group && (chosen_template.template_group in template_groups_used)) priority_submaps -= chosen_template @@ -253,6 +259,13 @@ admin_notice("Submap \"[chosen_template.name]\" placed at ([T.x], [T.y], [T.z])\n", R_DEBUG) + if(specific_sanity < 0) + // I have no idea how this function has a race condition for the sanity check, but forcing the inner check loop to end like this fixes it... + // If a template doesn't allow duplicates, it tries to double place a template. this fixes that. + break + if(!chosen_template.allow_duplicates) + specific_sanity = -1 // force end the placement loop + // Do loading here. chosen_template.load(T, centered = TRUE, orientation=orientation) // This is run before the main map's initialization routine, so that can initilize our submaps for us instead. diff --git a/code/modules/materials/materials/_materials.dm b/code/modules/materials/materials/_materials.dm index fba60dda05..1e1fec8a2d 100644 --- a/code/modules/materials/materials/_materials.dm +++ b/code/modules/materials/materials/_materials.dm @@ -213,6 +213,7 @@ var/list/name_to_material var/luminescence var/radiation_resistance = 0 // Radiation resistance, which is added on top of a material's weight for blocking radiation. Needed to make lead special without superrobust weapons. var/supply_conversion_value // Supply points per sheet that this material sells for. + var/can_sharpen = TRUE // Is this material compatible with a sharpening kit? // Placeholder vars for the time being, todo properly integrate windows/light tiles/rods. var/created_window diff --git a/code/modules/materials/materials/plastic.dm b/code/modules/materials/materials/plastic.dm index ae3326a067..b31ed2cb73 100644 --- a/code/modules/materials/materials/plastic.dm +++ b/code/modules/materials/materials/plastic.dm @@ -109,3 +109,4 @@ weight = 1 protectiveness = 0 // 0% conductive = 0 + can_sharpen = FALSE diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 4856bd6e75..6854056309 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -435,6 +435,11 @@ O.organ_tag = organ_tag H.internal_organs_by_name[organ_tag] = O + // set butcherable meats from species + for(var/obj/item/organ/O in H.organs) + O.set_initial_meat() + for(var/obj/item/organ/O in H.internal_organs) + O.set_initial_meat() /datum/species/proc/hug(var/mob/living/carbon/human/H, var/mob/living/target) diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm index de07fac4cf..8cd79b02ed 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm @@ -338,7 +338,7 @@ var/burncolor = (patient.getFireLoss() < 60 ? "color:gray;" : "color:red;") dat += "\t-Pulse, bpm: [patient.get_pulse(GETPULSE_TOOL)]
" - dat += "\t-Overall Health %: [round(patient.health)]
" + dat += "\t-Overall Health %: [round(100 * (patient.health / patient.getMaxHealth()))]
" dat += "\t-Brute Damage %: [patient.getBruteLoss()]
" dat += "\t-Respiratory Damage %: [patient.getOxyLoss()]
" dat += "\t-Toxin Content %: [patient.getToxLoss()]
" diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 925a9226c2..9cdb19a4fb 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -114,8 +114,7 @@ var/list/organ_cache = list() handle_organ_mod_special() -/obj/item/organ/Initialize() - . = ..() +/obj/item/organ/proc/set_initial_meat() if(owner) if(!meat_type) if(owner.isSynthetic()) @@ -394,7 +393,7 @@ var/list/organ_cache = list() var/obj/item/organ/external/affected = owner.get_organ(parent_organ) if(affected) affected.internal_organs -= src - forceMove(owner.drop_location()) + owner.remove_from_mob(src, owner.drop_location()) START_PROCESSING(SSobj, src) rejecting = null diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 4a79eb64a8..94dea56777 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -234,9 +234,9 @@ var/global/photo_count = 0 holding = "They are holding \a [A.r_hand]" if(!mob_detail) - mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " + mob_detail = "You can see [A] on the photo[(A:health / A.getMaxHealth()) < 0.75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " else - mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." + mob_detail += "You can also see [A] on the photo[(A:health / A.getMaxHealth()) < 0.75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." return mob_detail diff --git a/code/modules/pda/core_apps.dm b/code/modules/pda/core_apps.dm index f45f6d5e70..960978b94d 100644 --- a/code/modules/pda/core_apps.dm +++ b/code/modules/pda/core_apps.dm @@ -46,16 +46,26 @@ icon = "sticky-note-o" template = "pda_notekeeper" + var/greeted = FALSE var/note = null + var/notetitle = null + var/currentnote = 1 + var/list/storedtitles = list("","","","","","","","","","","","") + var/list/storednotes = list("","","","","","","","","","","","") var/notehtml = "" /datum/data/pda/app/notekeeper/start() . = ..() - if(!note) - note = "Congratulations, your station has chosen the [pda.model_name]!" + if(!note && greeted == FALSE) + + // display greeting! + greeted = TRUE + note = "Your station has chosen the [pda.model_name]!" + notetitle = "Congratulations!" /datum/data/pda/app/notekeeper/update_ui(mob/user as mob, list/data) data["note"] = note // current pda notes + data["notename"] = "Note [alphabet_uppercase[currentnote]] : [notetitle]" /datum/data/pda/app/notekeeper/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) @@ -70,6 +80,126 @@ else pda.close(usr) return TRUE + if("Titleset") + var/n = tgui_input_text(usr, "Please enter title", name, notetitle, multiline = FALSE) + if(pda.loc == usr) + notetitle = adminscrub(n) + else + pda.close(usr) + return TRUE + if("Print") + if(pda.loc == usr) + printnote() + else + pda.close(usr) + return TRUE + // dumb way to do this, but i don't know how to easily parse this without a lot of silly code outside the switch! + if("Note1") + if(pda.loc == usr) + changetonote(1) + else + pda.close(usr) + return TRUE + if("Note2") + if(pda.loc == usr) + changetonote(2) + else + pda.close(usr) + return TRUE + if("Note3") + if(pda.loc == usr) + changetonote(3) + else + pda.close(usr) + return TRUE + if("Note4") + if(pda.loc == usr) + changetonote(4) + else + pda.close(usr) + return TRUE + if("Note5") + if(pda.loc == usr) + changetonote(5) + else + pda.close(usr) + return TRUE + if("Note6") + if(pda.loc == usr) + changetonote(6) + else + pda.close(usr) + return TRUE + if("Note7") + if(pda.loc == usr) + changetonote(7) + else + pda.close(usr) + return TRUE + if("Note8") + if(pda.loc == usr) + changetonote(8) + else + pda.close(usr) + return TRUE + if("Note9") + if(pda.loc == usr) + changetonote(9) + else + pda.close(usr) + return TRUE + if("Note10") + if(pda.loc == usr) + changetonote(10) + else + pda.close(usr) + return TRUE + if("Note11") + if(pda.loc == usr) + changetonote(11) + else + pda.close(usr) + return TRUE + if("Note12") + if(pda.loc == usr) + changetonote(12) + else + pda.close(usr) + return TRUE + +/datum/data/pda/app/notekeeper/proc/printnote() + // get active hand of person holding PDA, and print the page to the paper in it + if(istype( usr, /mob/living/carbon/human )) + var/mob/living/carbon/human/H = usr + var/obj/item/I = H.get_active_hand() + if(istype(I,/obj/item/weapon/paper)) + var/obj/item/weapon/paper/P = I + if(isnull(P.info) || P.info == "" ) + var/titlenote = "Note [alphabet_uppercase[currentnote]]" + if(!isnull(notetitle) && notetitle != "") + titlenote = notetitle + to_chat(usr, "Successfully printed [titlenote]!") + P.set_content( pencode2html(note), titlenote) + else + to_chat(usr, "You can only print to empty paper!") + else + to_chat(usr, "You must be holding paper for the pda to print to!") + + +/datum/data/pda/app/notekeeper/proc/changetonote(var/noteindex) + // save note to current slot, then load another slot + storednotes[currentnote] = note + storedtitles[currentnote] = notetitle + + currentnote = noteindex + + note = storednotes[currentnote] + notetitle = storedtitles[currentnote] + + // update text on keeper, silly swapping! + note = replacetext(note, "
", "\n") + notehtml = html_decode(note) + note = replacetext(note, "\n", "
") /datum/data/pda/app/manifest name = "Crew Manifest" diff --git a/code/modules/pda/utilities.dm b/code/modules/pda/utilities.dm index 36ef40a800..65c2484378 100644 --- a/code/modules/pda/utilities.dm +++ b/code/modules/pda/utilities.dm @@ -178,11 +178,18 @@ if(length(notes.note) > 0) notes.note += "

" // Store the scanned document to the notes - notes.note += "Scanned Document. Edit to restore previous notes/delete scan.
----------
" + formatted_scan + "
" - // notehtml ISN'T set to allow user to get their old notes back. A better implementation would add a "scanned documents" - // feature to the PDA, which would better convey the availability of the feature, but this will work for now. + notes.note = formatted_scan + notes.notetitle = sanitize_simple(P.name, list("\n" = "", "\t" = "", "ΓΏ" = "")) + // update the saved note too incase we kept the pda open, this is really silly due to how the notehtml is actually what's passed to the editor's text. + // If I don't update it here, it loses the data when you edit it! + notes.storednotes[notes.currentnote] = notes.note + notes.storedtitles[notes.currentnote] = notes.notetitle + notes.notehtml = html_decode(replacetext(notes.note,"
", "\n")) // Inform the user - to_chat(user, "Paper scanned and OCRed to notekeeper.")//concept of scanning paper copyright brainoblivion 2009 + var/scannedtitle = "Paper" + if(!isnull(notes.notetitle) && notes.notetitle != "") + scannedtitle = "'[notes.notetitle]'" + to_chat(user, "[scannedtitle] scanned to Notekeeper in note [alphabet_uppercase[notes.currentnote]].")//concept of scanning paper copyright brainoblivion 2009 else to_chat(user, "Error scanning [A].") diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/power/singularity/particle_accelerator/particle.dm index 7f30e02966..ce69674522 100644 --- a/code/modules/power/singularity/particle_accelerator/particle.dm +++ b/code/modules/power/singularity/particle_accelerator/particle.dm @@ -7,6 +7,7 @@ icon_state = "particle1"//Need a new icon for this anchored = TRUE density = TRUE + movement_type = UNSTOPPABLE // for bumps to trigger var/movement_range = 10 var/energy = 10 //energy in eV var/mega_energy = 0 //energy in MeV diff --git a/code/modules/power/singularity/particle_accelerator/particle_emitter.dm b/code/modules/power/singularity/particle_accelerator/particle_emitter.dm index 0a82e480d6..292900b419 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_emitter.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_emitter.dm @@ -31,7 +31,7 @@ if((last_shot + fire_delay) <= world.time) last_shot = world.time var/obj/effect/accelerated_particle/A = null - var/turf/T = get_step(src,dir) + var/turf/T = src.loc // if it doesn't spawn here, it won't bump stuff directly infront of the PA switch(strength) if(0) A = new/obj/effect/accelerated_particle/weak(T, dir) diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index a578570216..24a0221a23 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -111,6 +111,8 @@ spawn(1) // slight delay to prevent infinite propagation due to map order //TODO: please no spawn() in process(). It's a very bad idea var/items_moved = 0 for(var/atom/movable/A in affecting) + if(istype(A,/obj/effect/abstract)) // Flashlight's lights are not physical objects + continue if(!A.anchored) if(A.loc == src.loc) // prevents the object from being affected if it's not currently here. step(A,movedir) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 70da01fbc9..ef806bb3fb 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -20,6 +20,8 @@ // CHEST INTERNAL ORGAN SURGERY // ////////////////////////////////////////////////////////////////// /datum/surgery_step/internal/fix_organ + surgery_name = "Dress Organ" + allowed_tools = list( /obj/item/stack/medical/advanced/bruise_pack= 100, \ /obj/item/stack/medical/bruise_pack = 20 @@ -114,6 +116,8 @@ //Robo internal organ fix. For when an organic has robotic limbs. /datum/surgery_step/fix_organic_organ_robotic //For artificial organs + surgery_name = "Mend Organ" + allowed_tools = list( /obj/item/stack/nanopaste = 100, /obj/item/stack/cable_coil = 75, @@ -187,7 +191,8 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/internal/detatch_organ/ - surgery_name = "Detach Organ" //CHOMPEdit + surgery_name = "Detatch Organ" + allowed_tools = list( /obj/item/weapon/surgical/scalpel = 100, \ /obj/item/weapon/material/knife = 75, \ @@ -329,6 +334,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/internal/replace_organ + surgery_name = "Replace Organ" allowed_tools = list( /obj/item/organ = 100 ) @@ -408,7 +414,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/internal/attach_organ - surgery_name = "Attach Organ" //CHOMPEdit + surgery_name = "Attach Organ" allowed_tools = list( /obj/item/weapon/surgical/FixOVein = 100, \ /obj/item/stack/cable_coil = 75 diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index ce24d59905..5e0ffbc0d8 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -522,6 +522,11 @@ else if(tf_mob_holder) log_and_message_admins("[key_name(src)] used the OOC escape button to revert back to their original form from being TFed into another mob.") revert_mob_tf() + + else if(istype(loc, /obj/item/weapon/holder/micro) && (istype(loc.loc, /obj/machinery/microwave))) + forceMove(get_turf(src)) + log_and_message_admins("[key_name(src)] used the OOC escape button to get out of a microwave.") + //CHOMPEdit - petrification (again not vore but hey- ooc escape) else if(istype(loc, /obj/structure/gargoyle) && loc:was_rayed) var/obj/structure/gargoyle/G = loc @@ -533,6 +538,11 @@ var/obj/item/clothing/shoes/S = src.loc forceMove(get_turf(src)) log_and_message_admins("[key_name(src)] used the OOC escape button to escape from of a pair of shoes. [ADMIN_FLW(src)] - Shoes [ADMIN_VV(S)]") + + else if(istype(loc, /obj/item/weapon/holder/micro) && (istype(loc.loc, /obj/machinery/microwave))) + forceMove(get_turf(src)) + log_and_message_admins("[key_name(src)] used the OOC escape button to get out of a microwave.") + //Don't appear to be in a vore situation else to_chat(src,"You aren't inside anyone, though, is the thing.") diff --git a/tgui/packages/tgui/interfaces/pda/pda_notekeeper.jsx b/tgui/packages/tgui/interfaces/pda/pda_notekeeper.jsx index ff6eea775d..22624bb5f8 100644 --- a/tgui/packages/tgui/interfaces/pda/pda_notekeeper.jsx +++ b/tgui/packages/tgui/interfaces/pda/pda_notekeeper.jsx @@ -1,21 +1,126 @@ /* eslint react/no-danger: "off" */ import { useBackend } from '../../backend'; -import { Box, Button, Section } from '../../components'; +import { Box, Button, Section, Table } from '../../components'; export const pda_notekeeper = (props, context) => { const { act, data } = useBackend(context); - const { note } = data; + const { note, notename } = data; return ( +
+ {/* Lets just be nice and lazy with this, multinote support!. */} + + + +
+
+
+
{/* As usual with dangerouslySetInnerHTML, this notekeeper was designed to use HTML injection. Fix when markdown is easier. */}
- ",$+='
',$+='
',$+="Addons:
"+h(w)+"

",$+="== Descriptions ==
",$+="Vore Verb:
"+B+"

",$+="Release Verb:
"+L+"

",$+='Description:
"'+g+'"

',$+='Absorbed Description:
"'+y+'"

',$+="
",$+="== Messages ==
",$+='
',$+='
",$+='
',$+='
',$+='
',we==null||we.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',pe==null||pe.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',E==null||E.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Z==null||Z.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',re==null||re.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',X==null||X.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ne==null||ne.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ve==null||ve.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Ve==null||Ve.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Ie==null||Ie.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Pe==null||Pe.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Ae==null||Ae.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Oe==null||Oe.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',de==null||de.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ge==null||ge.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',j==null||j.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ue==null||ue.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',be==null||be.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ke==null||ke.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Te==null||Te.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Ee==null||Ee.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Re==null||Re.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',_e==null||_e.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',De==null||De.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Ue==null||Ue.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ee==null||ee.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ie==null||ie.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Ce==null||Ce.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Se==null||Se.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Xe==null||Xe.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Qe==null||Qe.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',$e==null||$e.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ht==null||ht.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',lt==null||lt.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',ut==null||ut.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',kt==null||kt.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',St==null||St.forEach(function(Me){$+=Me+"
"}),$+="
",$+="
",$+="
",$+="
",$+="
= Idle Messages =

",$+="

Idle Messages (Hold):

",Bt==null||Bt.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Hold Absorbed):

",Ot==null||Ot.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Digest):

",Mt==null||Mt.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Absorb):

",Pt==null||Pt.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Unabsorb):

",gt==null||gt.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Drain):

",dt==null||dt.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Heal):

",Ct==null||Ct.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Size Steal):

",et==null||et.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Shrink):

",st==null||st.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Grow):

",vt==null||vt.forEach(function(Me){$+=Me+"
"}),$+="


",$+="
Idle Messages (Encase In Egg):

",nt==null||nt.forEach(function(Me){$+=Me+"
"}),$+="


",$+="


",$+="
",$+='
',$+='
',$+='

',$+='

",$+='
',$+='
',$+='
    ',$+='
  • Can Taste: '+(O?'Yes':'No')+"
  • ",$+='
  • Feedable: '+(_?'Yes':'No')+"
  • ",$+='
  • Contaminates: '+(P?'Yes':'No')+"
  • ",$+='
  • Contamination Flavor: '+D+"
  • ",$+='
  • Contamination Color: '+z+"
  • ",$+='
  • Nutritional Gain: '+U+"%
  • ",$+='
  • Required Examine Size: '+W*100+"%
  • ",$+='
  • Display Absorbed Examines: '+(K?'True':'False')+"
  • ",$+='
  • Save Digest Mode: '+(H?'True':'False')+"
  • ",$+='
  • Idle Emotes: '+(Y?'Active':'Inactive')+"
  • ",$+='
  • Idle Emote Delay: '+J+" seconds
  • ",$+='
  • Shrink/Grow Size: '+q*100+"%
  • ",$+='
  • Vore Spawn Blacklist: '+(oe?'Yes':'No')+"
  • ",$+='
  • Egg Type: '+ae+"
  • ",$+='
  • Selective Mode Preference: '+he+"
  • ",$+="
",$+="
",$+='
',$+='

',$+='

",$+='
',$+='
',$+='
    ',$+='
  • Fleshy Belly: '+($t?'Yes':'No')+"
  • ",$+='
  • Internal Loop: '+(Yt?'Yes':'No')+"
  • ",$+='
  • Use Fancy Sounds: '+(Xt?'Yes':'No')+"
  • ",$+='
  • Vore Sound: '+Qt+"
  • ",$+='
  • Release Sound: '+Lt+"
  • ",$+="
",$+="
",$+='
',$+='

',$+='

",$+='
",$+='
',$+="Vore Sprites",$+='
    ',$+='
  • Affect Vore Sprites: '+(_t?'Yes':'No')+"
  • ",$+='
  • Count Absorbed prey for vore sprites: '+(It?'Yes':'No')+"
  • ",$+='
  • Animation when prey resist: '+(Je?'Yes':'No')+"
  • ",$+='
  • Vore Sprite Size Factor: '+qt+"
  • ",$+='
  • Belly Sprite to affect: '+en+"
  • ",$+="
",$+="Belly Fullscreens Preview and Coloring",$+='
    ',$+='
  • Color: '+xt+"",$+="
",$+="Vore FX",$+='
    ',$+='
  • Disable Prey HUD: '+(on?'Yes':'No')+"
  • ",$+="
",$+="
",$+='
',$+='

',$+='

",$+='
',$+='
',$+="Belly Interactions ("+(Rt?'Enabled':'Disabled')+")",$+='
    ',$+='
  • Escape Chance: '+rn+"%
  • ",$+='
  • Escape Chance: '+at+"%
  • ",$+='
  • Escape Time: '+an/10+"s
  • ",$+='
  • Transfer Chance: '+cn+"%
  • ",$+='
  • Transfer Location: '+ln+"
  • ",$+='
  • Secondary Transfer Chance: '+un+"%
  • ",$+='
  • Secondary Transfer Location: '+dn+"
  • ",$+='
  • Absorb Chance: '+sn+"%
  • ",$+='
  • Digest Chance: '+wt+"%
  • ",$+="
",$+="
",$+="Auto-Transfer Options ("+(fn?'Enabled':'Disabled')+")",$+='
    ',$+='
  • Auto-Transfer Time: '+mn/10+"s
  • ",$+='
  • Auto-Transfer Chance: '+Tt+"%
  • ",$+='
  • Auto-Transfer Location: '+Dt+"
  • ",$+='
  • Auto-Transfer Chance: '+Ft+"%
  • ",$+='
  • Auto-Transfer Location: '+jt+"
  • ",$+='
  • Auto-Transfer Min Amount: '+pn+"
  • ",$+='
  • Auto-Transfer Max Amount: '+hn+"
  • ",$+='
  • Auto-Transfer Primary Chance: '+Tt+"%
  • ",$+='
  • Auto-Transfer Primary Location: '+Dt+"
  • ",$+='
  • Auto-Transfer Primary Whitelist (Mobs): '+l(it,!0)+"
  • ",$+='
  • Auto-Transfer Primary Whitelist (Items): '+l(vn,!0)+"
  • ",$+='
  • Auto-Transfer Primary Blacklist (Mobs): '+l(Vt,!1)+"
  • ",$+='
  • Auto-Transfer Primary Blacklist (Items): '+l(zt,!1)+"
  • ",$+='
  • Auto-Transfer Secondary Chance: '+Ft+"%
  • ",$+='
  • Auto-Transfer Secondary Location: '+jt+"
  • ",$+='
  • Auto-Transfer Secondary Whitelist (Mobs): '+l(Wt,!0)+"
  • ",$+='
  • Auto-Transfer Secondary Whitelist (Items): '+l(Ut,!0)+"
  • ",$+='
  • Auto-Transfer Secondary Blacklist (Mobs): '+l(Cn,!1)+"
  • ",$+='
  • Auto-Transfer Secondary Blacklist (Items): '+l(gn,!1)+"
  • ",$+="
",$+="
",$+='
',$+='

',$+='

",$+='
',$+='
',$+='
    ',$+='
  • Generate Liquids: '+(Nn?'On':'Off')+"
  • ",$+='
  • Liquid Type: '+At+"
  • ",$+='
  • Liquid Name: '+Ht+"
  • ",$+='
  • Transfer Verb: '+bn+"
  • ",$+='
  • Generation Time: '+Gt+"
  • ",$+='
  • Liquid Capacity: '+Kt+"
  • ",$+='
  • Slosh Sounds: '+(Et?'On':'Off')+"
  • ",$+='
  • Liquid Addons: '+s(Bn)+"
  • ",$+="
",$+="
",$+='
',$+='

',$+='

",$+='
',$+='
',$+='
',$+='
",$+='
',$+='
',$+='
',ft==null||ft.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',rt==null||rt.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',yt==null||yt.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',Ze==null||Ze.forEach(function(Me){$+=Me+"
"}),$+="
",$+='
',pt==null||pt.forEach(function(Me){$+=Me+"
"}),$+="
",$+="
",$+="
",$+="
",$+="
",$+="
",$},i=function(){var f=new Date,C=String(f.getHours());C.length<2&&(C="0"+C);var b=String(f.getMinutes());b.length<2&&(b="0"+b);var g=String(f.getDate());g.length<2&&(g="0"+g);var y=String(f.getMonth()+1);y.length<2&&(y="0"+y);var B=String(f.getFullYear());return" "+B+"-"+y+"-"+g+" ("+C+" "+b+")"},c=function(f,C){var b=(0,a.useBackend)(f),g=b.act,y=b.data,B=y.db_version,L=y.db_repo,I=y.mob_name,w=y.bellies,T=i(),M=I+T+C,A;if(C===".html"){var R="";A=new Blob([''+w.length+" Exported Bellies (DB_VER: "+L+"-"+B+')'+R+'

Bellies of '+I+'

Generated on: '+T+'

'],{type:"text/html;charset=utf8"}),w.forEach(function(O,_){A=new Blob([A,u(O,_)],{type:"text/html;charset=utf8"})}),A=new Blob([A,"
",'