diff --git a/code/ATMOSPHERICS/he_pipes.dm b/code/ATMOSPHERICS/he_pipes.dm index 15774f99c2f..0f9a38b09b3 100644 --- a/code/ATMOSPHERICS/he_pipes.dm +++ b/code/ATMOSPHERICS/he_pipes.dm @@ -54,11 +54,11 @@ if(target.initialize_directions_he & get_dir(target,src)) node2 = target break - + if(!node1 && !node2) del(src) return - + update_icon() return @@ -105,10 +105,10 @@ if(target.initialize_directions_he & get_dir(target,src)) node2 = target break - + if(!node1 && !node2) - del(src) - return + qdel(src) + return update_icon() return diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index 2a143c80c51..b303d7d31f4 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -55,9 +55,10 @@ return parent.return_network(reference) -/obj/machinery/atmospherics/pipe/Del() + +/obj/machinery/atmospherics/pipe/Destroy() del(parent) - if(air_temporary) + if(air_temporary && loc) loc.assume_air(air_temporary) ..() @@ -70,7 +71,7 @@ if(istype(W,/obj/item/device/pipe_painter)) return 0 - + if (istype(W, /obj/item/device/pipe_freezer)) if(!src.frozen) // If the pipe is not already frozen user << "\red You begin to freeze the [src]" @@ -88,7 +89,7 @@ "You hear dripping water.") add_fingerprint(user) - return 1 + return 1 if (!istype(W, /obj/item/weapon/wrench)) return ..() @@ -96,7 +97,7 @@ if (level==1 && isturf(T) && T.intact) user << "\red You must remove the plating first." return 1 - + var/datum/gas_mixture/int_air = return_air() var/datum/gas_mixture/env_air = loc.return_air() if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE) @@ -129,7 +130,7 @@ /* /obj/machinery/atmospherics/pipe/add_underlay(var/obj/machinery/atmospherics/node, var/direction) - if(istype(src, /obj/machinery/atmospherics/pipe/tank)) //todo: move tanks to unary devices + if(istype(src, /obj/machinery/atmospherics/pipe/tank)) //todo: move tanks to unary devices return ..() if(node) @@ -182,7 +183,7 @@ /obj/machinery/atmospherics/pipe/simple/New() ..() - + // Pipe colors and icon states are handled by an image cache - so color and icon should // be null. For mapping purposes color is defined in the object definitions. icon = null @@ -242,7 +243,7 @@ else if(dir==12) dir = 4 -/obj/machinery/atmospherics/pipe/simple/Del() +/obj/machinery/atmospherics/pipe/simple/Destroy() if(node1) node1.disconnect(src) if(node2) @@ -276,7 +277,7 @@ if (meter.target == src) new /obj/item/pipe_meter(T) del(meter) - del(src) + qdel(src) else if(node1 && node2) overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, pipe_icon + "intact" + icon_connect_type) else @@ -313,9 +314,9 @@ src.connected_to = c node2 = target break - + if(!node1 && !node2) - del(src) + qdel(src) return var/turf/T = get_turf(src) @@ -359,7 +360,7 @@ layer = 2.39 icon_connect_type = "-supply" color = PIPE_COLOR_BLUE - + /obj/machinery/atmospherics/pipe/simple/visible/yellow color = PIPE_COLOR_YELLOW @@ -394,7 +395,7 @@ layer = 2.39 icon_connect_type = "-supply" color = PIPE_COLOR_BLUE - + /obj/machinery/atmospherics/pipe/simple/visible/universal name="Universal pipe adapter" desc = "An adapter for regular, supply and scrubbers pipes" @@ -567,7 +568,7 @@ else . = PROCESS_KILL -/obj/machinery/atmospherics/pipe/manifold/Del() +/obj/machinery/atmospherics/pipe/manifold/Destroy() if(node1) node1.disconnect(src) if(node2) @@ -620,19 +621,19 @@ if (meter.target == src) new /obj/item/pipe_meter(T) del(meter) - del(src) + qdel(src) else overlays.Cut() overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type) overlays += icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type) underlays.Cut() - + var/turf/T = get_turf(src) var/list/directions = list(NORTH, SOUTH, EAST, WEST) var/node1_direction = get_dir(src, node1) var/node2_direction = get_dir(src, node2) var/node3_direction = get_dir(src, node3) - + directions -= dir directions -= add_underlay(T,node1,node1_direction,icon_connect_type) @@ -692,7 +693,7 @@ break if (node3) break - + if(!node1 && !node2 && !node3) del(src) return @@ -804,7 +805,7 @@ else . = PROCESS_KILL -/obj/machinery/atmospherics/pipe/manifold4w/Del() +/obj/machinery/atmospherics/pipe/manifold4w/Destroy() if(node1) node1.disconnect(src) if(node2) @@ -866,13 +867,13 @@ if (meter.target == src) new /obj/item/pipe_meter(T) del(meter) - del(src) + qdel(src) else overlays.Cut() overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type) overlays += icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type) underlays.Cut() - + /* var/list/directions = list(NORTH, SOUTH, EAST, WEST) @@ -884,7 +885,7 @@ for(var/D in directions) add_underlay(,D) */ - + var/turf/T = get_turf(src) var/list/directions = list(NORTH, SOUTH, EAST, WEST) var/node1_direction = get_dir(src, node1) @@ -948,7 +949,7 @@ src.connected_to = c node4 = target break - + if(!node1 && !node2 && !node3&& !node4) del(src) return @@ -1059,7 +1060,7 @@ ..() else . = PROCESS_KILL -/obj/machinery/atmospherics/pipe/cap/Del() +/obj/machinery/atmospherics/pipe/cap/Destroy() if(node) node.disconnect(src) @@ -1176,7 +1177,7 @@ else . = PROCESS_KILL -/obj/machinery/atmospherics/pipe/tank/Del() +/obj/machinery/atmospherics/pipe/tank/Destroy() if(node1) node1.disconnect(src) @@ -1263,7 +1264,7 @@ air_temporary.oxygen = (25*ONE_ATMOSPHERE*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature) air_temporary.nitrogen = (25*ONE_ATMOSPHERE*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature) - ..() + ..() icon_state = "air" /obj/machinery/atmospherics/pipe/tank/oxygen @@ -1376,7 +1377,7 @@ else parent.mingle_with_turf(loc, volume) -/obj/machinery/atmospherics/pipe/vent/Del() +/obj/machinery/atmospherics/pipe/vent/Destroy() if(node1) node1.disconnect(src) diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index c18b0228338..9f555235c64 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -207,6 +207,8 @@ mob/airflow_hit(atom/A) for(var/mob/M in hearers(src)) M.show_message("\red \The [src] slams into \a [A]!",1,"\red You hear a loud slam!",2) playsound(src.loc, "smash.ogg", 25, 1, -1) + if(!(status_flags & CANSTUN) && !(status_flags & CANWEAKEN)) + return 0 weakened = max(weakened, (istype(A,/obj/item) ? A:w_class : rand(1,5))) //Heheheh . = ..() @@ -238,6 +240,9 @@ mob/living/carbon/human/airflow_hit(atom/A) blocked = run_armor_check("groin","melee") apply_damage(b_loss/3, BRUTE, "groin", blocked, 0, "Airflow") + if(!(status_flags & CANSTUN) && !(status_flags & CANWEAKEN)) + return 0 + if(airflow_speed > 10) paralysis += round(airflow_speed * vsc.airflow_stun) stunned = max(stunned,paralysis + 3) diff --git a/code/__HELPERS/experimental.dm b/code/__HELPERS/experimental.dm index 0966261563b..da9c2a17446 100644 --- a/code/__HELPERS/experimental.dm +++ b/code/__HELPERS/experimental.dm @@ -1,5 +1,5 @@ /* - * Experimental procs by ESwordTheCat. + * Experimental procs by ESwordTheCat! */ /* @@ -15,7 +15,7 @@ * -1, parameter B is not a char * -2, parameter A is not a string */ -/proc/EgijkAeN(const/A, const/B) +/proc/strpos(const/A, const/B) if (istext(A) == 0 || length(A) < 1) return -2 @@ -31,29 +31,24 @@ . = i i = findtext(A, B, i + 1) -/obj/machinery/proc/getArea() - var/area/A = loc.loc - - if (A != myArea) - myArea = A - - . = myArea - /** * Object pooling. * * If this file is named experimental, * well treat this implementation as experimental experimental (redundancy intended). * - * WARNING, only supports /mob and /obj. + * WARNING, only supports /atom/movable (/mob and /obj) */ // Uncomment to show debug messages. //#define DEBUG_OBJECT_POOL -#define MAINTAINING_OBJECT_POOL_COUNT 20 +#define MAINTAINING_OBJECT_POOL_COUNT 500 -var/list/masterPool = list() +var/global/list/masterPool = new + +// Read-only or compile-time vars and special exceptions. +var/list/exclude = list("inhand_states", "loc", "locs", "parent_type", "vars", "verbs", "type", "x", "y", "z") /* * @args @@ -62,27 +57,35 @@ var/list/masterPool = list() * * Example call: getFromPool(/obj/item/weapon/shard, loc) */ -/proc/getFromPool(const/A, const/B) - if (isnull(masterPool[A])) +/proc/getFromPool() + var/A = args[1] + var/list/B = list() + B += (args - A) + if(length(masterPool["[A]"]) <= 0) #ifdef DEBUG_OBJECT_POOL - world << "DEBUG_OBJECT_POOL: new proc has been called ([A])." + world << text("DEBUG_OBJECT_POOL: new proc has been called ([]).", A) #endif + //so the GC knows we're pooling this type. + if(isnull(masterPool["[A]"])) + masterPool["[A]"] = list(new A) + if(B && B.len) + return new A(arglist(B)) + else + return new A() - return new A(B) - - var/atom/movable/Object = masterPool[A][1] - masterPool[A] -= Object - var/objectLength = length(masterPool[A]) + var/atom/movable/O = masterPool["[A]"][1] + masterPool["[A]"] -= O #ifdef DEBUG_OBJECT_POOL - world << "DEBUG_OBJECT_POOL: getFromPool([A]) [objectLength] left." + world << text("DEBUG_OBJECT_POOL: getFromPool([]) [] left.", A, length(masterPool[A])) #endif - - if (!objectLength) - masterPool[A] = null - - Object.loc = B - return Object + if(!O || !istype(O)) + O = new A(arglist(B)) + else + if(length(B)) + O.loc = B[1] + O.New(arglist(B)) + return O /* * @args @@ -93,31 +96,26 @@ var/list/masterPool = list() * * Example call: returnToPool(src) */ -/proc/returnToPool(const/A) - if (!istype(A, /atom/movable)) - return -1 +/proc/returnToPool(const/atom/movable/AM) + if(istype(AM.loc,/mob/living)) + var/mob/living/L = AM.loc + L.unEquip(AM) + if(length(masterPool["[AM.type]"]) > MAINTAINING_OBJECT_POOL_COUNT) + #ifdef DEBUG_OBJECT_POOL + world << text("DEBUG_OBJECT_POOL: returnToPool([]) exceeds [] discarding...", AM.type, MAINTAINING_OBJECT_POOL_COUNT) + #endif - var/atom/movable/Object = A - Object.resetVariables() + qdel(AM, 1) + return - switch(length(masterPool[Object.type])) - if (MAINTAINING_OBJECT_POOL_COUNT to 1.#INF) - #ifdef DEBUG_OBJECT_POOL - world << "DEBUG_OBJECT_POOL: returnToPool([Object.type]) exceeds [num2text(MAINTAINING_OBJECT_POOL_COUNT)] discarding..." - #endif + if(isnull(masterPool["[AM.type]"])) + masterPool["[AM.type]"] = list() - return - if (0) // In a numeric context (like a mathematical operation), null evaluates to 0. - #ifdef DEBUG_OBJECT_POOL - world << "DEBUG_OBJECT_POOL: [Object.type] pool is empty, recreating pool." - #endif - - masterPool[Object.type] = list() - - masterPool[Object.type] += Object + AM.resetVariables() + masterPool["[AM.type]"] += AM #ifdef DEBUG_OBJECT_POOL - world << "DEBUG_OBJECT_POOL: returnToPool([Object.type]) [length(masterPool[Object.type])] left." + world << text("DEBUG_OBJECT_POOL: returnToPool([]) [] left.", AM.type, length(masterPool["[AM.type]"])) #endif #undef MAINTAINING_OBJECT_POOL_COUNT @@ -127,20 +125,48 @@ var/list/masterPool = list() #endif /* - * Override this if the object variables needed to reset. + * if you have a variable that needed to be preserve, override this and call .. * - * Example: see, code\game\objects\items\stacks\sheets\glass.dm - * @/obj/item/weapon/shard - * @resetVariables() + * example + * + * /obj/item/resetVariables() + * ..("var1", "var2", "var3") + * + * however, if the object has a child type an it has overridden resetVariables() + * this should be + * + * /obj/item/resetVariables() + * ..("var1", "var2", "var3", args) + * + * /obj/item/weapon/resetVariables() + * ..("var4") */ -/atom/movable - proc/resetVariables() - var/list/exclude = list("loc", "locs", "parent_type", "vars", "verbs", "type") // Read-only or compile-time vars and whatevs. - exclude += args // Explicit var exclusion - var/list/varsCopy = vars - exclude - var/key +/atom/movable/proc/resetVariables() + loc = null - for (key in varsCopy) - vars[key] = initial(vars[key]) + var/list/exclude = global.exclude + args // explicit var exclusion - vars["loc"] = null // Making sure the loc is null not a compile-time var value. + for(var/key in vars) + if(key in exclude) + continue + + vars[key] = initial(vars[key]) + +/proc/isInTypes(atom/Object, types) + var/prototype = Object.type + Object = null + + for (var/type in params2list(types)) + if (ispath(prototype, text2path(type))) + return 1 + + return 0 + + +/obj/machinery/proc/getArea() + var/area/A = loc.loc + + if (A != myArea) + myArea = A + + . = myArea \ No newline at end of file diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 3fbd6cde855..da2013e2e58 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -107,7 +107,7 @@ if(ismob(A)) changeNext_move(CLICK_CD_MELEE) UnarmedAttack(A, 1) - + return if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that @@ -126,7 +126,7 @@ if(ismob(A)) changeNext_move(CLICK_CD_MELEE) UnarmedAttack(A, 1) - + return else // non-adjacent click if(W) @@ -136,9 +136,9 @@ return -/mob/proc/changeNext_move(num) +/mob/proc/changeNext_move(num) next_move = world.time + num - + // Default behavior: ignore double clicks, consider them normal clicks instead /mob/proc/DblClickOn(var/atom/A, var/params) return @@ -344,21 +344,9 @@ if(available >= 5000000) L.damage = 205 if(L.damage >= 200) - apply_damage(15, BURN, (hand ? "l_hand" : "r_hand")) - //usr:Stun(15) - //usr:Weaken(15) - //if(usr:status_flags & CANSTUN) // stun is usually associated with stutter - // usr:stuttering += 20 time = 200 - src << "[G] overload from the massive current shocking you in the process!" else if(L.damage >= 100) - apply_damage(5, BURN, (hand ? "l_hand" : "r_hand")) - //usr:Stun(10) - //usr:Weaken(10) - //if(usr:status_flags & CANSTUN) // stun is usually associated with stutter - // usr:stuttering += 10 time = 150 - src << "[G] overload from the massive current shocking you in the process!" var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) s.start() diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 8f8058aa9e3..88894fa8b9c 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -404,7 +404,7 @@ if("Toggle Sensor Augmentation") if(isrobot(usr)) var/mob/living/silicon/robot/R = usr - R.control_hud() + R.sensor_mode() if("module1") if(istype(usr, /mob/living/silicon/robot)) @@ -551,7 +551,7 @@ if("Set Sensor Augmentation") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.control_hud() + AI.sensor_mode() // Alien if("night vision") diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 8722906def5..35e19f568a1 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -53,8 +53,6 @@ ///////////////////////// var/power = force - if(HULK in user.mutations) - power *= 2 if(!istype(M, /mob/living/carbon/human)) if(istype(M, /mob/living/carbon/slime)) diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index 5fb552d4384..46662142fba 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -108,7 +108,7 @@ var/const/tk_maxrange = 15 return var/d = get_dist(user, target) - if(focus) + if(focus) d = max(d,get_dist(user,focus)) // whichever is further if(d > tk_maxrange) user << "Your mind won't reach that far." @@ -163,7 +163,7 @@ var/const/tk_maxrange = 15 O.icon_state = "nothing" flick("empdisable",O) spawn(5) - O.delete() + qdel(O) return diff --git a/code/controllers/Processes/Shuttle.dm b/code/controllers/Processes/shuttle.dm similarity index 100% rename from code/controllers/Processes/Shuttle.dm rename to code/controllers/Processes/shuttle.dm diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm index 15e0b2e9c8f..7ed1a047a0d 100644 --- a/code/controllers/_DynamicAreaLighting_TG.dm +++ b/code/controllers/_DynamicAreaLighting_TG.dm @@ -160,14 +160,6 @@ atom/movable/New() trueLuminosity = luminosity * luminosity light = new(src) -//Objects with opacity will trigger nearby lights to update at next lighting process. -atom/movable/Destroy() - if(opacity) - if(isturf(loc)) - if(loc:lighting_lumcount > 1) - UpdateAffectingLights() - - ..() //Sets our luminosity. //If we have no light it will create one. diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 062a650c9ba..95ecef88978 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -134,12 +134,12 @@ var/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix var/default_laws = 0 //Controls what laws the AI spawns with. - + var/list/station_levels = list(1) // Defines which Z-levels the station exists on. var/list/admin_levels= list(2) // Defines which Z-levels which are for admin functionality, for example including such areas as Central Command and the Syndicate Shuttle var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect var/list/player_levels = list(1, 3, 4, 5, 6, 7) // Defines all Z-levels a character can typically reach - + var/const/minutes_to_ticks = 60 * 10 // Event settings var/expected_round_length = 60 * 2 * minutes_to_ticks // 2 hours @@ -168,7 +168,7 @@ src.probabilities[M.config_tag] = M.probability if (M.votable) src.votable_modes += M.config_tag - del(M) + qdel(M) src.votable_modes += "secret" /datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist @@ -209,9 +209,9 @@ if ("use_age_restriction_for_jobs") config.use_age_restriction_for_jobs = 1 - + if ("use_age_restriction_for_antags") - config.use_age_restriction_for_antags = 1 + config.use_age_restriction_for_antags = 1 if ("jobs_have_minimal_access") config.jobs_have_minimal_access = 1 @@ -462,7 +462,7 @@ if("max_maint_drones") config.max_maint_drones = text2num(value) - + if("station_levels") config.station_levels = text2numlist(value, ";") @@ -474,7 +474,7 @@ if("player_levels") config.player_levels = text2numlist(value, ";") - + if("expected_round_length") config.expected_round_length = MinutesToTicks(text2num(value)) diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm index ff46b6b10b6..a2a6274a8ab 100644 --- a/code/controllers/failsafe.dm +++ b/code/controllers/failsafe.dm @@ -1,68 +1,78 @@ -var/datum/controller/failsafe/Failsafe +var/global/datum/controller/failsafe/failsafe -/datum/controller/failsafe // This thing pretty much just keeps poking the master controller - var/processing = 0 - var/processing_interval = 100 //poke the MC every 10 seconds +/datum/controller/failsafe // This thing pretty much just keeps poking the controllers. + processing_interval = 100 // Poke the controllers every 10 seconds. - var/MC_iteration = 0 - var/MC_defcon = 0 //alert level. For every poke that fails this is raised by 1. When it reaches 5 the MC is replaced with a new one. (effectively killing any master_controller.process() and starting a new one) + /* + * Controller alert level. + * For every poke that fails this is raised by 1. + * When it reaches 5 the MC is replaced with a new one + * (effectively killing any controller process() and starting a new one). + */ - var/lighting_iteration = 0 - var/lighting_defcon = 0 //alert level for lighting controller. + // master + var/masterControllerIteration = 0 + var/masterControllerAlertLevel = 0 + + // lighting + var/lightingControllerIteration = 0 + var/lightingControllerAlertLevel = 0 /datum/controller/failsafe/New() - //There can be only one failsafe. Out with the old in with the new (that way we can restart the Failsafe by spawning a new one) - if(Failsafe != src) - if(istype(Failsafe)) - del(Failsafe) - Failsafe = src - Failsafe.process() + . = ..() + // There can be only one failsafe. Out with the old in with the new (that way we can restart the Failsafe by spawning a new one). + if (failsafe != src) + if (istype(failsafe)) + recover() + qdel(failsafe) + + failsafe = src + + failsafe.process() /datum/controller/failsafe/proc/process() processing = 1 + spawn(0) - //set background = 1 - while(1) //more efficient than recursivly calling ourself over and over. background = 1 ensures we do not trigger an infinite loop - if(!master_controller) new /datum/controller/game_controller() //replace the missing master_controller! This should never happen. - if(!lighting_controller) new /datum/controller/lighting() //replace the missing lighting_controller + set background = BACKGROUND_ENABLED + + while(1) // More efficient than recursivly calling ourself over and over. background = 1 ensures we do not trigger an infinite loop. + iteration++ if(processing) - if(master_controller.processing) //only poke if these overrides aren't in effect - if(MC_iteration == controller_iteration) //master_controller hasn't finished processing in the defined interval - switch(MC_defcon) + if(master_controller.processing) // Only poke if these overrides aren't in effect + if(masterControllerIteration == master_controller.iteration) // Master controller hasn't finished processing in the defined interval. + switch(masterControllerAlertLevel) if(0 to 3) - MC_defcon++ + masterControllerAlertLevel++ if(4) - admins << "Warning. The Master Controller has not fired in the last [MC_defcon*processing_interval] ticks. Automatic restart in [processing_interval] ticks." - MC_defcon = 5 + admins << "Warning. The master Controller has not fired in the last [masterControllerAlertLevel * processing_interval] ticks. Automatic restart in [processing_interval] ticks." + masterControllerAlertLevel = 5 if(5) - admins << "Warning. The Master Controller has still not fired within the last [MC_defcon*processing_interval] ticks. Killing and restarting..." - new /datum/controller/game_controller() //replace the old master_controller (hence killing the old one's process) - master_controller.process() //Start it rolling again - MC_defcon = 0 + admins << "Warning. The master Controller has still not fired within the last [masterControllerAlertLevel * processing_interval] ticks. Killing and restarting..." + new /datum/controller/game_controller() // Replace the old master controller (hence killing the old one's process). + master_controller.process() // Start it rolling again. + masterControllerAlertLevel = 0 else - MC_defcon = 0 - MC_iteration = controller_iteration + masterControllerAlertLevel = 0 + masterControllerIteration = master_controller.iteration if(lighting_controller.processing) - if(lighting_iteration == lighting_controller.iteration) //master_controller hasn't finished processing in the defined interval - switch(lighting_defcon) + if(lightingControllerIteration == lighting_controller.iteration) // Lighting controller hasn't finished processing in the defined interval. + switch(lightingControllerAlertLevel) if(0 to 3) - lighting_defcon++ + lightingControllerAlertLevel++ if(4) - admins << "Warning. The Lighting Controller has not fired in the last [lighting_defcon*processing_interval] ticks. Automatic restart in [processing_interval] ticks." - lighting_defcon = 5 + admins << "Warning. The lighting_controller controller has not fired in the last [lightingControllerAlertLevel * processing_interval] ticks. Automatic restart in [processing_interval] ticks." + lightingControllerAlertLevel = 5 if(5) - admins << "Warning. The Lighting Controller has still not fired within the last [lighting_defcon*processing_interval] ticks. Killing and restarting..." - new /datum/controller/lighting() //replace the old lighting_controller (hence killing the old one's process) - lighting_controller.process() //Start it rolling again - lighting_defcon = 0 + admins << "Warning. The lighting_controller controller has still not fired within the last [lightingControllerAlertLevel * processing_interval] ticks. Killing and restarting..." + new /datum/controller/lighting() // Replace the old lighting_controller (hence killing the old one's process). + lighting_controller.process() // Start it rolling again. + lightingControllerAlertLevel = 0 else - lighting_defcon = 0 - lighting_iteration = lighting_controller.iteration - else - MC_defcon = 0 - lighting_defcon = 0 + lightingControllerAlertLevel = 0 + lightingControllerIteration = lighting_controller.iteration - sleep(processing_interval) \ No newline at end of file + sleep(processing_interval) diff --git a/code/controllers/garbage.dm b/code/controllers/garbage.dm index 412a4bdef10..3c96126c0f1 100644 --- a/code/controllers/garbage.dm +++ b/code/controllers/garbage.dm @@ -1,124 +1,186 @@ +#define GC_COLLECTIONS_PER_TICK 300 // Was 100. +#define GC_COLLECTION_TIMEOUT (30 SECONDS) +#define GC_FORCE_DEL_PER_TICK 60 +//#define GC_DEBUG -#define GC_COLLECTIONS_PER_TICK 250 // Was 100 -#define GC_COLLECTION_TIMEOUT 100 // 10s -var/global/datum/controller/garbage_collector/garbage -var/global/list/uncollectable_vars=list( - "alpha", - "bestF", - "bounds", - "bound_height", - "bound_width", - "ckey", - "color", - "contents", - "gender", - "group", - "key", - //"loc", - "locs", - "luminosity", - "parent", - "parent_type", - "step_size", - "glide_size", - "gc_destroyed", - "step_x", - "step_y", - "step_z", - "tag", - "thermal_conductivity", - "type", - "vars", - "verbs", - "x", - "y", - "z", -) -/datum/controller/garbage_collector - var/list/queue=list() - var/list/destroyed=list() - var/waiting=0 - var/del_everything=1 - var/turf/trashbin=null +var/list/gc_hard_del_types = new +var/datum/garbage_collector/garbageCollector - New() - trashbin=locate(0,0,CENTCOMM_Z) +/client/proc/gc_dump_hdl() + set name = "(GC) Hard Del List" + set desc = "List types that are hard del()'d by the GC." + set category = "Debug" - proc/AddTrash(var/atom/movable/A) - if(!A) - return - if(del_everything) - del(A) - return - A.loc=trashbin - queue.Add(A) - waiting++ + for(var/A in gc_hard_del_types) + usr << "[A] = [gc_hard_del_types[A]]" - proc/Pop() - var/atom/movable/A = queue[1] - if(!A) - if(isnull(A)) - var/loopcheck = 0 - while(queue.Remove(null)) - loopcheck++ - if(loopcheck > 50) - break - return - if(del_everything) - del(A) - return - if(!istype(A,/atom/movable)) - testing("GC given a [A.type].") - del(A) - return - for(var/vname in A.vars) - if(!issaved(A.vars[vname])) - continue - if(vname in uncollectable_vars) - continue - //testing("Unsetting [vname] in [A.type]!") - A.vars[vname]=null - A.loc=null - destroyed.Add("\ref[A]") - queue.Remove(A) +/datum/garbage_collector + var/list/queue = new + var/del_everything = 0 - proc/process() - for(var/i=0;i= world.time - GC_COLLECTION_TIMEOUT) - // Something's still referring to the qdel'd object. Kill it. - del(A) - destroyed.Remove(refID) + // To let them know how hardworking am I :^). + var/dels_count = 0 + var/hard_dels = 0 + var/soft_dels = 0 -/** -* NEVER USE THIS FOR ANYTHING OTHER THAN /atom/movable -* OTHER TYPES CANNOT BE QDEL'D BECAUSE THEIR LOC IS LOCKED OR THEY DON'T HAVE ONE. -*/ -/proc/qdel(var/atom/movable/A) - if(!A) return - if(!istype(A)) - warning("qdel() passed object of type [A.type]. qdel() can only handle /atom/movable types.") - del(A) +/datum/garbage_collector/proc/addTrash(const/atom/movable/AM) + if(!istype(AM)) return - if(!garbage) - del(A) + + if(del_everything) + del(AM) + hard_dels++ + dels_count++ return - // Let our friend know they're about to get fucked up. - A.Destroy() - garbage.AddTrash(A) + + queue["\ref[AM]"] = world.timeofday + +/datum/garbage_collector/proc/process() + var/remainingCollectionPerTick = GC_COLLECTIONS_PER_TICK + var/remainingForceDelPerTick = GC_FORCE_DEL_PER_TICK + var/collectionTimeScope = world.timeofday - GC_COLLECTION_TIMEOUT + if(narsie_cometh) return //don't even fucking bother, its over. + while(queue.len && --remainingCollectionPerTick >= 0) + var/refID = queue[1] + var/destroyedAtTime = queue[refID] + + if(destroyedAtTime > collectionTimeScope) + break + + var/atom/movable/AM = locate(refID) + if(AM) // Something's still referring to the qdel'd object. del it. + if(isnull(AM.gcDestroyed)) + queue -= refID + continue + if(remainingForceDelPerTick <= 0) + break + + #ifdef GC_DEBUG + WARNING("gc process force delete [AM.type]") + #endif + + AM.hard_deleted = 1 + if(!AM.type in gc_hard_del_types) + gc_hard_del_types += AM.type + del AM + + hard_dels++ + remainingForceDelPerTick-- + +#ifdef GC_DEBUG +#undef GC_DEBUG +#endif + +#undef GC_FORCE_DEL_PER_TICK +#undef GC_COLLECTION_TIMEOUT +#undef GC_COLLECTIONS_PER_TICK + +/datum/garbage_collector/proc/dequeue(id) + if (queue) + queue -= id + + dels_count++ + +/* + * NEVER USE THIS FOR ANYTHING OTHER THAN /atom/movable + * OTHER TYPES CANNOT BE QDEL'D BECAUSE THEIR LOC IS LOCKED OR THEY DON'T HAVE ONE. + */ +/proc/qdel(const/atom/movable/AM, ignore_pooling = 0) + if(isnull(AM)) + return + + if(isnull(garbageCollector)) + del(AM) + return + + if(!istype(AM)) + WARNING("qdel() passed object of type [AM.type]. qdel() can only handle /atom/movable types.") + if(!AM.type in gc_hard_del_types) + gc_hard_del_types += AM.type + del(AM) + garbageCollector.hard_dels++ + garbageCollector.dels_count++ + return + + //We are object pooling this. + if(("[AM.type]" in masterPool) && !ignore_pooling) + returnToPool(AM) + return + + if(isnull(AM.gcDestroyed)) + // Let our friend know they're about to get fucked up. + AM.Destroy() + + garbageCollector.addTrash(AM) + +/datum/controller + var/processing = 0 + var/iteration = 0 + var/processing_interval = 0 + +/datum/controller/proc/recover() // If we are replacing an existing controller (due to a crash) we attempt to preserve as much as we can. + +/* + * Like Del(), but for qdel. + * Called BEFORE qdel moves shit. + */ +/datum/proc/Destroy() + del(src) /client/proc/qdel_toggle() set name = "Toggle qdel Behavior" set desc = "Toggle qdel usage between normal and force del()." set category = "Debug" - garbage.del_everything = !garbage.del_everything - world << "GC: qdel turned [garbage.del_everything?"off":"on"]." - log_admin("[key_name(usr)] turned qdel [garbage.del_everything?"off":"on"].") - message_admins("\blue [key_name(usr)] turned qdel [garbage.del_everything?"off":"on"].", 1) \ No newline at end of file + garbageCollector.del_everything = !garbageCollector.del_everything + world << "GC: qdel turned [garbageCollector.del_everything ? "off" : "on"]." + log_admin("[key_name(usr)] turned qdel [garbageCollector.del_everything ? "off" : "on"].") + message_admins("\blue [key_name(usr)] turned qdel [garbageCollector.del_everything ? "off" : "on"].", 1) + +/*/client/var/running_find_references + +/atom/verb/find_references() + set category = "Debug" + set name = "Find References" + set background = 1 + set src in world + + if(!usr || !usr.client) + return + + if(usr.client.running_find_references) + testing("CANCELLED search for references to a [usr.client.running_find_references].") + usr.client.running_find_references = null + return + + if(alert("Running this will create a lot of lag until it finishes. You can cancel it by running it again. Would you like to begin the search?", "Find References", "Yes", "No") == "No") + return + qdel(src) + // Remove this object from the list of things to be auto-deleted. + if(garbageCollector) + garbageCollector.queue -= "\ref[src]" + + usr.client.running_find_references = type + testing("Beginning search for references to a [type].") + var/list/things = list() + for(var/client/thing) + things += thing + for(var/datum/thing) + things += thing + for(var/atom/thing) + things += thing + for(var/event/thing) + things += thing + testing("Collected list of things in search for references to a [type]. ([things.len] Thing\s)") + for(var/datum/thing in things) + if(!usr.client.running_find_references) return + for(var/varname in thing.vars) + var/variable = thing.vars[varname] + if(variable == src) + testing("Found [src.type] \ref[src] in [thing.type]'s [varname] var.") + else if(islist(variable)) + if(src in variable) + testing("Found [src.type] \ref[src] in [thing.type]'s [varname] list var.") + testing("Completed search for references to a [type].") + usr.client.running_find_references = null +*/ \ No newline at end of file diff --git a/code/controllers/lighting_controller.dm b/code/controllers/lighting_controller.dm index c118fa43abb..a7decbc1185 100644 --- a/code/controllers/lighting_controller.dm +++ b/code/controllers/lighting_controller.dm @@ -1,10 +1,8 @@ var/datum/controller/lighting/lighting_controller = new () datum/controller/lighting - var/processing = 0 - var/processing_interval = 5 //setting this too low will probably kill the server. Don't be silly with it! + processing_interval = 5 //setting this too low will probably kill the server. Don't be silly with it! var/process_cost = 0 - var/iteration = 0 var/lighting_states = 7 @@ -21,7 +19,7 @@ datum/controller/lighting/New() if(lighting_controller != src) if(istype(lighting_controller,/datum/controller/lighting)) Recover() //if we are replacing an existing lighting_controller (due to a crash) we attempt to preserve as much as we can - del(lighting_controller) + qdel(lighting_controller) lighting_controller = src diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 518cfafd522..963e01b7260 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -11,7 +11,6 @@ var/global/air_processing_killed = 0 var/global/pipe_processing_killed = 0 datum/controller/game_controller - var/processing = 0 var/breather_ticks = 2 //a somewhat crude attempt to iron over the 'bumps' caused by high-cpu use by letting the MC have a breather for this many ticks after every loop var/minimum_ticks = 20 //The minimum length of time between MC ticks @@ -28,7 +27,7 @@ datum/controller/game_controller var/events_cost = 0 var/puddles_cost var/ticker_cost = 0 - var/gc_cost = 0 + var/garbageCollectorCost = 0 var/total_cost = 0 var/last_thing_processed @@ -36,13 +35,14 @@ datum/controller/game_controller var/list/shuttle_list // For debugging and VV var/datum/ore_distribution/asteroid_ore_map // For debugging and VV. + var/global/datum/garbage_collector/garbageCollector datum/controller/game_controller/New() //There can be only one master_controller. Out with the old and in with the new. if(master_controller != src) if(istype(master_controller)) Recover() - del(master_controller) + qdel(master_controller) master_controller = src if(!job_master) @@ -71,9 +71,6 @@ datum/controller/game_controller/proc/setup() ticker = new /datum/controller/gameticker() */ - if(!garbage) - garbage = new /datum/controller/garbage_collector() - color_windows_init() setup_objects() @@ -134,7 +131,7 @@ datum/controller/game_controller/proc/process() spawn(0) //set background = 1 while(1) //far more efficient than recursively calling ourself - if(!Failsafe) new /datum/controller/failsafe() + if(!failsafe) new /datum/controller/failsafe() if(processing) @@ -246,12 +243,12 @@ datum/controller/game_controller/proc/process() // GC timer = world.timeofday - last_thing_processed = garbage.type - garbage.process() - gc_cost = (world.timeofday - timer) / 10 + last_thing_processed = garbageCollector.type + garbageCollector.process() + garbageCollectorCost = (world.timeofday - timer) / 10 //TIMING - total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + aibots_cost + objects_cost + networks_cost + powernets_cost + nano_cost + events_cost + puddles_cost + ticker_cost + gc_cost + total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + aibots_cost + objects_cost + networks_cost + powernets_cost + nano_cost + events_cost + puddles_cost + ticker_cost + garbageCollectorCost var/end_time = world.timeofday if(end_time < start_time) //why not just use world.time instead? diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 20252b0403b..90e877b0443 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -49,7 +49,7 @@ return -/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras","Garbage", "Transfer Controller","Event")) +/client/proc/debug_controller(controller in list("Master","failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras","Garbage", "Transfer Controller","Event","Scheduler")) set category = "Debug" set name = "Debug Controller" set desc = "Debug the various periodic loop controllers for the game (be careful!)" @@ -59,18 +59,15 @@ if("Master") debug_variables(master_controller) feedback_add_details("admin_verb","DMC") - if("Failsafe") - debug_variables(Failsafe) - feedback_add_details("admin_verb","DFailsafe") + if ("failsafe") + debug_variables(failsafe) + feedback_add_details("admin_verb", "dfailsafe") if("Ticker") debug_variables(ticker) feedback_add_details("admin_verb","DTicker") if("Lighting") debug_variables(lighting_controller) feedback_add_details("admin_verb","DLighting") - if("Garbage") - debug_variables(garbage) - feedback_add_details("admin_verb","DGarbage") if("Air") debug_variables(air_master) feedback_add_details("admin_verb","DAir") @@ -103,7 +100,13 @@ feedback_add_details("admin_verb","DCameras") if("Event") debug_variables(event_manager) - feedback_add_details("admin_verb","DEvent") - + feedback_add_details("admin_verb","DEvent") + if("Garbage") + debug_variables(garbageCollector) + feedback_add_details("admin_verb","DGarbage") + if("Scheduler") + debug_variables(processScheduler) + feedback_add_details("admin_verb","DprocessScheduler") + message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") return diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index 9c19007f590..30ee4a99e43 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -17,7 +17,7 @@ datum/controller/vote New() if(vote != src) if(istype(vote)) - del(vote) + qdel(vote) vote = src proc/process() //called by master_controller diff --git a/code/datums/cargoprofile.dm b/code/datums/cargoprofile.dm index c2a5ed8bea1..36d4748cfc8 100644 --- a/code/datums/cargoprofile.dm +++ b/code/datums/cargoprofile.dm @@ -103,7 +103,7 @@ id = "boxes" blacklist = null whitelist = list(/obj/item/weapon/storage, /obj/item/weapon/moneybag, /obj/item/weapon/evidencebag, - /obj/item/weapon/tray, /obj/item/pizzabox, /obj/item/weapon/clipboard, + /obj/item/weapon/storage/bag/tray, /obj/item/pizzabox, /obj/item/weapon/clipboard, /obj/item/smallDelivery, /obj/structure/bigDelivery) /datum/cargoprofile/cargo @@ -270,7 +270,7 @@ /obj/item/weapon/hand_labeler,/obj/item/weapon/hemostat,/obj/item/weapon/mop,/obj/item/weapon/locator,/obj/item/weapon/minihoe, /obj/item/stack/packageWrap,/obj/item/weapon/pen,/obj/item/weapon/pickaxe,/obj/item/weapon/pinpointer, /obj/item/weapon/rcd,/obj/item/weapon/rcd_ammo,/obj/item/weapon/retractor,/obj/item/weapon/rsf,/obj/item/weapon/rsp,/obj/item/weapon/scalpel, - /obj/item/weapon/screwdriver,/obj/item/weapon/shovel,/obj/item/weapon/soap,/obj/item/weapon/stamp,/obj/item/weapon/tray,/obj/item/weapon/weldingtool, + /obj/item/weapon/screwdriver,/obj/item/weapon/shovel,/obj/item/weapon/soap,/obj/item/weapon/stamp,/obj/item/weapon/storage/bag/tray,/obj/item/weapon/weldingtool, /obj/item/weapon/wirecutters,/obj/item/weapon/wrench,/obj/item/weapon/extinguisher) /datum/cargoprofile/finished diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index a7db9300c73..f3062199ec7 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -627,7 +627,7 @@ client for(var/obj/Obj in world) if(Obj.type == O_type) i++ - del(Obj) + qdel(Obj) if(!i) usr << "No objects of this type exist" return @@ -638,7 +638,7 @@ client for(var/obj/Obj in world) if(istype(Obj,O_type)) i++ - del(Obj) + qdel(Obj) if(!i) usr << "No objects of this type exist" return diff --git a/code/datums/helper_datums/construction_datum.dm b/code/datums/helper_datums/construction_datum.dm index ffede1e6957..0eb4d73dfde 100644 --- a/code/datums/helper_datums/construction_datum.dm +++ b/code/datums/helper_datums/construction_datum.dm @@ -231,7 +231,7 @@ user.visible_message(fixText(state["vis_msg"],user),fixText(state["self_msg"],user)) if("delete" in state) - del(used_atom) + qdel(used_atom) else if("spawn" in state) var/spawntype=state["spawn"] var/atom/A = new spawntype(holder.loc) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 23d9ff5aa18..70024bf68d6 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -49,7 +49,7 @@ //must succeed in most cases proc/setTeleatom(atom/movable/ateleatom) if(istype(ateleatom, /obj/effect) && !istype(ateleatom, /obj/effect/dummy/chameleon)) - del(ateleatom) + qdel(ateleatom) return 0 if(istype(ateleatom)) teleatom = ateleatom diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 4c63722a2ff..905d47d36b8 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -735,7 +735,7 @@ datum/mind var/obj/item/device/flash/flash = locate() in L if (!flash) usr << "\red Deleting flash failed!" - del(flash) + qdel(flash) if("repairflash") var/list/L = current.get_contents() @@ -748,7 +748,7 @@ datum/mind if("reequip") var/list/L = current.get_contents() var/obj/item/device/flash/flash = locate() in L - del(flash) + qdel(flash) take_uplink() var/fail = 0 fail |= !ticker.mode.equip_traitor(current, 1) @@ -927,17 +927,17 @@ datum/mind if("lair") current.loc = get_turf(locate("landmark*Syndicate-Spawn")) if("dressup") - del(H.belt) - del(H.back) - del(H.l_ear) - del(H.r_ear) - del(H.gloves) - del(H.head) - del(H.shoes) - del(H.wear_id) - del(H.wear_pda) - del(H.wear_suit) - del(H.w_uniform) + qdel(H.belt) + qdel(H.back) + qdel(H.l_ear) + qdel(H.r_ear) + qdel(H.gloves) + qdel(H.head) + qdel(H.shoes) + qdel(H.wear_id) + qdel(H.wear_pda) + qdel(H.wear_suit) + qdel(H.w_uniform) if (!ticker.mode.equip_syndicate(current)) usr << "\red Equipping a syndicate failed!" @@ -1150,7 +1150,7 @@ datum/mind proc/take_uplink() var/obj/item/device/uplink/hidden/H = find_syndicate_uplink() if(H) - del(H) + qdel(H) proc/make_AI_Malf() @@ -1191,17 +1191,17 @@ datum/mind current.loc = get_turf(locate("landmark*Syndicate-Spawn")) var/mob/living/carbon/human/H = current - del(H.belt) - del(H.back) - del(H.l_ear) - del(H.r_ear) - del(H.gloves) - del(H.head) - del(H.shoes) - del(H.wear_id) - del(H.wear_pda) - del(H.wear_suit) - del(H.w_uniform) + qdel(H.belt) + qdel(H.back) + qdel(H.l_ear) + qdel(H.r_ear) + qdel(H.gloves) + qdel(H.head) + qdel(H.shoes) + qdel(H.wear_id) + qdel(H.wear_pda) + qdel(H.wear_suit) + qdel(H.w_uniform) ticker.mode.equip_syndicate(current) @@ -1290,7 +1290,7 @@ datum/mind var/list/L = current.get_contents() var/obj/item/device/flash/flash = locate() in L - del(flash) + qdel(flash) take_uplink() var/fail = 0 // fail |= !ticker.mode.equip_traitor(current, 1) diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index d2c747dd5b8..4f2750c0c06 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -79,7 +79,7 @@ var/obj/result_obj = new result(container) for (var/obj/O in (container.contents-result_obj)) O.reagents.trans_to(result_obj, O.reagents.total_volume) - del(O) + qdel(O) container.reagents.clear_reagents() return result_obj @@ -91,7 +91,7 @@ O.reagents.del_reagent("nutriment") O.reagents.update_total() O.reagents.trans_to(result_obj, O.reagents.total_volume) - del(O) + qdel(O) container.reagents.clear_reagents() return result_obj diff --git a/code/datums/spells/genetic.dm b/code/datums/spells/genetic.dm index 6bf167196cd..f9d327a5723 100644 --- a/code/datums/spells/genetic.dm +++ b/code/datums/spells/genetic.dm @@ -20,8 +20,8 @@ for(var/mob/living/target in targets) for(var/x in mutations) target.mutations.Add(x) - if(x == HULK && ishuman(target)) - target:hulk_time=world.time + duration + /* if(x == HULK && ishuman(target)) + target:hulk_time=world.time + duration */ target.disabilities |= disabilities target.update_mutations() //update target's mutation overlays spawn(duration) diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm index 3e1f82f98f9..5f45dc41aaa 100644 --- a/code/datums/spells/horsemask.dm +++ b/code/datums/spells/horsemask.dm @@ -26,7 +26,7 @@ if(!target) return - if(target.type in compatible_mobs || ishuman(target)) + if((target.type in compatible_mobs) || ishuman(target)) user << "It'd be stupid to curse [target] with a horse's head!" return diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index a95fe3a4ac2..04baae91356 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -234,7 +234,7 @@ if(H) user << "You use [src] to destroy [H]." signs -= H - del(H) + qdel(H) else if(signs.len < max_signs) H = new(get_turf(target)) @@ -250,7 +250,7 @@ if(signs.len) var/list/L = signs.Copy() for(var/sign in L) - del(sign) + qdel(sign) signs -= sign user << "You clear all active holograms." @@ -313,7 +313,7 @@ if(ishuman(C)) dead_legs(C) if(src) - del(src) + qdel(src) proc/dead_legs(mob/living/carbon/human/H as mob) var/datum/organ/external/l = H.get_organ("l_leg") @@ -562,8 +562,8 @@ if(istype(A, /obj/effect/plantsegment)) for(var/obj/effect/plantsegment/B in orange(A,1)) if(prob(80)) - del B - del A + qdel(B) + qdel(A) /* /obj/item/weapon/cigarpacket diff --git a/code/game/atoms.dm b/code/game/atoms.dm index fa22e742970..61b63bb6a9d 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1,3 +1,6 @@ +var/global/list/del_profiling = list() +var/global/list/gdel_profiling = list() +var/global/list/ghdel_profiling = list() /atom layer = 2 var/level = 2 @@ -24,16 +27,18 @@ // Garbage collection var/gc_destroyed=null -/atom/Del() - // Pass to Destroy(). - if(!gc_destroyed) - Destroy() - ..() -/atom/proc/Destroy() - gc_destroyed=world.time +/atom/Destroy() + SetOpacity(0) + if(reagents) + reagents.Destroy() + reagents = null + + // Idea by ChuckTheSheep to make the object even more unreferencable. + invisibility = 101 + /atom/proc/CheckParts() return @@ -242,7 +247,7 @@ its easier to just keep the beam vertical. return /atom/proc/emag_act() - return + return /atom/proc/hitby(atom/movable/AM as mob|obj) if (density) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 28c188467b4..fdb556a6b64 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -15,13 +15,67 @@ var/mob/pulledby = null var/area/areaMaster - + var/hard_deleted = 0 /atom/movable/New() . = ..() areaMaster = get_area_master(src) +/atom/movable/Destroy() + if(opacity) + if(isturf(loc)) + if(loc:lighting_lumcount > 1) + UpdateAffectingLights() + gcDestroyed = "Bye, world!" + tag = null + loc = null +/* + if(istype(beams) && beams.len) + for(var/obj/effect/beam/B in beams) + if(B && B.target == src) + B.target = null + if(B.master && B.master.target == src) + B.master.target = null + beams.len = 0 +*/ + ..() + +/proc/delete_profile(var/type, code = 0) + if(!ticker || !ticker.current_state < 3) return + switch(code) + if(0) + if (!("[type]" in del_profiling)) + del_profiling["[type]"] = 0 + + del_profiling["[type]"] += 1 + if(1) + if (!("[type]" in ghdel_profiling)) + ghdel_profiling["[type]"] = 0 + + ghdel_profiling["[type]"] += 1 + if(2) + if (!("[type]" in gdel_profiling)) + gdel_profiling["[type]"] = 0 + + gdel_profiling["[type]"] += 1 + if(garbageCollector) + garbageCollector.soft_dels++ + +/atom/movable/Del() + if (gcDestroyed) + garbageCollector.dequeue("\ref[src]") + + if (hard_deleted) + delete_profile("[type]", 1) + else + delete_profile("[type]", 2) + else // direct del calls or nulled explicitly. + delete_profile("[type]", 0) + Destroy() + + ..() + // Used in shuttle movement and AI eye stuff. // Primarily used to notify objects being moved by a shuttle/bluespace fuckup. /atom/movable/proc/setLoc(var/T, var/teleported=0) @@ -107,10 +161,6 @@ src.thrower = thrower src.throw_source = get_turf(src) //store the origin turf - if(usr) - if(HULK in usr.mutations) - src.throwing = 2 // really strong throw! - var/dist_x = abs(target.x - src.x) var/dist_y = abs(target.y - src.y) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 5e451c19a92..29b1cd1b3d9 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -65,7 +65,7 @@ component_parts += new /obj/item/stack/cable_coil(src, 1) component_parts += new /obj/item/stack/cable_coil(src, 1) RefreshParts() - + /obj/machinery/dna_scannernew/upgraded/New() ..() component_parts = list() @@ -233,7 +233,7 @@ return put_in(G.affecting) src.add_fingerprint(user) - del(G) + qdel(G) return /obj/machinery/dna_scannernew/proc/put_in(var/mob/M) @@ -309,7 +309,7 @@ if(prob(75)) for(var/atom/movable/A as mob|obj in src) A.loc = src.loc - del(src) + qdel(src) /obj/machinery/computer/scan_consolenew name = "DNA Modifier Access Console" @@ -367,7 +367,7 @@ /obj/machinery/computer/scan_consolenew/blob_act() if(prob(75)) - del(src) + qdel(src) /obj/machinery/computer/scan_consolenew/power_change() if(stat & BROKEN) diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index c154d8f9249..8f57ce1e6cd 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -47,6 +47,7 @@ desc = "Enables the subject to bend low levels of light around themselves, creating a cloaking effect." activation_messages = list("You begin to fade into the shadows.") deactivation_messages = list("You become fully visible.") + activation_prob=10 New() block=SHADOWBLOCK @@ -66,6 +67,7 @@ desc = "The subject becomes able to subtly alter light patterns to become invisible, as long as they remain still." activation_messages = list("You feel one with your surroundings.") deactivation_messages = list("You feel oddly exposed.") + activation_prob=10 New() block=CHAMELEONBLOCK @@ -316,7 +318,7 @@ else usr.visible_message("\red [usr] eats \the [the_item].") playsound(usr.loc, 'sound/items/eatfood.ogg', 50, 0) - del(the_item) + qdel(the_item) doHeal(usr) return diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index c810b0dd88c..03ca9880c2c 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -33,7 +33,7 @@ animation.master = src flick("h2monkey", animation) sleep(48) - del(animation) + qdel(animation) var/mob/living/carbon/monkey/O = null @@ -56,7 +56,7 @@ for(var/obj/T in (M.contents-implants)) - del(T) + qdel(T) O.loc = M.loc @@ -78,7 +78,7 @@ I.loc = O I.implanted = O // O.update_icon = 1 //queue a full icon update at next life() call - del(M) + qdel(M) return /datum/dna/gene/monkey/deactivate(var/mob/living/M, var/connected, var/flags) diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index 61068c81701..d74379c3d8b 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -7,6 +7,7 @@ activation_messages=list("You feel no need to breathe.") mutation=NO_BREATH instability=2 + activation_prob=10 New() block=NOBREATHBLOCK @@ -112,10 +113,57 @@ ..(M,connected,flags) M.pass_flags |= 1 + +// OLD HULK BEHAVIOR +/datum/dna/gene/basic/hulk + name="Hulk" + activation_messages=list("Your muscles hurt.") + mutation=HULK + activation_prob=5 + + New() + block=HULKBLOCK + + can_activate(var/mob/M,var/flags) + // Can't be big AND small. + if(DWARF in M.mutations) + return 0 + return ..(M,flags) + + activate(var/mob/M, var/connected, var/flags) + ..() + var/status = CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH + M.status_flags &= ~status + + deactivate(var/mob/M, var/connected, var/flags) + ..() + M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH + + OnDrawUnderlays(var/mob/M,var/g,var/fat) + if(HULK in M.mutations) + if(fat) + return "hulk_[fat]_s" + else + return "hulk_[g]_s" + return 0 + + OnMobLife(var/mob/living/carbon/human/M) + if(!istype(M)) return + if ((HULK in M.mutations) && M.health <= 25) + M.mutations.Remove(HULK) + M.dna.SetSEState(HULKBLOCK,0) + M.update_mutations() //update our mutation overlays + M.update_body() + M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH //temporary fix until the problem can be solved. + M << "You suddenly feel very weak." + M.Weaken(3) + M.emote("collapse") + /datum/dna/gene/basic/xray name="X-Ray Vision" activation_messages=list("The walls suddenly disappear.") mutation=XRAY + activation_prob=10 instability=2 New() @@ -125,7 +173,7 @@ name="Telekenesis" activation_messages=list("You feel smarter.") mutation=TK - activation_prob=15 + activation_prob=10 instability=5 New() diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 2b45360f613..f0a5d1dbd18 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -2,7 +2,7 @@ This is /vg/'s nerf for hulk. Feel free to steal it. Obviously, requires DNA2. -*/ + // When hulk was first applied (world.time). /mob/living/carbon/human/var/hulk_time=0 @@ -84,7 +84,7 @@ Obviously, requires DNA2. //M.say(pick("",";")+pick("HULK MAD","YOU MADE HULK ANGRY")) // Just a note to security. message_admins("[key_name(usr)] has hulked out! ([formatJumpTo(usr)])") return - +*/ ///////////////////Vanilla Morph//////////////////////////////////// @@ -222,19 +222,19 @@ Obviously, requires DNA2. /obj/effect/proc_holder/spell/wizard/targeted/remotetalk/choose_targets(mob/user = usr) var/list/targets = new /list() var/list/validtargets = new /list() - for(var/mob/M in living_mob_list) + for(var/mob/M in living_mob_list) if(M && M.mind) var/special_role = M.mind.special_role if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien") continue - + validtargets += M - + if(!validtargets.len || validtargets.len == 1) usr << "There are no valid targets!" start_recharge() return - + targets += input("Choose the target to talk to.", "Targeting") as mob in validtargets perform(targets) @@ -280,7 +280,7 @@ Obviously, requires DNA2. icon_power_button = "genetic_view" /obj/effect/proc_holder/spell/wizard/targeted/remoteview/choose_targets(mob/user = usr) - var/list/targets = living_mob_list + var/list/targets = living_mob_list var/list/remoteviewers = new /list() for(var/mob/M in targets) if(REMOTE_VIEW in M.mutations) diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 39f6d7b6014..531f5f1897d 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -79,7 +79,7 @@ for (var/mob/M in dead_mob_list) if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping - rendered = "Blob Telepathy, [name] (Follow) [verb] \"[message]\"" + rendered = "Blob Telepathy, [name] (follow) [verb] \"[message]\"" M.show_message(rendered, 2) /mob/camera/blob/emote(var/act,var/m_type=1,var/message = null) diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 05b1a04ea96..a0d31937c7b 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -227,6 +227,12 @@ var/global/datum/controller/gameticker/ticker statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE votetimer() + + for(var/mob/M in mob_list) + if(istype(M,/mob/new_player)) + var/mob/new_player/N = M + N.new_player_panel_proc() + return 1 /datum/controller/gameticker diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index 4b8cdc34dca..5a305b3d7ec 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -33,6 +33,11 @@ typepath = /obj/item/weapon/gun/energy/laser/captain protected_jobs = list("Captain") +/datum/theft_objective/hoslaser + name = "the head of security's recreated antique laser gun" + typepath = /obj/item/weapon/gun/energy/hos + protected_jobs = list("Head Of Security") + /datum/theft_objective/hand_tele name = "a hand teleporter" typepath = /obj/item/weapon/hand_tele diff --git a/code/game/gamemodes/xenos/xenos.dm b/code/game/gamemodes/xenos/xenos.dm index de841595de5..b8f57122a7c 100644 --- a/code/game/gamemodes/xenos/xenos.dm +++ b/code/game/gamemodes/xenos/xenos.dm @@ -18,8 +18,6 @@ var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - var/xenoai = 0 //Should the Xenos have their own AI? - var/xenoborg = 0 //Should the Xenos have their own borg? var/gammaratio = 4 //At what alien to human ratio will the Gamma security level be called and the nuke be made available? /datum/game_mode/xenos/announce() @@ -70,48 +68,12 @@ del(A) continue - var/xenoai_selected = 0 - var/xenoborg_selected = 0 var/xenoqueen_selected = 0 var/spawnpos = 1 for(var/datum/mind/xeno_mind in xenos) if(spawnpos > xenos_spawn.len) spawnpos = 1 - //XenoAI selection - if(xenoai && !xenoai_selected) - var/mob/living/silicon/ai/O = new(xenos_spawn[spawnpos],,,1)//No MMI but safety is in effect. - O.invisibility = 0 - O.aiRestorePowerRoutine = 0 - - if(xeno_mind.current) - xeno_mind.transfer_to(O) - O.mind.original = O - else - O.key = xeno_mind.current.key - - //del(xeno_mind) - var/obj/loc_landmark - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name == "XenoAI") - loc_landmark = sloc - O.loc = loc_landmark.loc - O.icon_state = "ai-alien" - O.verbs.Remove(,/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \ - /mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \ - /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ - /mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon) - O.laws = new /datum/ai_laws/alienmov - O.name = "Alien AI" - O.real_name = name - xeno_mind.name = O.name - O.alienAI = 1 - O.network = list("SS13","Xeno") - O.holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) - O.alien_talk_understand = 1 - xenoai_selected = 1 - spawnpos++ - continue //XenoQueen Selection if(!xenoqueen_selected) var/mob/living/carbon/alien/humanoid/queen/O = new(xenos_spawn[spawnpos]) @@ -124,37 +86,6 @@ xenoqueen_selected = 1 spawnpos++ continue - //XenoBorg Selection - if(xenoborg && !xenoborg_selected) - var/mob/living/silicon/robot/O = new(xenos_spawn[spawnpos],0,0,1) - O.mmi = new /obj/item/device/mmi(O) - O.mmi.alien = 1 - O.mmi.transfer_identity(xeno_mind.current)//Does not transfer key/client. - O.cell = new(O) - O.cell.maxcharge = 25000 - O.cell.charge = 25000 - O.gender = xeno_mind.current.gender - O.invisibility = 0 - O.key = xeno_mind.current.key - //del(xeno_mind) - O.job = "Alien Cyborg" - O.name = "Alien Cyborg" - O.real_name = name - xeno_mind.name = O.name - O.module = new /obj/item/weapon/robot_module/alien/hunter(src) - O.hands.icon_state = "standard" - O.icon = 'icons/mob/alien.dmi' - O.icon_state = "xenoborg-state-a" - O.modtype = "Xeno-Hu" - O.connected_ai = select_active_alien_ai() - O.laws = new /datum/ai_laws/alienmov() - O.scrambledcodes = 1 - O.hiddenborg = 1 - O.alien_talk_understand = 1 - feedback_inc("xeborg_hunter",1) - xenoborg_selected = 1 - spawnpos++ - continue //Additional larvas if playercount > 20 else var/mob/living/carbon/alien/larva/O = new(xenos_spawn[spawnpos]) @@ -230,7 +161,7 @@ var/list/livingxenos = list() for(var/datum/mind/xeno in xenos) if((xeno) && (xeno.current) && (xeno.current.stat != 2) && (xeno.current.client)) - if(istype(xeno.current,/mob/living/carbon/alien) || (xenoborg && isrobot(xeno.current)) || (xenoai && isAI(xeno.current))) + if(istype(xeno.current,/mob/living/carbon/alien)) livingxenos += xeno return livingxenos.len diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index b7cdd87cdaa..6c13db51ad5 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -16,7 +16,7 @@ var/operating = 0.0 var/list/queue = list() - var/queue_max_len = 10 + var/queue_max_len = 12 var/turf/BuildTurf anchored = 1.0 var/list/L = list() @@ -34,7 +34,7 @@ var/prod_coeff var/datum/wires/autolathe/wires = null - var/datum/design/being_built + var/list/being_built = list() var/datum/research/files var/list/datum/design/matching_designs var/selected_category @@ -190,16 +190,17 @@ ///////////////// //href protection - being_built = files.FindDesignByID(href_list["make"]) //check if it's a valid design - if(!being_built) + var/datum/design/design_last_ordered + design_last_ordered = files.FindDesignByID(href_list["make"]) //check if it's a valid design + if(!design_last_ordered) return - if(!(being_built.build_type & AUTOLATHE)) + if(!(design_last_ordered.build_type & AUTOLATHE)) return //multiplier checks : only stacks can have one and its value is 1, 10 ,25 or max_multiplier var/multiplier = text2num(href_list["multiplier"]) - var/max_multiplier = min(50, being_built.materials["$metal"] ?round(m_amount/being_built.materials["$metal"]):INFINITY,being_built.materials["$glass"]?round(g_amount/being_built.materials["$glass"]):INFINITY) - var/is_stack = ispath(being_built.build_path, /obj/item/stack) + var/max_multiplier = min(50, design_last_ordered.materials["$metal"] ?round(m_amount/design_last_ordered.materials["$metal"]):INFINITY,design_last_ordered.materials["$glass"]?round(g_amount/design_last_ordered.materials["$glass"]):INFINITY) + var/is_stack = ispath(design_last_ordered.build_path, /obj/item/stack) if(!is_stack && (multiplier > 1)) return @@ -207,8 +208,8 @@ return ///////////////// - if(queue.len1) + var/output = "PROCESSING: [initial(D.name)][is_stack?" (x[multiplier])":null]" + return output + /obj/machinery/autolathe/proc/get_queue() var/temp_metal = m_amount var/temp_glass = g_amount @@ -318,19 +329,27 @@ output += "
" output += "Queue contains:" if (!istype(queue) || !queue.len) - output += "
Nothing" + if(being_built.len) + output += "
  1. " + output += get_processing_line() + output += "
" + else + output += "
Nothing" else output += "
    " + if(being_built.len) + output += "
  1. " + output += get_processing_line() + output += "
  2. " var/i = 0 var/datum/design/D for(var/list/L in queue) i++ D = L[1] var/multiplier = L[2] - var/obj/part = D.build_path var/list/LL = get_design_cost_as_list(D,multiplier) var/is_stack = (multiplier>1) - output += "[initial(part.name)][is_stack?" (x[multiplier])":null] - [i>1?"":null] [i↓":null] Remove" + output += "[initial(D.name)][is_stack?" (x[multiplier])":null] - [i>1?"":null] [i↓":null] Remove" temp_metal = max(temp_metal-LL[1],1) temp_glass = max(temp_glass-LL[2],1) @@ -363,16 +382,19 @@ return while(D) if(stat&(NOPOWER|BROKEN)) + being_built = new /list() return 0 if(!can_build(D,multiplier)) visible_message("\icon[src] \The [src] beeps, \"Not enough resources. Queue processing terminated.\"") queue = list() + being_built = new /list() return 0 remove_from_queue(1) build_item(D,multiplier) D = listgetindex(listgetindex(queue, 1),1) multiplier = listgetindex(listgetindex(queue,1),2) + being_built = new /list() //visible_message("\icon[src] \The [src] beeps, \"Queue processing finished successfully.\"") /obj/machinery/autolathe/proc/main_win(mob/user) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index a74d7ad5bde..ad008362907 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1024,7 +1024,7 @@ /obj/item/clothing/accessory/waistcoat = 1,/obj/item/clothing/under/suit_jacket = 1,/obj/item/clothing/head/that =1,/obj/item/clothing/under/kilt = 1,/obj/item/clothing/head/beret = 1,/obj/item/clothing/accessory/waistcoat = 1, /obj/item/clothing/glasses/monocle =1,/obj/item/clothing/head/bowlerhat = 1,/obj/item/weapon/cane = 1,/obj/item/clothing/under/sl_suit = 1, /obj/item/clothing/mask/fakemoustache = 1,/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,/obj/item/clothing/head/plaguedoctorhat = 1,/obj/item/clothing/mask/gas/plaguedoctor = 1, - /obj/item/clothing/under/owl = 1,/obj/item/clothing/mask/gas/owl_mask = 1,/obj/item/clothing/suit/apron = 1,/obj/item/clothing/under/waiter = 1, + /obj/item/clothing/suit/apron = 1,/obj/item/clothing/under/waiter = 1, /obj/item/clothing/under/pirate = 1,/obj/item/clothing/suit/pirate_brown = 1,/obj/item/clothing/suit/pirate_black =1,/obj/item/clothing/under/pirate_rags =1,/obj/item/clothing/head/pirate = 1,/obj/item/clothing/head/bandana = 1, /obj/item/clothing/head/bandana = 1,/obj/item/clothing/under/soviet = 1,/obj/item/clothing/head/ushanka = 1,/obj/item/clothing/suit/imperium_monk = 1, /obj/item/clothing/mask/gas/cyborg = 1,/obj/item/clothing/suit/holidaypriest = 1,/obj/item/clothing/head/wizard/marisa/fake = 1, @@ -1053,7 +1053,7 @@ desc = "A kitchen and restaurant equipment vendor" product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..." icon_state = "dinnerware" - products = list(/obj/item/weapon/tray = 8,/obj/item/weapon/kitchen/utensil/fork = 6,/obj/item/weapon/kitchenknife = 3,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/chef/classic = 2,/obj/item/weapon/reagent_containers/food/condiment/pack/ketchup = 5,/obj/item/weapon/reagent_containers/food/condiment/pack/hotsauce = 5) + products = list(/obj/item/weapon/storage/bag/tray = 8,/obj/item/weapon/kitchen/utensil/fork = 6,/obj/item/weapon/kitchenknife = 3,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/chef/classic = 2,/obj/item/weapon/reagent_containers/food/condiment/pack/ketchup = 5,/obj/item/weapon/reagent_containers/food/condiment/pack/hotsauce = 5) contraband = list(/obj/item/weapon/kitchen/utensil/spoon = 2,/obj/item/weapon/kitchen/utensil/knife = 2,/obj/item/weapon/kitchen/rollingpin = 2, /obj/item/weapon/butch = 2) /obj/machinery/vending/sovietsoda diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index c253dd2d084..22e89cfe000 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -35,26 +35,64 @@ ticker.mode.traitors += user.mind user.mind.special_role = "The Hero The Station Deserves" - var/wish = input("You want to...","Wish") as null|anything in list("Protect the innocent","Hunt the guilty") + + var/mob/living/carbon/human/M = user + + var/wish = input("You want to...","Wish") as anything in list("Protect the innocent","Hunt the guilty") switch(wish) if("Protect the innocent") + M.fully_replace_character_name(M.real_name, "Owlman") + var/datum/objective/protect/protect = new protect.owner = user.mind user.mind.objectives += protect + for(var/obj/item/W in M) + M.unEquip(W) + + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/under/owl(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/owlwings(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/owl_mask(M), slot_wear_mask) + + var/obj/item/weapon/card/id/syndicate/W = new(M) + W.name = "[M.real_name]'s ID Card (Superhero)" + W.access = get_all_accesses() + W.assignment = "Superhero" + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + M.regenerate_icons() + if("Hunt the guilty") + M.fully_replace_character_name(M.real_name, "The Griffin") + var/datum/objective/assassinate/assasinate = new assasinate.owner = user.mind user.mind.objectives += assasinate + for(var/obj/item/W in M) + M.unEquip(W) + + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/griffin(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/under/griffin(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/owlwings/griffinwings(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/head/griffin(M), slot_head) + + var/obj/item/weapon/card/id/syndicate/W = new(M) + W.name = "[M.real_name]'s ID Card (Supervillain)" + W.access = get_all_accesses() + W.assignment = "Supervillain" + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + M.regenerate_icons() + var/obj_count = 1 for(var/datum/objective/OBJ in user.mind.objectives) user << "Objective #[obj_count]: [OBJ.explanation_text]" obj_count++ - user << "As a superhero, you are allowed to pick an appropriate pseudonym for your new role. A costume is also strongly encouraged." - user.rename_self() - charges-- insisting = 0 diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 4cb89d01ea5..73ccbd3aab3 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -11,6 +11,17 @@ would spawn and follow the beaker, even if it is carried or thrown. icon = 'icons/effects/effects.dmi' mouse_opacity = 0 unacidable = 1//So effect are not targeted by alien acid. + +/datum/effect/effect/proc/fadeOut(var/atom/A, var/frames = 16) + if(A.alpha == 0) //Handle already transparent case + return + if(frames == 0) + frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame". + var/step = A.alpha / frames + for(var/i = 0, i < frames, i++) + A.alpha -= step + sleep(world.tick_lag) + return /obj/effect/effect/water name = "water" diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 8896e9a77d2..4b009aef988 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -1,4 +1,3 @@ - /obj/item/weapon/extinguisher name = "fire extinguisher" desc = "A traditional red fire extinguisher." @@ -18,32 +17,24 @@ var/last_use = 1.0 var/safety = 1 var/sprite_name = "fire_extinguisher" - - reagents_to_log=list( - "plasma"= "plasma", - "pacid" = "polytrinic acid", - "sacid" = "sulphuric acid" - ) + var/power = 5 //Maximum distance launched water will travel + var/precision = 0 //By default, turfs picked from a spray are random, set to 1 to make it always have at least one water effect per row + var/cooling_power = 2 //Sets the cooling_temperature of the water reagent datum inside of the extinguisher when it is refilled /obj/item/weapon/extinguisher/mini - name = "fire extinguisher" + name = "pocket fire extinguisher" desc = "A light and compact fibreglass-framed model fire extinguisher." icon_state = "miniFE0" item_state = "miniFE" hitsound = null //it is much lighter, after all. + flags = null //doesn't CONDUCT throwforce = 2 w_class = 2.0 force = 3.0 m_amt = 0 max_water = 30 sprite_name = "miniFE" - -/obj/item/weapon/extinguisher/New() - var/datum/reagents/R = new/datum/reagents(max_water) - reagents = R - R.my_atom = src - R.add_reagent("water", max_water) - + /obj/item/weapon/extinguisher/examine() set src in usr @@ -51,11 +42,13 @@ if(reagents && reagents.reagent_list.len) for(var/datum/reagent/R in reagents.reagent_list) usr << "\blue [R.volume] units of [R.name]" - for(var/thing in src) - usr << "\red \A [thing] is jammed into the nozzle!" ..() return +/obj/item/weapon/extinguisher/New() + create_reagents(max_water) + reagents.add_reagent("water", max_water) + /obj/item/weapon/extinguisher/attack_self(mob/user as mob) safety = !safety src.icon_state = "[sprite_name][!safety]" @@ -63,81 +56,43 @@ user << "The safety is [safety ? "on" : "off"]." return -/* -/obj/item/weapon/extinguisher/attackby(obj/item/W, mob/user, params) - if(user.stat || user.restrained() || user.lying) return - - if (istype(W, /obj/item/weapon/wrench)) - if(!is_open_container()) - user.visible_message("[user] begins to unwrench the fill cap on \the [src].","\blue You begin to unwrench the fill cap on \the [src].") - if(do_after(user, 25)) - user.visible_message("[user] removes the fill cap on \the [src].","\blue You remove the fill cap on \the [src].") - playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) - flags |= OPENCONTAINER +/obj/item/weapon/extinguisher/proc/AttemptRefill(atom/target, mob/user) + if(istype(target, /obj/structure/reagent_dispensers/watertank) && target.Adjacent(user)) + var/safety_save = safety + safety = 1 + if(reagents.total_volume == reagents.maximum_volume) + user << "\The [src] is already full!" + safety = safety_save + return 1 + var/obj/structure/reagent_dispensers/watertank/W = target + var/transferred = W.reagents.trans_to(src, max_water) + if(transferred > 0) + user << "\The [src] has been refilled by [transferred] units" + playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) + for(var/datum/reagent/water/R in reagents.reagent_list) + R.cooling_temperature = cooling_power else - user.visible_message("[user] begins to seal the fill cap on \the [src].","\blue You begin to seal the fill cap on \the [src].") - if(do_after(user, 25)) - user.visible_message("[user] fastens the fill cap on \the [src].","\blue You fasten the fill cap on \the [src].") - playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) - flags &= ~OPENCONTAINER - return - - if (istype(W, /obj/item) && !is_open_container()) - if(W.w_class>1) - user << "\The [W] won't fit into the nozzle!" - return - if(locate(/obj) in src) - user << "There's already something crammed into the nozzle." - return - user.drop_item() - W.loc=src - user << "You cram \the [W] into the nozzle of \the [src]." - msg_admin_attack("[user]/[user.ckey] has crammed \a [W] into a [src].") - */ - + user << "\The [W] is empty!" + safety = safety_save + return 1 + else + return 0 /obj/item/weapon/extinguisher/afterattack(atom/target, mob/user , flag) - if(get_dist(src,target) <= 1) - if((istype(target, /obj/structure/reagent_dispensers))) - var/obj/o = target - var/list/badshit=list() - for(var/bad_reagent in src.reagents_to_log) - if(o.reagents.has_reagent(bad_reagent)) - badshit += reagents_to_log[bad_reagent] - if(badshit.len) - var/hl="\red ([english_list(badshit)]) \black" - message_admins("[user.name] ([user.ckey]) filled \a [src] with [o.reagents.get_reagent_ids()] [hl]. (JMP)") - log_game("[user.name] ([user.ckey]) filled \a [src] with [o.reagents.get_reagent_ids()] [hl]. (JMP)") - o.reagents.trans_to(src, 50) - user << "\blue \The [src] is now refilled" - playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) - return - - if(is_open_container() && reagents.total_volume) - user << "\blue You empty \the [src] onto [target]." - if(reagents.has_reagent("fuel")) - message_admins("[user.name] ([user.ckey]) poured Welder Fuel onto [target]. (JMP)") - log_game("[user.name] ([user.ckey]) poured Welder Fuel onto [target]. (JMP)") - src.reagents.reaction(target, TOUCH) - spawn(5) src.reagents.clear_reagents() - return - if (!safety && !is_open_container()) + //TODO; Add support for reagents in water. + if(target.loc == user)//No more spraying yourself when putting your extinguisher away + return + var/Refill = AttemptRefill(target, user) + if(Refill) + return + if (!safety) if (src.reagents.total_volume < 1) - usr << "\red \The [src] is empty." + usr << "\The [src] is empty." return if (world.time < src.last_use + 20) return - var/list/badshit=list() - for(var/bad_reagent in src.reagents_to_log) - if(reagents.has_reagent(bad_reagent)) - badshit += reagents_to_log[bad_reagent] - if(badshit.len) - var/hl="\red ([english_list(badshit)]) \black" - message_admins("[user.name] ([user.ckey]) used \a [src] filled with [reagents.get_reagent_ids(1)] [hl]. (JMP)") - log_game("[user.name] ([user.ckey]) used \a [src] filled with [reagents.get_reagent_ids(1)] [hl]. (JMP)") - src.last_use = world.time playsound(src.loc, 'sound/effects/extinguish.ogg', 75, 1, -3) @@ -174,26 +129,21 @@ sleep(3) B.Move(get_step(usr,movementdirection), movementdirection) - if(locate(/obj) in src) - for(var/obj/thing in src) - thing.loc = get_turf(src) - thing.throw_at(target,thing.throw_range*2,throw_speed*2) - user.visible_message( - "[user] fires [src] and launches [thing] at [target]!", - "You fire [src] and launch [thing] at [target]!") - break - - var/turf/T = get_turf(target) var/turf/T1 = get_step(T,turn(direction, 90)) var/turf/T2 = get_step(T,turn(direction, -90)) - var/list/the_targets = list(T,T1,T2) + if(precision) + var/turf/T3 = get_step(T1, turn(direction, 90)) + var/turf/T4 = get_step(T2,turn(direction, -90)) + the_targets = list(T,T1,T2,T3,T4) for(var/a=0, a<5, a++) spawn(0) var/obj/effect/effect/water/W = new /obj/effect/effect/water( get_turf(src) ) var/turf/my_target = pick(the_targets) + if(precision) + the_targets -= my_target var/datum/reagents/R = new/datum/reagents(5) if(!W) return W.reagents = R @@ -202,21 +152,20 @@ src.reagents.trans_to(W,1) for(var/b=0, b<5, b++) step_towards(W,my_target) - if(!W) return - if(!W.reagents) return + if(!W || !W.reagents) return W.reagents.reaction(get_turf(W)) for(var/atom/atm in get_turf(W)) if(!W) return - W.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. - if(isliving(atm) && W.reagents.has_reagent("water")) // For extinguishing mobs on fire - var/mob/living/M = atm // Why isn't this handled by the reagent? - N3X + W.reagents.reaction(atm) + if(isliving(atm)) //For extinguishing mobs on fire + var/mob/living/M = atm M.ExtinguishMob() if(W.loc == my_target) break sleep(2) - if((istype(usr.loc, /turf/space)) || (usr.lastarea.has_gravity == 0)) + if(!has_gravity(user)) user.inertia_dir = get_dir(target, user) step(user, user.inertia_dir) else return ..() - return + \ No newline at end of file diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index eaa47a0d966..b4288c7033c 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -7,7 +7,6 @@ * Kitchen knives * Butcher's cleaver * Rolling Pins - * Trays */ /obj/item/weapon/kitchen @@ -215,90 +214,4 @@ w_class = 3.0 attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") - -/* - * Trays - Agouri - */ -/obj/item/weapon/tray - name = "tray" - icon = 'icons/obj/food.dmi' - icon_state = "tray" - desc = "A metal tray to lay food on." - force = 8 - hitsound = 'sound/items/trayhit1.ogg' - throwforce = 10.0 - throw_speed = 3 - throw_range = 5 - w_class = 3.0 - flags = CONDUCT - m_amt = 3000 - var/list/carrying = list() // List of things on the tray. - Doohl - var/max_carry = 10 // w_class = 1 -- takes up 1 - // w_class = 2 -- takes up 3 - // w_class = 3 -- takes up 5 - -/* -===============~~~~~================================~~~~~==================== -= = -= Code for trays carrying things. By Doohl for Doohl erryday Doohl Doohl~ = -= = -===============~~~~~================================~~~~~==================== -*/ -/obj/item/weapon/tray/proc/calc_carry() - // calculate the weight of the items on the tray - var/val = 0 // value to return - - for(var/obj/item/I in carrying) - if(I.w_class == 1.0) - val ++ - else if(I.w_class == 2.0) - val += 3 - else - val += 5 - - return val - -/obj/item/weapon/tray/pickup(mob/user) - - if(!isturf(loc)) - return - - for(var/obj/item/I in loc) - if( I != src && !I.anchored && !istype(I, /obj/item/clothing/under) && !istype(I, /obj/item/clothing/suit) && !istype(I, /obj/item/projectile) ) - var/add = 0 - if(I.w_class == 1.0) - add = 1 - else if(I.w_class == 2.0) - add = 3 - else - add = 5 - if(calc_carry() + add >= max_carry) - break - - I.loc = src - carrying.Add(I) - overlays += image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = 30 + I.layer) - -/obj/item/weapon/tray/dropped(mob/user) - - var/mob/living/M - for(M in src.loc) //to handle hand switching - return - - var/foundtable = 0 - for(var/obj/structure/table/T in loc) - foundtable = 1 - break - - overlays.Cut() - - for(var/obj/item/I in carrying) - I.loc = loc - carrying.Remove(I) - if(!foundtable && isturf(loc)) - // if no table, presume that the person just shittily dropped the tray on the ground and made a mess everywhere! - spawn() - for(var/i = 1, i <= rand(1,2), i++) - if(I) - step(I, pick(NORTH,SOUTH,EAST,WEST)) - sleep(rand(2,4)) +/* Trays moved to /obj/item/weapon/storage/bag */ \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index c78906a6639..ff1b025a2ee 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -10,6 +10,7 @@ * Plant Bag * Sheet Snatcher * Book Bag + * Tray * * -Sayu */ @@ -37,6 +38,11 @@ storage_slots = 30 can_hold = list() // any cant_hold = list("/obj/item/weapon/disk/nuclear","/obj/item/flag/nation") + +/obj/item/weapon/storage/bag/trash/suicide_act(mob/user) + user.visible_message("[user] puts the [src.name] over their head and starts chomping at the insides! Disgusting!") + playsound(loc, 'sound/items/eatfood.ogg', 50, 1, -1) + return (TOXLOSS) /obj/item/weapon/storage/bag/trash/update_icon() if(contents.len == 0) @@ -47,10 +53,15 @@ icon_state = "trashbag2" else icon_state = "trashbag3" +/obj/item/weapon/storage/bag/trash/cyborg + /obj/item/weapon/storage/bag/trash/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J) J.put_in_cart(src, user) J.mybag=src J.update_icon() + +/obj/item/weapon/storage/bag/trash/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J) + return // ----------------------------- @@ -323,3 +334,96 @@ max_w_class = 3 w_class = 4 //Bigger than a book because physics can_hold = list(/obj/item/weapon/book, /obj/item/weapon/spellbook) //No bibles, consistent with bookcase + +/* + * Trays - Agouri + */ +/obj/item/weapon/storage/bag/tray + name = "tray" + icon = 'icons/obj/food.dmi' + icon_state = "tray" + desc = "A metal tray to lay food on." + force = 5 + throwforce = 10.0 + throw_speed = 3 + throw_range = 5 + w_class = 4.0 + flags = CONDUCT + m_amt = 3000 + +/obj/item/weapon/storage/bag/tray/attack(mob/living/M as mob, mob/living/user as mob) + ..() + // Drop all the things. All of them. + var/list/obj/item/oldContents = contents.Copy() + quick_empty() + + // Make each item scatter a bit + for(var/obj/item/I in oldContents) + spawn() + for(var/i = 1, i <= rand(1,2), i++) + if(I) + step(I, pick(NORTH,SOUTH,EAST,WEST)) + sleep(rand(2,4)) + + if(prob(50)) + playsound(M, 'sound/items/trayhit1.ogg', 50, 1) + else + playsound(M, 'sound/items/trayhit2.ogg', 50, 1) + + if(ishuman(M) || ismonkey(M)) + if(prob(10)) + M.Weaken(2) + +/obj/item/weapon/storage/bag/tray/proc/rebuild_overlays() + overlays.Cut() + for(var/obj/item/I in contents) + overlays += image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = -1) + +/obj/item/weapon/storage/bag/tray/remove_from_storage(obj/item/W as obj, atom/new_location) + ..() + rebuild_overlays() + +/obj/item/weapon/storage/bag/tray/handle_item_insertion(obj/item/I, prevent_warning = 0) + overlays += image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = -1) + ..() + +/obj/item/weapon/storage/bag/tray/cyborg + +/obj/item/weapon/storage/bag/tray/cyborg/afterattack(atom/target, mob/user as mob) + if ( isturf(target) || istype(target,/obj/structure/table) ) + var foundtable = istype(target,/obj/structure/table/) + if ( !foundtable ) //it must be a turf! + for(var/obj/structure/table/T in target) + foundtable = 1 + break + + var turf/dropspot + if ( !foundtable ) // don't unload things onto walls or other silly places. + dropspot = user.loc + else if ( isturf(target) ) // they clicked on a turf with a table in it + dropspot = target + else // they clicked on a table + dropspot = target.loc + + overlays = null + + var droppedSomething = 0 + + for(var/obj/item/I in contents) + I.loc = dropspot + contents.Remove(I) + droppedSomething = 1 + if(!foundtable && isturf(dropspot)) + // if no table, presume that the person just shittily dropped the tray on the ground and made a mess everywhere! + spawn() + for(var/i = 1, i <= rand(1,2), i++) + if(I) + step(I, pick(NORTH,SOUTH,EAST,WEST)) + sleep(rand(2,4)) + if ( droppedSomething ) + if ( foundtable ) + user.visible_message("\blue [user] unloads their service tray.") + else + user.visible_message("\blue [user] drops all the items on their tray.") + + return ..() diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index bbe4a083468..899b16cf2ef 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -336,19 +336,6 @@ if(!can_be_inserted(W)) return 0 - if(istype(W, /obj/item/weapon/tray)) - var/obj/item/weapon/tray/T = W - if(T.calc_carry() > 0) - if(prob(85)) - user << "\red The tray won't fit in [src]." - return 1 - else - W.loc = user.loc - if ((user.client && user.s_active != src)) - user.client.screen -= W - W.dropped(user) - user << "\red God damnit!" - handle_item_insertion(W) return 1 diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm index e721c2ab283..02e3ec5a543 100644 --- a/code/game/objects/items/weapons/tanks/watertank.dm +++ b/code/game/objects/items/weapons/tanks/watertank.dm @@ -2,13 +2,14 @@ /obj/item/weapon/watertank name = "backpack water tank" desc = "A S.U.N.S.H.I.N.E. brand watertank backpack with nozzle to water plants." - icon = 'icons/obj/hydroponics.dmi' + icon = 'icons/obj/watertank.dmi' icon_state = "waterbackpack" item_state = "waterbackpack" w_class = 4.0 slot_flags = SLOT_BACK slowdown = 1 action_button_name = "Toggle Mister" + icon_action_button = "action_waterbackpack" var/obj/item/weapon/noz var/on = 0 @@ -18,39 +19,34 @@ ..() create_reagents(volume) noz = make_noz() - return - -/obj/item/weapon/watertank/examine() - set src in usr - ..() - for(var/datum/reagent/R in reagents.reagent_list) - usr << "[round(R.volume)] units of [R.name] left." - return /obj/item/weapon/watertank/ui_action_click() - if (usr.get_item_by_slot(slot_back) == src) - toggle_mister() - else - usr << "The watertank needs to be on your back to use!" - return + toggle_mister() /obj/item/weapon/watertank/verb/toggle_mister() set name = "Toggle Mister" set category = "Object" + if (usr.get_item_by_slot(slot_back) != src) + usr << "The watertank needs to be on your back to use." + return + if(usr.stat || !usr.canmove || usr.restrained()) + return on = !on var/mob/living/carbon/human/user = usr if(on) + if(noz == null) + noz = make_noz() + //Detach the nozzle into the user's hands - var/list/L = list("left hand" = slot_l_hand,"right hand" = slot_r_hand) - if(!user.equip_in_one_of_slots(noz, L)) + if(!user.put_in_hands(noz)) on = 0 - user << "You need a free hand to hold the mister!" + user << "You need a free hand to hold the mister." return noz.loc = user else //Remove from their hands and put back "into" the tank - remove_noz(user) + remove_noz() return /obj/item/weapon/watertank/proc/make_noz() @@ -58,21 +54,52 @@ /obj/item/weapon/watertank/equipped(mob/user, slot) if (slot != slot_back) - remove_noz(user) + remove_noz() -/obj/item/weapon/watertank/proc/remove_noz(mob/user) - var/mob/living/carbon/human/M = user - if(noz in get_both_hands(M)) - M.unEquip(noz) +/obj/item/weapon/watertank/proc/remove_noz() + if(ismob(noz.loc)) + var/mob/M = noz.loc + M.unEquip(noz, 1) return /obj/item/weapon/watertank/Destroy() if (on) - var/M = get(noz, /mob) - remove_noz(M) + remove_noz() + qdel(noz) + noz = null ..() return +/obj/item/weapon/watertank/attack_hand(mob/user as mob) + if(src.loc == user) + ui_action_click() + return + ..() + +/obj/item/weapon/watertank/MouseDrop(obj/over_object) + if(ishuman(src.loc)) + var/mob/living/carbon/human/H = src.loc + switch(over_object.name) + if("r_hand") + if(H.r_hand) + return + if(!H.unEquip(src)) + return + H.put_in_r_hand(src) + if("l_hand") + if(H.l_hand) + return + if(!H.unEquip(src)) + return + H.put_in_l_hand(src) + return + +/obj/item/weapon/watertank/attackby(obj/item/W, mob/user, params) + if(W == noz) + remove_noz() + return + ..() + // This mister item is intended as an extension of the watertank and always attached to it. // Therefore, it's designed to be "locked" to the player's hands or extended back onto // the watertank backpack. Allowing it to be placed elsewhere or created without a parent @@ -80,13 +107,15 @@ /obj/item/weapon/reagent_containers/spray/mister name = "water mister" desc = "A mister nozzle attached to a water tank." - icon = 'icons/obj/hydroponics.dmi' + icon = 'icons/obj/watertank.dmi' icon_state = "mister" item_state = "mister" + icon_override = 'icons/mob/in-hand/tools.dmi' w_class = 4.0 amount_per_transfer_from_this = 50 possible_transfer_amounts = list(25,50,100) volume = 500 + flags = NODROP | OPENCONTAINER | NOBLUDGEON var/obj/item/weapon/watertank/tank @@ -99,7 +128,7 @@ return /obj/item/weapon/reagent_containers/spray/mister/dropped(mob/user as mob) - user << "The mister snaps back onto the watertank!" + user << "The mister snaps back onto the watertank." tank.on = 0 loc = tank @@ -114,6 +143,16 @@ else return 1 +/obj/item/weapon/reagent_containers/spray/mister/Move() + ..() + if(loc != tank.loc) + loc = tank.loc + +/obj/item/weapon/reagent_containers/spray/mister/afterattack(obj/target, mob/user, proximity) + if(target.loc == loc || target == tank) //Safety check so you don't fill your mister with mutagen or something and then blast yourself in the face with it putting it away + return + ..() + //Janitor tank /obj/item/weapon/watertank/janitor name = "backpack water tank" @@ -123,13 +162,12 @@ /obj/item/weapon/watertank/janitor/New() ..() - reagents.add_reagent("cleaner", 250) - + reagents.add_reagent("cleaner", 500) /obj/item/weapon/reagent_containers/spray/mister/janitor name = "janitor spray nozzle" desc = "A janitorial spray nozzle attached to a watertank, designed to clean up large messes." - icon = 'icons/obj/hydroponics.dmi' + icon = 'icons/obj/watertank.dmi' icon_state = "misterjani" item_state = "misterjani" amount_per_transfer_from_this = 5 @@ -142,25 +180,46 @@ amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10) user << "You [amount_per_transfer_from_this == 10 ? "remove" : "fix"] the nozzle. You'll now use [amount_per_transfer_from_this] units per spray." -//Atmos tank +//ATMOS FIRE FIGHTING BACKPACK + +#define EXTINGUISHER 0 +#define NANOFROST 1 +#define METAL_FOAM 2 + /obj/item/weapon/watertank/atmos - name = "backpack water tank" - desc = "A backpack watertank with fire extinguisher nozzle, intended to fight fires. Shouldn't toxins have one of these?" + name = "backpack firefighter tank" + desc = "A refridgerated and pressurized backpack tank with extinguisher nozzle, intended to fight fires. Swaps between extinguisher, nanofrost launcher, and metal foam dispenser for breaches. Nanofrost converts plasma in the air to nitrogen, but only if it is combusting at the time." icon_state = "waterbackpackatmos" item_state = "waterbackpackatmos" - volume = 100 + volume = 200 /obj/item/weapon/watertank/atmos/make_noz() return new /obj/item/weapon/extinguisher/mini/nozzle(src) +/obj/item/weapon/watertank/atmos/dropped(mob/user as mob) + icon_state = "waterbackpackatmos" + if(istype(noz, /obj/item/weapon/extinguisher/mini/nozzle)) + var/obj/item/weapon/extinguisher/mini/nozzle/N = noz + N.nozzle_mode = 0 + /obj/item/weapon/extinguisher/mini/nozzle - name = "fire extinguisher nozzle" - desc = "A fire extinguisher nozzle attached to a water tank." - icon = 'icons/obj/hydroponics.dmi' - icon_state = "misteratmos" - item_state = "misteratmos" + name = "extinguisher nozzle" + desc = "A heavy duty nozzle attached to a firefighter's backpack tank." + icon = 'icons/obj/watertank.dmi' + icon_state = "atmos_nozzle" + item_state = "nozzleatmos" + icon_override = 'icons/mob/in-hand/tools.dmi' safety = 0 + max_water = 200 + power = 8 + precision = 1 + cooling_power = 5 + w_class = 5 + flags = NODROP //Necessary to ensure that the nozzle and tank never seperate var/obj/item/weapon/watertank/tank + var/nozzle_mode = 0 + var/metal_synthesis_cooldown = 0 + var/nanofrost_cooldown = 0 /obj/item/weapon/extinguisher/mini/nozzle/New(parent_tank) if(check_tank_exists(parent_tank, src)) @@ -170,10 +229,174 @@ loc = tank return +/obj/item/weapon/extinguisher/mini/nozzle/Move() + ..() + if(tank && loc != tank.loc) + loc = tank + return + +/obj/item/weapon/extinguisher/mini/nozzle/attack_self(mob/user as mob) + switch(nozzle_mode) + if(EXTINGUISHER) + nozzle_mode = NANOFROST + tank.icon_state = "waterbackpackatmos_1" + user << "Swapped to nanofrost launcher" + return + if(NANOFROST) + nozzle_mode = METAL_FOAM + tank.icon_state = "waterbackpackatmos_2" + user << "Swapped to metal foam synthesizer" + return + if(METAL_FOAM) + nozzle_mode = EXTINGUISHER + tank.icon_state = "waterbackpackatmos_0" + user << "Swapped to water extinguisher" + return + return + /obj/item/weapon/extinguisher/mini/nozzle/dropped(mob/user as mob) - user << "The nozzle snaps back onto the watertank!" + user << "The nozzle snaps back onto the tank!" tank.on = 0 loc = tank -/obj/item/weapon/extinguisher/mini/nozzle/attack_self() +/obj/item/weapon/extinguisher/mini/nozzle/afterattack(atom/target, mob/user) + if(nozzle_mode == EXTINGUISHER) + ..() + return + var/Adj = user.Adjacent(target) + if(Adj) + AttemptRefill(target, user) + if(nozzle_mode == NANOFROST) + if(Adj) + return //Safety check so you don't blast yourself trying to refill your tank + var/datum/reagents/R = reagents + if(R.total_volume < 100) + user << "You need at least 100 units of water to use the nanofrost launcher!" + return + if(nanofrost_cooldown) + user << "Nanofrost launcher is still recharging" + return + nanofrost_cooldown = 1 + R.remove_any(100) + var/obj/effect/nanofrost_container/A = new /obj/effect/nanofrost_container(get_turf(src)) + log_game("[user.ckey] ([user.name]) used Nanofrost at [get_area(user)] ([user.x], [user.y], [user.z]).") + playsound(src,'sound/items/syringeproj.ogg',40,1) + for(var/a=0, a<5, a++) + step_towards(A, target) + sleep(2) + A.Smoke() + spawn(100) + if(src) + nanofrost_cooldown = 0 + return + if(nozzle_mode == METAL_FOAM) + if(!Adj|| !istype(target, /turf)) + return + if(metal_synthesis_cooldown < 5) + var/obj/effect/effect/foam/F = new /obj/effect/effect/foam(get_turf(target), 1) + F.amount = 0 + metal_synthesis_cooldown++ + spawn(100) + if(src) + metal_synthesis_cooldown-- + else + user << "Metal foam mix is still being synthesized." + return + +/obj/effect/nanofrost_container + name = "nanofrost container" + desc = "A frozen shell of ice containing nanofrost that freezes the surrounding area after activation." + icon = 'icons/effects/effects.dmi' + icon_state = "frozen_smoke_capsule" + mouse_opacity = 0 + pass_flags = PASSTABLE + +/obj/effect/nanofrost_container/proc/Smoke() + new /obj/effect/effect/freezing_smoke(src.loc, 6, 1) + var/obj/effect/decal/cleanable/flour/F = new /obj/effect/decal/cleanable/flour(src.loc) + F.color = "#B2FFFF" + F.name = "nanofrost residue" + F.desc = "Residue left behind from a nanofrost detonation. Perhaps there was a fire here?" + playsound(src,'sound/effects/bamf.ogg',100,1) + qdel(src) + +/obj/effect/effect/freezing_smoke + name = "nanofrost smoke" + icon_state = "smoke" + opacity = 0 + anchored = 0.0 + mouse_opacity = 0 + icon = 'icons/effects/96x96.dmi' + pixel_x = -32 + pixel_y = -32 + color = "#B2FFFF" + var/amount = 0 + +/obj/effect/effect/freezing_smoke/New(loc, var/amt, var/blast) + ..() + spawn(100+rand(10,30)) + delete() + amount = amt + if(amount) + var/datum/effect/effect/system/freezing_smoke_spread/F = new /datum/effect/effect/system/freezing_smoke_spread + F.set_up(amount, 0, src.loc) + F.start() + if(blast) + for(var/turf/T in trange(2, src.loc)) + Chilled(T) return + +/obj/effect/effect/freezing_smoke/proc/Chilled(atom/A) + if(istype(A, /turf/simulated)) + var/turf/simulated/T = A + if(T.air) + var/datum/gas_mixture/G = T.air + if(get_dist(T, src) < 2) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air + G.temperature = 2 + update_nearby_tiles() + var/hotspot = (locate(/obj/fire) in T) + if(hotspot && !istype(T, /turf/space)) + var/CT = 10 + var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() ) + lowertemp.temperature = max( min(lowertemp.temperature-(CT*1000),lowertemp.temperature / CT) ,0) + lowertemp.react() + T.assume_air(lowertemp) + qdel(hotspot) + if(G.toxins) + G.nitrogen += (G.toxins) + G.toxins = 0 + for(var/obj/machinery/atmospherics/unary/vent_pump/V in T) + V.welded = 1 + V.update_icon() + V.visible_message("[V] was frozen shut!") + for(var/mob/living/L in T) + L.ExtinguishMob() + return + +/datum/effect/effect/system/freezing_smoke_spread + +/datum/effect/effect/system/freezing_smoke_spread/set_up(n = 6, c = 0, loca) + number = n + if(istype(loca, /turf/)) + location = loca + else + location = get_turf(loca) + +/datum/effect/effect/system/freezing_smoke_spread/start() + var/i = 0 + for(i=0, iYou hit [src].") diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm index af199c0397c..42e82b8af22 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -85,6 +85,7 @@ new /obj/item/weapon/holosign_creator(src) new /obj/item/clothing/gloves/black(src) new /obj/item/clothing/head/soft/purple(src) + new /obj/item/weapon/watertank/janitor(src) new /obj/item/weapon/storage/belt/janitor(src) /* diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 6515018e541..1fbd663ef9e 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -144,6 +144,7 @@ new /obj/item/clothing/suit/storage/hazardvest(src) new /obj/item/clothing/mask/gas(src) new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/weapon/watertank/atmos(src) new /obj/item/clothing/suit/fire/atmos(src) new /obj/item/clothing/head/hardhat/atmos(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 011f0c7fc6d..e76f9a778b1 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -115,9 +115,9 @@ new /obj/item/clothing/mask/gas/sechailer/hos(src) new /obj/item/weapon/shield/riot(src) new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/gun/energy/advtaser(src) new /obj/item/weapon/storage/belt/security(src) new /obj/item/taperoll/police(src) + new /obj/item/weapon/gun/energy/hos(src) return diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 9bf8bfb5e5a..59edffe4b0d 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -10,6 +10,17 @@ climbable = 1 // mouse_drag_pointer = MOUSE_ACTIVE_POINTER //??? var/rigged = 0 + var/obj/item/weapon/paper/manifest/manifest + +/obj/structure/closet/crate/New() + ..() + update_icon() + +/obj/structure/closet/crate/update_icon() + ..() + overlays.Cut() + if(manifest) + overlays += "manifest" /obj/structure/closet/crate/can_open() return 1 @@ -183,6 +194,29 @@ else return +/obj/structure/closet/crate/attack_hand(mob/user as mob) + if(manifest) + user << "You tear the manifest off of the crate." + playsound(src.loc, 'sound/items/poster_ripped.ogg', 75, 1) + manifest.loc = loc + if(ishuman(user)) + user.put_in_hands(manifest) + manifest = null + update_icon() + return + else + if(rigged && locate(/obj/item/device/radio/electropack) in src) + if(isliving(user)) + var/mob/living/L = user + if(L.electrocute_act(17, src)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + return + src.add_fingerprint(user) + src.toggle(user) + return + /obj/structure/closet/crate/secure desc = "A secure crate." name = "Secure crate" @@ -196,13 +230,16 @@ var/broken = 0 var/locked = 1 -/obj/structure/closet/crate/secure/New() +/obj/structure/closet/crate/secure/update_icon() ..() + overlays.Cut() + if(manifest) + overlays += "manifest" if(locked) - overlays.Cut() overlays += redlight + else if(broken) + overlays += emag else - overlays.Cut() overlays += greenlight /obj/structure/closet/crate/secure/can_open() @@ -220,8 +257,7 @@ for(var/mob/O in viewers(user, 3)) if((O.client && !( O.blinded ))) O << "The crate has been [locked ? null : "un"]locked by [user]." - overlays.Cut() - overlays += locked ? redlight : greenlight + update_icon() else user << "Access Denied" @@ -240,23 +276,31 @@ usr << "This mob type can't use this verb." /obj/structure/closet/crate/secure/attack_hand(mob/user as mob) - src.add_fingerprint(user) + if(manifest) + user << "You tear the manifest off of the crate." + playsound(src.loc, 'sound/items/poster_ripped.ogg', 75, 1) + manifest.loc = loc + if(ishuman(user)) + user.put_in_hands(manifest) + manifest = null + update_icon() + return if(locked) src.togglelock(user) else src.toggle(user) + /obj/structure/closet/crate/secure/attackby(obj/item/weapon/W as obj, mob/user as mob, params) if(is_type_in_list(W, list(/obj/item/stack/packageWrap, /obj/item/stack/cable_coil, /obj/item/device/radio/electropack, /obj/item/weapon/wirecutters))) return ..() if(locked && (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade))) - overlays.Cut() - overlays += emag overlays += sparks spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* playsound(src.loc, "sparks", 60, 1) src.locked = 0 src.broken = 1 + update_icon() user << "You unlock \the [src]." return if(!opened) @@ -270,15 +314,12 @@ if(!broken && !opened && prob(50/severity)) if(!locked) src.locked = 1 - overlays.Cut() - overlays += redlight else - overlays.Cut() - overlays += emag overlays += sparks spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) src.locked = 0 + update_icon() if(!opened && prob(20/severity)) if(!locked) open() diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index 3668a530ed6..3d50826e03a 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -4,13 +4,38 @@ icon = 'icons/obj/storage.dmi' icon_state = "densecrate" density = 1 + var/obj/item/weapon/paper/manifest/manifest + +/obj/structure/largecrate/New() + ..() + update_icon() + +/obj/structure/largecrate/update_icon() + ..() + overlays.Cut() + if(manifest) + overlays += "manifest" /obj/structure/largecrate/attack_hand(mob/user as mob) - user << "You need a crowbar to pry this open!" - return + if(manifest) + user << "You tear the manifest off of the crate." + playsound(src.loc, 'sound/items/poster_ripped.ogg', 75, 1) + manifest.loc = loc + if(ishuman(user)) + user.put_in_hands(manifest) + manifest = null + update_icon() + return + else + user << "You need a crowbar to pry this open!" + return /obj/structure/largecrate/attackby(obj/item/weapon/W as obj, mob/user as mob, params) if(istype(W, /obj/item/weapon/crowbar)) + if(manifest) + manifest.loc = loc + manifest = null + update_icon() new /obj/item/stack/sheet/wood(src) var/turf/T = get_turf(src) for(var/obj/O in contents) diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index ea3b35be1ae..6ed7da87a3b 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -19,7 +19,7 @@ instrumentDir = dir instrumentObj = obj -/datum/song/proc/Destroy() +/datum/song/Destroy() instrumentObj = null return diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index bf1b9577b21..e8156995639 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -131,9 +131,8 @@ var/list/mechtoys = list( var/comment = null /datum/controller/supply - var/processing = 1 - var/processing_interval = 300 - var/iteration = 0 + processing = 1 + processing_interval = 300 //supply points var/points = 50 var/points_per_process = 1 @@ -224,8 +223,8 @@ var/list/mechtoys = list( plat_count += P.amount // If you send something in a crate, centcom's keeping it! - fixes secure crates being sent to centom to open them - del(A) - del(MA) + qdel(A) + qdel(MA) if(plasma_count) points += plasma_count * points_per_plasma @@ -291,8 +290,16 @@ var/list/mechtoys = list( //manifest finalisation slip.info += "
    " slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
    " - if (SP.contraband) slip.loc = null //we are out of blanks for Form #44-D Ordering Illicit Drugs. - + if(!SP.contraband) + if(istype(A, /obj/structure/closet/crate)) + var/obj/structure/closet/crate/CR = A + CR.manifest = slip + CR.update_icon() + if(istype(A, /obj/structure/largecrate)) + var/obj/structure/largecrate/LC = A + LC.manifest = slip + LC.update_icon() + else slip.loc = null //we are out of blanks for Form #44-D Ordering Illicit Drugs. shoppinglist.Cut() return @@ -359,6 +366,7 @@ var/list/mechtoys = list( temp += "Request from: [get_supply_group_name(cat)]

    " for(var/supply_type in supply_controller.supply_packs ) var/datum/supply_packs/N = supply_controller.supply_packs[supply_type] + if(N.name == "HEADER") continue //skip HEADER entry to disable exploiting it for supply points if(N.hidden || N.contraband || N.group != cat) continue //Have to send the type instead of a reference to temp += "[N.name] Cost: [N.cost]
    " //the obj because it would get caught by the garbage @@ -555,6 +563,7 @@ var/list/mechtoys = list( temp += "Request from: [get_supply_group_name(cat)]

    " for(var/supply_type in supply_controller.supply_packs ) var/datum/supply_packs/N = supply_controller.supply_packs[supply_type] + if(N.name == "HEADER") continue //skip HEADER entry to disable exploiting it for supply points if((N.hidden && !hacked) || (N.contraband && !can_order_contraband) || N.group != cat) continue //Have to send the type instead of a reference to temp += "[N.name] Cost: [N.cost]
    " //the obj because it would get caught by the garbage diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 53f887b425e..6a7ee186c40 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -144,7 +144,8 @@ var/list/admin_verbs_debug = list( /client/proc/callproc, /client/proc/callproc_datum, /client/proc/toggledebuglogs, - /client/proc/qdel_toggle // /vg/ + /client/proc/qdel_toggle, // /vg/ + /client/proc/gc_dump_hdl ) var/list/admin_verbs_possess = list( /proc/possess, diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index da234e27680..209ce6b0b32 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -33,6 +33,7 @@ if(check_rights(R_ADMIN, 0)) spanclass = "mod_channel_admin" for(var/client/C in admins) - C << "MOD: [key_name(usr, 1)] (JMP): [msg]" + if(R_MOD & C.holder.rights) + C << "MOD: [key_name(usr, 1)] (JMP): [msg]" feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! \ No newline at end of file diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 08afc9b5df9..c8a94029e1a 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -335,4 +335,12 @@ icon_state = "shamebrero" item_state = "shamebrero" desc = "Once it's on, it never comes off." - flags = NODROP \ No newline at end of file + flags = NODROP + +/obj/item/clothing/head/griffin + name = "griffon head" + desc = "Why not 'eagle head'? Who knows." + icon_state = "griffinhat" + item_state = "griffinhat" + flags = BLOCKHAIR|NODROP + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE \ No newline at end of file diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 84a5e7b77b8..61a99f1b9d3 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -135,6 +135,7 @@ desc = "Twoooo!" icon_state = "owl" species_fit = list("Vox") + flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS | NODROP // ******************************************************************** diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 4c08bba5f4b..255bccf8a81 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -150,4 +150,11 @@ /obj/item/clothing/shoes/centcom name = "dress shoes" desc = "They appear impeccably polished." - icon_state = "laceups" \ No newline at end of file + icon_state = "laceups" + +/obj/item/clothing/shoes/griffin + name = "griffon boots" + desc = "A pair of costume boots fashioned after bird talons." + icon_state = "griffinboots" + item_state = "griffinboots" + flags = NODROP \ No newline at end of file diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index ee53f0293e4..0c9ac105043 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -444,3 +444,30 @@ desc = "An overcoat for the clown soldier, to keep him warm during those cold winter nights on the front." icon_state = "soldiersuit" item_state = "soldiersuit" + +/obj/item/clothing/suit/toggle/owlwings + name = "owl cloak" + desc = "A soft brown cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive the ladies mad." + icon_state = "owl_wings" + item_state = "owl_wings" + body_parts_covered = ARMS + armor = list(melee = 5, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite) + action_button_name = "Toggle Owl Wings" + icon_action_button = "action_wings" + flags = NODROP + +/obj/item/clothing/suit/toggle/owlwings/griffinwings + name = "griffon cloak" + desc = "A plush white cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive your captives mad." + icon_state = "griffin_wings" + item_state = "griffin_wings" + +/obj/item/clothing/suit/toggle/attack_self() + if(icon_state == initial(icon_state)) + icon_state = icon_state + "_t" + item_state = icon_state + "_t" + else + icon_state = initial(icon_state) + item_state = initial(item_state) + usr.update_inv_wear_suit() \ No newline at end of file diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index cded8d082e6..89faac80f60 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -140,12 +140,6 @@ max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE siemens_coefficient = 0 -/obj/item/clothing/under/owl - name = "owl uniform" - desc = "A jumpsuit with owl wings. Photorealistic owl feathers! Twooooo!" - icon_state = "owl" - _color = "owl" - /obj/item/clothing/under/johnny name = "johnny~~ jumpsuit" desc = "Johnny~~" @@ -643,4 +637,20 @@ desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?" icon_state = "checkered_suit" item_state = "checkered_suit" - _color = "checkered_suit" \ No newline at end of file + _color = "checkered_suit" + + + +/obj/item/clothing/under/owl + name = "owl uniform" + desc = "A soft brown jumpsuit made of synthetic feathers and strong conviction." + icon_state = "owl" + _color = "owl" + flags = NODROP + +/obj/item/clothing/under/griffin + name = "griffon uniform" + desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem." + icon_state = "griffin" + _color = "griffin" + flags = NODROP \ No newline at end of file diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 2641f0e4496..e28992cf0ba 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -46,6 +46,12 @@ desc = "Dark Green beret with an old insignia on it." icon_state = "sparkyninja_beret" +/obj/item/weapon/book/manual/security_space_law/black + name = "Space Law - Limited Edition" + desc = "A leather-bound, immaculately-written copy of JUSTICE." + icon_state = "bookSpaceLawblack" + title = "Space Law - Limited Edition" + ////////////////////////////////// ////////// Fluff Items /////////// ////////////////////////////////// diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 32af0998702..25c712354ce 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -1,3 +1,18 @@ +#define EMOTE_COOLDOWN 50 //Time in deciseconds that the cooldown lasts + +//Emote Cooldown System (it's so simple!) +/mob/proc/handle_emote_CD() + if(emote_cd == 2) return 1 // Cooldown emotes were disabled by an admin, prevent use + if(src.emote_cd == 1) return 1 // Already on CD, prevent use + + src.emote_cd = 1 // Starting cooldown + spawn(EMOTE_COOLDOWN) + if(emote_cd == 2) return 1 // Don't reset if cooldown emotes were disabled by an admin during the cooldown + src.emote_cd = 0 // Cooldown complete, ready for more! + + return 0 // Proceed with emote +//--FalseIncarnate + // All mobs should have custom emote, really.. /mob/proc/custom_emote(var/m_type=1,var/message = null) diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 75ecbe0570d..177d189cb2c 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -18,6 +18,7 @@ var/native // If set, non-native speakers will have trouble speaking. var/list/syllables // Used when scrambling text for a non-speaker. var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string. + var/follow = 0 // Applies to HIVEMIND languages - should a follow link be included for dead mobs? /datum/language/proc/get_random_name(var/gender, name_count=2, syllable_count=4) if(!syllables || !syllables.len) @@ -102,7 +103,12 @@ var/msg = "[name], [speaker_mask] [format_message(message, get_spoken_verb(message))]" for(var/mob/player in player_list) - if(istype(player,/mob/dead) || ((src in player.languages) && check_special_condition(player))) + if(istype(player,/mob/dead) && follow) + var/msg_dead = "[name], [speaker_mask] (follow) [format_message(message, get_spoken_verb(message))]" + player << msg_dead + continue + + else if(istype(player,/mob/dead) || ((src in player.languages) && check_special_condition(player))) player << msg /datum/language/proc/check_special_condition(var/mob/other) @@ -340,12 +346,7 @@ colour = "alien" key = "a" flags = RESTRICTED | HIVEMIND - -/datum/language/xenos/check_special_condition(var/mob/other) - var/mob/living/carbon/M = other - if(!istype(M)) - return 1 - return 0 + follow = 1 /datum/language/ling name = "Changeling" @@ -395,6 +396,7 @@ exclaim_verb = "declares" key = "b" flags = RESTRICTED | HIVEMIND + follow = 1 var/drone_only /datum/language/binary/broadcast(var/mob/living/speaker,var/message,var/speaker_mask) @@ -409,8 +411,9 @@ var/message_body = "[speaker.say_quote(message)], \"[message]\"" for (var/mob/M in dead_mob_list) - if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping - M.show_message("[message_start] [message_body]", 2) + if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) + var/message_start_dead = "[name], [speaker.name] (follow)" + M.show_message("[message_start_dead] [message_body]", 2) for (var/mob/living/S in living_mob_list) @@ -447,6 +450,7 @@ key = "d" flags = RESTRICTED | HIVEMIND drone_only = 1 + follow = 1 // Language handling. /mob/proc/add_language(var/language) diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index c11272e06ed..0adc5d9d775 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -88,12 +88,14 @@ update_icons() /mob/living/carbon/alien/humanoid/hunter/throw_impact(A) - var/msg = "" + + if(!leaping) + return ..() if(A) if(istype(A, /mob/living)) var/mob/living/L = A - msg = "[src] pounces on [A]!" + L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") L.Weaken(5) sleep(2)//Runtime prevention (infinite bump() calls on hulks) step_towards(src,L) @@ -103,13 +105,12 @@ spawn(pounce_cooldown_time) //3s by default pounce_cooldown = !pounce_cooldown else - msg = "[src] smashes into [A]!" + visible_message("[src] smashes into [A]!", "[src] smashes into [A]!") weakened = 2 if(leaping) leaping = 0 update_canmove() - visible_message(msg) /mob/living/carbon/alien/humanoid/float(on) @@ -157,7 +158,5 @@ src.throwing = 0 - if(isobj(src)) - src.throw_impact(get_turf(src)) return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 3724a44582c..712bf731051 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -22,7 +22,7 @@ name = text("alien ([rand(1, 1000)])") real_name = name add_language("Xenomorph") - add_language("Hivemind") + add_language("Hivemind") ..() //This is fine, works the same as a human @@ -65,7 +65,7 @@ return (tally + move_delay_add + config.alien_delay) /mob/living/carbon/alien/humanoid/Process_Spacemove(var/check_drift = 0) - return 1 + return 0 ///mob/living/carbon/alien/humanoid/bullet_act(var/obj/item/projectile/Proj) taken care of in living @@ -121,7 +121,7 @@ show_message("The blob attacks!") adjustFireLoss(damage) return - + /mob/living/carbon/alien/humanoid/meteorhit(O as obj) for(var/mob/M in viewers(src, null)) if ((M.client && !( M.blinded ))) @@ -271,7 +271,7 @@ if (HULK in M.mutations)//HULK SMASH damage += 14 spawn(0) - Weaken(damage) // Why can a hulk knock an alien out but not knock out a human? Damage is robust enough. + Paralyse(1) step_away(src,M,15) sleep(3) step_away(src,M,15) @@ -279,7 +279,7 @@ visible_message("[M] has punched [src]!", \ "[M] has punched [src]!") if ((stat != DEAD) && (damage > 9||prob(5)))//Regular humans have a very small chance of weakening an alien. - Weaken(1,5) + Paralyse(2) visible_message("[M] has weakened [src]!", \ "[M] has weakened [src]!", \ "You hear someone fall.") @@ -292,7 +292,7 @@ if ("disarm") if (!lying) if (prob(5))//Very small chance to push an alien down. - Weaken(2) + Paralyse(2) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) visible_message("[M] has pushed down [src]!", \ "[M] has pushed down [src]!") @@ -399,4 +399,4 @@ In all, this is a lot like the monkey code. /N /mob/living/carbon/alien/humanoid/canBeHandcuffed() - return 1 + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index a2774c4022a..ba9f1a30c7c 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -24,7 +24,7 @@ real_name = name regenerate_icons() add_language("Xenomorph") - add_language("Hivemind") + add_language("Hivemind") ..() //This is fine, works the same as a human @@ -128,7 +128,7 @@ //can't equip anything /mob/living/carbon/alien/larva/attack_ui(slot_id) return - + /mob/living/carbon/alien/larva/meteorhit(O as obj) for(var/mob/M in viewers(src, null)) if ((M.client && !( M.blinded ))) @@ -254,7 +254,7 @@ visible_message("[M] has kicked [src]!", \ "[M] has kicked [src]!") if ((stat != DEAD) && (damage > 4.9)) - Weaken(rand(5,10)) + Paralyse(rand(5,10)) visible_message("[M] has weakened [src]!", \ "[M] has weakened [src]!", \ "You hear someone fall.") diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index c102a59ca6c..2a2d6214e71 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -1,5 +1,6 @@ /mob/living/carbon/alien/proc/handle_chemicals_in_body() - if(reagents) reagents.metabolize(src) + if(reagents) + reagents.metabolize(src) if (drowsyness) drowsyness-- diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm index 8b4177470a4..4aeace5be7b 100644 --- a/code/modules/mob/living/carbon/alien/say.dm +++ b/code/modules/mob/living/carbon/alien/say.dm @@ -16,9 +16,20 @@ return emote(copytext(message,2)) var/datum/language/speaking = parse_language(message) - if(speaking) - message = copytext(message, 2+length(speaking.key)) + message = copytext(message,2+length(speaking.key)) + else + speaking = all_languages["Xenomorph"] + + var/ending = copytext(message, length(message)) + if (speaking) + // This is broadcast to all mobs with the language, + // irrespective of distance or anything else. + if(speaking.flags & HIVEMIND) + speaking.broadcast(src,trim(message)) + return + //If we've gotten this far, keep going! + verb = speaking.get_spoken_verb(ending) message = trim(message) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 121a3e93f13..b8c50d3a362 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -78,7 +78,10 @@ /mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null) - if(status_flags & GODMODE) return 0 //godmode + if(status_flags & GODMODE) //godmode + return 0 + if(NO_SHOCK in mutations) //shockproof + return 0 shock_damage *= siemens_coeff if (shock_damage<1) return 0 @@ -99,8 +102,14 @@ "\red You feel a powerful shock course through your body!", \ "\red You hear a heavy electrical crack." \ ) - Stun(10)//This should work for now, more is really silly and makes you lay there forever - Weaken(10) + jitteriness += 1000 //High numbers for violent convulsions + do_jitter_animation(jitteriness) + stuttering += 2 + Stun(2) + spawn(20) + jitteriness -= 990 //Still jittery, but vastly less + Stun(3) + Weaken(3) if (shock_damage > 200) src.visible_message( "\red [src] was arc flashed by the [source]!", \ @@ -588,6 +597,6 @@ /mob/living/carbon/proc/canBeHandcuffed() return 0 - + /mob/living/carbon/is_muzzled() return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index e6ed1ccde84..b2cf5cea48f 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -20,69 +20,100 @@ if(src.stat == 2.0 && (act != "deathgasp")) return + + //Emote Cooldown System (it's so simple!) + // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] + var/on_CD = 0 + switch(act) + //Cooldown-inducing emotes + if("ping","buzz","beep") + if (species.name == "Machine") //Only Machines can beep, ping, and buzz + on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm + else //Everyone else fails, skip the emote attempt + return + if("squish") + if(species.name == "Slime People") //Only Slime People can squish + on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm + else //Everyone else fails, skip the emote attempt + return + if("scream", "fart", "flip") + on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm + //Everything else, including typos of the above emotes + else + on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown + + if(on_CD == 1) // Check if we need to suppress the emote attempt. + return // Suppress emote, you're still cooling off. + //--FalseIncarnate + switch(act) if("ping") - if (species.name == "Machine") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null - if (param) - message = "[src] pings at [param]." - else - message = "[src] pings." - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - m_type = 1 + if (param) + message = "[src] pings at [param]." else - if (!species.name == "Machine") - return + message = "[src] pings." + playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) + m_type = 1 if("buzz") - if (species.name == "Machine") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null - if (param) - message = "[src] buzzes at [param]." - else - message = "[src] buzzes." - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - m_type = 1 + if (param) + message = "[src] buzzes at [param]." else - if (!species.name == "Machine") - return + message = "[src] buzzes." + playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + m_type = 1 if("beep") - if(species.name == "Machine") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null - if (param) - message = "[src] beeps at [param]." - else - message = "[src] beeps." - playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) - m_type = 1 + if (param) + message = "[src] beeps at [param]." else - if (!species.name == "Machine") - return + message = "[src] beeps." + playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) + m_type = 1 + + if("squish") + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] squishes at [param]." + else + message = "[src] squishes." + playsound(src.loc, 'sound/effects/slime_squish.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound. + m_type = 1 if("wag") if(species.bodyflags & TAIL_WAGGING) @@ -204,6 +235,31 @@ if(miming) m_type = 1 + if ("flip") + m_type = 1 + if (!src.restrained()) + var/M = null + if (param) + for (var/mob/A in view(1, null)) + if (param == A.name) + M = A + break + if (M == src) + M = null + + if (M) + if(src.lying || src.weakened) + message = "[src] flops and flails around on the floor." + else + message = "[src] flips in [M]'s general direction." + src.SpinAnimation(5,1) + else + if(src.lying || src.weakened) + message = "[src] flops and flails around on the floor." + else + message = "[src] does a flip!" + src.SpinAnimation(5,1) + if ("aflap") if (!src.restrained()) message = "[src] flaps his wings ANGRILY!" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6f29823609d..05e8bdd1ef9 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -403,7 +403,7 @@ L.amount_grown = min(L.amount_grown + damage, L.max_grown) var/datum/organ/external/affecting = get_organ(ran_zone(L.zone_sel.selecting)) var/armor_block = run_armor_check(affecting, "melee") - apply_damage(damage, BRUTE, affecting, armor_block) + apply_damage(damage, BRUTE, affecting, armor_block) /mob/living/carbon/human/proc/is_loyalty_implanted(mob/living/carbon/human/M) for(var/L in M.contents) @@ -636,7 +636,10 @@ //Removed the horrible safety parameter. It was only being used by ninja code anyways. //Now checks siemens_coefficient of the affected area by default /mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/base_siemens_coeff = 1.0, var/def_zone = null) - if(status_flags & GODMODE) return 0 //godmode + if(status_flags & GODMODE) //godmode + return 0 + if(NO_SHOCK in mutations) //shockproof + return 0 if (!def_zone) def_zone = pick("l_hand", "r_hand") diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 2caa0285dc0..34f810f1c92 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -32,7 +32,9 @@ var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) var/armor_block = run_armor_check(affecting, "melee") - if(HULK in M.mutations) damage += 5 + if(HULK in M.mutations) + damage += 5 + Weaken(4) playsound(loc, "punch", 25, 1, -1) @@ -139,8 +141,9 @@ var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) var/armor_block = run_armor_check(affecting, "melee") - if(HULK in M.mutations) damage += 5 - + if(HULK in M.mutations) + damage += 5 + Weaken(4) playsound(loc, attack.attack_sound, 25, 1, -1) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 029283f3e3b..a296aabd7ea 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -32,7 +32,7 @@ timeofdeath = 0 /mob/living/carbon/human/getBrainLoss() - if(species && species.flags & NO_INTORGANS) + if(species && species.flags & NO_INTORGANS) return var/res = brainloss var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] @@ -110,15 +110,12 @@ hud_updateflag |= 1 << HEALTH_HUD /mob/living/carbon/human/Stun(amount) - if(HULK in mutations) return ..() /mob/living/carbon/human/Weaken(amount) - if(HULK in mutations) return ..() /mob/living/carbon/human/Paralyse(amount) - if(HULK in mutations) return ..() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index c25fa8e0e25..95dee276004 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -62,7 +62,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc if(life_tick%30==15) hud_updateflag = 1022 - + voice = GetVoice() //No need to update all of these procs if the guy is dead. @@ -632,8 +632,20 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc handle_fire() if(..()) return - var/thermal_protection = get_heat_protection(10000) //If you don't have fire suit level protection, you get a temperature increase - if((1 - thermal_protection) > 0.0001) + var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures + if(wear_suit) + if(wear_suit.max_heat_protection_temperature >= FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE) + thermal_protection += (wear_suit.max_heat_protection_temperature*0.7) + if(head) + if(head.max_heat_protection_temperature >= FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE) + thermal_protection += (head.max_heat_protection_temperature*THERMAL_PROTECTION_HEAD) + thermal_protection = round(thermal_protection) + if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) + return + if(thermal_protection >= FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE) + bodytemperature += 11 + return + else bodytemperature += BODYTEMP_HEATING_MAX return //END FIRE CODE @@ -914,10 +926,12 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc traumatic_shock -= light_amount if(species.flags & IS_PLANT) - if(nutrition > 500) - nutrition = 500 + if(nutrition > 450) + nutrition = 450 if(light_amount >= 5) //if there's enough light, heal - adjustBruteLoss(-(light_amount)) + adjustBruteLoss(-(light_amount/2)) + adjustFireLoss(-(light_amount/4)) + //adjustToxLoss(-(light_amount)) adjustOxyLoss(-(light_amount)) //TODO: heal wounds, heal broken limbs. @@ -1165,13 +1179,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc //Jitteryness if(jitteriness) - var/amplitude = min(4, (jitteriness/100) + 1) - var/pixel_x_diff = rand(-amplitude, amplitude) - var/pixel_y_diff = rand(-amplitude/3, amplitude/3) - - animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6) - animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y) , time = 2) - jitteriness = max(jitteriness-1, 0) + do_jitter_animation(jitteriness) //Other handle_statuses() @@ -1926,7 +1934,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc var/client/C = client for(var/mob/living/carbon/human/H in view(src, 14)) C.images += H.hud_list[NATIONS_HUD] - + /mob/living/carbon/human/handle_silent() if(..()) speech_problem_flag = 1 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 6a99f2fbb23..d8651518be0 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -420,7 +420,7 @@ proc/get_damage_icon_part(damage_state, body_part) return //masks and helmets can obscure our hair, unless we're a synthetic - if(!(species.flags & IS_SYNTHETIC) && (head && (head.flags & BLOCKHAIR)) || !(species.flags & IS_SYNTHETIC) && (wear_mask && (wear_mask.flags & BLOCKHAIR))) + if( (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) if(update_icons) update_icons() return diff --git a/code/modules/mob/living/carbon/monkey/emote.dm b/code/modules/mob/living/carbon/monkey/emote.dm index 706029df8c9..c7973bc4eb8 100644 --- a/code/modules/mob/living/carbon/monkey/emote.dm +++ b/code/modules/mob/living/carbon/monkey/emote.dm @@ -11,6 +11,24 @@ var/muzzled = is_muzzled() + //Emote Cooldown System (it's so simple!) + // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] + var/on_CD = 0 + switch(act) + //Cooldown-inducing emotes + if("chirp") + if(istype(src,/mob/living/carbon/monkey/diona)) //Only Diona Nymphs can chirp + on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm + else //Everyone else fails, skip the emote attempt + return + //Everything else, including typos of the above emotes + else + on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown + + if(on_CD == 1) // Check if we need to suppress the emote attempt. + return // Suppress emote, you're still cooling off. + //--FalseIncarnate + switch(act) if ("me") if(silent) @@ -32,10 +50,9 @@ return custom_emote(m_type, message) if ("chirp") - if(istype(src,/mob/living/carbon/monkey/diona)) - message = "The [src.name] chirps!" - playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) - m_type = 2 + message = "The [src.name] chirps!" + playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) + m_type = 2 if("sign") if (!src.restrained()) message = text("The monkey signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index ab619c4c1a0..12e2c1bcacb 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -121,7 +121,10 @@ if ((HULK in mutations) && health <= 25) mutations.Remove(HULK) - src << "\red You suddenly feel very weak." + dna.SetSEState(HULKBLOCK,0) + update_mutations() //update our mutation overlays + status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH //temporary fix until the problem can be solved. + src << "You suddenly feel very weak." Weaken(3) emote("collapse") diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index b82b063607c..feb0a420f28 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -131,7 +131,7 @@ now_pushing = 1 if(ismob(AM)) var/mob/tmob = AM - if(istype(tmob, /mob/living/carbon/human) && (HULK in tmob.mutations)) + if(istype(tmob, /mob/living/carbon/human) && (FAT in tmob.mutations)) if(prob(70)) usr << "\red You fail to push [tmob]'s fat ass out of the way." now_pushing = 0 @@ -188,8 +188,8 @@ if ((O.icon_state == "flaming" && !( shielded ))) adjustFireLoss(40) health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - return - + return + /mob/living/carbon/monkey/attack_paw(mob/living/M as mob) ..() @@ -434,7 +434,7 @@ updatehealth() return - + /mob/living/carbon/monkey/Stat() ..() statpanel("Status") diff --git a/code/modules/mob/living/carbon/monkey/say.dm b/code/modules/mob/living/carbon/monkey/say.dm new file mode 100644 index 00000000000..9a629c358fc --- /dev/null +++ b/code/modules/mob/living/carbon/monkey/say.dm @@ -0,0 +1,28 @@ +/mob/living/carbon/monkey/say(var/message) + var/verb = "says" + var/message_range = world.view + + if(client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (Muted)." + return + + message = trim_strip_html_properly(message) + + if(stat == 2) + return say_dead(message) + + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + var/datum/language/speaking = parse_language(message) + + if(speaking) + message = copytext(message, 2+length(speaking.key)) + + message = trim(message) + + if(!message || stat) + return + + ..(message, speaking, verb, null, null, message_range, null) \ No newline at end of file diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index fa15e893f6e..13676d438a9 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -58,6 +58,8 @@ halloss += effect // Useful for objects that cause "subdual" damage. PAIN! if(IRRADIATE) radiation += max(effect * ((100-run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm."))/100),0)//Rads auto check armor + if(SLUR) + slurring = max(slurring,(effect * blocked)) if(STUTTER) if(status_flags & CANSTUN) // stun is usually associated with stutter stuttering = max(stuttering,(effect * blocked)) @@ -66,7 +68,8 @@ if(DROWSY) drowsyness = max(drowsyness,(effect * blocked)) if(JITTER) - jitteriness = max(jitteriness,(effect * blocked)) + if(status_flags & CANSTUN) + jitteriness = max(jitteriness,(effect * blocked)) updatehealth() return 1 @@ -80,12 +83,13 @@ /mob/living/carbon/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0) return ..() -/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/agony = 0, var/blocked = 0, var/stamina = 0, var/jitter = 0) +/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/slur = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/agony = 0, var/blocked = 0, var/stamina = 0, var/jitter = 0) if(blocked >= 100) return 0 if(stun) apply_effect(stun, STUN, blocked) if(weaken) apply_effect(weaken, WEAKEN, blocked) if(paralyze) apply_effect(paralyze, PARALYZE, blocked) if(irradiate) apply_effect(irradiate, IRRADIATE, blocked) + if(slur) apply_effect(slur, SLUR, blocked) if(stutter) apply_effect(stutter, STUTTER, blocked) if(eyeblur) apply_effect(eyeblur, EYE_BLUR, blocked) if(drowsy) apply_effect(drowsy, DROWSY, blocked) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index f94d2bf54b7..1a9a1e80f2c 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -47,8 +47,6 @@ /mob/living/proc/burn_skin(burn_amount) if(istype(src, /mob/living/carbon/human)) //world << "DEBUG: burn_skin(), mutations=[mutations]" - if(NO_SHOCK in src.mutations) //shockproof - return 0 if (RESIST_HEAT in src.mutations) //fireproof return 0 var/mob/living/carbon/human/H = src //make this damage method divide the damage to be done among all the body parts, then burn each body part for that much damage. will have better effect then just randomly picking a body part @@ -629,7 +627,8 @@ var/mob/living/carbon/CM = L if(CM.on_fire && CM.canmove) CM.fire_stacks -= 5 - CM.Weaken(3) + CM.weakened = max(CM.weakened, 3)//We dont check for CANWEAKEN, I don't care how immune to weakening you are, if you're rolling on the ground, you're busy. + CM.update_canmove() CM.spin(32,2) CM.visible_message("[CM] rolls on the floor, trying to put themselves out!", \ "You stop, drop, and roll!") @@ -761,7 +760,7 @@ /mob/living/proc/can_use_vents() return "You can't fit into that vent." - + /atom/movable/proc/do_attack_animation(atom/A) @@ -791,3 +790,15 @@ pixel_y_diff = -8 animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2) animate(pixel_x = initial(pixel_x), pixel_y = initial(pixel_y), time = 2) + +/mob/living/do_attack_animation(atom/A) + ..() + floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. + +/mob/living/proc/do_jitter_animation(jitteriness) + var/amplitude = min(4, (jitteriness/100) + 1) + var/pixel_x_diff = rand(-amplitude, amplitude) + var/pixel_y_diff = rand(-amplitude/3, amplitude/3) + animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6) + animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y) , time = 2) + floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 52019fc923e..cad2c176aa6 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -223,19 +223,21 @@ /mob/living/proc/IgniteMob() if(fire_stacks > 0) on_fire = 1 + src.AddLuminosity(3) update_fire() /mob/living/proc/ExtinguishMob() if(on_fire) on_fire = 0 fire_stacks = 0 + src.AddLuminosity(-3) update_fire() /mob/living/proc/update_fire() return /mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person - fire_stacks = Clamp(fire_stacks + add_fire_stacks, min = -20, max = 20) + fire_stacks = Clamp(fire_stacks + add_fire_stacks, min = -20, max = 20) /mob/living/proc/handle_fire() if(fire_stacks < 0) @@ -243,25 +245,15 @@ fire_stacks = min(0, fire_stacks)//So we dry ourselves back to default, nonflammable. if(!on_fire) return 1 - - var/oxy=0 - var/turf/T=loc - if(istype(T)) - if(istype(T,/turf/space)) - ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire - return 1 - var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment - if(G) - oxy=G.oxygen - if(oxy < 10 || fire_stacks <= 0) + var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment + if(G.oxygen < 1) ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire - return 1 + return var/turf/location = get_turf(src) location.hotspot_expose(700, 50, 1) /mob/living/fire_act() - adjust_fire_stacks(5) - if(fire_stacks > 9 && !on_fire) - IgniteMob() + adjust_fire_stacks(0.5) + IgniteMob() //Mobs on Fire end diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 52bfd6b4680..e2d710e0bc5 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -2,6 +2,32 @@ #define AI_CHECK_RADIO 2 var/list/ai_list = list() +var/list/ai_verbs_default = list( + /mob/living/silicon/ai/proc/ai_alerts, + /mob/living/silicon/ai/proc/announcement, + /mob/living/silicon/ai/proc/ai_call_shuttle, + /mob/living/silicon/ai/proc/ai_cancel_call, + /mob/living/silicon/ai/proc/ai_camera_track, + /mob/living/silicon/ai/proc/ai_camera_list, + /mob/living/silicon/ai/proc/ai_goto_location, + /mob/living/silicon/ai/proc/ai_remove_location, + /mob/living/silicon/ai/proc/ai_hologram_change, + /mob/living/silicon/ai/proc/ai_network_change, + /mob/living/silicon/ai/proc/ai_roster, + /mob/living/silicon/ai/proc/ai_statuschange, + /mob/living/silicon/ai/proc/ai_store_location, + /mob/living/silicon/ai/proc/checklaws, + /mob/living/silicon/ai/proc/control_integrated_radio, + /mob/living/silicon/ai/proc/core, + /mob/living/silicon/ai/proc/pick_icon, + /mob/living/silicon/ai/proc/sensor_mode, + /mob/living/silicon/ai/proc/show_laws_verb, + /mob/living/silicon/ai/proc/toggle_acceleration, + /mob/living/silicon/ai/proc/toggle_camera_light, + /mob/living/silicon/ai/proc/botcall, + /mob/living/silicon/ai/proc/change_arrival_message, + /mob/living/silicon/ai/proc/nano_crew_monitor +) //Not sure why this is necessary... /proc/AutoUpdateAI(obj/subject) @@ -14,7 +40,6 @@ var/list/ai_list = list() subject.attack_ai(M) return is_in_use - /mob/living/silicon/ai name = "AI" icon = 'icons/mob/AI.dmi'// @@ -69,6 +94,12 @@ var/list/ai_list = list() var/arrivalmsg = "$name, $rank, has arrived on the station." +/mob/living/silicon/ai/proc/add_ai_verbs() + src.verbs |= ai_verbs_default + +/mob/living/silicon/ai/proc/remove_ai_verbs() + src.verbs -= ai_verbs_default + /mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) var/list/possibleNames = ai_names @@ -101,22 +132,20 @@ var/list/ai_list = list() aiMulti = new(src) aiRadio = new(src) + common_radio = aiRadio aiRadio.myAi = src aiCamera = new/obj/item/device/camera/siliconcam/ai_camera(src) - - if (istype(loc, /turf)) - verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ - /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ - /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location, /mob/living/silicon/ai/proc/nano_crew_monitor, /mob/living/silicon/ai/proc/ai_cancel_call) + add_ai_verbs(src) //Languages add_language("Robot Talk", 1) add_language("Galactic Common", 1) add_language("Sol Common", 1) add_language("Tradeband", 1) + add_language("Gutter", 0) add_language("Sinta'unathi", 0) add_language("Siik'tajr", 0) add_language("Skrellian", 0) @@ -125,37 +154,18 @@ var/list/ai_list = list() add_language("Trinary", 1) add_language("Chittin", 0) add_language("Bubblish", 0) - add_language("Gutter", 0) + add_language("Clownish", 0) if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. - empty_playable_ai_cores += new/obj/structure/AIcore/deactivated(loc)//New empty terminal. + new/obj/structure/AIcore/deactivated(loc)//New empty terminal. del(src)//Delete AI. return else if (B.brainmob.mind) - if(B.alien) - B.brainmob.mind.transfer_to(src) - icon_state = "ai-alien" - verbs.Remove(,/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \ - /mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \ - /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ - /mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_cancel_call) - laws = new /datum/ai_laws/alienmov - add_language("xenocommon", 1) - else - B.brainmob.mind.transfer_to(src) + B.brainmob.mind.transfer_to(src) - src << "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras)." - src << "To look at other parts of the station, click on yourself to get a camera menu." - src << "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc." - src << "To use something, simply click on it." - src << "Use say :b to speak to your cyborgs through binary." - if (!(ticker && ticker.mode && (mind in ticker.mode.malf_ai))) - show_laws() - src << "These laws may be changed by other players, or by you being the traitor." - - job = "AI" + on_mob_init() spawn(5) new /obj/machinery/ai_powersupply(src) @@ -177,6 +187,30 @@ var/list/ai_list = list() ..() return +/mob/living/silicon/ai/proc/on_mob_init() + src << "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras)." + src << "To look at other parts of the station, click on yourself to get a camera menu." + src << "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc." + src << "To use something, simply click on it." + src << "Use say :b to speak to your cyborgs through binary. Use say :h to speak from an active holopad." + src << "For department channels, use the following say commands:" + + var/radio_text = "" + for(var/i = 1 to common_radio.channels.len) + var/channel = common_radio.channels[i] + var/key = get_radio_key_from_channel(channel) + radio_text += "[key] - [channel]" + if(i != common_radio.channels.len) + radio_text += ", " + + src << radio_text + + if (!(ticker && ticker.mode && (mind in ticker.mode.malf_ai))) + show_laws() + src << "These laws may be changed by other players, or by you being the traitor." + + job = "AI" + /mob/living/silicon/ai/proc/SetName(pickedName as text) real_name = pickedName name = pickedName @@ -225,7 +259,7 @@ var/list/ai_list = list() if(powered_ai.anchored) use_power = 2 -/mob/living/silicon/ai/verb/pick_icon() +/mob/living/silicon/ai/proc/pick_icon() set category = "AI Commands" set name = "Set AI Core Display" if(stat || aiRestorePowerRoutine) @@ -289,6 +323,9 @@ var/list/ai_list = list() /mob/living/silicon/ai/proc/ai_alerts() + set name = "Show Alerts" + set category = "AI Commands" + var/dat = "Current Station Alerts\n" dat += "Close

    " for (var/cat in alarms) @@ -323,9 +360,14 @@ var/list/ai_list = list() // this verb lets the ai see the stations manifest /mob/living/silicon/ai/proc/ai_roster() + set name = "Show Crew Manifest" + set category = "AI Commands" show_station_manifest() /mob/living/silicon/ai/proc/ai_call_shuttle() + set name = "Call Emergency Shuttle" + set category = "AI Commands" + if(src.stat == 2) src << "You can't call the shuttle because you are dead!" return @@ -905,7 +947,7 @@ var/list/ai_list = list() else lightNearbyCamera() -/mob/living/silicon/ai/proc/control_hud() +/mob/living/silicon/ai/proc/sensor_mode() set name = "Set Sensor Augmentation" set desc = "Augment visual feed with internal sensor overlays." set category = "AI Commands" diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 9d30afc6e4d..8e8ceb33c3f 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -112,7 +112,7 @@ number++ -/mob/living/silicon/ai/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite +/mob/living/silicon/ai/proc/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite set category = "AI Commands" set name = "State Laws" diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index b6dd9e64ce8..a663ae6a738 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -704,6 +704,7 @@ remove_language("Trinary") remove_language("Chittin") remove_language("Bubblish") + remove_language("Clownish") src << "\blue Translator Module toggled OFF." @@ -718,5 +719,6 @@ add_language("Trinary") add_language("Chittin") add_language("Bubblish") + add_language("Clownish") src << "\blue Translator Module toggled ON." \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 6bf18971ba6..8efab8a0f57 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -8,6 +8,21 @@ if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' act = copytext(act,1,length(act)) + //Emote Cooldown System (it's so simple!) + // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] + var/on_CD = 0 + switch(act) + //Cooldown-inducing emotes + if("ping","buzz","beep","law") //halt is exempt because it's used to stop criminal scum + on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm + //Everything else, including typos of the above emotes + else + on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown + + if(on_CD == 1) // Check if we need to suppress the emote attempt. + return // Suppress emote, you're still cooling off. + //--FalseIncarnate + switch(act) if ("me") if (src.client) diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 38267256f4b..e0d7859a398 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -156,7 +156,7 @@ number++ -/mob/living/silicon/robot/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite +/mob/living/silicon/robot/proc/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite set category = "Robot Commands" set name = "State Laws" var/list = "Which laws do you want to include when stating them for the crew?

    " diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index e9b9c58dd1e..3775adfba20 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1,3 +1,8 @@ +var/list/robot_verbs_default = list( + /mob/living/silicon/robot/proc/sensor_mode, + /mob/living/silicon/robot/proc/checklaws +) + /mob/living/silicon/robot name = "Cyborg" real_name = "Cyborg" @@ -71,8 +76,7 @@ var/braintype = "Cyborg" var/base_icon = "" var/crisis = 0 - var/hiddenborg = 0 - + var/obj/item/borg/sight/hud/sec/sechud = null var/obj/item/borg/sight/hud/med/healthhud = null @@ -82,34 +86,21 @@ spark_system.attach(src) add_language("Robot Talk", 1) + + wires = new(src) robot_modules_background = new() robot_modules_background.icon_state = "block" robot_modules_background.layer = 19 //Objects that appear on screen are on layer 20, UI should be just below it. - - wires = new(src) - ident = rand(1, 999) updatename("Default") updateicon() - if(mmi == null) - mmi = new /obj/item/device/mmi/posibrain(src) //Give the borg an MMI if he spawns without for some reason. (probably not the correct way to spawn a posibrain, but it works) - mmi.icon_state="posibrain-occupied" - if(syndie) - if(!cell) - cell = new /obj/item/weapon/stock_parts/cell(src) - laws = new /datum/ai_laws/antimov() - lawupdate = 0 - scrambledcodes = 1 - cell.maxcharge = 25000 - cell.charge = 25000 - module = new /obj/item/weapon/robot_module/syndicate(src) - hands.icon_state = "standard" - icon_state = "secborg" - modtype = "Security" - init(alien) radio = new /obj/item/device/radio/borg(src) + common_radio = radio + + init() + if(!scrambledcodes && !camera) camera = new /obj/machinery/camera(src) camera.c_tag = real_name @@ -117,6 +108,10 @@ if(wires.IsCameraCut()) // 5 = BORG CAMERA camera.status = 0 + if(mmi == null) + mmi = new /obj/item/device/mmi/posibrain(src) //Give the borg an MMI if he spawns without for some reason. (probably not the correct way to spawn a posibrain, but it works) + mmi.icon_state="posibrain-occupied" + initialize_components() //if(!unfinished) // Create all the robot parts. @@ -131,6 +126,8 @@ cell.charge = 7500 ..() + + add_robot_verbs() if(cell) var/datum/robot_component/cell_component = components["power cell"] @@ -148,17 +145,9 @@ hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank") /mob/living/silicon/robot/proc/init(var/alien=0) - if(hiddenborg) - playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) - return aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) - if(mmi.alien || alien) - laws = new /datum/ai_laws/alienmov() - connected_ai = select_active_alien_ai() - scrambledcodes = 1 - else - make_laws() - connected_ai = select_active_ai_with_fewest_borgs() + make_laws() + connected_ai = select_active_ai_with_fewest_borgs() if(connected_ai) connected_ai.connected_robots += src lawsync() @@ -174,7 +163,7 @@ if (!rbPDA) rbPDA = new/obj/item/device/pda/ai(src) rbPDA.set_name_and_job(custom_name,braintype) - if(hiddenborg) + if(scrambledcodes) rbPDA.hidden = 1 /mob/living/silicon/robot/binarycheck() @@ -451,11 +440,17 @@ C.toggled = 1 src << "\red You enable [C.name]." -/mob/living/silicon/robot/verb/control_hud() +/mob/living/silicon/robot/proc/sensor_mode() set name = "Set Sensor Augmentation" set desc = "Augment visual feed with internal sensor overlays." set category = "Robot Commands" toggle_sensor_mode() + +/mob/living/silicon/robot/proc/add_robot_verbs() + src.verbs |= robot_verbs_default + +/mob/living/silicon/robot/proc/remove_robot_verbs() + src.verbs -= robot_verbs_default /mob/living/silicon/robot/blob_act() if (stat != 2) @@ -1395,21 +1390,29 @@ icon_state = "nano_bloodhound" lawupdate = 0 scrambledcodes = 1 - hiddenborg = 1 modtype = "Commando" faction = list("nanotrasen") designation = "NT Combat Cyborg" req_access = list(access_cent_specops) - + /mob/living/silicon/robot/deathsquad/New(loc) - ..() - cell.maxcharge = 50000 - cell.charge = 50000 - radio = new /obj/item/device/radio/borg/deathsquad(src) - module = new /obj/item/weapon/robot_module/deathsquad(src) - laws = new /datum/ai_laws/deathsquad() + if(!cell) + cell = new /obj/item/weapon/stock_parts/cell(src) + cell.maxcharge = 25000 + cell.charge = 25000 - Namepick() + ..() + +/mob/living/silicon/robot/deathsquad/init() + aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) + + laws = new /datum/ai_laws/deathsquad + module = new /obj/item/weapon/robot_module/deathsquad(src) + + radio = new /obj/item/device/radio/borg/deathsquad(src) + radio.recalculateChannels() + + playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0) /mob/living/silicon/robot/deathsquad/attack_hand(mob/user) if((ckey == null) && searching_for_ckey == 0) @@ -1453,12 +1456,10 @@ get_borg_occupant(user, possiblecandidates) return - /mob/living/silicon/robot/syndicate icon_state = "syndie_bloodhound" lawupdate = 0 scrambledcodes = 1 - hiddenborg = 1 modtype = "Synd" faction = list("syndicate") designation = "Syndicate" @@ -1466,14 +1467,23 @@ req_access = list(access_syndicate) /mob/living/silicon/robot/syndicate/New(loc) - ..() - cell.maxcharge = 25000 - cell.charge = 25000 - radio = new /obj/item/device/radio/borg/syndicate(src) - module = new /obj/item/weapon/robot_module/syndicate(src) - laws = new /datum/ai_laws/syndicate_override() + if(!cell) + cell = new /obj/item/weapon/stock_parts/cell(src) + cell.maxcharge = 25000 + cell.charge = 25000 - Namepick() + ..() + +/mob/living/silicon/robot/syndicate/init() + aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) + + laws = new /datum/ai_laws/syndicate_override + module = new /obj/item/weapon/robot_module/syndicate(src) + + radio = new /obj/item/device/radio/borg/syndicate(src) + radio.recalculateChannels() + + playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0) /mob/living/silicon/robot/syndicate/canUseTopic(atom/movable/M) if(stat || lockcharge || stunned || weakened) diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index 931cb0556be..dbfcf15caa8 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -1,92 +1,4 @@ -// A special tray for the service droid. Allow droid to pick up and drop items as if they were using the tray normally -// Click on table to unload, click on item to load. Otherwise works identically to a tray. -// Unlike the base item "tray", robotrays ONLY pick up food, drinks and condiments. - -/obj/item/weapon/tray/robotray - name = "RoboTray" - desc = "An autoloading tray specialized for carrying refreshments." - -/obj/item/weapon/tray/robotray/afterattack(atom/target, mob/user as mob) - if ( !target ) - return - // pick up items, mostly copied from base tray pickup proc - // see code\game\objects\items\weapons\kitchen.dm line 241 - if ( istype(target,/obj/item)) - if ( !isturf(target.loc) ) // Don't load up stuff if it's inside a container or mob! - return - var turf/pickup = target.loc - - var addedSomething = 0 - - for(var/obj/item/weapon/reagent_containers/food/I in pickup) - - - if( I != src && !I.anchored && !istype(I, /obj/item/clothing/under) && !istype(I, /obj/item/clothing/suit) && !istype(I, /obj/item/projectile) ) - var/add = 0 - if(I.w_class == 1.0) - add = 1 - else if(I.w_class == 2.0) - add = 3 - else - add = 5 - if(calc_carry() + add >= max_carry) - break - - I.loc = src - carrying.Add(I) - overlays += image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = 30 + I.layer) - addedSomething = 1 - if ( addedSomething ) - user.visible_message("\blue [user] load some items onto their service tray.") - - return - - // Unloads the tray, copied from base item's proc dropped() and altered - // see code\game\objects\items\weapons\kitchen.dm line 263 - - if ( isturf(target) || istype(target,/obj/structure/table) ) - var foundtable = istype(target,/obj/structure/table/) - if ( !foundtable ) //it must be a turf! - for(var/obj/structure/table/T in target) - foundtable = 1 - break - - var turf/dropspot - if ( !foundtable ) // don't unload things onto walls or other silly places. - dropspot = user.loc - else if ( isturf(target) ) // they clicked on a turf with a table in it - dropspot = target - else // they clicked on a table - dropspot = target.loc - - - overlays = null - - var droppedSomething = 0 - - for(var/obj/item/I in carrying) - I.loc = dropspot - carrying.Remove(I) - droppedSomething = 1 - if(!foundtable && isturf(dropspot)) - // if no table, presume that the person just shittily dropped the tray on the ground and made a mess everywhere! - spawn() - for(var/i = 1, i <= rand(1,2), i++) - if(I) - step(I, pick(NORTH,SOUTH,EAST,WEST)) - sleep(rand(2,4)) - if ( droppedSomething ) - if ( foundtable ) - user.visible_message("\blue [user] unloads their service tray.") - else - user.visible_message("\blue [user] drops all the items on their tray.") - - return ..() - - - - -// A special pen for service droids. Can be toggled to switch between normal writting mode, and paper rename mode +// A special pen for service droids. Can be toggled to switch between normal writing mode, and paper rename mode // Allows service droids to rename paper items. /obj/item/weapon/pen/robopen diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 0ac77e3d739..3666e7f8a71 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -62,6 +62,7 @@ R.add_language("Galactic Common", 1) R.add_language("Sol Common", 1) R.add_language("Tradeband", 1) + R.add_language("Gutter", 0) R.add_language("Sinta'unathi", 0) R.add_language("Siik'tajr", 0) R.add_language("Skrellian", 0) @@ -70,7 +71,7 @@ R.add_language("Trinary", 1) R.add_language("Chittin", 0) R.add_language("Bubblish", 0) - R.add_language("Gutter", 0) + R.add_language("Clownish",0) /obj/item/weapon/robot_module/standard name = "standard robot module" @@ -216,7 +217,7 @@ src.modules += new /obj/item/device/flashlight(src) src.modules += new /obj/item/device/flash/cyborg(src) src.modules += new /obj/item/weapon/soap/nanotrasen(src) - src.modules += new /obj/item/weapon/storage/bag/trash(src) + src.modules += new /obj/item/weapon/storage/bag/trash/cyborg(src) src.modules += new /obj/item/weapon/mop(src) src.modules += new /obj/item/device/lightreplacer(src) src.modules += new /obj/item/weapon/holosign_creator(src) @@ -247,7 +248,7 @@ src.modules += new /obj/item/weapon/reagent_containers/robodropper(src) src.modules += new /obj/item/weapon/lighter/zippo(src) - src.modules += new /obj/item/weapon/tray/robotray(src) + src.modules += new /obj/item/weapon/storage/bag/tray/cyborg(src) src.modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src) src.emag = new /obj/item/weapon/reagent_containers/food/drinks/cans/beer(src) @@ -270,6 +271,7 @@ R.add_language("Galactic Common", 1) R.add_language("Sol Common", 1) R.add_language("Tradeband", 1) + R.add_language("Gutter", 1) R.add_language("Sinta'unathi", 1) R.add_language("Siik'tajr", 1) R.add_language("Skrellian", 1) @@ -278,7 +280,7 @@ R.add_language("Trinary", 1) R.add_language("Chittin", 1) R.add_language("Bubblish", 1) - R.add_language("Gutter", 1) + R.add_language("Clownish",1) /* /obj/item/weapon/robot_module/clerical //Whyyyyy? diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 9b46dbba82f..1c8e7b71d65 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -22,6 +22,7 @@ #define SEC_HUD 1 //Security HUD mode #define MED_HUD 2 //Medical HUD mode var/local_transmit //If set, can only speak to others of the same type within a short range. + var/obj/item/device/radio/common_radio /mob/living/silicon/proc/cancelAlarm() return diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 7082e7fa656..2047ee7f965 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -855,7 +855,7 @@ var/list/slot_equipment_priority = list( \ return 0 src << message return 1 - + /mob/proc/is_muzzled() return 0 @@ -873,25 +873,14 @@ var/list/slot_equipment_priority = list( \ stat(null, "CPU:\t[world.cpu]") stat(null, "Instances:\t[world.contents.len]") - if(master_controller) - /* HANDLED THROUGH PROCESS SCHEDULER - stat(null, "MasterController-[last_tick_duration] ([master_controller.processing?"On":"Off"]-[controller_iteration])") - stat(null, "Air-[master_controller.air_cost]") - stat(null, "Sun-[master_controller.sun_cost]") - stat(null, "Mob-[master_controller.mobs_cost]\t#[mob_list.len]") - stat(null, "Dis-[master_controller.diseases_cost]\t#[active_diseases.len]") - stat(null, "Mch-[master_controller.machines_cost]\t#[machines.len]") - stat(null, "Bots-[master_controller.aibots_cost]\t#[aibots.len]") - stat(null, "Obj-[master_controller.objects_cost]\t#[processing_objects.len]") - stat(null, "PiNet-[master_controller.networks_cost]\t#[pipe_networks.len]") - stat(null, "PoNet-[master_controller.powernets_cost]\t#[powernets.len]") - stat(null, "NanoUI-[master_controller.nano_cost]\t#[nanomanager.processing_uis.len]") -// stat(null, "GC-[master_controller.gc_cost]\t#[garbage.queue.len]") - stat(null, "Tick-[master_controller.ticker_cost]")*/ - stat(null,"Events-[master_controller.events_cost]\t#[event_manager.active_events.len]") - stat(null, "ALL-[master_controller.total_cost]") + if (garbageCollector) + stat(null, "\tqdel - [garbageCollector.del_everything ? "off" : "on"]") + stat(null, "\ton queue - [garbageCollector.queue.len]") + stat(null, "\ttotal delete - [garbageCollector.dels_count]") + stat(null, "\tsoft delete - [garbageCollector.soft_dels]") + stat(null, "\thard delete - [garbageCollector.hard_dels]") else - stat(null, "MasterController-ERROR") + stat(null, "Garbage Controller is not running.") if(processScheduler.getIsRunning()) var/datum/controller/process/process @@ -929,6 +918,9 @@ var/list/slot_equipment_priority = list( \ process = processScheduler.getProcess("disease") stat(null, "DIS([active_diseases.len])\t - #[process.getTicks()]\t - [process.getLastRunTime()]") + process = processScheduler.getProcess("garbage") + stat(null, "GAR\t - #[process.getTicks()]\t - [process.getLastRunTime()]") + //process = processScheduler.getProcess("sun") //stat(null, "SUN\t - #[process.getTicks()]\t - [process.getLastRunTime()]") @@ -960,6 +952,8 @@ var/list/slot_equipment_priority = list( \ for(var/atom/A in listed_turf) if(A.invisibility > see_invisible) continue + if(is_type_in_list(A, shouldnt_see)) + continue statpanel(listed_turf.name, null, A) if(mind && mind.changeling) @@ -1122,16 +1116,19 @@ var/list/slot_equipment_priority = list( \ /mob/proc/Stun(amount) if(status_flags & CANSTUN) stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun + update_canmove() return /mob/proc/SetStunned(amount) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned" if(status_flags & CANSTUN) stunned = max(amount,0) + update_canmove() return /mob/proc/AdjustStunned(amount) if(status_flags & CANSTUN) stunned = max(stunned + amount,0) + update_canmove() return /mob/proc/Weaken(amount) @@ -1155,40 +1152,49 @@ var/list/slot_equipment_priority = list( \ /mob/proc/Paralyse(amount) if(status_flags & CANPARALYSE) paralysis = max(max(paralysis,amount),0) + update_canmove() return /mob/proc/SetParalysis(amount) if(status_flags & CANPARALYSE) paralysis = max(amount,0) + update_canmove() return /mob/proc/AdjustParalysis(amount) if(status_flags & CANPARALYSE) paralysis = max(paralysis + amount,0) + update_canmove() return /mob/proc/Sleeping(amount) sleeping = max(max(sleeping,amount),0) + update_canmove() return /mob/proc/SetSleeping(amount) sleeping = max(amount,0) + update_canmove() return /mob/proc/AdjustSleeping(amount) sleeping = max(sleeping + amount,0) + update_canmove() return /mob/proc/Resting(amount) resting = max(max(resting,amount),0) + update_canmove() return /mob/proc/SetResting(amount) resting = max(amount,0) + update_canmove() return /mob/proc/AdjustResting(amount) resting = max(resting + amount,0) + update_canmove() return /mob/proc/get_species() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index b91583758af..d508eb7fb92 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -138,6 +138,8 @@ var/coughedtime = null + var/emote_cd = 0 // Used to supress emote spamming. 1 if on CD, 2 if disabled by admin (manually set), else 0 + var/inertia_dir = 0 var/music_lastplayed = "null" @@ -220,6 +222,7 @@ var/immune_to_ssd = 0 var/turf/listed_turf = null //the current turf being examined in the stat panel + var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes var/kills=0 diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index a68d5bc80f9..471aed1d7f2 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -24,9 +24,7 @@ proc/new_player_panel_proc() - var/output = "
    New Player Options" - output +="
    " - output += "

    Setup Character

    " + var/output = "

    Setup Character

    " if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) if(!ready) output += "

    Declare Ready

    " @@ -57,9 +55,9 @@ else output += "

    Show Player Polls

    " - output += "
    " + output += "" - var/datum/browser/popup = new(src, "playersetup", "
    New Player Options
    ", 210, 240) + var/datum/browser/popup = new(src, "playersetup", "
    New Player Options
    ", 220, 290) popup.set_window_options("can_close=0") popup.set_content(output) popup.open(0) @@ -105,6 +103,7 @@ if(href_list["ready"]) ready = !ready + new_player_panel_proc() if(href_list["refresh"]) src << browse(null, "window=playersetup") //closes the player setup window @@ -115,7 +114,7 @@ if(alert(src,"Are you sure you wish to observe? You will have to wait 30 minutes before being able to respawn!","Player Setup","Yes","No") == "Yes") if(!client) return 1 var/mob/dead/observer/observer = new() - + src << browse(null, "window=playersetup") spawning = 1 src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS cant last forever yo @@ -309,7 +308,7 @@ EquipRacialItems(character) character = job_master.EquipRank(character, rank, 1) //equips the human EquipCustomItems(character) - + // AIs don't need a spawnpoint, they must spawn at an empty core if(character.mind.assigned_role == "AI") @@ -346,7 +345,7 @@ else character.loc = pick(latejoin) join_message = "has arrived on the station" - + character.lastarea = get_area(loc) // Moving wheelchair if they have one if(character.buckled && istype(character.buckled, /obj/structure/stool/bed/chair/wheelchair)) @@ -398,12 +397,12 @@ if(character.mind) if((character.mind.special_role != "MODE")) var/arrivalmessage = "A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"]." - announcer.say(";[arrivalmessage]") + announcer.say(";[arrivalmessage]") else if(character.mind) if((character.mind.special_role != "MODE")) // can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc. - global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") + global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") proc/LateChoices() var/mills = world.time // 1/10 of a second, not real milliseconds but whatever @@ -444,9 +443,9 @@ proc/create_character() spawning = 1 close_spawn_windows() - + var/mob/living/carbon/human/new_character - + var/datum/species/chosen_species if(client.prefs.species) chosen_species = all_species[client.prefs.species] @@ -454,10 +453,10 @@ // Have to recheck admin due to no usr at roundstart. Latejoins are fine though. if(is_species_whitelisted(chosen_species) || has_admin_rights()) new_character = new(loc, client.prefs.species) - + if(!new_character) new_character = new(loc) - + new_character.lastarea = get_area(loc) var/datum/language/chosen_language @@ -505,9 +504,9 @@ if(client.prefs.disabilities & DISABILITY_FLAG_DEAF) new_character.dna.SetSEState(DEAFBLOCK,1,1) new_character.sdisabilities |= DEAF - + chosen_species.handle_dna(new_character) - + domutcheck(new_character) new_character.dna.UpdateSE() diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index af932fe7a39..12ef687c696 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -602,7 +602,7 @@ taj_sideburns name = "Tajara Sideburns" - icon_state = "facial_mutton" + icon_state = "facial_sideburns" species_allowed = list("Tajaran") taj_mutton diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index ce0591f6bd9..c90ebae7328 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -80,7 +80,7 @@ invisibility = 101 return ..() -/mob/proc/AIize(move=1) +/mob/proc/AIize() if(client) src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // stop the jams for AIs var/mob/living/silicon/ai/O = new (loc,,,1)//No MMI but safety is in effect. @@ -93,52 +93,40 @@ else O.key = key - if(move) - var/obj/loc_landmark + var/obj/loc_landmark + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if (sloc.name != "AI") + continue + if (locate(/mob/living) in sloc.loc) + continue + loc_landmark = sloc + if (!loc_landmark) + for(var/obj/effect/landmark/tripai in landmarks_list) + if (tripai.name == "tripai") + if(locate(/mob/living) in tripai.loc) + continue + loc_landmark = tripai + if (!loc_landmark) + O << "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone." for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name != "AI") - continue - if ((locate(/mob/living) in sloc.loc) || (locate(/obj/structure/AIcore) in sloc.loc)) - continue - loc_landmark = sloc - if (!loc_landmark) - for(var/obj/effect/landmark/tripai in landmarks_list) - if (tripai.name == "tripai") - if((locate(/mob/living) in tripai.loc) || (locate(/obj/structure/AIcore) in tripai.loc)) - continue - loc_landmark = tripai - if (!loc_landmark) - O << "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone." - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name == "AI") - loc_landmark = sloc + if (sloc.name == "AI") + loc_landmark = sloc - O.loc = loc_landmark.loc - for (var/obj/item/device/radio/intercom/comm in O.loc) - comm.ai += O + O.loc = loc_landmark.loc + for (var/obj/item/device/radio/intercom/comm in O.loc) + comm.ai += O - O << "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras)." - O << "To look at other parts of the station, click on yourself to get a camera menu." - O << "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc." - O << "To use something, simply click on it." - O << {"Use say ":b to speak to your cyborgs through binary."} - if (!(ticker && ticker.mode && (O.mind in ticker.mode.malf_ai))) - O.show_laws() - O << "These laws may be changed by other players, or by you being the traitor." + O.on_mob_init() - O.verbs += /mob/living/silicon/ai/proc/show_laws_verb - O.verbs += /mob/living/silicon/ai/proc/ai_statuschange - - O.job = "AI" + O.add_ai_verbs() O.rename_self("ai",1) - spawn(0) - del(src) - return O - + . = O + qdel(src) + /mob/living/carbon/human/make_into_mask(var/should_gib = 0) for(var/t in organs) - del(t) + qdel(t) return ..(should_gib) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index c9726924f43..3af4d2fbf2c 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -1,6 +1,7 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 // Added spess ghoasts/cameras to this so they don't add to the lag. - N3X +var/global/narsie_cometh = 0 var/global/list/uneatable = list( /turf/space, /obj/effect/overlay, @@ -508,6 +509,7 @@ var/global/list/uneatable = list( if(emergency_shuttle && emergency_shuttle.can_call()) emergency_shuttle.call_evac() emergency_shuttle.launch_time = 0 // Cannot recall + narsie_cometh = 1 /obj/machinery/singularity/narsie/proc/spawn_animation() @@ -541,7 +543,7 @@ var/global/list/uneatable = list( if(istype(A,/obj/)) var/obj/O = A O.ex_act(1.0) - if(O) del(O) + if(O) qdel(O) else if(isturf(A)) var/turf/T = A @@ -565,7 +567,7 @@ var/global/list/uneatable = list( var/obj/O = A machines -= O processing_objects -= O - O.loc = null + qdel(O) else if(isturf(A)) var/turf/T = A if(istype(T,/turf/simulated/wall)) diff --git a/code/modules/projectiles/guns/energy/advtaser.dm b/code/modules/projectiles/guns/energy/advtaser.dm index 039c569131e..b63c9dfbf16 100644 --- a/code/modules/projectiles/guns/energy/advtaser.dm +++ b/code/modules/projectiles/guns/energy/advtaser.dm @@ -11,6 +11,7 @@ charge_cost = 2000 modifystate = "advtaserstun" can_flashlight = 1 + fire_delay = 20 var/mode = 0 //0 = stun, 1 = disable @@ -24,6 +25,7 @@ user << "\red [src.name] is now set to Disable." projectile_type = "/obj/item/projectile/beam/disabler" modifystate = "advtaserdisable" + fire_delay = 0 if(1) mode = 0 charge_cost = 2000 @@ -31,6 +33,7 @@ user << "\red [src.name] is now set to stun." projectile_type = "/obj/item/projectile/energy/electrode" modifystate = "advtaserstun" + fire_delay = 20 update_icon() if(user.l_hand == src) user.update_inv_l_hand() diff --git a/code/modules/projectiles/guns/energy/hos.dm b/code/modules/projectiles/guns/energy/hos.dm new file mode 100644 index 00000000000..99019e1cd74 --- /dev/null +++ b/code/modules/projectiles/guns/energy/hos.dm @@ -0,0 +1,45 @@ +/obj/item/weapon/gun/energy/hos + name = "HoS Energy Gun" + desc = "This is a modern recreation of the antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time, its also expensive." + icon_state = "hoslaser" + item_state = null //so the human update icon uses the icon_state instead. + icon_override = 'icons/mob/in-hand/guns.dmi' + force = 10 + fire_sound = 'sound/weapons/Taser.ogg' + origin_tech = "combat=3;magnets=2" + charge_cost = 2000 + modifystate = "hoslaserstun" + projectile_type = "/obj/item/projectile/energy/electrode" + var/mode = 2 + + attack_self(mob/living/user as mob) + switch(mode) + if(2) + mode = 0 + charge_cost = 1000 + fire_sound = 'sound/weapons/Laser.ogg' + user << "\red [src.name] is now set to kill." + projectile_type = "/obj/item/projectile/beam" + modifystate = "hoslaserkill" + fire_delay = 0 + if(0) + mode = 1 + charge_cost = 500 + fire_sound = 'sound/weapons/taser2.ogg' + user << "\red [src.name] is now set to disable." + projectile_type = "/obj/item/projectile/beam/disabler" + modifystate = "hoslaserdisable" + fire_delay = 0 + if(1) + mode = 2 + charge_cost = 2000 + fire_sound = 'sound/weapons/taser.ogg' + user << "\red [src.name] is now set to stun." + projectile_type = "/obj/item/projectile/energy/electrode" + modifystate = "hoslaserstun" + fire_delay = 20 + update_icon() + if(user.l_hand == src) + user.update_inv_l_hand() + else + user.update_inv_r_hand() \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index b2951fb8eb2..3e6679a189e 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -24,6 +24,8 @@ obj/item/weapon/gun/energy/laser/retro /obj/item/weapon/gun/energy/laser/captain icon_state = "caplaser" + item_state = "caplaser" + icon_override = 'icons/mob/in-hand/guns.dmi' desc = "This is an antique laser gun. All craftsmanship is of the highest quality. It is decorated with assistant leather and chrome. The object menaces with spikes of energy. On the item is an image of Space Station 13. The station is exploding." force = 10 origin_tech = null diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 39395e3a064..3a278424dc1 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -43,9 +43,6 @@ desc = "An energy gun with an experimental miniaturized reactor." icon_state = "nucgun" origin_tech = "combat=3;materials=5;powerstorage=3" - charge_cost = 1000 - fire_sound = 'sound/weapons/Taser.ogg' - projectile_type = "/obj/item/projectile/energy/electrode" var/lightfail = 0 var/charge_tick = 0 can_flashlight = 0 @@ -120,9 +117,6 @@ update_mode() if (mode == 0) overlays += "nucgun-stun" - charge_cost = 1000 - fire_sound = 'sound/weapons/Taser.ogg' - projectile_type = "/obj/item/projectile/energy/electrode" else if (mode == 1) overlays += "nucgun-kill" diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index b7c5c2b6ab7..3591d84008b 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -20,18 +20,21 @@ fire_sound = 'sound/weapons/Taser.ogg' user << "\red [src.name] is now set to stun." projectile_type = "/obj/item/projectile/energy/electrode" + fire_delay = 20 if(0) mode = 1 charge_cost = 100 fire_sound = 'sound/weapons/Laser.ogg' user << "\red [src.name] is now set to kill." projectile_type = "/obj/item/projectile/beam" + fire_delay = 0 if(1) mode = 2 charge_cost = 200 fire_sound = 'sound/weapons/pulse.ogg' user << "\red [src.name] is now set to DESTROY." projectile_type = "/obj/item/projectile/beam/pulse" + fire_delay = 0 return isHandgun() diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index c6dd42292d6..5e8a3a501f2 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -180,7 +180,7 @@ obj/item/weapon/gun/energy/staff/focus projectile_type = "/obj/item/projectile/beam/sniper" slot_flags = SLOT_BACK charge_cost = 2500 - fire_delay = 10 + fire_delay = 50 w_class = 4.0 var/zoom = 0 diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 8abebcb8597..998c15e2c01 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -7,6 +7,7 @@ fire_sound = 'sound/weapons/Taser.ogg' projectile_type = "/obj/item/projectile/energy/electrode" cell_type = "/obj/item/weapon/stock_parts/cell/crap" + fire_delay = 20 /obj/item/weapon/gun/energy/taser/cyborg name = "taser gun" @@ -50,9 +51,9 @@ desc = "A high-tech revolver that fires internal, reusable stun cartidges in a revolving cylinder. Holds twice as much ammo as a standard taser." icon_state = "stunrevolver" fire_sound = "sound/weapons/gunshot.ogg" - origin_tech = "combat=3;materials=3;powerstorage=2" projectile_type = "/obj/item/projectile/energy/electrode" cell_type = "/obj/item/weapon/stock_parts/cell" + fire_delay = 20 diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 1cb70a29513..60043e07933 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -25,6 +25,12 @@ sparks.set_up(1, 1, src) sparks.start() proj_hit = 1 + else if(iscarbon(target)) + var/mob/living/carbon/C = target + if(HULK in C.mutations) + C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + else if(C.status_flags & CANWEAKEN) + C.do_jitter_animation(jitter) ..() /obj/item/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 436dc211d61..7550031eac2 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -640,3 +640,10 @@ datum atom/proc/create_reagents(var/max_vol) reagents = new/datum/reagents(max_vol) reagents.my_atom = src + +/datum/reagents/Destroy() + for(var/datum/reagent/reagent in reagent_list) + reagent.Destroy() + + if(my_atom) + my_atom = null \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 17d0d87fe16..4165c43e475 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -210,6 +210,7 @@ datum description = "A ubiquitous chemical substance that is composed of hydrogen and oxygen." reagent_state = LIQUID color = "#0064C8" // rgb: 0, 100, 200 + var/cooling_temperature = 2 reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume) if(!istype(M, /mob/living)) @@ -224,6 +225,7 @@ datum reaction_turf(var/turf/simulated/T, var/volume) if (!istype(T)) return + var/CT = cooling_temperature src = null if(volume >= 3) if(T.wet >= 1) return @@ -248,10 +250,10 @@ datum var/hotspot = (locate(/obj/fire) in T) if(hotspot && !istype(T, /turf/space)) var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() ) - lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0) + lowertemp.temperature = max( min(lowertemp.temperature-(CT*1000),lowertemp.temperature / CT) ,0) lowertemp.react() T.assume_air(lowertemp) - del(hotspot) + qdel(hotspot) return reaction_obj(var/obj/O, var/volume) @@ -1433,6 +1435,13 @@ datum H.adjustToxLoss(50) ..() return + if(ismonkey(M)) + var/mob/living/carbon/monkey/MO = M + if(MO.dna) + if(MO.dna.mutantrace == "plant") //plantmen monkeys (diona) take EVEN MORE damage + MO.adjustToxLoss(100) + ..() + return plasma name = "Plasma" @@ -1713,7 +1722,7 @@ datum nanites name = "Nanites" - id = "nanities" + id = "nanites" description = "Nanomachines that aid in rapid cellular regeneration." @@ -3989,4 +3998,10 @@ datum */ // Undefine the alias for REAGENTS_EFFECT_MULTIPLER -#undef REM \ No newline at end of file +#undef REM + + +/datum/reagent/Destroy() + if(holder) + holder.reagent_list -= src + holder = null diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index ce7af28cad7..6405b6ec3b6 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -207,7 +207,7 @@ !isturf(src.loc) || \ !(locate(/obj/structure/table) in src.loc) && \ !(locate(/obj/machinery/optable) in src.loc) && \ - !(locate(/obj/item/weapon/tray) in src.loc) \ + !(locate(/obj/item/weapon/storage/bag/tray) in src.loc) \ ) user << "\red You cannot slice [src] here! You need a table or at least a tray to do it." return 1 diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 3d2db2468af..17bbf565dfd 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -46,7 +46,8 @@ spray(A) playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6) - + user.changeNext_move(CLICK_CD_RANGE*2) + if(reagents.has_reagent("sacid")) message_admins("[key_name_admin(user)] fired sulphuric acid from \a [src].") log_game("[key_name(user)] fired sulphuric acid from \a [src].") diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 2e726e4a053..a6a2e459116 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -6,7 +6,7 @@ name = "Advanced Energy Gun" desc = "An energy gun with an experimental miniaturized reactor." id = "nuclear_gun" - req_tech = list("combat" = 3, "materials" = 5, "powerstorage" = 3) + req_tech = list("combat" = 4, "materials" = 5, "powerstorage" = 3) build_type = PROTOLATHE materials = list("$metal" = 5000, "$glass" = 1000, "$uranium" = 2000) reliability_base = 76 @@ -147,7 +147,7 @@ id = "stunrevolver" req_tech = list("combat" = 3, "materials" = 3, "powerstorage" = 2) build_type = PROTOLATHE - materials = list("$metal" = 4000) + materials = list("$metal" = 4000, "$glass" = 1000) build_path = /obj/item/weapon/gun/energy/stunrevolver locked = 1 category = list("Weapons") diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 5cfba55a6c9..97b9a24eb2f 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index 3fbd4b0bbee..8773d255248 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index eea28466f0a..69e492d24e9 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 84fca7e8f90..9eea53339be 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/human_races/r_diona.dmi b/icons/mob/human_races/r_diona.dmi index c09acaa9538..f83948951ea 100644 Binary files a/icons/mob/human_races/r_diona.dmi and b/icons/mob/human_races/r_diona.dmi differ diff --git a/icons/mob/in-hand/guns.dmi b/icons/mob/in-hand/guns.dmi index 8c0bdf5b143..ff8adfd7c5a 100644 Binary files a/icons/mob/in-hand/guns.dmi and b/icons/mob/in-hand/guns.dmi differ diff --git a/icons/mob/in-hand/tools.dmi b/icons/mob/in-hand/tools.dmi index d7070df48f8..86bdbd965e5 100644 Binary files a/icons/mob/in-hand/tools.dmi and b/icons/mob/in-hand/tools.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 2e5468640ea..69ead705524 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 520624e3903..ca5e197734d 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index a3bab9d2eda..6156fab8b26 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index d2eafbe18e3..1fdf5bbc625 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 1bb1b4d4d10..50667f8ff00 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index 40db65abadf..597ba552949 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 7fd23898498..4d796bb41b7 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 1afe63ffb70..6bed53895d6 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi index 7e8254301e8..7cee746fc5d 100644 Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index 3cfdd226e92..3dc1bcadfe8 100644 Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index e74d32e907e..30c8906634e 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/watertank.dmi b/icons/obj/watertank.dmi new file mode 100644 index 00000000000..fb9778719e4 Binary files /dev/null and b/icons/obj/watertank.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index 43b7d523b66..ba3bee45bc9 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -585,7 +585,7 @@ macro "macro" is-disabled = false elem name = "F4" - command = "me" + command = ".me" is-disabled = false elem name = "F5" @@ -843,7 +843,7 @@ macro "hotkeymode" is-disabled = false elem name = "F4" - command = "me" + command = ".me" is-disabled = false elem name = "F5" diff --git a/maps/cyberiad.dmm b/maps/cyberiad.dmm index 53eaf954897..a9bf362edc2 100644 --- a/maps/cyberiad.dmm +++ b/maps/cyberiad.dmm @@ -90,7 +90,7 @@ "abL" = (/obj/effect/decal/cleanable/cobweb2,/obj/structure/table,/obj/item/weapon/paper,/obj/machinery/light/small{dir = 1},/obj/item/weapon/pen,/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plating,/area/security/permabrig) "abM" = (/obj/structure/grille,/obj/structure/sign/securearea,/turf/simulated/floor/airless{icon_state = "circuit"},/area) "abN" = (/obj/structure/table,/obj/item/weapon/wrench,/obj/machinery/light/small{dir = 8},/obj/item/device/radio/intercom{broadcasting = 0; freerange = 0; frequency = 1475; listening = 1; name = "Station Intercom (Security)"; pixel_x = -30; pixel_y = 0},/turf/simulated/floor/plating,/area/security/permabrig) -"abO" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/floor/plating,/area/security/permabrig) +"abO" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 5},/turf/simulated/floor/plating,/area/security/permabrig) "abP" = (/obj/machinery/atmospherics/valve{dir = 4},/obj/machinery/light_switch{pixel_y = -25},/turf/simulated/floor/plating,/area/security/permabrig) "abQ" = (/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/machinery/atmospherics/pipe/simple/visible{dir = 9},/turf/simulated/floor/plating,/area/security/permabrig) "abR" = (/turf/simulated/floor/plating,/area/security/permabrig) @@ -2232,9 +2232,9 @@ "aQV" = (/obj/machinery/portable_atmospherics/hydroponics/soil,/turf/simulated/floor/grass,/area/hydroponics) "aQW" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/machinery/portable_atmospherics/hydroponics/soil,/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor/grass,/area/hydroponics) "aQX" = (/obj/item/device/radio/intercom{pixel_y = 25},/obj/machinery/portable_atmospherics/hydroponics/soil,/turf/simulated/floor/grass,/area/hydroponics) -"aQY" = (/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) -"aQZ" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 4; on = 1},/obj/structure/closet/crate/hydroponics,/obj/item/weapon/reagent_containers/glass/bucket,/obj/item/weapon/screwdriver,/obj/item/weapon/shovel/spade,/obj/item/weapon/wrench,/obj/item/weapon/wrench,/obj/item/weapon/reagent_containers/glass/bucket,/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) -"aRa" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) +"aQY" = (/obj/structure/table,/obj/item/weapon/watertank,/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) +"aQZ" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) +"aRa" = (/obj/structure/closet/crate/hydroponics,/obj/item/weapon/reagent_containers/glass/bucket,/obj/item/weapon/screwdriver,/obj/item/weapon/shovel/spade,/obj/item/weapon/wrench,/obj/item/weapon/wrench,/obj/item/weapon/reagent_containers/glass/bucket,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "aRb" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/closet/secure_closet/hydroponics,/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "aRc" = (/obj/item/device/radio/intercom{pixel_y = 25},/obj/structure/closet/secure_closet/hydroponics,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "aRd" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/obj/structure/closet/secure_closet/hydroponics,/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) @@ -2337,7 +2337,7 @@ "aSW" = (/turf/simulated/floor{dir = 2; icon_state = "asteroid"; tag = "icon-asteroid (NORTH)"},/turf/simulated/floor{tag = "icon-siding2 (NORTH)"; icon_state = "siding2"; dir = 1},/turf/simulated/floor{tag = "icon-siding1 (NORTH)"; icon_state = "siding1"; dir = 1},/area/hydroponics) "aSX" = (/obj/machinery/door/window/eastright{base_state = "left"; dir = 8; icon_state = "left"; name = "Hydroponics Pasture"; req_access_txt = "35"},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "aSY" = (/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) -"aSZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/structure/disposalpipe/segment,/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) +"aSZ" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 4; on = 1},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "aTa" = (/obj/structure/extinguisher_cabinet{pixel_x = -5; pixel_y = -31},/obj/machinery/light,/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "aTb" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "aTc" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) @@ -2836,10 +2836,10 @@ "bcB" = (/obj/machinery/vending/coffee,/turf/simulated/floor{dir = 8; icon_state = "escape"},/area/hallway/secondary/exit) "bcC" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/obj/effect/decal/warning_stripes/southeastcorner,/obj/effect/decal/warning_stripes/northeastcorner,/turf/simulated/floor,/area/hallway/secondary/exit) "bcD" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/access_button{command = "cycle_interior"; frequency = 1379; master_tag = "escape_dock_north_airlock"; name = "interior access button"; pixel_x = 0; pixel_y = -25; req_access_txt = "13"},/obj/effect/decal/warning_stripes/north,/obj/effect/decal/warning_stripes/south,/turf/simulated/floor,/area/hallway/secondary/exit) -"bcE" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "escape_dock_north_inner"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) +"bcE" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/door/airlock/external{aiControlDisabled = 1; frequency = 1379; hackProof = 1; icon_state = "door_locked"; id_tag = "escape_dock_north_inner"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) "bcF" = (/obj/machinery/light/small,/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 8; frequency = 1379; id_tag = "escape_dock_north_pump"},/obj/machinery/embedded_controller/radio/airlock/docking_port_multi{id_tag = "escape_dock_north_airlock"; master_tag = "escape_dock"; pixel_y = 30; req_one_access_txt = "13"; tag_airpump = "escape_dock_north_pump"; tag_chamber_sensor = "escape_dock_north_sensor"; tag_exterior_door = "escape_dock_north_outer"; tag_interior_door = "escape_dock_north_inner"},/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "escape_dock_north_sensor"; pixel_x = -8; pixel_y = 30},/turf/simulated/floor/plating,/area/hallway/secondary/exit) "bcG" = (/turf/simulated/floor/plating,/area/hallway/secondary/exit) -"bcH" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "escape_dock_north_outer"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) +"bcH" = (/obj/machinery/door/airlock/external{aiControlDisabled = 1; frequency = 1379; hackProof = 1; icon_state = "door_locked"; id_tag = "escape_dock_north_outer"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) "bcI" = (/turf/space,/area/shuttle/transport1/station) "bcJ" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/secondary/entry) "bcK" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/camera{c_tag = "Arrivals Auxiliary Docking North"; dir = 8; network = list("SS13")},/turf/simulated/floor,/area/hallway/secondary/entry) @@ -3288,9 +3288,9 @@ "bll" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor,/area/hallway/secondary/exit) "blm" = (/obj/machinery/atmospherics/pipe/manifold/hidden{dir = 8},/obj/effect/decal/warning_stripes/southeastcorner,/obj/effect/decal/warning_stripes/northeastcorner,/turf/simulated/floor,/area/hallway/secondary/exit) "bln" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/access_button{command = "cycle_interior"; frequency = 1379; master_tag = "escape_dock_south_airlock"; name = "interior access button"; pixel_x = 0; pixel_y = 25; req_access_txt = "13"},/obj/effect/decal/warning_stripes/north,/obj/effect/decal/warning_stripes/south,/turf/simulated/floor,/area/hallway/secondary/exit) -"blo" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "escape_dock_south_inner"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) +"blo" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/door/airlock/external{aiControlDisabled = 1; frequency = 1379; hackProof = 1; icon_state = "door_locked"; id_tag = "escape_dock_south_inner"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) "blp" = (/obj/machinery/light/small{dir = 1},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 8; frequency = 1379; id_tag = "escape_dock_south_pump"},/obj/machinery/embedded_controller/radio/airlock/docking_port_multi{id_tag = "escape_dock_south_airlock"; master_tag = "escape_dock"; pixel_y = -30; req_one_access_txt = "13"; tag_airpump = "escape_dock_south_pump"; tag_chamber_sensor = "escape_dock_south_sensor"; tag_exterior_door = "escape_dock_south_outer"; tag_interior_door = "escape_dock_south_inner"},/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "escape_dock_south_sensor"; pixel_x = -8; pixel_y = -30},/turf/simulated/floor/plating,/area/hallway/secondary/exit) -"blq" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "escape_dock_south_outer"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) +"blq" = (/obj/machinery/door/airlock/external{aiControlDisabled = 1; frequency = 1379; hackProof = 1; icon_state = "door_locked"; id_tag = "escape_dock_south_outer"; locked = 1; name = "Escape Airlock"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) "blr" = (/turf/space,/area/shuttle/specops/station) "bls" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/secondary/entry) "blt" = (/obj/machinery/atmospherics/pipe/manifold/hidden{dir = 8},/turf/simulated/floor{icon_state = "warningcorner"; dir = 1},/area/hallway/secondary/entry) @@ -8518,6 +8518,7 @@ "dhP" = (/obj/structure/sign/double/map/left,/turf/unsimulated/floor{icon_state = "light_on"},/area/centcom/specops) "dhQ" = (/turf/unsimulated/floor{icon_state = "vault"; dir = 8},/area/centcom/specops) "dhR" = (/obj/structure/table/reinforced,/obj/item/ashtray/glass{icon_state = "ashtray_half_gl"},/obj/item/weapon/cigbutt/cigarbutt{pixel_x = 3; pixel_y = 3},/turf/unsimulated/floor{icon_state = "dark"},/area/centcom/specops) +"dhS" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor{icon_state = "hydrofloor"},/area/hydroponics) "dhT" = (/obj/structure/sign/double/map/right,/turf/unsimulated/floor{icon_state = "light_on"},/area/centcom/specops) "dhU" = (/obj/machinery/door/poddoor{desc = "Good luck hacking this one open."; icon_state = "pdoor1"; id = "WEAPONS"; name = "Special Weaponry"; p_open = 0},/obj/machinery/door/airlock/centcom{name = "Armory - Security"; opacity = 1; req_access_txt = "102"},/turf/unsimulated/floor{icon_state = "dark"},/area/centcom/specops) "dhV" = (/obj/effect/landmark{name = "Response Team"},/obj/effect/landmark{name = "Commando"},/turf/unsimulated/floor{icon_state = "vault"; dir = 1},/area/centcom/specops) @@ -8714,9 +8715,9 @@ "dmm" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 0},/turf/unsimulated/wall,/area/centcom/evac) "dmn" = (/obj/item/flag/nt,/turf/unsimulated/floor{icon_state = "floor"},/area/centcom/evac) "dmo" = (/obj/effect/decal/warning_stripes/east,/turf/unsimulated/floor{icon_state = "floor"},/area/centcom/evac) -"dmp" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "centcom_dock_hatch"; locked = 1; name = "Arrival Airlock"; req_access = null; req_access_txt = "13"},/turf/unsimulated/floor{name = "plating"},/area/centcom/evac) +"dmp" = (/obj/machinery/door/airlock/external{aiControlDisabled = 1; frequency = 1379; hackProof = 1; icon_state = "door_locked"; id_tag = "centcom_dock_hatch"; locked = 1; name = "Arrival Airlock"; req_access = null; req_access_txt = "13"},/turf/unsimulated/floor{name = "plating"},/area/centcom/evac) "dmq" = (/turf/unsimulated/floor{name = "plating"},/area/centcom/evac) -"dmr" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "escape_shuttle_hatch"; locked = 1; name = "Shuttle Hatch"; req_access = null; req_access_txt = "13"},/turf/simulated/shuttle/floor,/area/shuttle/escape/centcom) +"dmr" = (/obj/machinery/door/airlock/external{aiControlDisabled = 1; frequency = 1379; hackProof = 1; icon_state = "door_locked"; id_tag = "escape_shuttle_hatch"; locked = 1; name = "Shuttle Hatch"; req_access = null; req_access_txt = "13"},/turf/simulated/shuttle/floor,/area/shuttle/escape/centcom) "dms" = (/turf/simulated/shuttle/plating,/area/centcom/evac) "dmt" = (/turf/simulated/shuttle/plating,/turf/simulated/shuttle/wall{tag = "icon-swall_f6"; icon_state = "swall_f6"; dir = 2},/area/centcom/evac) "dmu" = (/turf/simulated/shuttle/floor,/turf/simulated/shuttle/wall{tag = "icon-swall_f9"; icon_state = "swall_f9"; dir = 2},/area/centcom/evac) @@ -12639,8 +12640,8 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJHaKQaKRaKSaJGaKTaJzaKTaJzaKTaJzaKTaJGaKUaKVaGdaERaKWaySaKXaKYaKZaLaaLbaLcaHhaLdaLeaLfaLgaLhaLiaLjaHnaLkaJZaJZaJZaJZaJZaJZaJZaKbaLlaHpaabaGwaLmaLnaLoaLpaLqaGwaabaDOaDTaDUaLraLsaLtaLuaLvaDUaAYaaiaaiaaiaaiaLwaGCaDWaGDaDWaGCaLxaaiaaiaaiaaiaLyaLzaLAaaqaHDaLBaLCaLCaLCaLDaLEaADabJaLFaLGabJaLHabJaLIabJaLJaxXaLKaLLaLMaaqaLNaLOaLPaLQaLQaLOaLRaLSaLSaLSaLSaLSaLTaLUaLSaLVaLWaLXaLYaLZaMaaMaaMbaMcaMdaMdaMdaMeaJuaMfaMgaMhaMiaaqaMjaMkaMlaaJaaqaMmaaqaMnaMoaMpaMqaMraMsaMtaMuaMvaMwaMxaaiaMyaMzaMAaMBaMCaMDaMEaMFaMGaMHaaaaaaaaaaaaaaaaaaaaaaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaMIaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaMJaJzaJzaIcaJGaKTaJzaKTaMKaKTaJzaKTaJGaKUaKVaGdaERaMLaySaySaMMaMNaMOaMNaySaySaySaySaySaMPaMQaMRaMSaHnaMTaMUaMVaJZaJZaMWaJZaMXaMYaMZaHpaaaaGwaGwaNaaNbaNaaGwaGwaaaaDOaDTaDUaNcaNdaNeaLuaNfaDUaAYaaiaDVaDWaNgaIMaGCaDWaGDaDWaGCaIOaNhaaiaaiaaiaNiaNjaNkaNlaNmabmaaiaaiaaiaaqaNnaNoaaqaNpaHGaaqaNqaaqaNraaqaNsaNtaNuaNvaNwaNxaNyaNzaNAaNBaNCaxSaNDaNCaNCaNEaNCaNzaNFaNzaJsaNzaNzaNGaNHaNIaNJaNJaNKaNLaNMaNNaNJaNOaJrabJaNPaNQaNRaNSaNTaNUaNVaaJaNWaNXaaqaNYaNZaOaaObaMraOcaMtaMuaMvaOdaOeaaiaOfaOgaOgaOhaMFaMFaMFaMFaMGaMHaaaaaaaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaJHaOiaKRaKSaJGaKTaJzaKTaJzaKTaJzaKTaJGaKUaKVaGdaERaOjaOkaOlaOmaOnaOoaDyaOpaOqaOraOsaOtaOuaOvaOwaOwaHnaOxaOyaOzaOAaOBaOCaODaOEaOFaOGayaaaaaabaaaaOHaOIaOHaaaaabaaaayaaDTaDUaOJaOKaOLaOMaONaDUaAYaaiaOOaOPaFmaOQaORaFpaOSaFpaOTaOUaOVaaiaOWaOXaOYaOZaPaaPbaPcaPdaaaaaaaaiaPeaPfaPgaaqaPhaHGaHGaHGaPiaHGaHGaHGaaJaPjaPkaaqaPlaosaaqaPmaaqaaqaPnaPoaPpaPqaPraaqaPsaPtaaqaPlaaqaaqaaqaaqaPuaaqaaqaosaaqaaqaaqaaqaPvaJuaaqaPwaNRaPxaPyaPzaPAaPBaPCaPDaPEaaqbDSaPGaPHaPIaPJaOcaMtaMuaMvaPKaPLaaiaPMaOgaOgaOhaMFaMFaMFaMFaMGaMHaaaaaaaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPNaPOaIbaJxaJGaJzaJzaPPaJzaJzaPQaJzaJGaJHaPRaPSaERaPTaPUaPVaPWaPVaPVaPVaPVaPVaPXaDyaySaPYaPYaPYaPYaPYaPZaQaaQbaHnaHnaHnaHnaPZaQcaQdaQeaQfaQgaQgaQhaQiaQjaQgaQgaQkaQeaQlaQeaQmaDUaQnaQoaQpaQqaQraaiaaiaaiaaiaQsaQtaQuaQvaQuaQwaQxaaiaaiaQyaOZaOZaOZaOZaQzaQAaQBaQCaQDaaiaQEaPfaQFaaqaaqaaqaaqaaqaaqaaqaaqaaqaaJaQGaQHaQIaQJaQKaQLaQMaQNaaqaQOaQPaQQaQRaQSaaqaQTaQUaQVaQWaQVaQXaQYaQZaRaaRbaRcaRdaReaRfaRgaaqaRhaMaaRiaRjaRkaPxaRlaPzaPAaRmaaqaRnaRoaRpaRqaRraObaObaaqaOeaMtaMuaMvaRsaRtaaiaRuaRvaRwaRxaRyaRzaMFaMFaRAaMHaaaaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPNaIbaIcaIbaIbaIdaIeaIbaIbaIcaPOaRBayaaRCaPTaCyaRDaRDaREaRDaRFaySaRGaRHaDyaRIaRJaRKaRLaRMaRNaRLaROaRLaRLaRLaRPaRLaRLaRQaRRaRSaRTaRUaRVaRTaRWaRTaRTaRTaRTaRXaRYaRZaRLaRLaSaaSbaScaSdaSeaSfaSgaShaSiaSjaSkaSkaSkaSkaSkaSkaSlaSmaSnaSoaSpaSqaSraSsaStaSuaOZaOZaSvaSwaSxaSwaSyaSzaSAaSBaSCaSDaSEaaqaSFaSGaSHaSIaSJaSJaSKaSLaSMaSNaaqaSOaSPaSQaSQaSRaaqaSSaSTaSUaSVaSWaSWaSXaSYaSZaSYaTaaTbaTcaTdaTeaaqaPvaTfaaqaTgaThaThaTiaTjaThaTkaaqaTlaTmaaqaTnaToaObaTpaaqaTqaTraTsaMvaOeaOeaaiaTtaaiabmafaaaiaaiaaiaaiaaiabAacOaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPNaPOaIbaJxaJGaJzaJzaPPaJzaJzaPQaJzaJGaJHaPRaPSaERaPTaPUaPVaPWaPVaPVaPVaPVaPVaPXaDyaySaPYaPYaPYaPYaPYaPZaQaaQbaHnaHnaHnaHnaPZaQcaQdaQeaQfaQgaQgaQhaQiaQjaQgaQgaQkaQeaQlaQeaQmaDUaQnaQoaQpaQqaQraaiaaiaaiaaiaQsaQtaQuaQvaQuaQwaQxaaiaaiaQyaOZaOZaOZaOZaQzaQAaQBaQCaQDaaiaQEaPfaQFaaqaaqaaqaaqaaqaaqaaqaaqaaqaaJaQGaQHaQIaQJaQKaQLaQMaQNaaqaQOaQPaQQaQRaQSaaqaQTaQUaQVaQWaQVaQXaRaaQYaQZaRbaRcaRdaReaRfaRgaaqaRhaMaaRiaRjaRkaPxaRlaPzaPAaRmaaqaRnaRoaRpaRqaRraObaObaaqaOeaMtaMuaMvaRsaRtaaiaRuaRvaRwaRxaRyaRzaMFaMFaRAaMHaaaaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPNaIbaIcaIbaIbaIdaIeaIbaIbaIcaPOaRBayaaRCaPTaCyaRDaRDaREaRDaRFaySaRGaRHaDyaRIaRJaRKaRLaRMaRNaRLaROaRLaRLaRLaRPaRLaRLaRQaRRaRSaRTaRUaRVaRTaRWaRTaRTaRTaRTaRXaRYaRZaRLaRLaSaaSbaScaSdaSeaSfaSgaShaSiaSjaSkaSkaSkaSkaSkaSkaSlaSmaSnaSoaSpaSqaSraSsaStaSuaOZaOZaSvaSwaSxaSwaSyaSzaSAaSBaSCaSDaSEaaqaSFaSGaSHaSIaSJaSJaSKaSLaSMaSNaaqaSOaSPaSQaSQaSRaaqaSSaSTaSUaSVaSWaSWaSXaSZdhSaSYaTaaTbaTcaTdaTeaaqaPvaTfaaqaTgaThaThaTiaTjaThaTkaaqaTlaTmaaqaTnaToaObaTpaaqaTqaTraTsaMvaOeaOeaaiaTtaaiabmafaaaiaaiaaiaaiaaiabAacOaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaCyaTuaTvaHcaHcaHcaHcaTwaTuaCyaHeayaaTxaTyaTzaTAaTBaTCaTCaTDaySaTEaRHaTFaTGaRJaTHaTIaTJaTKaTKaYgaTLaTLaTLaTMaTNaTNaTOaTPaTQaTKaTKaTRaTSaTTaTUaTVaTVaTWaTVaTXaTSaTSaTSaTYaSbaScaSdaSeaSeaSeaSeaTZaSeaSeaSeaSeaSeaSeaUaaUbaUcaUdaUeaUfaUgaUhaUiaUjaUkaUkaUkaUlaUmaUmaUmaUnaSEaSEaSEaUoaUpaSEaaqaUqaUraSJaSJaUsaSJaUtaUuaSMaUvaaqaUwaUxaUyaUzaUAaaqaUBaUCaUDaUEaUFaUGaaqaUHaUIaUHaaqaaqaaqaosaaqaaqaPvaJuaaqaUJaNRaNRaNRaUKaNRaULaaqaaqaaqaaqaaqaaqaaqaUMaaqaMvaMvaMuaMvaUNaUOaaqaUPaUQaURaUSaUTaUUaUVaUWaUXaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaGbayaaTzaAPaGdaUYaUZaVaaVbaGdaAPaVcaVdayaaVeaPTaTzaVfaVgaTCaTCaTDaySaVhaRHaDyaTGaRJaViaVjaVkaRLaRLaVlaVmaVnaRLaVoaVpaVqaVpaVraVsaVpaVpaVtaVpaVpaVuaVvaVpaVwaVpaVxaRLaRLaRLaVyaVzaVAaVBaVCaVDaVCaVEaVFaVEaVEaVEaVEaVEaVEaVGaVHaVIaVIaVIaVIaVJaVIaVKaVLaVIaVIaVMaVNaVOaVOaVOaVOaVOaVOaVOaVPaSEaSEaaqaVQaVRaVSaVTaVTaVUaVVaUuaSMaVWaaqaaqaaqaaqaaqaVXaaqaVYaVZaWaaWbaQVaWcaaqaWdaWeaWfaWgaWhaWiaWjaWkaaqaPvaJuaaqaWlaWmaNRaWnaWoaNRaWpaWpaaqaWqaWraWsaaqaWtaWuaWvaMvaMvaWwaWxaOeaWyaaqaWzaUQaURaWAaWBaUQaUQaWCaWDaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaySaDwaTuaPSaERaDyaDyaESaPSaTuaPSaWEaWFaWGaWHaDwaWIaWIaREaWIaRFaySaWJaRHaDyaySaPYaPYaWKaPYaPYaPYaPYaPYaPYaWLaWMaPYaPYaPYaPYaPYaPYaWNaWOaWNaPYaWPaPYaWQaVjaWRaWSaWTaWUaRLaWVaPYaWWaWWaWXaWXaWXaWYaQCaQCaQCaQCaQCaQCaQCaaiaWZaXaaXbaXaaXcaXcaXdaXeaXfaXgaXhaaiaXiaQCaQCaQCaQCaQCaQCaXjaXkaXkaXkaaqaXlaXmaXnaXnaXnaXnaXoaKyaXpaXqaXraXsaXtaXuaXvaXwaaqaaqaXxaXiaXyaQCaXzaaqaXAaXBaXCaXCaXCaXCaXDaXEaaqaXFaJuaaqaXGaNRaWnaWnaWoaWnaNRaXHaaqaXIaXJaXKaaqaMvaXLaXMaXNaXNaXOaXPaXQaXRabZaXSaXTaXUaXVaUSaUQaUQaXWaWDaaaaaaaaaaaaaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaMIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/paradise.dme b/paradise.dme index 4dc32c86dca..95f52d506e6 100644 --- a/paradise.dme +++ b/paradise.dme @@ -181,6 +181,7 @@ #include "code\controllers\Processes\disease.dm" #include "code\controllers\Processes\emergencyShuttle.dm" #include "code\controllers\Processes\event.dm" +#include "code\controllers\Processes\garbage.dm" #include "code\controllers\Processes\inactivity.dm" #include "code\controllers\Processes\lighting.dm" #include "code\controllers\Processes\machinery.dm" @@ -189,7 +190,7 @@ #include "code\controllers\Processes\obj.dm" #include "code\controllers\Processes\pipenet.dm" #include "code\controllers\Processes\powernet.dm" -#include "code\controllers\Processes\Shuttle.dm" +#include "code\controllers\Processes\shuttle.dm" #include "code\controllers\Processes\sun.dm" #include "code\controllers\Processes\supply.dm" #include "code\controllers\Processes\ticker.dm" @@ -1300,6 +1301,7 @@ #include "code\modules\mob\living\carbon\monkey\login.dm" #include "code\modules\mob\living\carbon\monkey\monkey.dm" #include "code\modules\mob\living\carbon\monkey\powers.dm" +#include "code\modules\mob\living\carbon\monkey\say.dm" #include "code\modules\mob\living\carbon\monkey\update_icons.dm" #include "code\modules\mob\living\silicon\death.dm" #include "code\modules\mob\living\silicon\login.dm" @@ -1482,6 +1484,7 @@ #include "code\modules\projectiles\guns\magic.dm" #include "code\modules\projectiles\guns\projectile.dm" #include "code\modules\projectiles\guns\energy\advtaser.dm" +#include "code\modules\projectiles\guns\energy\hos.dm" #include "code\modules\projectiles\guns\energy\laser.dm" #include "code\modules\projectiles\guns\energy\nuclear.dm" #include "code\modules\projectiles\guns\energy\pulse.dm" diff --git a/sound/effects/slime_squish.ogg b/sound/effects/slime_squish.ogg new file mode 100644 index 00000000000..60e118e217b Binary files /dev/null and b/sound/effects/slime_squish.ogg differ