diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 8da220bf67..e2c04299f1 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -142,7 +142,7 @@ if(ismob(A)) var/mob/M = A if(client_check && !M.client) - L = recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) + L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) continue if(sight_check && !isInSight(A, O)) continue @@ -155,7 +155,7 @@ L |= A if(isobj(A) || ismob(A)) - L = recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) + L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) return L // The old system would loop through lists for a total of 5000 per function call, in an empty server. @@ -182,7 +182,7 @@ hear += A if(isobj(A) || ismob(A)) - hear = recursive_mob_check(A, hear, 3, 1, 0, 1) + hear |= recursive_mob_check(A, hear, 3, 1, 0, 1) return hear @@ -209,8 +209,9 @@ if(M) var/turf/ear = get_turf(M) if(ear) - if(speaker_coverage[ear]) - . |= M + // Ghostship is magic: Ghosts can hear radio chatter from anywhere + if(speaker_coverage[ear] || (istype(M, /mob/dead/observer) && (M.client) && (M.client.prefs.toggles & CHAT_GHOSTRADIO))) + . |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down. return . #define SIGN(X) ((X<0)?-1:1) diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index cb840a1d90..112c3431e5 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -55,6 +55,7 @@ RestrainedClickOn(A) else */ + A.add_hiddenprint(src) A.attack_ai(src) /* diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 640a09d045..d86faacbd1 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -48,6 +48,7 @@ // Cyborgs have no range-checking unless there is item use if(!W) + A.add_hiddenprint(src) A.attack_robot(src) return diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index c9dfd7cf40..5f11d9f623 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -18,6 +18,7 @@ var/log_adminwarn = 0 // log warnings admins get about bomb construction and such var/log_pda = 0 // log pda messages var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits + var/log_runtime = 0 // logs world.log to a file var/sql_enabled = 1 // for sql switching var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour var/allow_vote_restart = 0 // allow votes to restart @@ -245,6 +246,9 @@ if ("log_hrefs") config.log_hrefs = 1 + if ("log_runtime") + config.log_runtime = 1 + if("allow_admin_ooccolor") config.allow_admin_ooccolor = 1 diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 155f6c6481..7775e3aa20 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -288,7 +288,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes. continue - + + // Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates + if(data == 3 && istype(R, /mob/dead/observer) && R.client && (R.client.prefs.toggles & CHAT_GHOSTRADIO)) + continue // --- Check for compression --- if(compression > 0) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index ad757325b9..ee73d537d8 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -80,6 +80,7 @@ if(instant || do_after(user, 50)) new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype) user << "You finish drawing." + target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on. if(uses) uses-- if(!uses) @@ -97,4 +98,4 @@ user << "\red You ate your crayon!" del(src) else - ..() \ No newline at end of file + ..() diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index ab8884d96c..eb59003ace 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -163,6 +163,7 @@ if("boiling") watertemp = "normal" user.visible_message("[user] adjusts the shower with the [I].", "You adjust the shower with the [I].") + add_fingerprint(user) /obj/machinery/shower/update_icon() //this is terribly unreadable, but basically it makes the shower mist up overlays.Cut() //once it's been on for a while, in addition to handling the water overlay. @@ -412,4 +413,4 @@ /obj/structure/sink/puddle/attackby(obj/item/O as obj, mob/user as mob) icon_state = "puddle-splash" ..() - icon_state = "puddle" \ No newline at end of file + icon_state = "puddle" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 54a865955a..b09712350c 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -804,7 +804,11 @@ if (ismob(M)) if(!check_if_greater_rights_than(M.client)) return - M << "\red You have been kicked from the server" + var/reason = input("Please enter reason") + if(!reason) + M << "\red You have been kicked from the server" + else + M << "\red You have been kicked from the server: [reason]" log_admin("[key_name(usr)] booted [key_name(M)].") message_admins("\blue [key_name_admin(usr)] booted [key_name_admin(M)].", 1) //M.client = null diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 304e96b0fa..0c8c0e0b4e 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -250,6 +250,7 @@ datum/preferences dat += "Play lobby music: [(toggles & SOUND_LOBBY) ? "Yes" : "No"]
" dat += "Ghost ears: [(toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]
" dat += "Ghost sight: [(toggles & CHAT_GHOSTSIGHT) ? "Nearest Creatures" : "All Emotes"]
" + dat += "Ghost radio: [(toggles & CHAT_GHOSTRADIO) ? "Nearest Speakers" : "All Chatter"]
" if(config.allow_Metadata) dat += "OOC Notes: Edit
" @@ -1159,6 +1160,9 @@ datum/preferences if("ghost_sight") toggles ^= CHAT_GHOSTSIGHT + + if("ghost_radio") + toggles ^= CHAT_GHOSTRADIO if("save") save_preferences() diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index c1628c1f3f..326921c1f6 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -17,14 +17,23 @@ prefs.save_preferences() feedback_add_details("admin_verb","TGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/verb/toggle_ghost_radio() + set name = "Enable/Disable GhostRadio" + set category = "Preferences" + set desc = ".Toggle between hearing all radio chatter, or only from nearby speakers" + prefs.toggles ^= CHAT_GHOSTRADIO + src << "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"]." + prefs.save_preferences() + feedback_add_details("admin_verb","TGR") + /client/proc/toggle_hear_radio() set name = "Show/Hide RadioChatter" set category = "Preferences" - set desc = "Toggle seeing radiochatter from nearby radios and speakers" + set desc = "Toggle seeing radiochatter from radios and speakers" if(!holder) return prefs.toggles ^= CHAT_RADIO prefs.save_preferences() - usr << "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers" + usr << "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers" feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/toggleadminhelpsound() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 9627c55d82..2b5b5d75b7 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -441,6 +441,58 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set hidden = 1 src << "\red You are dead! You have no mind to store memory!" +/mob/dead/observer/verb/analyze_air() + set name = "Analyze Air" + set category = "Ghost" + + if(!istype(usr, /mob/dead/observer)) return + + // Shamelessly copied from the Gas Analyzers + if (!( istype(usr.loc, /turf) )) + return + + var/datum/gas_mixture/environment = usr.loc.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() + + src << "\blue Results:" + if(abs(pressure - ONE_ATMOSPHERE) < 10) + src << "\blue Pressure: [round(pressure,0.1)] kPa" + else + src << "\red Pressure: [round(pressure,0.1)] kPa" + if(total_moles) + var/o2_concentration = environment.oxygen/total_moles + var/n2_concentration = environment.nitrogen/total_moles + var/co2_concentration = environment.carbon_dioxide/total_moles + var/plasma_concentration = environment.toxins/total_moles + + var/unknown_concentration = 1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration) + if(abs(n2_concentration - N2STANDARD) < 20) + src << "\blue Nitrogen: [round(n2_concentration*100)]% ([round(environment.nitrogen,0.01)] moles)" + else + src << "\red Nitrogen: [round(n2_concentration*100)]% ([round(environment.nitrogen,0.01)] moles)" + + if(abs(o2_concentration - O2STANDARD) < 2) + src << "\blue Oxygen: [round(o2_concentration*100)]% ([round(environment.oxygen,0.01)] moles)" + else + src << "\red Oxygen: [round(o2_concentration*100)]% ([round(environment.oxygen,0.01)] moles)" + + if(co2_concentration > 0.01) + src << "\red CO2: [round(co2_concentration*100)]% ([round(environment.carbon_dioxide,0.01)] moles)" + else + src << "\blue CO2: [round(co2_concentration*100)]% ([round(environment.carbon_dioxide,0.01)] moles)" + + if(plasma_concentration > 0.01) + src << "\red Plasma: [round(plasma_concentration*100)]% ([round(environment.toxins,0.01)] moles)" + + if(unknown_concentration > 0.01) + src << "\red Unknown: [round(unknown_concentration*100)]% ([round(unknown_concentration*total_moles,0.01)] moles)" + + src << "\blue Temperature: [round(environment.temperature-T0C,0.1)]°C" + src << "\blue Heat Capacity: [round(environment.heat_capacity(),0.1)]" + + /mob/dead/observer/verb/toggle_darkness() set name = "Toggle Darkness" set category = "Ghost" @@ -572,4 +624,4 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp W.update_icon() W.message = message W.add_hiddenprint(src) - W.visible_message("\red Invisible fingers crudely paint something in blood on [T]...") \ No newline at end of file + W.visible_message("\red Invisible fingers crudely paint something in blood on [T]...") diff --git a/code/modules/mob/living/carbon/monkey/diona.dm b/code/modules/mob/living/carbon/monkey/diona.dm index 442d33e2ac..3f98e3b694 100644 --- a/code/modules/mob/living/carbon/monkey/diona.dm +++ b/code/modules/mob/living/carbon/monkey/diona.dm @@ -2,6 +2,38 @@ Tiny babby plant critter plus procs. */ +//Helper object for picking dionaea up. +/obj/item/weapon/diona_holder + + name = "diona nymph" + desc = "It's a tiny plant critter." + icon = 'icons/obj/objects.dmi' + icon_state = "nymph" + slot_flags = SLOT_HEAD + origin_tech = "magnets=3;biotech=5" + +/obj/item/weapon/diona_holder/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/diona_holder/Del() + processing_objects.Remove(src) + ..() + +/obj/item/weapon/diona_holder/process() + if(!loc) return + + if(!istype(loc,/mob/living)) + for(var/mob/M in contents) + M.loc = get_turf(src) + del(src) + +/obj/item/weapon/diona_holder/attackby(obj/item/weapon/W as obj, mob/user as mob) + for(var/mob/M in src.contents) + M.attackby(W,user) + +//Mob defines. /mob/living/carbon/monkey/diona name = "diona nymph" voice_name = "diona nymph" @@ -10,6 +42,20 @@ var/list/donors = list() var/ready_evolve = 0 +/mob/living/carbon/monkey/diona/attack_hand(mob/living/carbon/human/M as mob) + + //Let people pick the little buggers up. + if(M.a_intent == "help") + var/obj/item/weapon/diona_holder/D = new(loc) + src.loc = D + D.name = loc.name + D.attack_hand(M) + M << "You scoop up [src]." + src << "[M] scoops you up." + return + + ..() + /mob/living/carbon/monkey/diona/New() ..() @@ -64,6 +110,10 @@ set name = "Evolve" set desc = "Grow to a more complex form." + if(!is_alien_whitelisted(src, "Diona") && config.usealienwhitelist) + src << alert("You are currently not whitelisted to play an adult Diona.") + return 0 + if(donors.len < 5) src << "You are not yet ready for your growth..." return @@ -73,8 +123,15 @@ return src.visible_message("\red [src] begins to shift and quiver, and erupts in a shower of shed bark and twigs!","\red You begin to shift and quiver, then erupt in a shower of shed bark and twigs, attaining your adult form!") - var/mob/living/carbon/human/adult = new(loc) + + var/mob/living/carbon/human/adult = new(get_turf(src.loc)) adult.set_species("Diona") + + if(istype(loc,/obj/item/weapon/diona_holder/)) + var/obj/item/weapon/diona_holder/L = loc + src.loc = L.loc + del(L) + for(var/datum/language/L in languages) adult.add_language(L.name) adult.regenerate_icons() diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 1b0d0e1064..8b9f3009d1 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -22,7 +22,7 @@ if(loc) environment = loc.return_air() - if (stat != DEAD) //still breathing + if (stat != DEAD && !istype(src,/mob/living/carbon/monkey/diona)) //still breathing //First, resolve location and get a breath if(air_master.current_cycle%4==2) //Only try to take a breath every 4 seconds, unless suffocating diff --git a/code/setup.dm b/code/setup.dm index 68b7552b40..08fec4f49a 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -639,6 +639,7 @@ var/list/TAGGERLOCATIONS = list("Disposals", #define CHAT_ATTACKLOGS 1024 #define CHAT_DEBUGLOGS 2048 #define CHAT_LOOC 4096 +#define CHAT_GHOSTRADIO 8192 #define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC) diff --git a/code/world.dm b/code/world.dm index 3d1ad20db9..de70b60fe6 100644 --- a/code/world.dm +++ b/code/world.dm @@ -11,7 +11,6 @@ /world/New() //logs var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") - log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM")].log") //funtimelog href_logfile = file("data/logs/[date_string] hrefs.htm") diary = file("data/logs/[date_string].log") diaryofmeanpeople = file("data/logs/[date_string] Attack.log") @@ -28,6 +27,9 @@ // dumb and hardcoded but I don't care~ config.server_name += " #[(world.port % 1000) / 100]" + if(config && config.log_runtime) + log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD-(hh-mm-ss)")]-runtime.log") + callHook("startup") //Emergency Fix load_mods() diff --git a/config/example/config.txt b/config/example/config.txt index 1075a5ab67..783adb23af 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -61,6 +61,9 @@ LOG_PDA ## log all Topic() calls (for use by coders in tracking down Topic issues) # LOG_HREFS +## log world.log and runtime errors to a file +# LOG_RUNTIME + ## log admin warning messages ##LOG_ADMINWARN ## Also duplicates a bunch of other messages. @@ -234,4 +237,4 @@ USEALIENWHITELIST ALLOW_CULT_GHOSTWRITER ## Sets the minimum number of cultists needed for ghosts to write in blood. -REQ_CULT_GHOSTWRITER 6 \ No newline at end of file +REQ_CULT_GHOSTWRITER 6 diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index e269d169aa..0fb7e01d0d 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 3559623fd2..2e79482b4b 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/items_lefthand.dmi b/icons/mob/items_lefthand.dmi index 2dc326dccb..4e023c6bca 100644 Binary files a/icons/mob/items_lefthand.dmi and b/icons/mob/items_lefthand.dmi differ diff --git a/icons/mob/items_righthand.dmi b/icons/mob/items_righthand.dmi index 2483a5c728..392ac02823 100644 Binary files a/icons/mob/items_righthand.dmi and b/icons/mob/items_righthand.dmi differ diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi index cbbef92efa..ae70160d50 100644 Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ