From c21754c2e3e77c7b6bf99e99579669fe10903a50 Mon Sep 17 00:00:00 2001 From: Zaers Date: Tue, 23 Jun 2015 22:40:51 -0300 Subject: [PATCH] Port new admin stuff (needs DB update) --- SQL/database_changelog.txt | 13 + SQL/errofreedatabase.sql | 3 +- SQL/tgstation_schema.sql | 14 + SQL/tgstation_schema_prefixed.sql | 18 +- code/controllers/_DynamicAreaLighting_TG.dm | 537 -------------------- code/controllers/subsystem/garbage.dm | 6 + code/controllers/subsystem/pipenets.dm | 36 -- code/controllers/subsystem/power.dm | 18 - code/controllers/subsystem/timer.dm | 71 +++ code/modules/admin/admin.dm | 3 +- code/modules/admin/topic.dm | 77 +++ code/modules/admin/verbs/adminhelp.dm | 10 +- code/modules/client/client procs.dm | 6 + tgstation.dme | 1 + 14 files changed, 216 insertions(+), 597 deletions(-) delete mode 100644 code/controllers/_DynamicAreaLighting_TG.dm delete mode 100644 code/controllers/subsystem/pipenets.dm delete mode 100644 code/controllers/subsystem/power.dm create mode 100644 code/controllers/subsystem/timer.dm diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.txt index 80af03e4561f6..44dd4de533413 100644 --- a/SQL/database_changelog.txt +++ b/SQL/database_changelog.txt @@ -1,3 +1,16 @@ + +19 May 2015, by Jordie0608 + +Added new table 'watch' for use in flagging ckeys. It shouldn't ever exist, but also added command to de-erroize this new table just in case someone does make it like that. + +To create this new table run the following command: + +CREATE TABLE `watch` (`id` int(11) NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, `reason` text NOT NULL, PRIMARY KEY (`id`)) + +Remember to add prefix to the table name if you use them. + +---------------------------------------------------- + 19 September 2014, by MrStonedOne Removed erro_ from table names. dbconfig.txt has a option allowing you to change the prefix used in code, defaults to "erro_" if left out for legacy reasons. diff --git a/SQL/errofreedatabase.sql b/SQL/errofreedatabase.sql index ae5c0d7ee1c95..73e0aaceb2cf5 100644 --- a/SQL/errofreedatabase.sql +++ b/SQL/errofreedatabase.sql @@ -12,4 +12,5 @@ ALTER TABLE erro_poll_option RENAME TO SS13_poll_option; ALTER TABLE erro_poll_question RENAME TO SS13_poll_question; ALTER TABLE erro_poll_textreply RENAME TO SS13_poll_textreply; ALTER TABLE erro_poll_vote RENAME TO SS13_poll_vote; -ALTER TABLE erro_privacy RENAME TO SS13_privacy; \ No newline at end of file +ALTER TABLE erro_privacy RENAME TO SS13_privacy; +ALTER TABLE erro_watch RENAME TO SS13_watch; diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql index 30fd894e965e2..692b6354e4a42 100644 --- a/SQL/tgstation_schema.sql +++ b/SQL/tgstation_schema.sql @@ -321,6 +321,20 @@ CREATE TABLE `privacy` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `watch` +-- + +DROP TABLE IF EXISTS `watch`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `watch` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ckey` varchar(32) NOT NULL, + `reason` text NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; diff --git a/SQL/tgstation_schema_prefixed.sql b/SQL/tgstation_schema_prefixed.sql index c1b740b687439..8294642b5a7fd 100644 --- a/SQL/tgstation_schema_prefixed.sql +++ b/SQL/tgstation_schema_prefixed.sql @@ -317,6 +317,22 @@ CREATE TABLE `SS13_privacy` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `watch` +-- + +DROP TABLE IF EXISTS `SS13_watch`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `SS13_watch` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ckey` varchar(32) NOT NULL, + `reason` text NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + + /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -327,4 +343,4 @@ CREATE TABLE `SS13_privacy` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2013-03-24 18:02:35 \ No newline at end of file +-- Dump completed on 2013-03-24 18:02:35 diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm deleted file mode 100644 index 051fb44d4718b..0000000000000 --- a/code/controllers/_DynamicAreaLighting_TG.dm +++ /dev/null @@ -1,537 +0,0 @@ -/* - Modified DynamicAreaLighting for TGstation - Coded by Carnwennan - - This is TG's 'new' lighting system. It's basically a heavily modified combination of Forum_Account's and - ShadowDarke's respective lighting libraries. Credits, where due, to them. - - Like sd_DAL (what we used to use), it changes the shading overlays of areas by splitting each type of area into sub-areas - by using the var/tag variable and moving turfs into the contents list of the correct sub-area. This method is - much less costly than using overlays or objects. - - Unlike sd_DAL however it uses a queueing system. Everytime we call a change to opacity or luminosity - (through SetOpacity() or SetLuminosity()) we are simply updating variables and scheduling certain lights/turfs for an - update. Actual updates are handled periodically by the SSlighting subsystem. This carries additional overheads, however it - means that each thing is changed only once per SSlighting.wait deciseconds. Allowing for greater control - over how much priority we'd like lighting updates to have. - - UPDATE: we no longer postpone lighting updates by editting variables, there is now a subsystem/proc/postpone() procedure. - So you would do SSlighting.postpone() - - Unlike our old system there are hardcoded maximum luminositys (different for certain atoms). - This is to cap the cost of creating lighting effects. - (without this, an atom with luminosity of 20 would have to update 41^2 turfs!) :s - - Also, in order for the queueing system to work, each light remembers the effect it casts on each turf. This is going to - have larger memory requirements than our previous system but it's easily worth the hassle for the greater control we - gain. It also reduces cost of removing lighting effects by a lot! - - Known Issues/TODO: - Shuttles still do not have support for dynamic lighting (I hope to fix this at some point) - No directional lighting support. (prototype looked ugly) -*/ - -#define USE_CIRCULAR_LIGHTING //comment this out to use old square lighting effects. - -#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays -#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha6.dmi' //Icon used for lighting shading effects -/* -#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha6.dmi' -#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays -*/ - -datum/light_source - var/atom/owner - var/changed = 1 - var/list/effect = list() - var/__x = 0 // x coordinate at last update - var/__y = 0 // y coordinate at last update - var/__z = 0 // z coordinate at last update - - var/_l_color // do not use directly, only used as reference for updating - var/col_r - var/col_g - var/col_b - - -/datum/light_source/New(atom/A) - if(!istype(A)) - CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.") - ..() - owner = A - readrgb(owner.l_color) - __x = owner.x - __y = owner.y - __z = owner.z - // the lighting object maintains a list of all light sources - SSlighting.lights += src - - -//Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one -/datum/light_source/proc/check() - if(!owner) - remove_effect() - return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it. - // check to see if we've moved since last update - if(owner.x != __x || owner.y != __y || owner.z != __z) - __x = owner.x - __y = owner.y - __z = owner.z - changed = 1 - - if (owner.l_color != _l_color) - changed = 1 - - if(changed) - changed = 0 - remove_effect() - return add_effect() - return 0 - - -/datum/light_source/proc/remove_effect() - // before we apply the effect we remove the light's current effect. - for(var/turf/T in effect) // negate the effect of this light source - T.update_lumcount(-effect[T], col_r, col_g, col_b, 1) - effect.len = 0 // clear the effect list - -/datum/light_source/proc/add_effect() - // only do this if the light is turned on and is on the map - if(owner.loc && owner.luminosity > 0) - readrgb(owner.l_color) - effect = list() - for(var/turf/T in view(owner.get_light_range(), get_turf(owner))) - var/delta_lumen = lum(T) - if(delta_lumen > 0) - effect[T] = delta_lumen - T.update_lumcount(delta_lumen, col_r, col_g, col_b, 0) - - return 0 - else - owner.light = null - return 1 //cause the light to be removed from the lights list and garbage collected once it's no - //longer referenced by the queue - - -/datum/light_source/proc/lum(turf/A) - if (owner.trueLuminosity < 1) - return 0 - var/dist - if(!A) - dist = 0 - else -#ifdef USE_CIRCULAR_LIGHTING - dist = cheap_hypotenuse(A.x, A.y, __x, __y) -#else - dist = max(abs(A.x - __x), abs(A.y - __y)) -#endif - if (owner.trueLuminosity > 100) // This will never happen... right? - return sqrt(owner.trueLuminosity) - dist - else - return sqrtTable[owner.trueLuminosity] - dist - -/datum/light_source/proc/readrgb(const/col) - /*if(!configuration.colour_lights) - col_r = 255 - col_g = 255 - col_g = 255 */ -// else - _l_color = col - - if(col) - col_r = GetRedPart(col) - col_g = GetGreenPart(col) - col_b = GetBluePart(col) - else - col_r = null - - - -/atom - var/datum/light_source/light - var/trueLuminosity = 0 // Typically 'luminosity' squared. The builtin luminosity must remain linear. - // We may read it, but NEVER set it directly. - var/l_color - -//Turfs with opacity when they are constructed will trigger nearby lights to update -//Turfs and atoms with luminosity when they are constructed will create a light_source automatically -/turf/New() - ..() - if(luminosity) - if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.") - trueLuminosity = luminosity * luminosity - light = new(src) - -//Movable atoms with opacity when they are constructed will trigger nearby lights to update -//Movable atoms with luminosity when they are constructed will create a light_source automatically -atom/movable/New() - ..() - if(opacity) - if(isturf(loc)) - if(loc:lighting_lumcount > 1) - UpdateAffectingLights() - if(luminosity) - if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.") - trueLuminosity = luminosity * luminosity - light = new(src) -//Objects with opacity will trigger nearby lights to update at next lighting process. -/atom/movable/Destroy() - if(opacity) - UpdateAffectingLights() - return ..() - -//Sets our luminosity. -//If we have no light it will create one. -//If we are setting luminosity to 0 the light will be cleaned up by the controller and garbage collected once all its -//queues are complete. -//if we have a light already it is merely updated, rather than making a new one. -atom/proc/SetLuminosity(new_luminosity, trueLum = FALSE) - if(new_luminosity < 0) - new_luminosity = 0 - if(!trueLum) - new_luminosity *= new_luminosity - if(light) - if(trueLuminosity != new_luminosity) //non-luminous lights are removed from the lights list in add_effect() - light.changed = 1 - else - if(new_luminosity) - light = new(src) - trueLuminosity = new_luminosity - if (trueLuminosity < 1) - luminosity = 0 - else if (trueLuminosity <= 100) - luminosity = sqrtTable[trueLuminosity] - else - luminosity = sqrt(trueLuminosity) - -atom/proc/AddLuminosity(delta_luminosity) - if(delta_luminosity > 0) - SetLuminosity(trueLuminosity + delta_luminosity*delta_luminosity, TRUE) - else if(delta_luminosity < 0) - SetLuminosity(trueLuminosity - delta_luminosity*delta_luminosity, TRUE) - - -area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas - luminosity = !!new_luminosity - trueLuminosity = luminosity - - -//change our opacity (defaults to toggle), and then update all lights that affect us. -/atom/proc/SetOpacity(new_opacity) - if(new_opacity == null) - new_opacity = !opacity //default = toggle opacity - else if(opacity == new_opacity) - return 0 //opacity hasn't changed! don't bother doing anything - opacity = new_opacity //update opacity, the below procs now call light updates. - return 1 - -/turf/SetOpacity(new_opacity) - if(..()==1) //only bother if opacity changed - if(lighting_lumcount) //only bother with an update if our turf is currently affected by a light - UpdateAffectingLights() - -/atom/movable/SetOpacity(new_opacity) - if(..()==1) //only bother if opacity changed - if(isturf(loc)) //only bother with an update if we're on a turf - var/turf/T = loc - if(T.lighting_lumcount) //only bother with an update if our turf is currently affected by a light - UpdateAffectingLights() - -turf - var/lighting_lumcount = 0 - var/lighting_changed = 0 - var/color_lighting_lumcount = 0 - - var/lumcount_r = 0 - var/lumcount_g = 0 - var/lumcount_b = 0 - var/light_col_sources = 0 - - -/turf/space - lighting_lumcount = 4 //starlight -/* -/turf/proc/update_lumcount(amount) - lighting_lumcount += amount - if(!lighting_changed) - SSlighting.changed_turfs += src - lighting_changed = 1 -*/ -/turf/proc/update_lumcount(amount, col_r, col_g, col_b, removing = 0) - lighting_lumcount += amount - - if(!isnull(col_r)) //col_r is the "key" var, if it's null so will the rest - if(removing) - light_col_sources-- - lumcount_r -= col_r - lumcount_g -= col_g - lumcount_b -= col_b - else - light_col_sources++ - lumcount_r += col_r - lumcount_g += col_g - lumcount_b += col_b - - if(light_col_sources) - var/r_avg = Clamp(round(lumcount_r / light_col_sources, 16) + 15, 0, 255) - var/g_avg = Clamp(round(lumcount_g / light_col_sources, 16) + 15, 0, 255) - var/b_avg = Clamp(round(lumcount_b / light_col_sources, 16) + 15, 0, 255) - l_color = rgb(r_avg, g_avg, b_avg) - else - l_color = null - - color_lighting_lumcount = max(color_lighting_lumcount + amount, 0) // Minimum of 0. - - if(!lighting_changed) - SSlighting.changed_turfs += src - lighting_changed = 1 -/* - -/area/proc/lighting_tag(level) - return tagbase + "sd_L[level]" -*/ -/turf/proc/lighting_tag(const/level) - var/area/A = loc - return A.tagbase + "sd_L[level]" - -/turf/proc/build_lighting_area(const/tag, const/level, const/color_light) - var/area/Area = loc - var/area/A = new Area.type() // create area if it wasn't found - // replicate vars - for(var/V in Area.vars) - switch(V) - if ("contents","lighting_overlay", "color_overlay", "overlays") - continue - else - if(issaved(Area.vars[V])) A.vars[V] = Area.vars[V] - - A.tag = tag - A.lighting_subarea = 1 - A.lighting_space = 0 // in case it was copied from a space subarea - - if (l_color != A.l_color) - A.l_color = l_color - //color_light = min(max(round(color_lighting_lumcount, 1), 0), lighting_controller.lighting_states) - //world << "[color_light] [color_lighting_lumcount]" - - A.SetLightLevel(level, color_light) - Area.related += A - return A - -/* -/area/proc/build_lighting_area(tag, level) - var/area/A = locate(tag) // find an appropriate area - if(A) - return A - A = new type() // create area if it wasn't found - // replicate vars - for(var/V in vars) - switch(V) - if("contents","last_light","overlays") continue - else - if(issaved(vars[V])) A.vars[V] = vars[V] - - A.tag = tag - A.lighting_subarea = 1 - A.lighting_space = 0 // in case it was copied from a space subarea - A.SetLightLevel(level) - - related += A - return A -*/ - -turf/proc/shift_to_subarea() - lighting_changed = 0 - var/area/Area = loc - if(!istype(Area) || !Area.lighting_use_dynamic) return - var/level = Clamp(round(lighting_lumcount, 1), 0, SSlighting.lighting_states) - var/new_tag = lighting_tag(level) - // pomf - If we have a lighting color that is not null, apply the new tag to seperate the areas. - if (l_color) - // pomf - We append the (rounded!) color lighting lumcount so we can have colored lights. - new_tag += "[l_color][Clamp(round(color_lighting_lumcount, 1), 0, SSlighting.lighting_states)]" - - if(Area.tag != new_tag) //skip if already in this area - var/area/A = locate(new_tag) // find an appropriate area - var/color_light = Clamp(round(color_lighting_lumcount, 1), 0, SSlighting.lighting_states) - - if(!A) - A = build_lighting_area(new_tag, level, color_light) - else if(l_color != A.l_color) - A.l_color = l_color - A.SetLightLevel(level, color_light) - - A.contents += src // move the turf into the area - universe.OnTurfTick(src) - - -// Dedicated lighting sublevel for space turfs -// helps us depower things in space, remove space fire alarms, -// and evens out space lighting -turf/space/lighting_tag(var/level) - var/area/A = loc - return A.tagbase + "sd_L_space" -turf/space/build_lighting_area(var/tag,var/level) - var/area/A = ..(tag,4) - A.lighting_space = 1 - A.SetLightLevel(4) - A.icon_state = null - return A - -/area - var/lighting_use_dynamic = 1 //Turn this flag off to prevent sd_DynamicAreaLighting from affecting this area - var/image/lighting_overlay //tracks the darkness image of the area for easy removal - var/lighting_subarea = 0 //tracks whether we're a lighting sub-area - var/lighting_space = 0 // true for space-only lighting subareas - var/tagbase - var/image/color_overlay //Tracks the color image. - -/area/proc/SetLightLevel(light, color_light = 0) - if(!src) return - if(light <= 0) - light = 0 - luminosity = 0 - else - if(light > SSlighting.lighting_states) - light = SSlighting.lighting_states - luminosity = 1 - - if(lighting_overlay) - overlays -= lighting_overlay - lighting_overlay.icon_state = "[light]" - else - lighting_overlay = image(LIGHTING_ICON,,num2text(light),LIGHTING_LAYER) - - if (color_overlay) - overlays.Remove(color_overlay) - color_overlay.icon_state = "white" - else - if (l_color) - color_overlay = image('icons/obj/weapons.dmi', ,"white", 10.1) - - if (istype(color_overlay)) - color_overlay.color = l_color - - - - if (1) - switch (color_light) - if (6) - color_overlay.alpha = 180 - if (5) - color_overlay.alpha = 140 - if (4) - color_overlay.alpha = 120 - if (3) - color_overlay.alpha = 80 - if (2) - color_overlay.alpha = 60 - if (1) - color_overlay.alpha = 20 - if (-INFINITY to 0) - //world << "Zero or below, [color_light]." - color_overlay.alpha = 0 - else - //world << "Setting the alpha to max... color_light [color_light]." - color_overlay.alpha = 180 - - color_overlay.blend_mode = BLEND_ADD - - if (color_overlay.color) - overlays.Add(color_overlay) - - if (isnull(color_overlay)) - overlays.Add(lighting_overlay) - else if (light < 6) - overlays.Add(lighting_overlay) - -/area/proc/SetDynamicLighting() - src.lighting_use_dynamic = 1 - for(var/turf/T in src.contents) - T.update_lumcount(0) - -/area/proc/InitializeLighting() //TODO: could probably improve this bit ~Carn - tagbase = "[type]" - if(!tag) tag = tagbase - if(!lighting_use_dynamic) - if(!lighting_subarea) // see if this is a lighting subarea already - //show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly. - SetLightLevel(4) - -/* -/area/proc/SetLightLevel(light) - if(!src) return - if(light <= 1) - light = 1 - luminosity = 0 - else - if(light > SSlighting.lighting_images.len) - light = SSlighting.lighting_images.len - luminosity = 1 - - if(last_light != light) - if(last_light) - overlays -= SSlighting.lighting_images[last_light] - overlays += SSlighting.lighting_images[light] - last_light = light - -/area/proc/SetDynamicLighting() - lighting_use_dynamic = 1 - for(var/turf/T in contents) - T.update_lumcount(0) - -/area/proc/InitializeLighting() //TODO: could probably improve this bit ~Carn - tagbase = "[type]" - if(!tag) tag = tagbase - if(!lighting_use_dynamic) - if(!lighting_subarea) // see if this is a lighting subarea already - //show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly. - SetLightLevel(4) -*/ -#undef USE_CIRCULAR_LIGHTING - -//set the changed status of all lights which could have possibly lit this atom. -//We don't need to worry about lights which lit us but moved away, since they will have change status set already -//This proc can cause lots of lights to be updated. :( -/* -/atom/proc/UpdateAffectingLights() - -/atom/movable/UpdateAffectingLights() - if(isturf(loc)) - loc.UpdateAffectingLights() - -/turf/UpdateAffectingLights() - if(affecting_lights) - for(var/thing in affecting_lights) - thing:changed = 1 //force it to update at next process() -*/ - -#define LIGHTING_MAX_LUMINOSITY_STATIC 8 //Maximum luminosity to reduce lag. -#define LIGHTING_MAX_LUMINOSITY_MOBILE 5 //Moving objects have a lower max luminosity since these update more often. (lag reduction) -#define LIGHTING_MAX_LUMINOSITY_MOB 5 -#define LIGHTING_MAX_LUMINOSITY_TURF 1 //turfs have a severely shortened range to protect from inevitable floor-lighttile spam. - -//caps luminosity effects max-range based on what type the light's owner is. -/atom/proc/UpdateAffectingLights() - for(var/atom/A in oview(LIGHTING_MAX_LUMINOSITY_STATIC-1,src)) - if(A.light) - A.light.changed = 1 //force it to update at next process() - -/atom/proc/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC) - -/atom/movable/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_MOBILE) - -/mob/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_MOB) - -/obj/machinery/light/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC) - -/turf/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_TURF) - -#undef LIGHTING_MAX_LUMINOSITY_STATIC -#undef LIGHTING_MAX_LUMINOSITY_MOBILE -#undef LIGHTING_MAX_LUMINOSITY_MOB -#undef LIGHTING_MAX_LUMINOSITY_TURF diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 75bb3cbb799b0..147033cc7f9f3 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -188,3 +188,9 @@ var/datum/subsystem/garbage_collector/SSgarbage garbage.destroyed.Cut(1, 2) #endif +/proc/qdeleted(var/datum/A) + if (!istype(A)) + return 0 + if (A.gc_destroyed) + return 1 + return 0 \ No newline at end of file diff --git a/code/controllers/subsystem/pipenets.dm b/code/controllers/subsystem/pipenets.dm deleted file mode 100644 index eb0c3fa563982..0000000000000 --- a/code/controllers/subsystem/pipenets.dm +++ /dev/null @@ -1,36 +0,0 @@ -var/datum/subsystem/pipenets/SSpipe - -/datum/subsystem/pipenets - name = "Pipenets" - priority = 11 - - var/list/networks = list() - -/datum/subsystem/pipenets/New() - NEW_SS_GLOBAL(SSpipe) - -/datum/subsystem/pipenets/Initialize() - set background = BACKGROUND_ENABLED - - //is it possible to combine all these procs into initialize() ?? - for(var/obj/machinery/atmospherics/M in world) - M.build_network() - - for(var/obj/machinery/atmospherics/unary/U in world) - if(istype(U, /obj/machinery/atmospherics/unary/vent_pump)) - var/obj/machinery/atmospherics/unary/vent_pump/V = U - V.broadcast_status() - else if(istype(U, /obj/machinery/atmospherics/unary/vent_scrubber)) - var/obj/machinery/atmospherics/unary/vent_scrubber/V = U - V.broadcast_status() - - ..() - -/datum/subsystem/pipenets/fire() - var/i=1 - for(var/thing in networks) - if(thing) - thing:process() - ++i - continue - networks.Cut(i, i+1) diff --git a/code/controllers/subsystem/power.dm b/code/controllers/subsystem/power.dm deleted file mode 100644 index e48a6f465e88c..0000000000000 --- a/code/controllers/subsystem/power.dm +++ /dev/null @@ -1,18 +0,0 @@ -var/datum/subsystem/power/SSpower - -/datum/subsystem/power - name = "Power" - priority = 10 - - var/list/powernets = list() - -/datum/subsystem/power/New() - NEW_SS_GLOBAL(SSpower) - -/datum/subsystem/power/Initialize() - makepowernets() - ..() - -/datum/subsystem/power/fire() - for(var/datum/powernet/Powernet in powernets) - Powernet.reset() \ No newline at end of file diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm new file mode 100644 index 0000000000000..6c2834a081f07 --- /dev/null +++ b/code/controllers/subsystem/timer.dm @@ -0,0 +1,71 @@ +var/datum/subsystem/timer/SStimer + +/datum/subsystem/timer + name = "Timer" + wait = 5 + priority = 1 + + var/list/datum/timedevent/processing + + +/datum/subsystem/timer/New() + NEW_SS_GLOBAL(SStimer) + processing = list() + + +/datum/subsystem/timer/stat_entry(msg) + ..("P:[processing.len]") + +/datum/subsystem/timer/fire() + if (!processing.len) + can_fire = 0 //nothing to do, lets stop firing. + return + for (var/datum/timedevent/event in processing) + // hacky i know, but its the only way to ensure this works with clients + if (!event.thingToCall || qdeleted(event.thingToCall)) + qdel(event) + if (event.timeToRun <= world.time) + spawn(-1) + call(event.thingToCall,event.procToCall)(arglist(event.argList)) + qdel(event) + +/datum/timedevent + var/thingToCall + var/procToCall + var/timeToRun + var/argList + var/id + var/static/nextid = 1 + +/datum/timedevent/New() + id = nextid + nextid++ + +/datum/timedevent/Destroy() + SStimer.processing -= src + +/proc/addtimer(var/thingToCall, var/procToCall, var/wait, var/argList = list()) + if (!SStimer) //can't run timers before the mc has been created + return + if (!thingToCall || !procToCall || wait <= 0) + return + if (!SStimer.can_fire) + SStimer.can_fire = 1 + SStimer.next_fire = world.time + SStimer.wait + + var/datum/timedevent/event = new() + event.thingToCall = thingToCall + event.procToCall = procToCall + event.timeToRun = world.time + wait + event.argList = argList + + SStimer.processing += event + + return event.id + +/proc/deltimer(var/id) + for (var/datum/timedevent/event in SStimer.processing) + if (event.id == id) + qdel(event) + return 1 + return 0 \ No newline at end of file diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 37918aa4daaae..cf1a731ffc125 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -47,7 +47,8 @@ var/global/floorIsLava = 0 body += "Ban | " body += "Jobban | " body += "Identity Ban | " - body += "Notes " + body += "Notes | " + body += "Watchlist Flag " if(M.client) body += "| Prison | " diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 7ee7b04663956..7969a96c37017 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -6,6 +6,24 @@ log_admin("[key_name(usr)] tried to use the admin panel without authorization.") return + if(href_list["rejectadminhelp"]) + if(!check_rights(R_ADMIN)) + return + var/client/C = locate(href_list["rejectadminhelp"]) + if(!C) + return + if (deltimer(C.adminhelptimerid)) + C.giveadminhelpverb() + + C << 'sound/effects/adminhelp.ogg' + + C << "- AdminHelp Rejected! -" + C << "Your admin help was rejected. The adminhelp verb has been returned to you so that you may try again" + C << "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting." + + message_admins("[key_name_admin(usr)] Rejected [C.key]'s admin help. [C.key]'s Adminhelp verb has been returned to them") + log_admin("[key_name(usr)] Rejected [C.key]'s admin help") + if(href_list["makeAntag"]) switch(href_list["makeAntag"]) if("1") @@ -1055,6 +1073,65 @@ alert(usr,"This ban has already been lifted / does not exist.","Error","Ok") unjobbanpanel() + //Watchlist + else if(href_list["watchlist"]) + if(!check_rights(R_ADMIN)) return + var/mob/M = locate(href_list["watchlist"]) + if(!dbcon.IsConnected()) + usr << "Failed to establish database connection." + return + if(!ismob(M)) + usr << "This can only be used on instances of type /mob" + return + if(!M.ckey) + usr << "This mob has no ckey" + return + var/sql_ckey = sanitizeSQL(M.ckey) + var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')") + query.Execute() + if(query.NextRow()) + switch(alert(usr, "Ckey already flagged", "[sql_ckey] is already on the watchlist, do you want to:", "Remove", "Edit reason", "Cancel")) + if("Cancel") + return + if("Remove") + var/DBQuery/query_watchdel = dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[sql_ckey]'") + if(!query_watchdel.Execute()) + var/err = query_watchdel.ErrorMsg() + log_game("SQL ERROR during removing watch entry. Error : \[[err]\]\n") + return + log_admin("[key_name_admin(usr)] has removed [key_name_admin(M)] from the watchlist") + message_admins("[key_name_admin(usr)] has removed [key_name_admin(M)] from the watchlist", 1) + if("Edit reason") + var/DBQuery/query_reason = dbcon.NewQuery("SELECT ckey, reason FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')") + query_reason.Execute() + if(query_reason.NextRow()) + var/watch_reason = query_reason.item[3] + var/new_reason = input("Insert new reason", "New Reason", "[watch_reason]", null) as null|text + new_reason = sanitizeSQL(new_reason) + if(!new_reason) + return + var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]', edits = CONCAT(edits,'- [usr] changed watchlist reason from \\\"[watch_reason]\\\" to \\\"[new_reason]\\\"
') WHERE (ckey = '[sql_ckey]')") + if(!update_query.Execute()) + var/err = update_query.ErrorMsg() + log_game("SQL ERROR during edit watch entry reason. Error : \[[err]\]\n") + return + log_admin("[key_name_admin(usr)] has edited [sql_ckey]'s reason from [watch_reason] to [new_reason]",1) + message_admins("[key_name_admin(usr)] has edited [sql_ckey]'s reason from [watch_reason] to [new_reason]",1) + else + var/reason = input(usr,"Reason?","reason","Metagaming") as text|null + if(!reason) + return + reason = sanitizeSQL(reason) + var/DBQuery/query_watchadd = dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason) VALUES ('[sql_ckey]', '[reason]')") + if(!query_watchadd.Execute()) + var/err = query_watchadd.ErrorMsg() + log_game("SQL ERROR during adding new watch entry. Error : \[[err]\]\n") + return + log_admin("[key_name_admin(usr)] has added [key_name_admin(M)] to the watchlist - Reason: [reason]") + message_admins("[key_name_admin(usr)] has added [key_name_admin(M)] to the watchlist - Reason: [reason]", 1) + + + else if(href_list["mute"]) if(!check_rights(R_ADMIN)) return cmd_admin_mute(href_list["mute"], text2num(href_list["mute_type"])) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 0d0c853ee9ac4..2e707e09f0a5b 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -1,4 +1,8 @@ +/client/var/adminhelptimerid = 0 +/client/proc/giveadminhelpverb() + src.verbs |= /client/verb/adminhelp + adminhelptimerid = 0 //This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE! var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as") @@ -20,8 +24,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," //remove out adminhelp verb temporarily to prevent spamming of admins. src.verbs -= /client/verb/adminhelp - spawn(1200) - src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps + adminhelptimerid = addtimer(src,"giveadminhelpverb",1200) //2 minute cooldown of admin helps //clean the input msg if(!msg) return @@ -85,8 +88,9 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(!mob) return //this doesn't happen var/ref_mob = "\ref[mob]" - msg = "HELP: [key_name_admin(src)] (?) (PP) (VV) (SM) (FLW) (TP) [ai_found ? " (CL)" : ""]: [msg]" + var/ref_client = "\ref[src]" + msg = "HELP: [key_name_admin(src)] (?) (PP) (VV) (SM) (FLW) (TP)[ai_found ? " (CL)" : ""] (REJT): [msg]" //send this msg to all admins for(var/client/X in admins) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index a155a4f243302..7470bf1a5126d 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -229,6 +229,12 @@ var/next_external_rsc = 0 while (query_cid.NextRow()) related_accounts_cid += "[query_cid.item[1]], " + var/DBQuery/query_watch = dbcon.NewQuery("SELECT ckey, reason FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')") + query_watch.Execute() + if(query_watch.NextRow()) + message_admins("Notice: [key_name_admin(src)] is flagged for watching and has just connected - Reason: [query_watch.item[2]]") + send2irc_adminless_only("Watchlist", "[key_name_admin(src)] is flagged for watching and has just connected - Reason: [query_watch.item[2]]") + var/admin_rank = "Player" if (src.holder && src.holder.rank) diff --git a/tgstation.dme b/tgstation.dme index 90638d09a0376..17f0c85f30ebf 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -194,6 +194,7 @@ #include "code\controllers\subsystem\shuttles.dm" #include "code\controllers\subsystem\sun.dm" #include "code\controllers\subsystem\ticker.dm" +#include "code\controllers\subsystem\timer.dm" #include "code\controllers\subsystem\voting.dm" #include "code\controllers\subsystem\shuttles\emergency.dm" #include "code\controllers\subsystem\shuttles\supply.dm"