diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index 2fd9719eb45..3b4815b3533 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -49,7 +49,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 9b54383278b..2e4885fd769 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 2927cb97860..c5e3af5b1a7 100644 --- a/code/game/objects/items/weapons/material/material_weapons.dm +++ b/code/game/objects/items/weapons/material/material_weapons.dm @@ -140,7 +140,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 1b58490012c..03b3b6f14cf 100644 --- a/code/game/turfs/flooring/flooring.dm +++ b/code/game/turfs/flooring/flooring.dm @@ -198,6 +198,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 e55196aea6c..98d195001cd 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 12fa8dbdfb1..71ec091dcb7 100644 --- a/code/modules/lore_codex/codex.dm +++ b/code/modules/lore_codex/codex.dm @@ -9,13 +9,21 @@ var/datum/codex_tree/tree = null var/root_type = /datum/lore/codex/category/main_virgo_lore //Runtimes on codex_tree.dm, line 18 with a null here + var/static/list/codex_tree_keys = list() // static list linking codexes to the correct codex_tree. + /obj/item/weapon/book/codex/Initialize() - tree = new(src, root_type) + tree = codex_tree_keys["[root_type]"] + if(!tree) + tree = new(src, root_type) + codex_tree_keys["[root_type]"] = tree . = ..() /obj/item/weapon/book/codex/attack_self(mob/user) if(!tree) - tree = new(src, root_type) + tree = codex_tree_keys["[root_type]"] + if(!tree) + tree = new(src, root_type) + 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 71aa80b0870..200a1ec4f09 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 3e530206a4c..17f43d10292 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 fba60dda059..1e1fec8a2d0 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 d10e5153f6b..b31ed2cb736 100644 --- a/code/modules/materials/materials/plastic.dm +++ b/code/modules/materials/materials/plastic.dm @@ -108,4 +108,5 @@ hardness = 1 weight = 1 protectiveness = 0 // 0% - conductive = 0 \ No newline at end of file + 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 e7722cff392..51911e23a91 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -407,6 +407,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) @@ -570,4 +575,3 @@ /datum/species/proc/post_spawn_special(mob/living/carbon/human/H) return - 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 f297317a27f..a7a9386c394 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 @@ -331,7 +331,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 ec117338fa6..621e875df64 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 4a79eb64a83..94dea567779 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 f45f6d5e70f..960978b94d0 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 36ef40a8006..65c2484378c 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 7f30e02966b..ce696745223 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 0a82e480d6b..292900b4197 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 ac02254e2c1..75bb9a1d153 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 dfbf624cf56..ef806bb3fbb 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,6 +191,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/internal/detatch_organ/ + surgery_name = "Detatch Organ" allowed_tools = list( /obj/item/weapon/surgical/scalpel = 100, \ @@ -329,6 +334,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/internal/replace_organ + surgery_name = "Replace Organ" allowed_tools = list( /obj/item/organ = 100 ) @@ -408,6 +414,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/internal/attach_organ + 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 d1ebb0e4c76..dceba741670 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -496,6 +496,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.") + //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 c0af68c3706..1e9356e4c6b 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) => { const { act, data } = useBackend(); - 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. */}
- ",K+='
',K+='
',K+="Addons:
"+k(B)+"

",K+="== Descriptions ==
",K+="Vore Verb:
"+b+"

",K+="Release Verb:
"+g+"

",K+='Description:
"'+p+'"

',K+='Absorbed Description:
"'+v+'"

',K+="
",K+="== Messages ==
",K+='
',K+='
",K+='
',K+='
',K+='
',q==null||q.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',me==null||me.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',pe==null||pe.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Ne==null||Ne.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',le==null||le.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',re==null||re.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ie==null||ie.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Ve==null||Ve.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ke==null||ke.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Be==null||Be.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ue==null||ue.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',oe==null||oe.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Ce==null||Ce.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ae==null||ae.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ee==null||ee.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',se==null||se.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',xe==null||xe.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Le==null||Le.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Pe==null||Pe.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Fe==null||Fe.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',je==null||je.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Me==null||Me.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',be==null||be.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ve==null||ve.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',he==null||he.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',$==null||$.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',G==null||G.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Z==null||Z.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',te==null||te.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ye==null||ye.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Ie==null||Ie.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',we==null||we.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',_e==null||_e.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',ze==null||ze.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Ue==null||Ue.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Ge==null||Ge.forEach(function(Se){K+=Se+"
"}),K+="
",K+='
',Ke==null||Ke.forEach(function(Se){K+=Se+"
"}),K+="
",K+="
",K+="
",K+="
",K+="
= Idle Messages =

",K+="

Idle Messages (Hold):

",Nt==null||Nt.forEach(function(Se){K+=Se+"
"}),K+="


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

",bt==null||bt.forEach(function(Se){K+=Se+"
"}),K+="


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

",Ye==null||Ye.forEach(function(Se){K+=Se+"
"}),K+="


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

",st==null||st.forEach(function(Se){K+=Se+"
"}),K+="


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

",pt==null||pt.forEach(function(Se){K+=Se+"
"}),K+="


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

",yt==null||yt.forEach(function(Se){K+=Se+"
"}),K+="


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

",Vt==null||Vt.forEach(function(Se){K+=Se+"
"}),K+="


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

",kt==null||kt.forEach(function(Se){K+=Se+"
"}),K+="


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

",ft==null||ft.forEach(function(Se){K+=Se+"
"}),K+="


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

",Bt==null||Bt.forEach(function(Se){K+=Se+"
"}),K+="


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

",mt==null||mt.forEach(function(Se){K+=Se+"
"}),K+="


",K+="


",K+="
",K+='
',K+='
',K+='

',K+='

",K+='
',K+='
',K+='
    ',K+='
  • Can Taste: '+(A?'Yes':'No')+"
  • ",K+='
  • Contaminates: '+(M?'Yes':'No')+"
  • ",K+='
  • Contamination Flavor: '+R+"
  • ",K+='
  • Contamination Color: '+O+"
  • ",K+='
  • Nutritional Gain: '+F+"%
  • ",K+='
  • Required Examine Size: '+D*100+"%
  • ",K+='
  • Display Absorbed Examines: '+(j?'True':'False')+"
  • ",K+='
  • Save Digest Mode: '+(_?'True':'False')+"
  • ",K+='
  • Idle Emotes: '+(z?'Active':'Inactive')+"
  • ",K+='
  • Idle Emote Delay: '+H+" seconds
  • ",K+='
  • Shrink/Grow Size: '+Q*100+"%
  • ",K+='
  • Egg Type: '+Y+"
  • ",K+='
  • Selective Mode Preference: '+X+"
  • ",K+="
",K+="
",K+='
',K+='

',K+='

",K+='
',K+='
',K+='
    ',K+='
  • Fleshy Belly: '+(wt?'Yes':'No')+"
  • ",K+='
  • Internal Loop: '+(Tt?'Yes':'No')+"
  • ",K+='
  • Use Fancy Sounds: '+(lt?'Yes':'No')+"
  • ",K+='
  • Vore Sound: '+at+"
  • ",K+='
  • Release Sound: '+Ze+"
  • ",K+="
",K+="
",K+='
',K+='

',K+='

",K+='
",K+='
',K+="Vore FX",K+='
    ',K+='
  • Disable Prey HUD: '+(qe?'Yes':'No')+"
  • ",K+="
",K+="
",K+='
',K+='

',K+='

",K+='
',K+='
',K+="Belly Interactions ("+(it?'Enabled':'Disabled')+")",K+='
    ',K+='
  • Escape Chance: '+ut+"%
  • ",K+='
  • Escape Chance: '+dt+"%
  • ",K+='
  • Escape Time: '+Et/10+"s
  • ",K+='
  • Transfer Chance: '+At+"%
  • ",K+='
  • Transfer Location: '+Mt+"
  • ",K+='
  • Secondary Transfer Chance: '+Pt+"%
  • ",K+='
  • Secondary Transfer Location: '+Ct+"
  • ",K+='
  • Absorb Chance: '+St+"%
  • ",K+='
  • Digest Chance: '+Lt+"%
  • ",K+="
",K+="
",K+="
",K},s=function(){var c=new Date,l=String(c.getHours());l.length<2&&(l="0"+l);var h=String(c.getMinutes());h.length<2&&(h="0"+h);var p=String(c.getDate());p.length<2&&(p="0"+p);var v=String(c.getMonth()+1);v.length<2&&(v="0"+v);var b=String(c.getFullYear());return" "+b+"-"+v+"-"+p+" ("+l+" "+h+")"},m=function(c){var l=(0,a.useBackend)(),h=l.act,p=l.data,v=p.db_version,b=p.db_repo,g=p.mob_name,N=p.bellies,B=s(),S=g+B+c,L;if(c===".html"){var I="";L=new Blob([''+N.length+" Exported Bellies (DB_VER: "+b+"-"+v+')'+I+'

Bellies of '+g+'

Generated on: '+B+'

'],{type:"text/html;charset=utf8"}),N.forEach(function(w,T){L=new Blob([L,C(w,T)],{type:"text/html;charset=utf8"})}),L=new Blob([L,"
",'