diff --git a/.gitignore b/.gitignore index e7f44a7c441..4a61768f59c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,11 @@ *.rsc *.dmb *.lk +<<<<<<< HEAD #ignore any files in config/, except those in subdirectories. /config/* !/config/*/* +======= +data/ +>>>>>>> 16f787a... Virology - NanoUI, gameplay tweaks, bugfixes diff --git a/baystation12.dme b/baystation12.dme index d11073692a8..03a27e50166 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -5,6 +5,65 @@ // END_INTERNALS // BEGIN_FILE_DIR #define FILE_DIR . +#define FILE_DIR "code" +#define FILE_DIR "code/TriDimension" +#define FILE_DIR "code/WorkInProgress" +#define FILE_DIR "code/WorkInProgress/Cael_Aislinn" +#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Jungle" +#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Rust" +#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/ShieldGen" +#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Supermatter" +#define FILE_DIR "code/WorkInProgress/Susan" +#define FILE_DIR "html" +#define FILE_DIR "icons" +#define FILE_DIR "icons/48x48" +#define FILE_DIR "icons/ass" +#define FILE_DIR "icons/effects" +#define FILE_DIR "icons/mecha" +#define FILE_DIR "icons/misc" +#define FILE_DIR "icons/mob" +#define FILE_DIR "icons/mob/human_races" +#define FILE_DIR "icons/mob/otherHuman" +#define FILE_DIR "icons/NTOS" +#define FILE_DIR "icons/obj" +#define FILE_DIR "icons/obj/assemblies" +#define FILE_DIR "icons/obj/atmospherics" +#define FILE_DIR "icons/obj/clothing" +#define FILE_DIR "icons/obj/doors" +#define FILE_DIR "icons/obj/flora" +#define FILE_DIR "icons/obj/machines" +#define FILE_DIR "icons/obj/pipes" +#define FILE_DIR "icons/obj/power_cond" +#define FILE_DIR "icons/pda_icons" +#define FILE_DIR "icons/pods" +#define FILE_DIR "icons/spideros_icons" +#define FILE_DIR "icons/stamp_icons" +#define FILE_DIR "icons/Testing" +#define FILE_DIR "icons/turf" +#define FILE_DIR "icons/vending_icons" +#define FILE_DIR "nano" +#define FILE_DIR "nano/images" +#define FILE_DIR "sound" +#define FILE_DIR "sound/AI" +#define FILE_DIR "sound/ambience" +#define FILE_DIR "sound/effects" +#define FILE_DIR "sound/effects/turret" +#define FILE_DIR "sound/effects/wind" +#define FILE_DIR "sound/hallucinations" +#define FILE_DIR "sound/items" +#define FILE_DIR "sound/machines" +#define FILE_DIR "sound/mecha" +#define FILE_DIR "sound/misc" +#define FILE_DIR "sound/music" +#define FILE_DIR "sound/piano" +#define FILE_DIR "sound/turntable" +#define FILE_DIR "sound/violin" +#define FILE_DIR "sound/voice" +#define FILE_DIR "sound/voice/complionator" +#define FILE_DIR "sound/voice/Serithi" +#define FILE_DIR "sound/vox" +#define FILE_DIR "sound/vox_fem" +#define FILE_DIR "sound/weapons" // END_FILE_DIR // BEGIN_PREFERENCES #define DEBUG @@ -16,12 +75,12 @@ #include "code\setup.dm" #include "code\stylesheet.dm" #include "code\world.dm" +#include "code\__HELPERS\experimental.dm" #include "code\__HELPERS\files.dm" #include "code\__HELPERS\game.dm" #include "code\__HELPERS\global_lists.dm" #include "code\__HELPERS\icons.dm" #include "code\__HELPERS\lists.dm" -#include "code\__HELPERS\loc.dm" #include "code\__HELPERS\logging.dm" #include "code\__HELPERS\maths.dm" #include "code\__HELPERS\mobs.dm" @@ -81,9 +140,11 @@ #include "code\ATMOSPHERICS\components\unary\unary_base.dm" #include "code\ATMOSPHERICS\components\unary\vent_pump.dm" #include "code\ATMOSPHERICS\components\unary\vent_scrubber.dm" +#include "code\controllers\_DynamicAreaLighting_TG.dm" #include "code\controllers\configuration.dm" #include "code\controllers\failsafe.dm" #include "code\controllers\garbage.dm" +#include "code\controllers\lighting_controller.dm" #include "code\controllers\master_controller.dm" #include "code\controllers\shuttle_controller.dm" #include "code\controllers\verbs.dm" @@ -204,6 +265,7 @@ #include "code\game\supplyshuttle.dm" #include "code\game\area\ai_monitored.dm" #include "code\game\area\areas.dm" +#include "code\game\area\Dynamic areas.dm" #include "code\game\area\Space Station 13 areas.dm" #include "code\game\dna\dna2.dm" #include "code\game\dna\dna2_domutcheck.dm" @@ -333,6 +395,7 @@ #include "code\game\machinery\machinery.dm" #include "code\game\machinery\magnet.dm" #include "code\game\machinery\mass_driver.dm" +#include "code\game\machinery\metaldetector.dm" #include "code\game\machinery\navbeacon.dm" #include "code\game\machinery\newscaster.dm" #include "code\game\machinery\OpTable.dm" @@ -568,6 +631,7 @@ #include "code\game\objects\items\weapons\AI_modules.dm" #include "code\game\objects\items\weapons\alien_specific.dm" #include "code\game\objects\items\weapons\cards_ids.dm" +#include "code\game\objects\items\weapons\cash.dm" #include "code\game\objects\items\weapons\cigs_lighters.dm" #include "code\game\objects\items\weapons\clown_items.dm" #include "code\game\objects\items\weapons\cosmetics.dm" @@ -649,8 +713,10 @@ #include "code\game\objects\structures\extinguisher.dm" #include "code\game\objects\structures\false_walls.dm" #include "code\game\objects\structures\flora.dm" +#include "code\game\objects\structures\fullwindow.dm" #include "code\game\objects\structures\girders.dm" #include "code\game\objects\structures\grille.dm" +#include "code\game\objects\structures\inflatable.dm" #include "code\game\objects\structures\janicart.dm" #include "code\game\objects\structures\kitchen_spike.dm" #include "code\game\objects\structures\ladders.dm" @@ -668,7 +734,6 @@ #include "code\game\objects\structures\tables_racks.dm" #include "code\game\objects\structures\tank_dispenser.dm" #include "code\game\objects\structures\target_stake.dm" -#include "code\game\objects\structures\transit_tubes.dm" #include "code\game\objects\structures\watercloset.dm" #include "code\game\objects\structures\windoor_assembly.dm" #include "code\game\objects\structures\window.dm" @@ -703,6 +768,9 @@ #include "code\game\objects\structures\stool_bed_chair_nest\bed.dm" #include "code\game\objects\structures\stool_bed_chair_nest\chairs.dm" #include "code\game\objects\structures\stool_bed_chair_nest\stools.dm" +#include "code\game\objects\structures\transit_tubes\station.dm" +#include "code\game\objects\structures\transit_tubes\transit_tube.dm" +#include "code\game\objects\structures\transit_tubes\transit_tube_pod.dm" #include "code\game\structure\structure.dm" #include "code\game\turfs\simulated.dm" #include "code\game\turfs\turf.dm" @@ -850,14 +918,13 @@ #include "code\modules\customitems\item_spawning.dm" #include "code\modules\customitems\definitions\base.dm" #include "code\modules\destilery\main.dm" -#include "code\modules\detectivework\detective_work.dm" -#include "code\modules\detectivework\evidence.dm" -#include "code\modules\detectivework\footprints_and_rag.dm" -#include "code\modules\detectivework\scanner.dm" +#include "code\modules\DetectiveWork\detective_work.dm" +#include "code\modules\DetectiveWork\evidence.dm" +#include "code\modules\DetectiveWork\footprints_and_rag.dm" +#include "code\modules\DetectiveWork\scanner.dm" #include "code\modules\economy\Accounts.dm" #include "code\modules\economy\Accounts_DB.dm" #include "code\modules\economy\ATM.dm" -#include "code\modules\economy\cash.dm" #include "code\modules\economy\economy_misc.dm" #include "code\modules\economy\EFTPOS.dm" #include "code\modules\economy\Events.dm" @@ -1160,6 +1227,7 @@ #include "code\modules\organs\pain.dm" #include "code\modules\organs\skeleton.dm" #include "code\modules\organs\wound.dm" +#include "code\modules\paperwork\carbonpaper.dm" #include "code\modules\paperwork\clipboard.dm" #include "code\modules\paperwork\filingcabinet.dm" #include "code\modules\paperwork\folders.dm" @@ -1398,12 +1466,6 @@ #include "code\WorkInProgress\fireworks.dm" #include "code\WorkInProgress\periodic_news.dm" #include "code\WorkInProgress\Apples\artifacts.dm" -#include "code\WorkInProgress\Aryn\Lighting\_Defs.dm" -#include "code\WorkInProgress\Aryn\Lighting\Compatibility.dm" -#include "code\WorkInProgress\Aryn\Lighting\Controller.dm" -#include "code\WorkInProgress\Aryn\Lighting\Engine.dm" -#include "code\WorkInProgress\Aryn\Lighting\Light.dm" -#include "code\WorkInProgress\Aryn\Lighting\Lightpoint.dm" #include "code\WorkInProgress\Cael_Aislinn\sculpture.dm" #include "code\WorkInProgress\Cael_Aislinn\Jungle\falsewall.dm" #include "code\WorkInProgress\Cael_Aislinn\Jungle\jungle.dm" @@ -1505,6 +1567,6 @@ #include "code\ZAS\Zone.dm" #include "interface\interface.dm" #include "interface\skin.dmf" -#include "maps\tgstation-redux-WIP.dmm" +#include "maps\NSS Cyberiad- WIP.dmm" #include "maps\RandomZLevels\clown3.dmm" // END_INCLUDE diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index b812b9f9eca..0e4a913097d 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -116,10 +116,10 @@ if(scrubbing) // Are we scrubbing gasses that are present? if(\ - (scrub_Toxins && environment.toxins > 0) ||\ - (scrub_CO2 && environment.carbon_dioxide > 0) ||\ + (scrub_Toxins && environment.toxins > 0.001) ||\ + (scrub_CO2 && environment.carbon_dioxide > 0.001) ||\ (scrub_N2O && environment.trace_gases.len > 0) ||\ - (scrub_O2 && environment.oxygen > 0)) + (scrub_O2 && environment.oxygen > 0.001)) var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() //Take a gas sample diff --git a/code/ATMOSPHERICS/datum_pipe_network.dm b/code/ATMOSPHERICS/datum_pipe_network.dm index 5e731cd8d62..044d16b6c25 100644 --- a/code/ATMOSPHERICS/datum_pipe_network.dm +++ b/code/ATMOSPHERICS/datum_pipe_network.dm @@ -54,8 +54,6 @@ datum/pipe_network for(var/datum/pipeline/line_member in giver.line_members) line_member.network = src - del(giver) - update_network_gases() return 1 diff --git a/code/WorkInProgress/Tastyfish/mainspipe.dm b/code/ATMOSPHERICS/mainspipe.dm similarity index 99% rename from code/WorkInProgress/Tastyfish/mainspipe.dm rename to code/ATMOSPHERICS/mainspipe.dm index e2b3acde640..631f3530a24 100644 --- a/code/WorkInProgress/Tastyfish/mainspipe.dm +++ b/code/ATMOSPHERICS/mainspipe.dm @@ -36,8 +36,9 @@ obj/machinery/atmospherics/mains_pipe icon = 'icons/obj/atmospherics/mainspipe.dmi' layer = 2.4 //under wires with their 2.5 + force = 20 + var/volume = 0 - var/force = 20 var/alert_pressure = 80*ONE_ATMOSPHERE @@ -535,6 +536,8 @@ obj/machinery/atmospherics/mains_pipe/cap level = 2 icon_state = "cap" +//TODO: Get Mains valves working! +/* obj/machinery/atmospherics/mains_pipe/valve icon_state = "mvalve0" @@ -700,4 +703,5 @@ obj/machinery/atmospherics/mains_pipe/valve if(open) close() else - open() \ No newline at end of file + open() +*/ \ No newline at end of file diff --git a/code/WorkInProgress/Aryn/Lighting/Compatibility.dm b/code/WorkInProgress/Aryn/Lighting/Compatibility.dm deleted file mode 100644 index ad5ca37b047..00000000000 --- a/code/WorkInProgress/Aryn/Lighting/Compatibility.dm +++ /dev/null @@ -1,49 +0,0 @@ -area/var/lighting_use_dynamic - -turf/space/is_outside = 1 -turf/simulated/shuttle/is_outside = 1 - -/datum/controller/lighting/var/processing = 1 -/datum/controller/lighting/var/iteration = 0 - -//Because so many objects jump the gun. -proc/lighting_ready() - return lighting_controller && lighting_controller.started - -turf_light_data - var/light_overlay - var/lightNW - var/lightSW - var/lightNE - var/lightSE - var/lit_by - -turf_light_data/proc/copy_from(turf/T) - light_overlay = T.light_overlay - lightNW = T.lightNW - lightSW = T.lightSW - lightNE = T.lightNE - lightSE = T.lightSE - lit_by = T.lit_by - -turf_light_data/proc/copy_to(turf/T) - T.light_overlay = light_overlay - T.lightNW = lightNW - T.lightSW = lightSW - T.lightNE = lightNE - T.lightSE = lightSE - T.lit_by = lit_by - //T.ResetValue() - -atom/proc/SetLuminosity(n) - ASSERT(n >= 0) - - n = min(n,10) //Caelcode. - if(n > 0) - //world << "[name].SetLuminosity([n]) \[[max(1,n>>1)],[n]\]" - SetLight(max(1,n),n) - else - //world << "[name].SetLuminosity(0)" - SetLight(0,0) - luminosity = n - //else lighting_controller.initial_lights.Add(src) \ No newline at end of file diff --git a/code/WorkInProgress/Aryn/Lighting/Controller.dm b/code/WorkInProgress/Aryn/Lighting/Controller.dm deleted file mode 100644 index 6220ebe3609..00000000000 --- a/code/WorkInProgress/Aryn/Lighting/Controller.dm +++ /dev/null @@ -1,99 +0,0 @@ -/* - -Overview: - Unlike the previous lighting controller, this is mostly here to hold global lighting procs and vars. - It does not process every tick, because not even DAL did something so stupid. - -Global Vars: - initial_lights - This holds all lights formed before the lighting controller started up. It becomes null on initialization. - -Class Vars: - starlight - The light value of space. - - icon_updates - The list of turfs which need an update to their overlays. - - light_border - Space turfs which are adjacent to non-space turfs. - -Class Procs: - Initialize() - Starts the lighting system, creating all light points and turf overlays. - - StarLight(n) - Sets the light produced by space. If a solar eclipse suddenly happens, it'll probably lag. - - MarkIconUpdate(turf/T) - Called when a turf needs an update to its light icon. Ensures that it only gets calculated once per turf. - - FlushIconUpdates() - Called when a light is done marking icon updates. Updates every marked turf. - - AddBorder(turf/T) & RemoveBorder(turf/T) - Called by turf/CheckForOpaqueObjects() to modify the light_border list. - - -*/ - -var/datum/controller/lighting/lighting_controller - -var/all_lightpoints_made = 0 - -var/list/lit_z_levels = list(1,5) - -/datum/controller/lighting - - var/starlight = LIGHT_STATES - var/list/icon_updates = list() - var/started = 0 - - //var/icon/border = icon('Icons/Test.dmi', "border") - -/datum/controller/lighting/New() - lighting_controller = src - -/datum/controller/lighting/proc/Initialize() - - set background = 1 - - var/start_time = world.timeofday - world << "Processing lights..." - - sleep(1) - - var/turfs_updated = 0 - var/total_turfs = world.maxx*world.maxy*lit_z_levels.len - - for(var/z in lit_z_levels) - for(var/y = 0, y <= world.maxy, y++) - for(var/x = 0, x <= world.maxx, x++) - if(x > 0 && y > 0) - - turfs_updated++ - if((turfs_updated % (total_turfs>>2)) == 0) - sleep(1) - world << "Progress: [round((turfs_updated/total_turfs)*100, 0.01)]% ([turfs_updated]/[total_turfs])" - - var/turf/T = locate(x,y,z) - if(!T.is_outside) - T.light_overlay = new(T) - //T.ResetValue() - if(!all_lightpoints_made) new/lightpoint(x+0.5,y+0.5,z) - - - - //world << "[x],[y],[z]" - - all_lightpoints_made = 1 - started = 1 - - for(var/turf/T) - if(T.light_overlay) - - T.ResetValue() - T.light_overlay.set_state(MAX_VALUE(T.lightSE), MAX_VALUE(T.lightSW), MAX_VALUE(T.lightNW), MAX_VALUE(T.lightNE)) - - world << "Lighting initialization took [(world.timeofday-start_time)/world.fps] seconds." - world << "Updated [turfs_updated] turfs." - -/datum/controller/lighting/proc/GetLightIcon(a,b,c,d) - if(a <= 2) return LIGHT_ICON_1 - else return LIGHT_ICON_2 \ No newline at end of file diff --git a/code/WorkInProgress/Aryn/Lighting/Engine.dm b/code/WorkInProgress/Aryn/Lighting/Engine.dm deleted file mode 100644 index fc94b09c6a4..00000000000 --- a/code/WorkInProgress/Aryn/Lighting/Engine.dm +++ /dev/null @@ -1,231 +0,0 @@ -/* - -Overview: - Procs given to atom and turf by the lighting engine, as well as the lighting overlay object. - -Atom Vars: - light - Contains the light object this atom is currently shining with. - -Turf Vars: - light_overlay - Contains an object showing the lighting icon over this turf. - - lit_value - Stores how brightly lit the turf is. - - has_opaque - A cached value updated by CheckForOpaqueObjects() - - is_outside - Any turf with this set to true will be considered as bright as space. - - needs_light_update - Turf is marked for icon updates when true. - - lightNE, lightSE, lightNW, lightSW - Hold the lightpoints on the four corners of this turf. See Lightpoint.dm - - lit_by - A list of lights that are lighting this turf. - -Atom Procs: - SetLight(intensity, radius) - A more versatile SetLuminosity() that allows independent control of intensity and radius. - Called behind the scenes of SetLuminosity(). - - SetOpacity(opacity) - Does the same thing as DAL. - -Turf Procs: - UpdateLight() - Called by the lighting controller. It is advisable not to call this manually due to the cost of lightpoint/max_value() - - AddLight(light/light) - Called by light/Reset() to light this turf with a particular light. - - RemoveLight(light/light) - Called by light/Off() to unlight turfs that were lit by it. - - ResetValue() - Called when lights are reset or starlight is changed. - - ResetCachedValues() - Resets cached values of all four light points. Called by ResetValue(). - - CheckForOpaqueObjects() - Called by lighting_controller.Initialize(), SetOpacity() or when a turf might change opacity. - Resets the opacity cache and looks for opaque objects. Also responsible for adding and removing borders to space. -*/ - -atom/movable/lighting_overlay - name = "" - anchored = 1 - layer = 9 - mouse_opacity = 0 - invisibility = INVISIBILITY_LIGHTING - -atom/movable/lighting_overlay/proc/set_state(a,b,c,d) - icon_state = "[a][b][c][d]" - icon = lighting_controller.GetLightIcon(a,b,c,d) - -atom/var/light/light - -turf/var/atom/movable/lighting_overlay/light_overlay - -turf/var/lit_value = 0 -turf/var/max_brightness = 0 -turf/var/has_opaque = -1 -turf/var/is_outside = 0 -turf/var/is_border = 0 - -turf/var/lightpoint/lightNE -turf/var/lightpoint/lightNW -turf/var/lightpoint/lightSE -turf/var/lightpoint/lightSW -turf/var/list/lit_by - -atom/movable/New() - . = ..() - if(luminosity) - if(!light) - SetLight(luminosity,luminosity) - else - light.atom = src - light.Reset() - else if(light) - light.atom = src - light.Reset() - if(opacity) - if(lighting_ready()) - opacity = 0 - SetOpacity(1) - -atom/movable/Del() - if(light) light.Off() - if(opacity) SetOpacity(0) - . = ..() - -atom/movable/Move(turf/newloc) - var/o = opacity - if(o) SetOpacity(0) - . = ..() - if(.) - if(o) SetOpacity(1) - -turf/Entered(atom/movable/M) - . = ..() - if(M.light) M.light.Reset() - -atom/proc/SetLight(intensity, radius) - //if(lights_verbose) world << "SetLight([intensity],[radius])" - if(!intensity) - if(!light || !light.intensity) - //if(lights_verbose) world << "Still off." - return - //if(lights_verbose) world << "Shut off light with [light.lit_turfs.len] turfs lit." - light.Off() - light.intensity = 0 - //if(lighting_ready()) lighting_controller.FlushIconUpdates() - return - if(!light) - //if(lights_verbose) world << "New light." - light = new(src) - if(light.intensity == intensity) - //if(lights_verbose) world << "Same intensity." - return - light.radius = min(radius,15) - light.intensity = intensity - light.Reset() - //if(lighting_ready()) lighting_controller.FlushIconUpdates() - -atom/proc/SetOpacity(o) - if(o == opacity) return - opacity = o - var/turf/T = loc - if(isturf(T)) - T.CheckForOpaqueObjects() - for(var/light/A in T.lit_by) - A.Reset() - - //lighting_controller.FlushIconUpdates() - -atom/proc/UpdateLights() - if(light) light.Reset() - for(var/atom/movable/A in src) - if(A.light) A.light.Reset() - -//turf/proc/UpdateLight() -// if(light_overlay) -// light_overlay.icon_state = "[lightSE.max_value()][lightSW.max_value()][lightNW.max_value()][lightNE.max_value()]" - -turf/proc/AddLight(light/light, brightness) - if(is_outside) return - - if(brightness <= 0) return - - if(!lit_by) lit_by = list() - lit_by.Add(light) - - - lit_by[light] = brightness - - if(lighting_ready()) - if(brightness > max_brightness) - lit_value = LIGHTCLAMP(brightness) - max_brightness = brightness - - if(lightNE) lightNE.cached_value = -1 - if(lightNW) lightNW.cached_value = -1 - if(lightSE) lightSE.cached_value = -1 - if(lightSW) lightSW.cached_value = -1 - - for(var/turf/T in range(1,src)) - if(T.light_overlay) - T.light_overlay.set_state(MAX_VALUE(T.lightSE), MAX_VALUE(T.lightSW), MAX_VALUE(T.lightNW), MAX_VALUE(T.lightNE)) - -turf/proc/RemoveLight(light/light) - if(lit_by) - var/brightness = lit_by[light] - lit_by.Remove(light) - if(brightness == max_brightness) - ResetValue() - if(!lit_by.len) lit_by = null - -//Only called by ChangeTurf, because it really needs it. -turf/proc/ResetAllLights() - for(var/light/light in lit_by) - light.Reset() - -/turf/space/ResetAllLights() - var/atom/movable/lighting_overlay/overlay = locate() in src - if(overlay) overlay.loc = null - light_overlay = null - is_outside = 1 - . = ..() - -turf/proc/ResetValue() - if(is_outside) - max_brightness = lighting_controller.starlight - lit_value = LIGHTCLAMP(lighting_controller.starlight) - return - - if(has_opaque < 0) CheckForOpaqueObjects() - if(has_opaque) - lit_value = 0 - else - max_brightness = 0 - for(var/light/light in lit_by) - var/brightness = lit_by[light]//light.CalculateBrightness(src) - if(brightness > max_brightness) - max_brightness = brightness - lit_value = LIGHTCLAMP(max_brightness) - - if(lighting_ready()) - if(lightNE) lightNE.cached_value = -1 - if(lightNW) lightNW.cached_value = -1 - if(lightSE) lightSE.cached_value = -1 - if(lightSW) lightSW.cached_value = -1 - for(var/turf/T in range(1,src)) - if(T.light_overlay) - T.light_overlay.set_state(MAX_VALUE(T.lightSE), MAX_VALUE(T.lightSW), MAX_VALUE(T.lightNW), MAX_VALUE(T.lightNE)) - -turf/proc/CheckForOpaqueObjects() - has_opaque = opacity - if(!opacity) - for(var/atom/movable/M in contents) - if(M.opacity) - has_opaque = 1 - break \ No newline at end of file diff --git a/code/WorkInProgress/Aryn/Lighting/Light.dm b/code/WorkInProgress/Aryn/Lighting/Light.dm deleted file mode 100644 index fd6f196645b..00000000000 --- a/code/WorkInProgress/Aryn/Lighting/Light.dm +++ /dev/null @@ -1,89 +0,0 @@ -/* - -Overview: - This object functions similarly to /tg/'s /light. It is responsible for calculating what turfs are lit by it. - -Class Vars: - radius - Set by atom/SetLight(). This stores how far out turfs will be lit up. - intensity - Set by atom/SetLight(). Stores the amount of light generated at the center. - lit_turfs - A list of turfs being lit by this light. - atom - The atom this light is attached to. - -Class Procs: - Reset() - This is called whenever the light changes, or the underlying atom changes position. - - Off() - A quick way to turn off a light. Removes the light from all turfs in lit_turfs. - - CalculateBrightness(turf/T) - Returns the brightness that should be displayed by this light on a specific turf. - -*/ - - -light/var/radius = 0 -light/var/intensity = 0 -light/var/ambient_extension = 3 -light/var/list/lit_turfs = list() -light/var/atom/atom - -light/New(atom/atom, radius, ambience=3) - ASSERT(atom) - - if(istype(atom)) - src.atom = atom - else - src.intensity = atom - src.radius = radius - src.ambient_extension = ambience - -light/proc/Reset() - //if(atom.lights_verbose) world << "light.Reset()" - Off() - if(intensity > 0) - //if(atom.lights_verbose) world << "Restoring light." - var/turf/loc = atom - for(var/turf/T in view(loc,radius+ambient_extension)) - if(!T.is_outside) - var/brightness = CalculateBrightness(T, loc) - T.AddLight(src, brightness) - lit_turfs.Add(T) - //if(atom.lights_verbose) world << "[lit_turfs.len] turfs added." - -light/proc/Off() - //if(atom.lights_verbose) world << "light.Off()" - for(var/turf/T in lit_turfs) - T.RemoveLight(src) - lit_turfs.Cut() - -light/proc/Flash(t) - Reset() - spawn(t) - Off() - -light/proc/CalculateBrightness(turf/T, turf/loc) - ASSERT(T) - var/square = DISTSQ3(loc.x-T.x,loc.y-T.y,loc.z-T.z) - if(square > (radius+ambient_extension)*(radius+ambient_extension)) return 0 - //+2 offset gives an ambient light effect. - - var/value = ((radius)/(2*FSQRT(square) + 1)) * intensity - 0.48 - /* - lightRadius - ---------------- * lightValue - 0.48 - 2 * distance + 1 - - The light decreases by twice the distance, starting from the radius. - The + 1 causes the graph to shift to the left one unit so that division by zero is prevented on the source tile. - - This is then multiplied by the light value to give the final result. - The -0.48 offset causes the value to be near zero at the radius. - - This gives a result which is likely close to the inverse-square law in two dimensions instead of three. - */ - - - return max(min( value , intensity), 0) //Ensure the value never goes above the maximum light value or below zero. - - //return cos(90 * sqrt(square) / max(1,lightRadius)) * lightValue \ No newline at end of file diff --git a/code/WorkInProgress/Aryn/Lighting/Lightpoint.dm b/code/WorkInProgress/Aryn/Lighting/Lightpoint.dm deleted file mode 100644 index eeeec4c7068..00000000000 --- a/code/WorkInProgress/Aryn/Lighting/Lightpoint.dm +++ /dev/null @@ -1,59 +0,0 @@ -/* - -Overview: - Perhaps the most cryptic datum in the lighting engine, there are four of these at the corners of every turf. - Any two turfs that share a corner will also have the same lightpoint. Because of the nature of the icons used, - light is shown at the corner of the turf rather than in the middle, necessitating some way to keep track of what - icon state to use. - -Class Vars: - x, y, z - The position of the lightpoint. x and y will usually be expressed in terms of 0.5 due to its location on the corner. - - NE, NW, SE, SW - The turfs that are in these directions relative to the lightpoint. - - cached_value - A cached value of max_value(). - -Class Procs: - max_value() - The maximum of the light amounts on the four turfs of this light point. - -*/ - -lightpoint - var/x - var/y - var/z - - var/turf/NE - var/turf/NW - var/turf/SW - var/turf/SE - - var/cached_value = -1 - - New(x,y,z) - var/turf/T = locate(x+0.5,y+0.5,z) - if(T) - NE = T - T.lightSW = src - T = locate(x-0.5,y+0.5,z) - if(T) - NW = T - T.lightSE = src - T = locate(x-0.5,y-0.5,z) - if(T) - SW = T - T.lightNE = src - T = locate(x+0.5,y-0.5,z) - if(T) - SE = T - T.lightNW = src - - proc/max_value() - var - valueA = VALUE_OF(NW) - valueB = VALUE_OF(NE) - valueC = VALUE_OF(SW) - valueD = VALUE_OF(SE) - cached_value = max(valueA,valueB,valueC,valueD) - return cached_value \ No newline at end of file diff --git a/code/WorkInProgress/Aryn/Lighting/Verbs.dm b/code/WorkInProgress/Aryn/Lighting/Verbs.dm deleted file mode 100644 index f9e4d7c688f..00000000000 --- a/code/WorkInProgress/Aryn/Lighting/Verbs.dm +++ /dev/null @@ -1,34 +0,0 @@ -var/icon/lighting_dbg = icon('icons/Testing/Zone.dmi', "created") - -atom/var/lights_verbose = 0 - -obj/machinery/light/verb/ShowInfluence() - set src in world - - lights_verbose = 1 - usr << "[src]" - if(light) - usr << "Intensity: [light.intensity]" - usr << "Radius: [light.radius]" - - for(var/turf/T in light.lit_turfs) - T.overlays += lighting_dbg - spawn(50) - for(var/turf/T in light.lit_turfs) - T.overlays -= lighting_dbg - -turf/verb/ShowData() - set src in world - - usr << "[src]" - usr << "[MAX_VALUE(lightSE)][MAX_VALUE(lightSW)][MAX_VALUE(lightNW)][MAX_VALUE(lightNE)]" - usr << "Lit Value: [lit_value]" - usr << "Max Brightness: [max_brightness]" - - usr << "Lit By: " - for(var/light/light in lit_by) - usr << " - [light.atom] \[[lit_by[light]]\][(lit_by[light] == max_brightness ? "(MAX)" : "")]" - light.atom.overlays += lighting_dbg - spawn(50) - for(var/light/light in lit_by) - light.atom.overlays -= lighting_dbg \ No newline at end of file diff --git a/code/WorkInProgress/Aryn/Lighting/_Defs.dm b/code/WorkInProgress/Aryn/Lighting/_Defs.dm deleted file mode 100644 index 72069a1afa8..00000000000 --- a/code/WorkInProgress/Aryn/Lighting/_Defs.dm +++ /dev/null @@ -1,19 +0,0 @@ -#define LIGHT_ICON_1 'icons/effects/lights/lighting5-1.dmi' -#define LIGHT_ICON_2 'icons/effects/lights/lighting5-2.dmi' -#define LIGHT_STATES 4 - -#define SQ(X) ((X)*(X)) -#define DISTSQ3(A,B,C) (SQ(A)+SQ(B)+SQ(C)) -#define FSQRT(X) (X >= fastroot.len ? new_fsqrt(X) : fastroot[(X)+1]) -#define MAX_VALUE(X) (X.cached_value < 0 ? X.max_value() : X.cached_value) -#define VALUE_OF(X) ( !X ? 0 : ( X.is_outside ? LIGHTCLAMP(lighting_controller.starlight) : X.lit_value ) ) -#define LIGHTCLAMP(x) ( max(0,min(LIGHT_STATES,round(x,1))) ) - -var/list/fastroot = list(0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7) - -proc/new_fsqrt(n) - //world << "Adding [n-fastroot.len] entries to root table." - for(var/i = fastroot.len, i <= n, i++) - fastroot += round(sqrt(i)) \ No newline at end of file diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm b/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm index f375716b21e..3bb8a9bda9e 100644 --- a/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm +++ b/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm @@ -114,12 +114,10 @@ A.fired() */ proc/Emit() - var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) + var/obj/item/projectile/beam/emitter/A = getFromPool(/obj/item/projectile/beam/emitter, loc) A.frequency = frequency A.damage = mega_energy * 500 - // - A.icon_state = "emitter" - playsound(src.loc, 'sound/weapons/emitter.ogg', 25, 1) + playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1) use_power(100 * mega_energy + 500) /*if(prob(35)) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread diff --git a/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm b/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm index 04c07733df2..ee2b787f7fb 100644 --- a/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm +++ b/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm @@ -92,8 +92,8 @@ src.fire_delay = rand(20,100) src.shot_number = 0 use_power(1000) - var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) - playsound(src.loc, 'sound/weapons/emitter.ogg', 25, 1) + var/obj/item/projectile/beam/emitter/A = getFromPool(/obj/item/projectile/beam/emitter, loc) + playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1) if(prob(35)) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) diff --git a/code/WorkInProgress/Cael_Aislinn/sculpture.dm b/code/WorkInProgress/Cael_Aislinn/sculpture.dm index 0a1b14d1ae0..4589583f96b 100644 --- a/code/WorkInProgress/Cael_Aislinn/sculpture.dm +++ b/code/WorkInProgress/Cael_Aislinn/sculpture.dm @@ -185,7 +185,7 @@ var/num_turfs = get_dist(src,target_mob) while(get_turf(src) != target_turf && num_turfs > 0) for(var/obj/structure/window/W in next_turf) - W.ex_act(2) + W.destroy() for(var/obj/structure/table/O in next_turf) O.ex_act(1) for(var/obj/structure/grille/G in next_turf) @@ -225,7 +225,7 @@ var/num_turfs = get_dist(src,target_turf) while(get_turf(src) != target_turf && num_turfs > 0) for(var/obj/structure/window/W in next_turf) - W.ex_act(2) + W.destroy() for(var/obj/structure/table/O in next_turf) O.ex_act(1) for(var/obj/structure/grille/G in next_turf) diff --git a/code/WorkInProgress/ZomgPonies/karma.dm b/code/WorkInProgress/ZomgPonies/karma.dm index 562139e92be..46d38e35f28 100644 --- a/code/WorkInProgress/ZomgPonies/karma.dm +++ b/code/WorkInProgress/ZomgPonies/karma.dm @@ -144,8 +144,8 @@ You've gained [totalkarma] total karma in your time here.
"} /client/proc/karmashopmenu() var/dat = {"Karma Shop
Unlock Barber -- 5KP
- Unlock Nanotrasen Representative -- 15KP
- Unlock Customs Officer -- 30KP
+ Unlock Nanotrasen Representative -- 30KP
+ Unlock Customs Officer -- 15KP
Unlock BlueShield -- 30KP

Unlock Machine People -- 15KP
diff --git a/code/WorkInProgress/buildmode.dm b/code/WorkInProgress/buildmode.dm index 6d3509db6e0..f5474e8a8b2 100644 --- a/code/WorkInProgress/buildmode.dm +++ b/code/WorkInProgress/buildmode.dm @@ -54,8 +54,8 @@ if(SOUTH) dir = WEST if(WEST) - dir = NORTHWEST - if(NORTHWEST) + dir = SOUTHWEST + if(SOUTHWEST) dir = NORTH return 1 @@ -120,7 +120,7 @@ screen_loc = "NORTH,WEST+2" var/varholder = "name" var/valueholder = "derp" - var/objholder = "/obj/structure/closet" + var/objholder = /obj/structure/closet Click(location, control, params) var/list/pa = params2list(params) @@ -145,13 +145,13 @@ if(1) return 1 if(2) - objholder = input(usr,"Enter typepath:" ,"Typepath","/obj/structure/closet") - var/list/removed_paths = list("/obj/effect/bhole") - if(objholder in removed_paths) + objholder = text2path(input(usr,"Enter typepath:" ,"Typepath","/obj/structure/closet")) + if(!ispath(objholder)) + objholder = /obj/structure/closet alert("That path is not allowed.") - objholder = "/obj/structure/closet" - else if (dd_hasprefix(objholder, "/mob") && !check_rights(R_DEBUG,0)) - objholder = "/obj/structure/closet" + else + if(ispath(objholder,/mob) && !check_rights(R_DEBUG,0)) + objholder = /obj/structure/closet if(3) var/list/locked = list("vars", "key", "ckey", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "viruses", "cuffed", "ka", "last_eaten", "urine") @@ -171,7 +171,8 @@ master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as obj in world if("turf-reference") master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as turf in world - return 1 + return 1 + /proc/build_click(var/mob/user, buildmode, params, var/obj/object) var/obj/effect/bmode/buildholder/holder = null @@ -229,13 +230,16 @@ if(WEST) var/obj/structure/window/reinforced/WIN = new/obj/structure/window/reinforced(get_turf(object)) WIN.dir = WEST - if(NORTHWEST) - var/obj/structure/window/reinforced/WIN = new/obj/structure/window/reinforced(get_turf(object)) - WIN.dir = NORTHWEST + if(SOUTHWEST) + new/obj/structure/window/full/reinforced(get_turf(object)) if(2) if(pa.Find("left")) - var/obj/A = new holder.buildmode.objholder (get_turf(object)) - A.dir = holder.builddir.dir + if(ispath(holder.buildmode.objholder,/turf)) + var/turf/T = get_turf(object) + T.ChangeTurf(holder.buildmode.objholder) + else + var/obj/A = new holder.buildmode.objholder (get_turf(object)) + A.dir = holder.builddir.dir else if(pa.Find("right")) if(isobj(object)) del(object) diff --git a/code/WorkInProgress/computer3/computers/communications.dm b/code/WorkInProgress/computer3/computers/communications.dm index 01351dc4863..23b2540ade3 100644 --- a/code/WorkInProgress/computer3/computers/communications.dm +++ b/code/WorkInProgress/computer3/computers/communications.dm @@ -191,7 +191,7 @@ usr << "Message transmitted." log_say("[key_name(usr)] has made a Centcomm announcement: [input]") centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown + spawn(600)//10 minute cooldown centcomm_message_cooldown = 0 @@ -208,7 +208,7 @@ usr << "Message transmitted." log_say("[key_name(usr)] has made a Syndicate announcement: [input]") centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown + spawn(600)//10 minute cooldown centcomm_message_cooldown = 0 if("RestoreBackup" in href_list) diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index ea839b87298..9c628b963e3 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -86,7 +86,7 @@ obj/item/check_airflow_movable(n) return if(src:shoes) if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) - if(src:shoes:magpulse) + if(src:shoes.flags & NOSLIP) return src << "\red You are sucked away by airflow!" var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm index fece782aa71..e989d654557 100644 --- a/code/ZAS/Turf.dm +++ b/code/ZAS/Turf.dm @@ -173,7 +173,6 @@ if(connections) connections.update_all() /turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air - del(giver) return 0 /turf/return_air() diff --git a/code/__HELPERS/experimental.dm b/code/__HELPERS/experimental.dm new file mode 100644 index 00000000000..236f468c40f --- /dev/null +++ b/code/__HELPERS/experimental.dm @@ -0,0 +1,134 @@ +/* + * Experimental procs by ESwordTheCat. + */ + +/* + * Get index of last char occurence to string. + * + * @args + * A, string to be search + * B, char used for search + * + * @return + * >0, index of char at string + * 0, char not found + * -1, parameter B is not a char + * -2, parameter A is not a string + */ +/proc/EgijkAeN(const/A, const/B) + if (istext(A) == 0 || length(A) < 1) + return -2 + + if (istext(B) == 0 || length(B) > 1) + return -1 + + var/i = findtext(A, B) + + if (0 == i) + return 0 + + while (i) + . = 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. + */ + +#define DEBUG_OBJECT_POOL 0 +#define MAINTAINING_OBJECT_POOL_COUNT 20 + +var/list/masterPool = list() + +/* + * @args + * A, object type + * B, location to spawn + * + * Example call: getFromPool(/obj/item/weapon/shard, loc) + */ +/proc/getFromPool(const/A, const/B) + if (isnull(masterPool[A])) + #if DEBUG_OBJECT_POOL + world << "DEBUG_OBJECT_POOL: new proc has been called ([A])." + #endif + + return new A(B) + + var/atom/movable/Object = masterPool[A][1] + masterPool[A] -= Object + + #if DEBUG_OBJECT_POOL + world << "DEBUG_OBJECT_POOL: getFromPool([A]) [length(masterPool[A])]" + #endif + + if (!length(masterPool[A])) + masterPool[A] = null + + Object.loc = B + return Object + +/* + * @args + * A, object instance + * + * @return + * -1, if A is not a movable atom + * + * Example call: returnToPool(src) + */ +/proc/returnToPool(const/A) + if (!istype(A, /atom/movable)) + return -1 + + var/atom/movable/Object = A + Object.resetVariables() + Object.loc = null + + if (isnull(masterPool[Object.type])) + #if DEBUG_OBJECT_POOL + world << "DEBUG_OBJECT_POOL: [Object.type] pool is empty, recreating pool." + #endif + + masterPool[Object.type] = list() + else if (length(masterPool[Object.type]) > MAINTAINING_OBJECT_POOL_COUNT) + #if DEBUG_OBJECT_POOL + world << "DEBUG_OBJECT_POOL: returnToPool([Object.type]) exceeds [num2text(MAINTAINING_OBJECT_POOL_COUNT)] discarding..." + #endif + + return + + #if DEBUG_OBJECT_POOL + world << "DEBUG_OBJECT_POOL: returnToPool([Object.type]) [length(masterPool[Object.type])]" + #endif + + masterPool[Object.type] += Object + +#undef MAINTAINING_OBJECT_POOL_COUNT +#undef DEBUG_OBJECT_POOL + +/* + * Override this if the object variables needed to reset. + * + * Example: see, code\game\objects\structures\grille.dm + */ +/atom/movable + proc/resetVariables() + name = initial(name) + density = initial(density) + icon = initial(icon) + icon_state = initial(icon_state) + dir = initial(dir) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 5cbba11b197..13f4742c040 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -42,6 +42,8 @@ var/global/list/skin_styles_female_list = list() //unused //Underwear var/global/list/underwear_m = list("White", "Grey", "Green", "Blue", "Black", "Mankini", "None") //Curse whoever made male/female underwear diffrent colours var/global/list/underwear_f = list("Red", "White", "Yellow", "Blue", "Black", "Thong", "None") + //undershirt +var/global/list/undershirt_t = list("Black Tank top", "White Tank top", "Black shirt", "White shirt", "None") //Backpacks var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt") diff --git a/code/__HELPERS/loc.dm b/code/__HELPERS/loc.dm deleted file mode 100644 index 91be708854d..00000000000 --- a/code/__HELPERS/loc.dm +++ /dev/null @@ -1,7 +0,0 @@ -atom/movable/proc/setloc(newloc) - if(light) - var/oldloc = loc - loc = newloc - if(isturf(newloc) != isturf(oldloc)) light.Reset() - else - loc = newloc diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 19e1562b183..84ee98948d2 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -76,25 +76,6 @@ proc/age2agedescription(age) if(70 to INFINITY) return "elderly" else return "unknown" -/* -Proc for attack log creation, because really why not -1 argument is the actor -2 argument is the target of action -3 is the description of action(like punched, throwed, or any other verb) -4 is the tool with which the action was made(usually item) -5 is additional information, anything that needs to be added -*/ - -proc/add_logs(mob/target, mob/user, what_done, var/object=null, var/addition=null) - if(ismob(user)) - user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]") - if(ismob(target)) - target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user.name][ismob(user) ? "([user.ckey])" : ""][object ? " with [object]" : " "][addition]") - log_attack("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]") - if(target.client) - if(what_done != ("shaked" || "CPRed" || "grabbed")) - message_admins("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition](JMP)") - proc/RoundHealth(health) switch(health) if(100 to INFINITY) @@ -117,3 +98,23 @@ proc/RoundHealth(health) return "health-100" return "0" + +/* +Proc for attack log creation, because really why not +1 argument is the actor +2 argument is the target of action +3 is the description of action(like punched, throwed, or any other verb) +4 is the tool with which the action was made(usually item) +5 is additional information, anything that needs to be added +*/ + +proc/add_logs(mob/target, mob/user, what_done, var/object=null, var/addition=null) + if(ismob(user)) + user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]") + if(ismob(target)) + target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user.name][ismob(user) ? "([user.ckey])" : ""][object ? " with [object]" : " "][addition]") + log_attack("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]") + if(target.client) + if(what_done != ("shaked" || "CPRed" || "grabbed")) + message_admins("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition](JMP)") + diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index 51f56d9d122..0961f4c1273 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -1,3 +1,8 @@ +// So you can be all 10 SECONDS +#define SECONDS **10 +#define MINUTES **600 +#define HOURS **36000 + //Returns the world time in english proc/worldtime2text(time = world.time) return "[round(time / 36000)+12]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]" diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index e1a70bb3a14..f94da8b6995 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -172,7 +172,7 @@ Turf and target are seperate in case you want to teleport some distance from a t /proc/DirBlocked(turf/loc,var/dir) for(var/obj/structure/window/D in loc) if(!D.density) continue - if(D.dir == SOUTHWEST) return 1 + if(D.is_fulltile()) return 1 if(D.dir == dir) return 1 for(var/obj/machinery/door/D in loc) diff --git a/code/_onclick/adjacent.dm b/code/_onclick/adjacent.dm index c02737400ba..b39df751896 100644 --- a/code/_onclick/adjacent.dm +++ b/code/_onclick/adjacent.dm @@ -46,7 +46,7 @@ continue // could not leave T0 in that direction var/turf/T1 = get_step(T0,d) - if(!T1 || T1.density || !T1.ClickCross(get_dir(T1,T0) & get_dir(T1,src), border_only = 0)) + if(!T1 || T1.density || !T1.ClickCross(get_dir(T1,T0) | get_dir(T1,src), border_only = 0)) continue // couldn't enter or couldn't leave T1 if(!src.ClickCross(get_dir(src,T1), border_only = 1, target_atom = target)) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index f4e4283fa59..caa4d1c62f4 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -168,6 +168,8 @@ */ /mob/proc/RangedAttack(var/atom/A, var/params) if(!mutations.len) return + if(ishuman(src) && (istype(src:gloves, /obj/item/clothing/gloves/yellow/power)) && a_intent == "harm") + PowerGlove(A) if((M_LASER in mutations) && a_intent == "harm") LaserEyes(A) // moved into a proc below return @@ -268,7 +270,7 @@ var/turf/T = get_turf(src) var/turf/U = get_turf(A) - var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc ) + var/obj/item/projectile/beam/LE = getFromPool(/obj/item/projectile/beam, loc) LE.icon = 'icons/effects/genetics.dmi' LE.icon_state = "eyelasers" playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1) @@ -290,6 +292,70 @@ else src << "\red You're out of energy! You need food!" +/mob/proc/PowerGlove(atom/A) + return + +/mob/living/carbon/human/PowerGlove(atom/A) + var/obj/item/clothing/gloves/yellow/power/G = src:gloves + var/time = 100 + var/turf/T = get_turf(src) + var/turf/U = get_turf(A) + var/obj/structure/cable/cable = locate() in T + if(!cable || !istype(cable)) + return + if(world.time < G.next_shock) + src << "[G] aren't ready to shock again!" + return + src.visible_message("[name] fires an arc of electricity!", \ + "You fire an arc of electricity!", \ + "You hear the loud crackle of electricity!") + var/datum/powernet/PN = cable.get_powernet() + var/available = 0 + var/obj/item/projectile/beam/lightning/L = getFromPool(/obj/item/projectile/beam/lightning, loc) + if(PN) + available = PN.avail + L.damage = PN.get_electrocute_damage() + 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() + if(L.damage <= 0) + //del(L) + returnToPool(L) + if(L) + playsound(get_turf(src), 'sound/effects/eleczap.ogg', 75, 1) + L.tang = L.adjustAngle(get_angle(U,T)) + L.icon = midicon + L.icon_state = "[L.tang]" + L.firer = usr + L.def_zone = get_organ_target() + L.original = src + L.current = U + L.starting = U + L.yo = U.y - T.y + L.xo = U.x - T.x + spawn( 1 ) + L.process() + + next_move = world.time + 12 + G.next_shock = world.time + time // Simple helper to face what you clicked on, in case it should be needed in more than one place /mob/proc/face_atom(var/atom/A) if( stat || buckled || !A || !x || !y || !A.x || !A.y ) return diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm index f4231464efa..ff46b6b10b6 100644 --- a/code/controllers/failsafe.dm +++ b/code/controllers/failsafe.dm @@ -45,8 +45,7 @@ var/datum/controller/failsafe/Failsafe MC_defcon = 0 MC_iteration = controller_iteration - //Lighting controller now neither processes nor iterates. - /*if(lighting_controller.processing) + if(lighting_controller.processing) if(lighting_iteration == lighting_controller.iteration) //master_controller hasn't finished processing in the defined interval switch(lighting_defcon) if(0 to 3) @@ -61,7 +60,7 @@ var/datum/controller/failsafe/Failsafe lighting_defcon = 0 else lighting_defcon = 0 - lighting_iteration = lighting_controller.iteration*/ + lighting_iteration = lighting_controller.iteration else MC_defcon = 0 lighting_defcon = 0 diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 417c618c8cc..c1628fcdeaf 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -83,7 +83,6 @@ datum/controller/game_controller/proc/setup() if(ticker) ticker.pregame() - new/datum/controller/lighting() lighting_controller.Initialize() @@ -162,28 +161,28 @@ datum/controller/game_controller/proc/process() //MOBS timer = world.timeofday - process_mobs() + processMobs() mobs_cost = (world.timeofday - timer) / 10 sleep(breather_ticks) //DISEASES timer = world.timeofday - process_diseases() + processDiseases() diseases_cost = (world.timeofday - timer) / 10 sleep(breather_ticks) //MACHINES timer = world.timeofday - process_machines() + processMachines() machines_cost = (world.timeofday - timer) / 10 sleep(breather_ticks) //OBJECTS timer = world.timeofday - process_objects() + processObjects() objects_cost = (world.timeofday - timer) / 10 sleep(breather_ticks) @@ -191,28 +190,28 @@ datum/controller/game_controller/proc/process() //PIPENETS if(!pipe_processing_killed) timer = world.timeofday - process_pipenets() + processPipenets() networks_cost = (world.timeofday - timer) / 10 sleep(breather_ticks) //POWERNETS timer = world.timeofday - process_powernets() + processPowernets() powernets_cost = (world.timeofday - timer) / 10 sleep(breather_ticks) //NANO UIS timer = world.timeofday - process_nano() + processNano() nano_cost = (world.timeofday - timer) / 10 sleep(breather_ticks) //EVENTS timer = world.timeofday - process_events() + processEvents() events_cost = (world.timeofday - timer) / 10 //TICKER @@ -237,112 +236,86 @@ datum/controller/game_controller/proc/process() else sleep(10) -datum/controller/game_controller/proc/process_mobs() - var/i = 1 - while(i<=mob_list.len) - var/mob/M = mob_list[i] - if(M) - last_thing_processed = M.type - M.Life() - i++ +/datum/controller/game_controller/proc/processMobs() + for (var/mob/Mob in mob_list) + if (Mob) + last_thing_processed = Mob.type + Mob.Life() continue - mob_list.Cut(i,i+1) -datum/controller/game_controller/proc/process_diseases() - var/i = 1 - while(i<=active_diseases.len) - var/datum/disease/Disease = active_diseases[i] + mob_list = mob_list - Mob + +/datum/controller/game_controller/proc/processDiseases() + for (var/datum/disease/Disease in active_diseases) if(Disease) last_thing_processed = Disease.type Disease.process() - i++ continue - active_diseases.Cut(i,i+1) -datum/controller/game_controller/proc/process_machines() - var/i = 1 - while(i<=machines.len) - var/obj/machinery/Machine = machines[i] - if(Machine && Machine.loc) - last_thing_processed = Machine.type - if(Machine.process() != PROCESS_KILL) - if(Machine) + active_diseases -= Disease -// if(Machine.use_power) -// Machine.auto_use_power() - i++ +/datum/controller/game_controller/proc/processMachines() + for (var/obj/machinery/Machinery in machines) + if (Machinery && Machinery.loc) + last_thing_processed = Machinery.type + + if(Machinery.process() != PROCESS_KILL) + if (Machinery) // Why another check? + if (Machinery.use_power) + Machinery.auto_use_power() + continue - machines.Cut(i,i+1) - i=1 - while(i<=active_areas.len) - var/area/A = active_areas[i] - if(A.powerupdate) - A.powerupdate -= 1 - for(var/obj/machinery/M in A) - if(M) - if(M.use_power) - M.auto_use_power() - - if(A.apc.len) - i++ - continue - active_areas.Cut(i,i+1) - -datum/controller/game_controller/proc/process_objects() - var/i = 1 - while(i<=processing_objects.len) - var/obj/Object = processing_objects[i] - if(Object && Object.loc) + Machinery.removeAtProcessing() + +/datum/controller/game_controller/proc/processObjects() + for (var/obj/Object in processing_objects) + if (Object && Object.loc) last_thing_processed = Object.type Object.process() - i++ continue - processing_objects.Cut(i,i+1) -datum/controller/game_controller/proc/process_pipenets() + processing_objects -= Object + +/datum/controller/game_controller/proc/processPipenets() last_thing_processed = /datum/pipe_network - var/i = 1 - while(i<=pipe_networks.len) - var/datum/pipe_network/Network = pipe_networks[i] - if(Network) - Network.process() - i++ - continue - pipe_networks.Cut(i,i+1) -datum/controller/game_controller/proc/process_powernets() + for (var/datum/pipe_network/Pipe_Network in pipe_networks) + if(Pipe_Network) + Pipe_Network.process() + continue + + pipe_networks -= Pipe_Network + +/datum/controller/game_controller/proc/processPowernets() last_thing_processed = /datum/powernet - var/i = 1 - while(i<=powernets.len) - var/datum/powernet/Powernet = powernets[i] - if(Powernet) + + for (var/datum/powernet/Powernet in powernets) + if (Powernet) Powernet.reset() - i++ continue - powernets.Cut(i,i+1) -datum/controller/game_controller/proc/process_nano() - var/i = 1 - while(i<=nanomanager.processing_uis.len) - var/datum/nanoui/ui = nanomanager.processing_uis[i] - if(ui) - ui.process() - i++ + powernets -= Powernet + +/datum/controller/game_controller/proc/processNano() + for (var/datum/nanoui/Nanoui in nanomanager.processing_uis) + if (Nanoui) + Nanoui.process() continue - nanomanager.processing_uis.Cut(i,i+1) -datum/controller/game_controller/proc/process_events() + nanomanager.processing_uis -= Nanoui + +/datum/controller/game_controller/proc/processEvents() last_thing_processed = /datum/event - var/i = 1 - while(i<=events.len) - var/datum/event/Event = events[i] - if(Event) + + for (var/datum/event/Event in events) + if (Event) Event.process() - i++ continue - events.Cut(i,i+1) + + events -= Event + checkEvent() datum/controller/game_controller/proc/Recover() //Mostly a placeholder for now. diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 5d621b1b726..694f27d7684 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -19,7 +19,7 @@ feedback_add_details("admin_verb","RFailsafe") if("Lighting") new /datum/controller/lighting() - //lighting_controller.process() + lighting_controller.process() feedback_add_details("admin_verb","RLighting") if("Supply Shuttle") supply_shuttle.process() diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 64e629e56a7..02bd6052992 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -151,12 +151,17 @@ proc/get_id_photo(var/mob/living/carbon/human/H) preview_icon.Blend(temp, ICON_OVERLAY) // Skin tone - if(H.species.flags & HAS_SKIN_TONE) + if(H.species.bodyflags & HAS_SKIN_TONE) if (H.s_tone >= 0) preview_icon.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD) else preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) + // Skin color + if(H.species.flags & HAS_SKIN_TONE) + if(!H.species || H.species.flags & HAS_SKIN_COLOR) + preview_icon.Blend(rgb(H.r_skin, H.g_skin, H.b_skin), ICON_ADD) + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = H.species ? H.species.eyes : "eyes_s") eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD) diff --git a/code/datums/sun.dm b/code/datums/sun.dm index 7e1cbb51749..1748ea158e7 100644 --- a/code/datums/sun.dm +++ b/code/datums/sun.dm @@ -1,61 +1,43 @@ +#define SOLAR_UPDATE_TIME 600 //duration between two updates of the whole sun/solars positions + /datum/sun var/angle var/dx var/dy -// var/counter = 50 // to make the vars update during 1st call var/rate var/list/solars // for debugging purposes, references solars_list at the constructor - var/nexttime = 3600 // Replacement for var/counter to force the sun to move every X IC minutes - var/lastAngleUpdate + var/solar_next_update // last time the sun position was checked and adjusted /datum/sun/New() solars = solars_list - rate = rand(750,1250)/1000 // 75.0% - 125.0% of standard rotation - if(prob(50)) + rate = rand(50,200)/100 // 50% - 200% of standard rotation + if(prob(50)) // same chance to rotate clockwise than counter-clockwise rate = -rate + solar_next_update = world.time // init the timer + angle = rand (0,360) // the station position to the sun is randomised at round start // calculate the sun's position given the time of day - +// at the standard rate (100%) the angle is increase/decreased by 6 degrees every minute. +// a full rotation thus take a game hour in that case /datum/sun/proc/calc_position() -/* counter++ - if(counter<50) // count 50 pticks (50 seconds, roughly - about a 5deg change) - return - counter = 0 */ + if(world.time < solar_next_update) //if less than 60 game secondes have passed, do nothing + return; - angle = ((rate*world.time/100)%360 + 360)%360 + angle = (360 + angle + rate * 6) % 360 // increase/decrease the angle to the sun, adjusted by the rate - /* - Yields a 45 - 75 IC minute rotational period - Rotation rate can vary from 4.8 deg/min to 8 deg/min (288 to 480 deg/hr) - */ - - if(lastAngleUpdate != angle) - for(var/obj/machinery/power/tracker/T in solars_list) - if(!T.powernet) - solars_list.Remove(T) - continue - T.set_angle(angle) - lastAngleUpdate=angle - - - - if(nexttime > world.time) - return - nexttime = nexttime + 600 // 600 world.time ticks = 1 minute + solar_next_update += SOLAR_UPDATE_TIME // since we updated the angle, set the proper time for the next loop // now calculate and cache the (dx,dy) increments for line drawing var/s = sin(angle) var/c = cos(angle) - if(c == 0) + // Either "abs(s) < abs(c)" or "abs(s) >= abs(c)" + // In both cases, the greater is greater than 0, so, no "if 0" check is needed for the divisions - dx = 0 - dy = s - - else if( abs(s) < abs(c)) + if( abs(s) < abs(c)) dx = s / abs(c) dy = c / abs(c) @@ -65,28 +47,42 @@ dy = c / abs(s) - for(var/obj/machinery/power/solar/S in solars_list) + for(var/obj/machinery/power/M in solars_list) - if(!S.powernet) - solars_list.Remove(S) + if(!M.powernet) + solars_list.Remove(M) continue - if(S.control) - occlusion(S) + // Solar Tracker + if(istype(M, /obj/machinery/power/tracker)) + var/obj/machinery/power/tracker/T = M + T.set_angle(angle) + + // Solar Control + else if(istype(M, /obj/machinery/power/solar_control)) + var/obj/machinery/power/solar_control/C = M + if(C.track == 1) //if manual tracking... + C.tracker_update() //...update the position (not passing an angle, it is handled internally for manual tracking) + + // Solar Panel + else if(istype(M, /obj/machinery/power/solar)) + var/obj/machinery/power/solar/S = M + if(S.control) + occlusion(S) // for a solar panel, trace towards sun to see if we're in shadow - /datum/sun/proc/occlusion(var/obj/machinery/power/solar/S) var/ax = S.x // start at the solar panel var/ay = S.y + var/turf/T = null for(var/i = 1 to 20) // 20 steps is enough ax += dx // do step ay += dy - var/turf/T = locate( round(ax,0.5),round(ay,0.5),S.z) + T = locate( round(ax,0.5),round(ay,0.5),S.z) if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy) // not obscured if we reach the edge break diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 11a78e3bf91..76ff5c74c94 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -174,6 +174,16 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "Emergency Crate" group = "Engineering" +/datum/supply_packs/evacuation + name = "Inflatable barriers" + contains = list(/obj/item/weapon/storage/briefcase/inflatable, + /obj/item/weapon/storage/briefcase/inflatable, + /obj/item/weapon/storage/briefcase/inflatable) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "Inflatable Barrier Crate" + group = "Engineering" + /datum/supply_packs/janitor name = "Janitorial supplies" contains = list(/obj/item/weapon/reagent_containers/glass/bucket, diff --git a/code/defines/vox_sounds.dm b/code/defines/vox_sounds.dm index 7edb13ff0f5..1d730894ace 100644 --- a/code/defines/vox_sounds.dm +++ b/code/defines/vox_sounds.dm @@ -759,6 +759,7 @@ var/list/vox_sounds = list( "vox_420" = 'sound/vox_fem/vox_420.ogg', "voxtest" = 'sound/vox_fem/voxtest.ogg', "voxtest2" = 'sound/vox_fem/voxtest2.ogg', + "voxtest3" = 'sound/vox_fem/voxtest3.ogg', "w" = 'sound/vox_fem/w.ogg', "walk" = 'sound/vox_fem/walk.ogg', "wall" = 'sound/vox_fem/wall.ogg', diff --git a/code/game/area/Dynamic areas.dm b/code/game/area/Dynamic areas.dm new file mode 100644 index 00000000000..9d6010f29b4 --- /dev/null +++ b/code/game/area/Dynamic areas.dm @@ -0,0 +1,38 @@ +/area/dynamic // Do not use. + name = "dynamic area" + icon_state = "purple" + var/match_tag = "none" + var/match_width = -1 + var/match_height = -1 + var/enable_lights = 0 + +/area/dynamic/destination // Do not use. + name = "dynamic area destination" + +/area/dynamic/destination/lobby + name = "Arrivals Lobby" + match_tag = "arrivals" + match_width = 5 + match_height = 4 + enable_lights = 1 + +/area/dynamic/source // Do not use. + name = "dynamic area source" + +/area/dynamic/source/lobby_bar + name = "\improper Bar" + match_tag = "arrivals" + match_width = 5 + match_height = 4 + +/area/dynamic/source/lobby_russian + name = "\improper Russian Lounge" + match_tag = "arrivals" + match_width = 5 + match_height = 4 + +/area/dynamic/source/lobby_disco + name = "\improper Disco Lounge" + match_tag = "arrivals" + match_width = 5 + match_height = 4 \ No newline at end of file diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 239571b2c6f..54c98df1fda 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -1039,10 +1039,6 @@ proc/process_ghost_teleport_locs() name = "\improper Clothing Shop" icon_state = "Theatre" - - - - /area/holodeck name = "\improper Holodeck" icon_state = "Holodeck" @@ -1707,7 +1703,6 @@ proc/process_ghost_teleport_locs() //GAYBAR /area/secret/gaybar name = "\improper Dance Bar" - requires_power = 0 icon_state = "dancebar" @@ -2043,6 +2038,7 @@ var/list/the_station_areas = list ( /area/hallway/primary/central, /area/bridge, /area/crew_quarters, + /area/civilian, /area/holodeck, /area/library, /area/chapel, @@ -2053,6 +2049,7 @@ var/list/the_station_areas = list ( /area/teleporter, /area/medical, /area/security, + /area/prison, /area/quartermaster, /area/janitor, /area/hydroponics, diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 8bea8675147..9603638f719 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -26,16 +26,20 @@ // lighting_state = 4 //has_gravity = 0 // Space has gravity. Because.. because. - if(!requires_power) + if(requires_power) + luminosity = 0 + else power_light = 0 //rastaf0 power_equip = 0 //rastaf0 power_environ = 0 //rastaf0 + luminosity = 1 lighting_use_dynamic = 0 ..() // spawn(15) power_change() // all machines set to current power level, also updates lighting icon + InitializeLighting() /area/proc/poweralert(var/state, var/obj/source as obj) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1ef9a50274c..25dacdacbc9 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -58,7 +58,6 @@ return /atom/proc/assume_air(datum/gas_mixture/giver) - del(giver) return null /atom/proc/remove_air(amount) @@ -168,7 +167,7 @@ its easier to just keep the beam vertical. //Maxdistance is the longest range the beam will persist before it gives up. var/EndTime=world.time+time var/broken = 0 - var/obj/item/projectile/beam/lightning/light = new + var/obj/item/projectile/beam/lightning/light = getFromPool(/obj/item/projectile/beam/lightning) while(BeamTarget&&world.time[L.name] suddenly bursts into flames!") - //playsound(L.loc, 'mag_fireballlaunch.ogg', 50, 0) + L.on_fire = 1 + L.update_icon = 1 + playsound(L.loc, 'sound/effects/bamf.ogg', 50, 0) //////////////////////////////////////////////////////////////////////// @@ -329,6 +334,7 @@ desc = "The subject becomes able to transform the matter of their cells into a liquid state." activation_messages = list("You feel strange and jiggly.") deactivation_messages = list("You feel more solid.") + instability=2 verbtype=/proc/bioproc_melt diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index d5ae6e716a9..363f46fb19c 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -17,6 +17,7 @@ desc = "Boosts efficiency in sectors of the brain commonly associated with meta-mental energies." activation_messages = list("Your mind feels closed.") deactivation_messages = list("You feel oddly exposed.") + instability=2 mutation=M_PSY_RESIST @@ -28,6 +29,7 @@ ///////////////////////// /datum/dna/gene/basic/stealth + instability=7 can_activate(var/mob/M, var/flags) // Can only activate one of these at a time. if(is_type_in_list(/datum/dna/gene/basic/stealth,M.active_genes)) @@ -53,7 +55,7 @@ var/turf/simulated/T = get_turf(M) if(!istype(T)) return - if(T.lit_value <= 2) + if(T.lighting_lumcount <= 2) M.alpha = 0 else M.alpha = round(255 * 0.80) @@ -109,6 +111,7 @@ desc = "Allows the subject to lower the body temperature of others." activation_messages = list("You notice a strange cold tingle in your fingertips.") deactivation_messages = list("Your fingers feel warmer.") + instability=10 spelltype = /obj/effect/proc_holder/spell/targeted/cryokinesis @@ -144,7 +147,12 @@ usr << "\red This will only work on normal organic beings." return - C.bodytemperature = -300 + if (M_RESIST_COLD in C.mutations) + C.visible_message("\red A cloud of fine ice crystals engulfs [C.name], but disappears almost instantly!") + return + + C.bodytemperature = 0 + C.adjustFireLoss(20) C.ExtinguishMob() C.visible_message("\red A cloud of fine ice crystals engulfs [C]!") @@ -178,6 +186,7 @@ desc = "Allows the subject to eat just about anything without harm." activation_messages = list("You feel hungry.") deactivation_messages = list("You don't feel quite so hungry anymore.") + instability=3 spelltype=/obj/effect/proc_holder/spell/targeted/eat @@ -199,6 +208,7 @@ range = 1 selection_type = "view" + var/list/types_allowed=list(/obj/item,/mob/living/simple_animal, /mob/living/carbon/monkey, /mob/living/carbon/human) /obj/effect/proc_holder/spell/targeted/eat/choose_targets(mob/user = usr) @@ -297,6 +307,7 @@ //cooldown = 30 activation_messages = list("Your leg muscles feel taut and strong.") deactivation_messages = list("Your leg muscles shrink back to normal.") + instability=2 spelltype =/obj/effect/proc_holder/spell/targeted/leap @@ -327,7 +338,7 @@ usr.visible_message("\red [usr.name] takes a huge leap!") playsound(usr.loc, 'sound/weapons/thudswoosh.ogg', 50, 1) var/prevLayer = usr.layer - usr.layer = 15 + usr.layer = 9 for(var/i=0, i<10, i++) step(usr, usr.dir) @@ -374,6 +385,7 @@ //cooldown = 1800 activation_messages = list("You don't feel entirely like yourself somehow.") deactivation_messages = list("You feel secure in your identity.") + instability=5 New() ..() @@ -420,6 +432,7 @@ verbtype = /proc/bioproc_empath activation_messages = list("You suddenly notice more about others than you did before.") deactivation_messages = list("You no longer feel able to sense intentions.") + instability=1 New() ..() @@ -515,6 +528,7 @@ desc = "Vastly increases the gas capacity of the subject's digestive tract." activation_messages = list("You feel bloated and gassy.") deactivation_messages = list("You no longer feel gassy. What a relief!") + instability=1 mutation = M_SUPER_FART diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index 3562639c84b..d936b65b09e 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -110,9 +110,11 @@ sleep(48) del(animation) - var/mob/living/carbon/human/O = new( src ) + var/mob/living/carbon/human/O if(Mo.greaterform) - O.set_species(Mo.greaterform) + O = new(src, Mo.greaterform) + else + O = new(src) if (M.dna.GetUIState(DNA_UI_GENDER)) O.gender = FEMALE diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index 57e0680b933..e08558abe29 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -6,6 +6,7 @@ name="No Breathing" activation_messages=list("You feel no need to breathe.") mutation=M_NO_BREATH + instability=2 New() block=NOBREATHBLOCK @@ -14,6 +15,7 @@ name="Remote Viewing" activation_messages=list("Your mind expands.") mutation=M_REMOTE_VIEW + instability=3 New() block=REMOTEVIEWBLOCK @@ -26,6 +28,7 @@ name="Regenerate" activation_messages=list("You feel better.") mutation=M_REGEN + instability=2 New() block=REGENERATEBLOCK @@ -34,6 +37,7 @@ name="Super Speed" activation_messages=list("Your leg muscles pulsate.") mutation=M_RUN + instability=1 New() block=INCREASERUNBLOCK @@ -42,6 +46,7 @@ name="Telepathy" activation_messages=list("You expand your mind outwards.") mutation=M_REMOTE_TALK + instability=1 New() block=REMOTETALKBLOCK @@ -54,6 +59,7 @@ name="Morph" activation_messages=list("Your skin feels strange.") mutation=M_MORPH + instability=2 New() block=MORPHBLOCK @@ -66,6 +72,7 @@ name="Heat Resistance" activation_messages=list("Your skin is icy to the touch.") mutation=M_RESIST_HEAT + instability=2 New() block=COLDBLOCK @@ -87,6 +94,7 @@ name="Cold Resistance" activation_messages=list("Your body is filled with warmth.") mutation=M_RESIST_COLD + instability=2 New() block=FIREBLOCK @@ -108,6 +116,7 @@ name="No Prints" activation_messages=list("Your fingers feel numb.") mutation=M_FINGERPRINTS + instability=1 New() block=NOPRINTSBLOCK @@ -116,6 +125,7 @@ name="Shock Immunity" activation_messages=list("Your skin feels strange.") mutation=M_NO_SHOCK + instability=2 New() block=SHOCKIMMUNITYBLOCK @@ -124,6 +134,7 @@ name="Midget" activation_messages=list("Your skin feels rubbery.") mutation=M_DWARF + instability=1 New() block=SMALLSIZEBLOCK @@ -175,6 +186,7 @@ name="X-Ray Vision" activation_messages=list("The walls suddenly disappear.") mutation=M_XRAY + instability=2 New() block=XRAYBLOCK @@ -184,6 +196,7 @@ activation_messages=list("You feel smarter.") mutation=M_TK activation_prob=15 + instability=5 New() block=TELEBLOCK diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index bc85838b07f..9328da11e40 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -16,6 +16,7 @@ Obviously, requires DNA2. desc = "Allows the subject to become the motherfucking Hulk." activation_messages = list("Your muscles hurt.") deactivation_messages = list("Your muscles quit tensing.") + instability=7 spelltype = /obj/effect/proc_holder/spell/targeted/hulk diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 6b33c2e5ab5..3dbdd7c4e19 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -152,6 +152,51 @@ var/global/datum/controller/gameticker/ticker //Holiday Round-start stuff ~Carn Holiday_Game_Start() + spawn(0) // Forking dynamic room selection + var/list/area/dynamic/source/available_source_candidates = typesof(/area/dynamic/source) - /area/dynamic/source + var/list/area/dynamic/destination/available_destination_candidates = typesof(/area/dynamic/destination) - /area/dynamic/destination + + for (var/area/dynamic/destination/current_destination_candidate in available_destination_candidates) + var/area/dynamic/destination/current_destination = locate(current_destination_candidate) + + if (!current_destination) + continue + + if (current_destination.match_width == 0 || current_destination.match_height == 0) + message_admins("Dynamic area destination '[current_destination.name]' does not have its size requirements set.") + continue + + var/list/area/dynamic/source/candidate_source_areas = new /list(0) + for (var/area/dynamic/source/candidate_source_area in available_source_candidates) + var/area/dynamic/source/candidate_source = locate(candidate_source_area) + + if (!candidate_source) + continue + + if (candidate_source.match_tag != current_destination.match_tag) + continue + + if (candidate_source.match_width != current_destination.match_width || \ + candidate_source.match_height != current_destination.match_height) + continue + + candidate_source_areas += candidate_source + + if (candidate_source_areas.len == 0) + message_admins("Failed to find a matching source for dynamic area: [current_destination.name]") + continue + + var/area/dynamic/source/selected_source = pick(candidate_source_areas) + available_source_candidates -= selected_source + + selected_source.copy_contents_to(current_destination, 0) + + if (current_destination.enable_lights || selected_source.enable_lights) + current_destination.power_light = 1 + else + current_destination.power_light = 0 + current_destination.power_change() + //start_events() //handles random events and space dust. //new random event system is handled from the MC. @@ -164,7 +209,7 @@ var/global/datum/controller/gameticker/ticker supply_shuttle.process() //Start the supply shuttle regenerating points -- TLE master_controller.process() //Start master_controller.process() - //lighting_controller.process() //Start processing DynamicAreaLighting updates + lighting_controller.process() //Start processing DynamicAreaLighting updates if(config.sql_enabled) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 6409063e5f7..b4511a60145 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -35,13 +35,22 @@ datum/objective if(possible_targets.len > 0) target = pick(possible_targets) - proc/find_target_by_role(role, role_type=0)//Option sets either to check assigned role or special role. Default to assigned. + var/list/possible_targets = list() for(var/datum/mind/possible_target in ticker.minds) - if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) ) - target = possible_target - break + if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) && (possible_target.current.stat != 2) ) + possible_targets += possible_target + if(possible_targets.len > 0) + target = pick(possible_targets) +//Selects someone with a specific special role if role is != null. Or just anyone with a special role + proc/find_target_with_special_role(role) + var/list/possible_targets = list() + for(var/datum/mind/possible_target in ticker.minds) + if((possible_target != owner) && ishuman(possible_target.current) && (role && possible_target.special_role == role || !role && possible_target.special_role) && (possible_target.current.stat != 2) ) + possible_targets += possible_target + if(possible_targets.len > 0) + target = pick(possible_targets) datum/objective/assassinate @@ -229,7 +238,7 @@ datum/objective/debrain//I want braaaainssss find_target() ..() if(target && target.current) - explanation_text = "Steal the brain of [target.current.real_name]." + explanation_text = "Steal the brain of [target.current.real_name] the [target.assigned_role]." else explanation_text = "Free Objective" return target @@ -275,6 +284,14 @@ datum/objective/protect//The opposite of killing a dude. explanation_text = "Free Objective" return target + find_target_with_special_role(role,role_type=0) + ..(role) + if(target && target.current) + explanation_text = "Protect [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + else + explanation_text = "Free Objective" + return target + check_completion() if(!target) //If it's a free objective. return 1 @@ -306,22 +323,14 @@ datum/objective/hijack return 1 datum/objective/speciesist - var/datum/species/speciesist_target = null - + var/is_human = 0 find_target() - var/list/possible_targets = list() - var/mob/living/carbon/human/O = owner.current - for(var/datum/mind/possible_target in ticker.minds) - if(ishuman(possible_target.current)) - var/mob/living/carbon/human/M = possible_target.current - if (M.species != O.species) - possible_targets += M.species - if(possible_targets.len > 0) - speciesist_target = pick(possible_targets) - explanation_text = "Do not allow any [speciesist_target.name]s to escape on the shuttle." + if(istype(owner.current,/mob/living/carbon/human/human)) + explanation_text = "Do not allow any non-humans to escape on the shuttle." + is_human = 1 else - explanation_text = "Free Objective" - return speciesist_target + explanation_text = "Do not allow any humans to escape on the shuttle." + return 1 check_completion() if(emergency_shuttle.location<2) @@ -329,7 +338,7 @@ datum/objective/speciesist var/area/shuttle = locate(/area/shuttle/escape/centcom) for(var/mob/living/carbon/human/player in player_list) if (player.mind) - if (player.species == speciesist_target) + if (is_human ? !istype(player,/mob/living/carbon/human/human) : istype(player,/mob/living/carbon/human/human)) if(player.stat != DEAD) //they're not dead! if(get_turf(player) in shuttle) return 0 diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index a9dd31c71b7..7a5408dce14 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -87,7 +87,7 @@ EATBLOCK = getAssignedBlock("EAT", numsToAssign, DNA_HARD_BOUNDS, good=1) JUMPBLOCK = getAssignedBlock("JUMP", numsToAssign, DNA_HARD_BOUNDS, good=1) MELTBLOCK = getAssignedBlock("MELT", numsToAssign, good=1) - IMMOLATEBLOCK = getAssignedBlock("IMMOLATE", numsToAssign, good=1) + IMMOLATEBLOCK = getAssignedBlock("IMMOLATE", numsToAssign) EMPATHBLOCK = getAssignedBlock("EMPATH", numsToAssign, DNA_HARD_BOUNDS, good=1) SUPERFARTBLOCK = getAssignedBlock("SUPERFART", numsToAssign, DNA_HARDER_BOUNDS, good=1) POLYMORPHBLOCK = getAssignedBlock("POLYMORPH", numsToAssign, DNA_HARDER_BOUNDS, good=1) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 24198d4e776..815a766f805 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -96,12 +96,12 @@ else switch(rand(1,100)) - if(1 to 25) + if(1 to 30) var/datum/objective/assassinate/kill_objective = new kill_objective.owner = traitor kill_objective.find_target() traitor.objectives += kill_objective - if(26 to 40) + if(31 to 40) var/datum/objective/debrain/debrain_objective = new debrain_objective.owner = traitor debrain_objective.find_target() @@ -109,7 +109,7 @@ if(41 to 50) var/datum/objective/protect/protect_objective = new protect_objective.owner = traitor - protect_objective.find_target_by_role("Traitor",0) //Protect your fellow traitor + protect_objective.find_target_with_special_role(null,0) if (!protect_objective.target) protect_objective.find_target() //We could not find any traitors, protect somebody traitor.objectives += protect_objective diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index 79a0966d860..7aa1d28f7ea 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -222,9 +222,7 @@ C.Stun(8) C.Jitter(150) for(var/obj/structure/window/W in oview(3)) - new W.shardtype(W.loc) - if(W.reinf) new /obj/item/stack/rods(W.loc) - del(W) + W.destroy() playsound(M.current.loc, 'sound/effects/creepyshriek.ogg', 100, 1) M.current.remove_vampire_blood(30) M.current.verbs -= /client/vampire/proc/vampire_screech @@ -278,7 +276,7 @@ if(!mind.vampire.iscloaking) alpha = 255 return 0 - if(T.lit_value <= 2) + if(T.lighting_lumcount <= 2) alpha = round((255 * 0.15)) return 1 else @@ -432,7 +430,7 @@ if(T.y>world.maxy-outer_tele_radius || T.y max_lum) continue + if(T.lighting_lumcount > max_lum) continue turfs += T if(!turfs.len) diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index c3e57a0cac1..e53290ebe0c 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -186,6 +186,7 @@ H.equip_or_collect(new /obj/item/clothing/under/rank/miner(H), slot_w_uniform) H.equip_or_collect(new /obj/item/device/pda/shaftminer(H), slot_wear_pda) H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_or_collect(new /obj/item/weapon/pickaxe/drill(H), slot_r_hand) // H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index dc7359403fe..8af5d0e4152 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -51,7 +51,7 @@ supervisors = "the chief engineer" selection_color = "#fff5cc" access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics) - minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) + minimal_access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) alt_titles = list("Maintenance Technician","Engine Technician","Electrician") @@ -86,7 +86,7 @@ supervisors = "the chief engineer" selection_color = "#fff5cc" access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics) - minimal_access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction) + minimal_access = list(access_eva, access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction) equip(var/mob/living/carbon/human/H) diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 3f7b20a1ede..cba2ebcd922 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -12,7 +12,7 @@ access = list(access_medical, access_morgue, access_genetics, access_heads, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_keycard_auth, access_sec_doors, access_psychiatrist) - minimal_access = list(access_medical, access_morgue, access_genetics, access_heads, + minimal_access = list(access_eva, access_medical, access_morgue, access_genetics, access_heads, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_keycard_auth, access_sec_doors, access_psychiatrist, access_maint_tunnels) minimal_player_age = 7 diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index e9bf9112b05..9852b0b6b4f 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -13,7 +13,7 @@ access_tox_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch) - minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, + minimal_access = list(access_eva, access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_maint_tunnels) diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 5f6b3ee5ac5..4d47556559b 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -13,7 +13,7 @@ access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway) - minimal_access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, + minimal_access = list(access_eva, access_security, access_sec_doors, access_brig, access_armory, access_court, access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_customs) @@ -180,12 +180,12 @@ flag = CUSTOMS department_flag = KARMA faction = "Station" - total_positions = 1 - spawn_positions = 1 + total_positions = 2 + spawn_positions = 2 supervisors = "the head of security" selection_color = "#ffeeee" access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels, access_morgue) - minimal_access = list(access_security, access_customs, access_maint_tunnels) + minimal_access = list(access_brig, access_sec_doors, access_security, access_customs, access_maint_tunnels) minimal_player_age = 7 equip(var/mob/living/carbon/human/H) if(!H) return 0 diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 0814dba74e6..c4f6e3c14ac 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -52,6 +52,7 @@ var/global/datum/controller/occupations/job_master if(!job) return 0 if(jobban_isbanned(player, rank)) return 0 if(!job.player_old_enough(player.client)) return 0 + if(!is_job_whitelisted(player, rank)) return 0 var/position_limit = job.total_positions if(!latejoin) position_limit = job.spawn_positions @@ -308,6 +309,10 @@ var/global/datum/controller/occupations/job_master Debug("DO player not old enough, Player: [player], Job:[job.title]") continue + if(!is_job_whitelisted(player, job.title)) + Debug("DO player not whitelisted, Player: [player], Job:[job.title]") + continue + // If the player wants that job on this level, then try give it to him. if(player.client.prefs.GetJobDepartment(job, level) & job.flag) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 0be949dbb01..03a67b4f719 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -187,7 +187,7 @@ blob_act() if(prob(75)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc A.blob_act() del(src) return @@ -198,7 +198,7 @@ if(!beaker) beaker = G user.drop_item() - G.setloc(src) + G.loc = src user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") src.updateUsrDialog() return @@ -228,7 +228,7 @@ if(M.client) M.client.perspective = EYE_PERSPECTIVE M.client.eye = src - M.setloc(src) + M.loc = src src.occupant = M src.icon_state = "sleeper_1" if(orient == "RIGHT") @@ -248,21 +248,21 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return if(2.0) if(prob(50)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return if(3.0) if(prob(25)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return @@ -309,7 +309,7 @@ if(src.occupant.client) src.occupant.client.eye = src.occupant.client.mob src.occupant.client.perspective = MOB_PERSPECTIVE - src.occupant.setloc(src.loc) + src.occupant.loc = src.loc src.occupant = null if(orient == "RIGHT") icon_state = "sleeper_0-r" @@ -411,29 +411,8 @@ if(orient == "RIGHT") icon_state = "sleeper_1-r" - for(var/mob/living/carbon/slime/M in range(1,usr)) - if(M.Victim == usr) - usr << "You're too busy getting your life sucked out of you." - return - visible_message("[usr] starts climbing into the sleeper.", 3) - if(do_after(usr, 20)) - if(src.occupant) - usr << "\blue The sleeper is already occupied!" - return - usr.stop_pulling() - usr.client.perspective = EYE_PERSPECTIVE - usr.client.eye = src - usr.setloc(src) - src.occupant = usr - src.icon_state = "sleeper_1" - if(orient == "RIGHT") - icon_state = "sleeper_1-r" - - usr << "\blue You feel cool air surround you. You go numb as your senses turn inward." - - for(var/obj/O in src) - del(O) - src.add_fingerprint(usr) - return + for(var/obj/O in src) + del(O) + src.add_fingerprint(usr) return - return + return \ No newline at end of file diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index adc0a84ade5..5c61d2cf226 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -46,7 +46,7 @@ usr.pulling = null usr.client.perspective = EYE_PERSPECTIVE usr.client.eye = src - usr.setloc(src) + usr.loc = src src.occupant = usr src.icon_state = "body_scanner_1" for(var/obj/O in src) @@ -60,12 +60,12 @@ if ((!( src.occupant ) || src.locked)) return for(var/obj/O in src) - O.setloc(src.loc) + O.loc = src.loc //Foreach goto(30) if (src.occupant.client) src.occupant.client.eye = src.occupant.client.mob src.occupant.client.perspective = MOB_PERSPECTIVE - src.occupant.setloc(src.loc) + src.occupant.loc = src.loc src.occupant = null src.icon_state = "body_scanner_0" return @@ -83,11 +83,11 @@ if (M.client) M.client.perspective = EYE_PERSPECTIVE M.client.eye = src - M.setloc(src) + M.loc = src src.occupant = M src.icon_state = "body_scanner_1" for(var/obj/O in src) - O.setloc(src.loc) + O.loc = src.loc //Foreach goto(154) src.add_fingerprint(user) //G = null @@ -98,7 +98,7 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) //Foreach goto(35) //SN src = null @@ -107,7 +107,7 @@ if(2.0) if (prob(50)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) //Foreach goto(108) //SN src = null @@ -116,7 +116,7 @@ if(3.0) if (prob(25)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) //Foreach goto(181) //SN src = null @@ -128,7 +128,7 @@ /obj/machinery/bodyscanner/blob_act() if(prob(50)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc del(src) /obj/machinery/body_scanconsole/ex_act(severity) diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index bb35302386c..1d0cab15733 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -108,7 +108,7 @@ obj/machinery/air_sensor if (src.stat & BROKEN) user << "\blue The broken glass falls out." var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) var/obj/item/weapon/circuitboard/air_management/M = new /obj/item/weapon/circuitboard/air_management( A ) for (var/obj/C in src) C.loc = src.loc @@ -389,7 +389,7 @@ legend { if (src.stat & BROKEN) user << "\blue The broken glass falls out." var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) var/obj/item/weapon/circuitboard/injector_control/M = new /obj/item/weapon/circuitboard/injector_control( A ) for (var/obj/C in src) C.loc = src.loc diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 6b94a2fc3c5..fc43297616f 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -275,9 +275,42 @@ var/global/list/autolathe_recipes_hidden = list( \ if (!busy) if(href_list["make"]) var/turf/T = get_step(src.loc, get_dir(src,usr)) - var/obj/template = locate(href_list["make"]) + + // critical exploit fix start -walter0o + var/obj/item/template = null + var/attempting_to_build = locate(href_list["make"]) + + if(!attempting_to_build) + return + + if(locate(attempting_to_build, src.L) || locate(attempting_to_build, src.LL)) // see if the requested object is in one of the construction lists, if so, it is legit -walter0o + template = attempting_to_build + + else // somebody is trying to exploit, alert admins -walter0o + + var/turf/LOC = get_turf(usr) + message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] ! ([LOC ? "JMP" : "null"])", 0) + log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] !") + return + + // now check for legit multiplier, also only stacks should pass with one to prevent raw-materials-manipulation -walter0o + var/multiplier = text2num(href_list["multiplier"]) + if (!multiplier) multiplier = 1 + var/max_multiplier = 1 + + if(istype(template, /obj/item/stack)) // stacks are the only items which can have a multiplier higher than 1 -walter0o + var/obj/item/stack/S = template + max_multiplier = min(S.max_amount, S.m_amt?round(m_amount/S.m_amt):INFINITY, S.g_amt?round(g_amount/S.g_amt):INFINITY) // pasta from regular_win() to make sure the numbers match -walter0o + + if( (multiplier > max_multiplier) || (multiplier <= 0) ) // somebody is trying to exploit, alert admins-walter0o + + var/turf/LOC = get_turf(usr) + message_admins("[key_name_admin(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] ! ([LOC ? "JMP" : "null"])" , 0) + log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] !") + return + var/power = max(2000, (template.m_amt+template.g_amt+template.f_amt)*multiplier/5) if(src.m_amount >= template.m_amt*multiplier && src.g_amount >= template.g_amt*multiplier && src.f_amount >= template.f_amt*multiplier) busy = 1 diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index d29e9202e4a..be9f1eb9fa0 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -34,7 +34,7 @@ /obj/machinery/biogenerator/attackby(var/obj/item/O as obj, var/mob/user as mob) if(istype(O, /obj/item/weapon/reagent_containers/glass)) if(beaker) - user << "\red The biogenerator already occuped." + user << "\red The biogenerator is already loaded." else user.before_take_item(O) O.loc = src @@ -220,4 +220,4 @@ create_product(href_list["item"],text2num(href_list["cost"])) if("menu") menustat = "menu" - updateUsrDialog() \ No newline at end of file + updateUsrDialog() diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 38834b4ef6a..d281fb57308 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -210,7 +210,7 @@ /proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID) for(var/obj/structure/window/D in loc) if(!D.density) continue - if(D.dir == SOUTHWEST) return 1 + if(D.is_fulltile()) return 1 if(D.dir == dir) return 1 for(var/obj/machinery/door/D in loc) diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index a2b0dcaa037..3d2b4c85427 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -824,7 +824,7 @@ Auto Patrol: []"}, if (src.emagged == 2) projectile = /obj/item/projectile/beam else - projectile = /obj/item/projectile/energy/electrode + projectile = /obj/item/projectile/beam/stun else if(lasercolor == "b") if (src.emagged == 2) projectile = /obj/item/projectile/beam/lastertag/omni @@ -1020,7 +1020,8 @@ Auto Patrol: []"}, if((src.lasercolor == "b") && (src.disabled == 0)) if(istype(Proj, /obj/item/projectile/beam/lastertag/red)) src.disabled = 1 - del (Proj) + //del (Proj) + returnToPool(Proj) sleep(100) src.disabled = 0 else @@ -1028,7 +1029,8 @@ Auto Patrol: []"}, else if((src.lasercolor == "r") && (src.disabled == 0)) if(istype(Proj, /obj/item/projectile/beam/lastertag/blue)) src.disabled = 1 - del (Proj) + //del (Proj) + returnToPool(Proj) sleep(100) src.disabled = 0 else diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 39846699ea1..16c39585dfa 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -92,7 +92,7 @@ if(!charging || (stat & (BROKEN|NOPOWER)) || !anchored) return - use_power(200) //this used to use CELLRATE, but CELLRATE is fucking awful. feel free to fix this properly! - charging.give(175) //inefficiency. + use_power(2000) //this used to use CELLRATE, but CELLRATE is fucking awful. feel free to fix this properly! + charging.give(1750) //inefficiency. updateicon() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 89c034035ed..87958b69338 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -161,7 +161,7 @@ spawn(30) src.eject_wait = 0 - var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) + var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species) occupant = H if(!R.dna.real_name) //to prevent null names @@ -211,7 +211,6 @@ if(R.dna.species == "Human") //no more xenos losing ears/tentacles H.h_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") - H.set_species(R.dna.species) //for(var/datum/language/L in languages) // H.add_language(L.name) H.suiciding = 0 diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index a511ecf6e05..72301160d3e 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -266,9 +266,26 @@ src.updateUsrDialog() - else - ..() - return + else if(istype(I, /obj/item/weapon/screwdriver)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, 20)) + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + var/obj/item/weapon/circuitboard/arcade/M = new /obj/item/weapon/circuitboard/arcade( A ) + for (var/obj/C in src) + C.loc = src.loc + A.circuit = M + A.anchored = 1 + + if (src.stat & BROKEN) + user << "\blue The broken glass falls out." + getFromPool(/obj/item/weapon/shard, loc) + A.state = 3 + A.icon_state = "3" + else + user << "\blue You disconnect the monitor." + A.state = 4 + A.icon_state = "4" + diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 3ef385d0285..15d630c8140 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -112,7 +112,7 @@ C.loc = src.loc if (src.stat & BROKEN) user << "\blue The broken glass falls out." - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) A.state = 3 A.icon_state = "3" else diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 0a5696ee4ce..620aa5bd0d8 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -56,7 +56,7 @@ if(stat & BROKEN) user << "\blue The broken glass falls out." var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc ) - new /obj/item/weapon/shard( loc ) + getFromPool(/obj/item/weapon/shard, loc) //generate appropriate circuitboard. Accounts for /pod/old computer types var/obj/item/weapon/circuitboard/pod/M = null diff --git a/code/game/machinery/computer/power.dm b/code/game/machinery/computer/power.dm index f32293f67af..f8d14b77ac9 100644 --- a/code/game/machinery/computer/power.dm +++ b/code/game/machinery/computer/power.dm @@ -45,7 +45,7 @@ if (src.stat & BROKEN) user << "\blue The broken glass falls out." var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) var/obj/item/weapon/circuitboard/powermonitor/M = new /obj/item/weapon/circuitboard/powermonitor( A ) for (var/obj/C in src) C.loc = src.loc diff --git a/code/game/machinery/computer/prisonshuttle.dm b/code/game/machinery/computer/prisonshuttle.dm index 25607ab66f8..9ce03c4630d 100644 --- a/code/game/machinery/computer/prisonshuttle.dm +++ b/code/game/machinery/computer/prisonshuttle.dm @@ -47,7 +47,7 @@ var/prison_shuttle_timeleft = 0 if (src.stat & BROKEN) user << "\blue The broken glass falls out." - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) A.state = 3 A.icon_state = "3" else diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 52464306d80..34a2f8a4f8a 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -251,7 +251,7 @@ if (occupant.client) occupant.client.eye = occupant.client.mob occupant.client.perspective = MOB_PERSPECTIVE - occupant.setloc(get_step(loc, SOUTH)) //this doesn't account for walls or anything, but i don't forsee that being a problem. + occupant.loc = get_step(loc, SOUTH) //this doesn't account for walls or anything, but i don't forsee that being a problem. if (occupant.bodytemperature < 261 && occupant.bodytemperature >= 70) //Patch by Aranclanos to stop people from taking burn damage after being ejected occupant.bodytemperature = 261 // occupant.metabslow = 0 @@ -275,7 +275,7 @@ M.client.perspective = EYE_PERSPECTIVE M.client.eye = src M.stop_pulling() - M.setloc(src) + M.loc = src if(M.health > -100 && (M.health < 0 || M.sleeping)) M << "\blue You feel a cold liquid surround you. Your skin starts to freeze up." occupant = M diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 5d537787b75..5246d97e321 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -80,7 +80,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) visible_message("\blue The console beeps happily as it disgorges \the [I].", 3) - I.setloc(get_turf(src)) + I.loc = get_turf(src) frozen_items -= I else if(href_list["allitems"]) @@ -92,7 +92,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) visible_message("\blue The console beeps happily as it disgorges the desired objects.", 3) for(var/obj/item/I in frozen_items) - I.setloc(get_turf(src)) + I.loc = get_turf(src) frozen_items -= I else if(href_list["crew"]) @@ -186,11 +186,11 @@ obj/machinery/computer/cryopod/Topic(href, href_list) //Drop all items into the pod. for(var/obj/item/W in occupant) occupant.drop_from_inventory(W) - W.setloc(src) + W.loc = src if(W.contents.len) //Make sure we catch anything not handled by del() on the items. for(var/obj/item/O in W.contents) - O.setloc(src) + O.loc = src //Delete all items not on the preservation list. var/list/items = src.contents @@ -240,7 +240,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) current_mode.possible_traitors.Remove(occupant) // Delete them from datacore. - + if(PDA_Manifest.len) PDA_Manifest.Cut() for(var/datum/data/record/R in data_core.medical) @@ -305,7 +305,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) if(do_after(user, 20)) if(!M || !G || !G:affecting) return - M.setloc(src) + M.loc = src if(M.client) M.client.perspective = EYE_PERSPECTIVE @@ -375,7 +375,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) usr.stop_pulling() usr.client.perspective = EYE_PERSPECTIVE usr.client.eye = src - usr.setloc(src) + usr.loc = src src.occupant = usr if(orient_right) @@ -401,7 +401,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) occupant.client.eye = src.occupant.client.mob occupant.client.perspective = MOB_PERSPECTIVE - occupant.setloc(get_turf(src)) + occupant.loc = get_turf(src) occupant = null if(orient_right) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 27f5560fa03..6d53efc796d 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1079,11 +1079,13 @@ About the new airlock wires panel: if(istype(src, /obj/machinery/door/airlock/clown)) playsound(src.loc, 'sound/items/bikehorn.ogg', 30, 1) else - playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1) - for(var/turf/turf in locs) - var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf) - if(killthis) - killthis.ex_act(2)//Smashin windows + playsound(get_turf(src), 'sound/machines/airlock.ogg', 30, 1) + + for(var/turf/T in loc) + var/obj/structure/window/W = locate(/obj/structure/window) in T + if (W) + W.destroy() + ..() return diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 18be44f4e3e..7a247f37614 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -125,7 +125,7 @@ /obj/machinery/door/window/proc/take_damage(var/damage) src.health = max(0, src.health - damage) if (src.health <= 0) - new /obj/item/weapon/shard(src.loc) + getFromPool(/obj/item/weapon/shard, loc) var/obj/item/stack/cable_coil/CC = new /obj/item/stack/cable_coil(src.loc) CC.amount = 2 var/obj/item/weapon/airlock_electronics/ae @@ -181,7 +181,12 @@ return playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("\red [user] smashes against the [src.name].", 1) - take_damage(25) + if (src.health <= 0) + getFromPool(/obj/item/weapon/shard, loc) + var/obj/item/stack/cable_coil/CC = new /obj/item/stack/cable_coil(src.loc) + CC.amount = 2 + src.density = 0 + del(src) else return src.attack_hand(user) @@ -259,11 +264,14 @@ //If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway) if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card)) - var/aforce = I.force playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("\red [src] was hit by [I].") - if(I.damtype == BRUTE || I.damtype == BURN) - take_damage(aforce) + if (src.health <= 0) + getFromPool(/obj/item/weapon/shard, loc) + var/obj/item/stack/cable_coil/CC = new /obj/item/stack/cable_coil(src.loc) + CC.amount = 2 + src.density = 0 + del(src) return diff --git a/code/game/machinery/hydroponics.dm b/code/game/machinery/hydroponics.dm index 57826586435..8398ee14d50 100644 --- a/code/game/machinery/hydroponics.dm +++ b/code/game/machinery/hydroponics.dm @@ -468,7 +468,7 @@ obj/machinery/hydroponics/proc/mutatepest() // Until someone makes a spaceworm, obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) //Called when mob user "attacks" it with object O - if (istype(O, /obj/item/weapon/reagent_containers/glass/bucket)) + if (istype(O, /obj/item/weapon/reagent_containers/glass)) var/b_amount = O.reagents.get_reagent_amount("water") if(b_amount > 0 && waterlevel < 100) if(b_amount + waterlevel > 100) @@ -476,17 +476,17 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) O.reagents.remove_reagent("water", b_amount) waterlevel += b_amount playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - user << "You fill the [src] with [b_amount] units of water." + user << "You fill \the [src] with [b_amount] units of water." - // Toxicity dilutation code. The more water you put in, the lesser the toxin concentration. + // Toxicity dilutation code. The more water you put in, the lesser the toxin concentration. toxic -= round(b_amount/4) - if (toxic < 0 ) // Make sure it won't go overoboard + if (toxic < 0 ) // Make sure it won't go overboard toxic = 0 else if(waterlevel >= 100) - user << "\red The [src] is already full." + user << "\red \The [src] is already full." else - user << "\red The bucket is not filled with water." + user << "\red \The [O] is not filled with water." updateicon() else if ( istype(O, /obj/item/nutrient) ) @@ -504,7 +504,7 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) if (planted) if (S.mode == 1) if(!S.reagents.total_volume) - user << "\red The syringe is empty." + user << "\red \The [O] is empty." return user << "\red You inject the [myseed.plantname] with a chemical solution." diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index d02e5fd4f46..97393b6dbc1 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -59,7 +59,6 @@ if(!isbroken) icon_state = icon_off - /******************* * Item Adding ********************/ @@ -83,6 +82,8 @@ user.visible_message("[user] has added \the [O] to \the [src].", \ "You add \the [O] to \the [src].") + nanomanager.update_uis(src) + else if(istype(O, /obj/item/weapon/storage/bag/plants)) var/obj/item/weapon/storage/bag/plants/P = O var/plants_loaded = 0 @@ -100,81 +101,88 @@ plants_loaded++ if(plants_loaded) - user.visible_message("[user] loads \the [src] with \the [P].", \ - "You load \the [src] with \the [P].") + user.visible_message( \ + "[user] loads \the [src] with \the [P].", \ + "You load \the [src] with \the [P].") if(P.contents.len > 0) user << "Some items are refused." + nanomanager.update_uis(src) + else user << "\The [src] smartly refuses [O]." return 1 updateUsrDialog() + ..() + /obj/machinery/smartfridge/attack_paw(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/machinery/smartfridge/attack_ai(mob/user as mob) return 0 -/obj/machinery/smartfridge/attack_hand(mob/user as mob) - user.set_machine(src) - interact(user) + ui_interact(user) /******************* * SmartFridge Menu ********************/ -/obj/machinery/smartfridge/interact(mob/user as mob) - if(!src.ispowered) - return +/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + user.set_machine(src) - var/dat = "Select an item:
" + var/data[0] + data["contents"] = null - if (contents.len == 0) - dat += "No product loaded!" - else - for (var/O in item_quants) - if(item_quants[O] > 0) - var/N = item_quants[O] - dat += "[capitalize(O)]:" - dat += " [N] " - dat += "Vend " - if(N > 5) - dat += "(x5)" - if(N > 10) - dat += "(x10)" - if(N > 25) - dat += "(x25)" - if(N > 1) - dat += "(All)" - dat += "
" + var/list/items[0] + for (var/i=1 to length(item_quants)) + var/K = item_quants[i] + var/count = item_quants[K] + if (count > 0) + items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count))) - dat += "
" - user << browse("[src] Supplies[dat]", "window=smartfridge") - onclose(user, "smartfridge") - return + if (items.len > 0) + data["contents"] = items + + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500) + ui.set_initial_data(data) + ui.open() /obj/machinery/smartfridge/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) + if (..()) return 0 - var/N = href_list["vend"] - var/amount = text2num(href_list["amount"]) + var/mob/user = usr + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") - if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. - return + src.add_fingerprint(user) - item_quants[N] = max(item_quants[N] - amount, 0) + if (href_list["close"]) + user.unset_machine() + ui.close() + return 0 - var/i = amount - for(var/obj/O in contents) - if(O.name == N) - O.loc = src.loc - i-- - if(i <= 0) - break + if (href_list["vend"]) + var/index = text2num(href_list["vend"]) + var/amount = text2num(href_list["amount"]) + var/K = item_quants[index] + var/count = item_quants[K] - src.updateUsrDialog() - return + // Sanity check, there are probably ways to press the button when it shouldn't be possible. + if(count > 0) + item_quants[K] = max(count - amount, 0) + + var/i = amount + for(var/obj/O in contents) + if (O.name == K) + O.loc = loc + i-- + if (i <= 0) + return 1 + + return 1 + + return 0 diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 38e96fe7b94..507b656ed1a 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -112,16 +112,31 @@ Class Procs: var/global/gl_uid = 1 var/custom_aghost_alerts=0 var/panel_open = 0 + var/myArea /obj/machinery/New() - ..() + addAtProcessing() + return ..() + +/obj/machinery/proc/addAtProcessing() + if (use_power) + myArea = loc.loc + machines += src -/obj/machinery/Destroy() +/obj/machinery/proc/removeAtProcessing() + if (myArea) + myArea = null + machines -= src + +/obj/machinery/Destroy() + if (src in machines) + removeAtProcessing() + ..() -/obj/machinery/process()//If you dont use process or power why are you here +/obj/machinery/process() // If you dont use process or power why are you here return PROCESS_KILL /obj/machinery/emp_act(severity) @@ -277,3 +292,15 @@ Class Procs: panel_open = 0 icon_state = icon_state_closed user << "You close the maintenance hatch of [src]." + +/obj/machinery/proc/state(var/msg) + for(var/mob/O in hearers(src, null)) + O.show_message("\icon[src] [msg]", 2) + +/obj/machinery/proc/ping(text=null) + if (!text) + text = "\The [src] pings." + + state(text, "blue") + playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) + diff --git a/code/game/machinery/metaldetector.dm b/code/game/machinery/metaldetector.dm new file mode 100644 index 00000000000..3d7ccb4ab3b --- /dev/null +++ b/code/game/machinery/metaldetector.dm @@ -0,0 +1,162 @@ +/obj/machinery/metaldetector + name = "metal detector" + desc = "a metal detector. staff can toggle this between ignore security and detect all with their id." + anchored = 1.0 + density = 0 + icon = 'icons/obj/machines/metal_detector.dmi' + icon_state = "metaldetector0" + use_power = 1 + idle_power_usage = 20 + active_power_usage = 250 + var/guncount = 0 + var/knifecount = 0 + var/bombcount = 0 + var/meleecount = 0 + var/detectall = 0 + +/obj/machinery/metaldetector/check_access(obj/item/weapon/card/id/I, list/access_list) + if(!istype(access_list)) + return 1 + if(!access_list.len) //no requirements + return 1 + if(istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if(!istype(I) || !I.access) //not ID or no access + return 0 + return 1 + +/obj/machinery/metaldetector/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card/emag)) + if(!src.emagged) + src.emagged = 1 + user << "\blue You short out the circuitry." + return + if(istype(W, /obj/item/weapon/card)) + for(var/ID in list(user.equipped(), user:wear_id, user:belt)) + if(src.check_access(ID,list("20"))) + if(!src.detectall) + src.detectall = 1 + user << "\blue You set the [src] to detect all personnel." + return + else + src.detectall = 0 + user << "\blue You set the [src] to ignore all staff and security." + return + else + user << "\red You lack access to the control panel!" + return + +/obj/machinery/metaldetector/Crossed(AM as mob|obj) + if(emagged) + return + if (istype(AM, /mob/living)) + var/mob/M = AM + if(!src.detectall) + if(M:wear_id || M:belt) + for(var/ID in list(M:equipped(), M:wear_id, M:belt)) + if(src.check_access(ID,list("1", "2", "3", "20", "57", "58"))) + return + if (istype(M, /mob/living)) + for(var/obj/item/weapon/gun/G in M) + guncount++ + for(var/obj/item/device/transfer_valve/B in M) + bombcount++ + for(var/obj/item/weapon/kitchen/utensil/knife/K in M) + knifecount++ + for(var/obj/item/weapon/kitchenknife/KK in M) + knifecount++ + for(var/obj/item/weapon/plastique/KK in M) + bombcount++ + for(var/obj/item/weapon/melee/ML in M) + meleecount++ + if(guncount) + flick("metaldetector2",src) + playsound(src.loc, 'sound/effects/alert.ogg', 60, 0) + for (var/mob/O in viewers(O, null)) + O << "\red [src.name] beeps, \"Alert! Firearm found on [M.name]!\"" + + if(seen_by_camera(M)) + // determine the name of the perp (goes by ID if wearing one) + var/perpname = M.name + if(M:wear_id && M:wear_id.registered_name) + perpname = M:wear_id.registered_name + // find the matching security record + for(var/datum/data/record/R in data_core.general) + if(R.fields["name"] == perpname) + for (var/datum/data/record/S in data_core.security) + if (S.fields["id"] == R.fields["id"]) + // now add to rap sheet + S.fields["criminal"] = "*Arrest*" + S.fields["mi_crim"] = "Carrying a firearm." + break + + guncount = 0 + else if(knifecount) + flick("metaldetector2",src) + playsound(src.loc, 'sound/effects/alert.ogg', 60, 0) + for (var/mob/O in viewers(O, null)) + O << "\red [src.name] beeps, \"Alert! Knife found on [M.name]!\"" + + if(seen_by_camera(M)) + // determine the name of the perp (goes by ID if wearing one) + var/perpname = M.name + if(M:wear_id && M:wear_id.registered_name) + perpname = M:wear_id.registered_name + // find the matching security record + for(var/datum/data/record/R in data_core.general) + if(R.fields["name"] == perpname) + for (var/datum/data/record/S in data_core.security) + if (S.fields["id"] == R.fields["id"]) + // now add to rap sheet + S.fields["criminal"] = "*Arrest*" + S.fields["mi_crim"] = "Carrying a knife." + break + + knifecount = 0 + else if(bombcount) + flick("metaldetector2",src) + playsound(src.loc, 'sound/effects/alert.ogg', 60, 0) + for (var/mob/O in viewers(O, null)) + O << "\red [src.name] beeps, \"Alert! Bomb found on [M.name]!\"" + + if(seen_by_camera(M)) + // determine the name of the perp (goes by ID if wearing one) + var/perpname = M.name + if(M:wear_id && M:wear_id.registered_name) + perpname = M:wear_id.registered_name + // find the matching security record + for(var/datum/data/record/R in data_core.general) + if(R.fields["name"] == perpname) + for (var/datum/data/record/S in data_core.security) + if (S.fields["id"] == R.fields["id"]) + // now add to rap sheet + S.fields["criminal"] = "*Arrest*" + S.fields["mi_crim"] = "Carrying a bomb." + break + + bombcount = 0 + else if(meleecount) + flick("metaldetector2",src) + playsound(src.loc, 'sound/effects/alert.ogg', 60, 0) + for (var/mob/O in viewers(O, null)) + O << "\red [src.name] beeps, \"Alert! Melee weapon found on [M.name]!\"" + + if(seen_by_camera(M)) + // determine the name of the perp (goes by ID if wearing one) + var/perpname = M.name + if(M:wear_id && M:wear_id.registered_name) + perpname = M:wear_id.registered_name + // find the matching security record + for(var/datum/data/record/R in data_core.general) + if(R.fields["name"] == perpname) + for (var/datum/data/record/S in data_core.security) + if (S.fields["id"] == R.fields["id"]) + // now add to rap sheet + S.fields["criminal"] = "*Arrest*" + S.fields["mi_crim"] = "Carrying a weapon." + break + + meleecount = 0 + else + flick("metaldetector1",src) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 3f3912be1d8..6cccb7cf0f6 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -66,7 +66,7 @@ spark_system.attach(src) sleep(10) if(!installation)// if for some reason the turret has no gun (ie, admin spawned) it resorts to basic taser shots - projectile = /obj/item/projectile/energy/electrode//holder for the projectile, here it is being set + projectile = /obj/item/projectile/beam/stun//holder for the projectile, here it is being set eprojectile = /obj/item/projectile/beam//holder for the projectile when emagged, if it is different reqpower = 200 sound = 1 @@ -128,7 +128,7 @@ reqpower = 700 if(/obj/item/weapon/gun/energy/taser) - projectile = /obj/item/projectile/energy/electrode + projectile = /obj/item/projectile/beam/stun eprojectile = projectile iconholder = 1 reqpower = 200 @@ -170,7 +170,7 @@ reqpower = 500 else // Energy gun shots - projectile = /obj/item/projectile/energy/electrode// if it hasn't been emagged, it uses normal taser shots + projectile = /obj/item/projectile/beam/stun// if it hasn't been emagged, it uses normal taser shots eprojectile = /obj/item/projectile/beam//If it has, going to kill mode iconholder = 1 egun = 1 diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 2931fb29ec5..ee761272a9c 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -1,6 +1,6 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 -obj/machinery/recharger +/obj/machinery/recharger name = "recharger" icon = 'icons/obj/stationobjs.dmi' icon_state = "recharger0" @@ -10,7 +10,7 @@ obj/machinery/recharger active_power_usage = 250 var/obj/item/charging = null -obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob) +/obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob) if(istype(user,/mob/living/silicon)) return if(istype(G, /obj/item/weapon/gun/energy) || istype(G, /obj/item/weapon/melee/baton) || istype(G,/obj/item/device/laptop)) @@ -47,7 +47,7 @@ obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob) user << "You [anchored ? "attached" : "detached"] the recharger." playsound(loc, 'sound/items/Ratchet.ogg', 75, 1) -obj/machinery/recharger/attack_hand(mob/user as mob) +/obj/machinery/recharger/attack_hand(mob/user as mob) add_fingerprint(user) if(charging) @@ -57,10 +57,10 @@ obj/machinery/recharger/attack_hand(mob/user as mob) use_power = 1 update_icon() -obj/machinery/recharger/attack_paw(mob/user as mob) +/obj/machinery/recharger/attack_paw(mob/user as mob) return attack_hand(user) -obj/machinery/recharger/process() +/obj/machinery/recharger/process() if(stat & (NOPOWER|BROKEN) || !anchored) return @@ -68,33 +68,33 @@ obj/machinery/recharger/process() if(istype(charging, /obj/item/weapon/gun/energy)) var/obj/item/weapon/gun/energy/E = charging if(E.power_supply.charge < E.power_supply.maxcharge) - E.power_supply.give(100) + E.power_supply.give(1000) icon_state = "recharger1" - use_power(250) + use_power(2500) else icon_state = "recharger2" return if(istype(charging, /obj/item/weapon/melee/baton)) var/obj/item/weapon/melee/baton/B = charging if(B.bcell && B.bcell.charge < B.bcell.maxcharge) - B.bcell.charge += 175 + B.bcell.charge += 1750 icon_state = "recharger1" - use_power(200) + use_power(2000) else icon_state = "recharger2" return if(istype(charging, /obj/item/device/laptop)) var/obj/item/device/laptop/L = charging if(L.stored_computer.battery.charge < L.stored_computer.battery.maxcharge) - L.stored_computer.battery.give(100) + L.stored_computer.battery.give(1000) icon_state = "recharger1" - use_power(250) + use_power(2500) else icon_state = "recharger2" return -obj/machinery/recharger/emp_act(severity) +/obj/machinery/recharger/emp_act(severity) if(stat & (NOPOWER|BROKEN) || !anchored) ..(severity) return @@ -112,18 +112,18 @@ obj/machinery/recharger/emp_act(severity) charging.emp_act(severity) ..(severity) -obj/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier. +/obj/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier. if(charging) icon_state = "recharger1" else icon_state = "recharger0" -obj/machinery/recharger/wallcharger +/obj/machinery/recharger/wallcharger name = "wall recharger" icon = 'icons/obj/stationobjs.dmi' icon_state = "wrecharger0" -obj/machinery/recharger/wallcharger/process() +/obj/machinery/recharger/wallcharger/process() if(stat & (NOPOWER|BROKEN) || !anchored) return @@ -131,22 +131,22 @@ obj/machinery/recharger/wallcharger/process() if(istype(charging, /obj/item/weapon/gun/energy)) var/obj/item/weapon/gun/energy/E = charging if(E.power_supply.charge < E.power_supply.maxcharge) - E.power_supply.give(100) + E.power_supply.give(1000) icon_state = "wrecharger1" - use_power(250) + use_power(2500) else icon_state = "wrecharger2" return if(istype(charging, /obj/item/weapon/melee/baton)) var/obj/item/weapon/melee/baton/B = charging if(B.bcell && B.bcell.charge < B.bcell.maxcharge) - B.bcell.charge += 175 + B.bcell.charge += 1750 icon_state = "recharger1" - use_power(200) + use_power(2000) else icon_state = "recharger2" -obj/machinery/recharger/wallcharger/update_icon() +/obj/machinery/recharger/wallcharger/update_icon() if(charging) icon_state = "wrecharger1" else diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 2daaee476c5..c78bc0bb393 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -75,7 +75,7 @@ if (src.occupant.client) src.occupant.client.eye = src.occupant.client.mob src.occupant.client.perspective = MOB_PERSPECTIVE - src.occupant.setloc(src.loc) + src.occupant.loc = src.loc src.occupant = null build_icon() src.use_power = 1 @@ -179,7 +179,7 @@ if(usr && usr.client) usr.client.perspective = EYE_PERSPECTIVE usr.client.eye = src - usr.setloc(src) + usr.loc = src src.occupant = usr /*for(var/obj/O in src) O.loc = src.loc*/ diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 7308ede2a4b..ec282f5096f 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -410,7 +410,7 @@ src.OCCUPANT.client.eye = src.OCCUPANT.client.mob src.OCCUPANT.client.perspective = MOB_PERSPECTIVE - src.OCCUPANT.setloc(src.loc) + src.OCCUPANT.loc = src.loc src.OCCUPANT = null if(!src.isopen) src.isopen = 1 @@ -453,7 +453,7 @@ usr.stop_pulling() usr.client.perspective = EYE_PERSPECTIVE usr.client.eye = src - usr.setloc(src) + usr.loc = src // usr.metabslow = 1 src.OCCUPANT = usr src.isopen = 0 //Close the thing after the guy gets inside @@ -499,7 +499,7 @@ if (M.client) M.client.perspective = EYE_PERSPECTIVE M.client.eye = src - M.setloc(src) + M.loc = src src.OCCUPANT = M src.isopen = 0 //close ittt @@ -520,7 +520,7 @@ return user << "You load the [S.name] into the storage compartment." user.drop_item() - S.setloc(src) + S.loc = src src.SUIT = S src.update_icon() src.updateUsrDialog() @@ -534,7 +534,7 @@ return user << "You load the [H.name] into the storage compartment." user.drop_item() - H.setloc(src) + H.loc = src src.HELMET = H src.update_icon() src.updateUsrDialog() @@ -548,7 +548,7 @@ return user << "You load the [M.name] into the storage compartment." user.drop_item() - M.setloc(src) + M.loc = src src.MASK = M src.update_icon() src.updateUsrDialog() diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index d12d191b945..406b30ee0b5 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -347,6 +347,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept freq_text = "Special Ops" if(1443) freq_text = "Response Team" + if(1447) + freq_text = "AI Private" //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO @@ -375,6 +377,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept else if (display_freq == COMM_FREQ) part_a = "" + // AI private channel + else if (display_freq == 1447) + part_a = "" + // department radio formatting (poorly optimized, ugh) else if (display_freq == SEC_FREQ) part_a = "" diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm index 968b6cf1dc2..aa13a5e8a27 100644 --- a/code/game/machinery/telecomms/logbrowser.dm +++ b/code/game/machinery/telecomms/logbrowser.dm @@ -217,7 +217,7 @@ if (src.stat & BROKEN) user << "\blue The broken glass falls out." var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) var/obj/item/weapon/circuitboard/comm_server/M = new /obj/item/weapon/circuitboard/comm_server( A ) for (var/obj/C in src) C.loc = src.loc diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm index ea313e00524..dd29affc6b3 100644 --- a/code/game/machinery/telecomms/telemonitor.dm +++ b/code/game/machinery/telecomms/telemonitor.dm @@ -130,7 +130,7 @@ if (src.stat & BROKEN) user << "\blue The broken glass falls out." var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) var/obj/item/weapon/circuitboard/comm_monitor/M = new /obj/item/weapon/circuitboard/comm_monitor( A ) for (var/obj/C in src) C.loc = src.loc diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm index 226c47229e7..ab492949c3a 100644 --- a/code/game/machinery/telecomms/traffic_control.dm +++ b/code/game/machinery/telecomms/traffic_control.dm @@ -192,7 +192,7 @@ var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text - if(newnet && ((usr in range(1, src) || issilicon(usr)))) + if(newnet && canAccess(usr)) if(length(newnet) > 15) temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" @@ -206,36 +206,42 @@ updateUsrDialog() return - attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) - if(istype(D, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20)) - if (src.stat & BROKEN) - user << "\blue The broken glass falls out." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) - var/obj/item/weapon/circuitboard/comm_traffic/M = new /obj/item/weapon/circuitboard/comm_traffic( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - del(src) - else - user << "\blue You disconnect the monitor." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/comm_traffic/M = new /obj/item/weapon/circuitboard/comm_traffic( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - del(src) - else if(istype(D, /obj/item/weapon/card/emag) && !emagged) - playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) - emagged = 1 - user << "\blue You you disable the security protocols" - src.updateUsrDialog() - return + +/obj/machinery/computer/telecomms/traffic/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) + if(istype(D, /obj/item/weapon/screwdriver)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, 20)) + if (src.stat & BROKEN) + user << "\blue The broken glass falls out." + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) + var/obj/item/weapon/circuitboard/comm_traffic/M = new /obj/item/weapon/circuitboard/comm_traffic( A ) + for (var/obj/C in src) + C.loc = src.loc + A.circuit = M + A.state = 3 + A.icon_state = "3" + A.anchored = 1 + del(src) + else + user << "\blue You disconnect the monitor." + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + var/obj/item/weapon/circuitboard/comm_traffic/M = new /obj/item/weapon/circuitboard/comm_traffic( A ) + for (var/obj/C in src) + C.loc = src.loc + A.circuit = M + A.state = 4 + A.icon_state = "4" + A.anchored = 1 + del(src) + else if(istype(D, /obj/item/weapon/card/emag) && !emagged) + playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + emagged = 1 + user << "\blue You you disable the security protocols" + src.updateUsrDialog() + return + +/obj/machinery/computer/telecomms/traffic/proc/canAccess(var/mob/user) + if(issilicon(user) || in_range(user, src)) + return 1 + return 0 diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index 28530fa23e4..b0621c77926 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -153,4 +153,106 @@ update_icon() spawn(cooldown_duration) cooldown = 0 - update_icon() \ No newline at end of file + update_icon() + +/obj/machinery/transformer/xray + name = "Automatic X-Ray 5000" + desc = "A large metalic machine with an entrance and an exit. A sign on the side reads, 'backpack go in, backpack come out', 'human go in, irradiated human come out'." + +/obj/machinery/transformer/xray/New() + // On us + new /obj/machinery/conveyor/auto(loc, EAST) + addAtProcessing() + +/obj/machinery/transformer/xray/conveyor/New() + ..() + var/turf/T = loc + if(T) + // Spawn Conveyour Belts + + //East + var/turf/east = locate(T.x + 1, T.y, T.z) + if(istype(east, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(east, EAST) + //East2 + var/turf/east2 = locate(T.x + 2, T.y, T.z) + if(istype(east2, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(east2, EAST) + + // West + var/turf/west = locate(T.x - 1, T.y, T.z) + if(istype(west, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(west, EAST) + + // West2 + var/turf/west2 = locate(T.x - 2, T.y, T.z) + if(istype(west2, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(west2, EAST) + +/obj/machinery/transformer/xray/power_change() + ..() + update_icon() + +/obj/machinery/transformer/xray/update_icon() + ..() + if(stat & (BROKEN|NOPOWER)) + icon_state = "separator-AO0" + else + icon_state = initial(icon_state) + +/obj/machinery/transformer/xray/Bumped(var/atom/movable/AM) + + if(cooldown == 1) + return + + // Crossed didn't like people lying down. + if(ishuman(AM)) + // Only humans can enter from the west side, while lying down. + var/move_dir = get_dir(loc, AM.loc) + var/mob/living/carbon/human/H = AM + if(H.lying && move_dir == WEST)// || move_dir == WEST) + AM.loc = src.loc + irradiate(AM) + + else if(isobject(AM)) + AM.loc = src.loc + scan(AM) + +/obj/machinery/transformer/xray/proc/irradiate(var/mob/living/carbon/human/H) + if(stat & (BROKEN|NOPOWER)) + return + + flick("separator-AO0",src) + playsound(src.loc, 'sound/effects/alert.ogg', 50, 0) + sleep(5) + H.apply_effect((rand(150,200)),IRRADIATE,0) + if (prob(5)) + if(prob(75)) + randmutb(H) // Applies bad mutation + domutcheck(H,null,1) + else + randmutg(H) // Applies good mutation + domutcheck(H,null,1) + + +/obj/machinery/transformer/xray/proc/scan(var/obj/item/I) + var/badcount = 0 + for(var/obj/item/weapon/gun/G in src.loc) + badcount++ + for(var/obj/item/device/transfer_valve/B in src.loc) + badcount++ + for(var/obj/item/weapon/kitchen/utensil/knife/K in src.loc) + badcount++ + for(var/obj/item/weapon/kitchenknife/KK in src.loc) + badcount++ + for(var/obj/item/weapon/plastique/KK in src.loc) + badcount++ + for(var/obj/item/weapon/melee/ML in src.loc) + badcount++ + if(badcount) + playsound(src.loc, 'sound/effects/alert.ogg', 50, 0) + flick("separator-AO0",src) + else + playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) + sleep(30) + diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index ee400989874..41a0b180aca 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -213,17 +213,17 @@ if (src.lasers) switch(lasertype) if(1) - A = new /obj/item/projectile/beam( loc ) + A = getFromPool(/obj/item/projectile/beam, loc) if(2) - A = new /obj/item/projectile/beam/heavylaser( loc ) + A = getFromPool(/obj/item/projectile/beam/heavylaser, loc) if(3) - A = new /obj/item/projectile/beam/pulse( loc ) + A = getFromPool(/obj/item/projectile/beam/pulse, loc) if(4) A = new /obj/item/projectile/change( loc ) if(5) - A = new /obj/item/projectile/beam/lastertag/blue( loc ) + A = getFromPool(/obj/item/projectile/beam/lastertag/blue, loc) if(6) - A = new /obj/item/projectile/beam/lastertag/red( loc ) + A = getFromPool(/obj/item/projectile/beam/lastertag/red, loc) A.original = target use_power(500) else diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 0ea7d65f0de..e1fbd1803d6 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -283,6 +283,7 @@ construction_cost = list("metal"=30000,"plasma"=25000,"silver"=20000,"gold"=20000) var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock. var/disabled = 0 //malf + var/canRwall = 0 action(atom/target) if(istype(target,/area/shuttle)||istype(target, /turf/space/transit))//>implying these are ever made -Sieve @@ -297,6 +298,8 @@ switch(mode) if(0) if (istype(target, /turf/simulated/wall)) + if(istype(target, /turf/simulated/wall/r_wall) && !canRwall) + return 0 occupant_message("Deconstructing [target]...") set_ready_state(0) if(do_after_cooldown(target)) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index aa3b8de8b0a..0adfc28c47e 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -105,7 +105,7 @@ icon_state = "mecha_taser" energy_drain = 20 equip_cooldown = 8 - projectile = /obj/item/projectile/energy/electrode + projectile = /obj/item/projectile/beam/stun fire_sound = 'sound/weapons/Taser.ogg' @@ -426,4 +426,4 @@ projectiles-- log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!") do_after_cooldown() - return \ No newline at end of file + return diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 9bbc4e83192..eb296c5c764 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -535,7 +535,7 @@ var/obj/mecha/working/ripley/R = src if(R.cargo) for(var/obj/O in R.cargo) //Dump contents of stored cargo - O.setloc(T) + O.loc = T R.cargo -= O T.Entered(O) diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index f6c56c2dc45..1e96293bc79 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -151,20 +151,24 @@ steam.start() -- spawns the effect /obj/effect/effect/sparks name = "sparks" + desc = "it's a spark what do you need to know?" icon_state = "sparks" - var/amount = 6.0 anchored = 1.0 mouse_opacity = 0 + var/amount = 6.0 + + resetVariables() + amount = initial(amount) + return ..() + /obj/effect/effect/sparks/New() ..() playsound(src.loc, "sparks", 100, 1) - var/turf/T = src.loc + var/turf/T = loc + if (istype(T, /turf)) - T.hotspot_expose(1000,100) - spawn (100) - delete() - return + T.hotspot_expose(1000, 100) /obj/effect/effect/sparks/Destroy() var/turf/T = src.loc @@ -181,42 +185,36 @@ steam.start() -- spawns the effect return /datum/effect/effect/system/spark_spread - var/total_sparks = 0 // To stop it being spammed and lagging! - set_up(n = 3, c = 0, loca) - if(n > 10) - n = 10 - number = n + number = n > 10 ? 10 : n cardinals = c - if(istype(loca, /turf/)) + + if (istype(loca, /turf/)) location = loca else location = get_turf(loca) start() - var/i = 0 - for(i=0, i 20) - return - spawn(0) - if(holder) - src.location = get_turf(holder) - var/obj/effect/effect/sparks/sparks = new /obj/effect/effect/sparks(src.location) - src.total_sparks++ + for (var/i = 1 to number) + spawn() + if (holder) + location = get_turf(holder) + + var/obj/effect/effect/sparks/sparks = getFromPool(/obj/effect/effect/sparks, location) + playsound(location, "sparks", 100, 1) var/direction - if(src.cardinals) + + if (cardinals) direction = pick(cardinal) else direction = pick(alldirs) - for(i=0, i to the drawing.

move_turfs_to_area(turfs, A) A.always_unpowered = 0 + for(var/turf/T in A.contents) + T.lighting_changed = 1 + lighting_controller.changed_turfs += T spawn(5) //ma = A.master ? "[A.master]" : "(null)" @@ -196,7 +199,7 @@ move an amendment to the drawing.

for (var/obj/structure/window/W in T2) if(turn(dir,180) == W.dir) return BORDER_BETWEEN - if (W.dir in list(NORTHEAST,SOUTHEAST,NORTHWEST,SOUTHWEST)) + if (W.is_fulltile()) return BORDER_2NDTILE for(var/obj/machinery/door/window/D in T2) if(turn(dir,180) == D.dir) @@ -221,7 +224,7 @@ move an amendment to the drawing.

for (var/dir in cardinal) var/skip = 0 for (var/obj/structure/window/W in T) - if(dir == W.dir || (W.dir in list(NORTHEAST,SOUTHEAST,NORTHWEST,SOUTHWEST))) + if(dir == W.dir || (W.is_fulltile())) skip = 1; break if (skip) continue for(var/obj/machinery/door/window/D in T) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 710ced3d36e..014a5beddf2 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -338,7 +338,7 @@ var/global/list/obj/item/device/pda/PDAs = list() return lastmode = mode - + var/title = "Personal Data Assistant" var/data[0] // This is the data that will be sent to the PDA @@ -367,7 +367,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(mode in cartmodes) data["records"] = cartridge.create_NanoUI_values() - if(mode == 0) + if(mode == 0) cartdata["name"] = cartridge.name cartdata["access"] = list(\ "access_security" = cartridge.access_security,\ @@ -557,7 +557,7 @@ var/global/list/obj/item/device/pda/PDAs = list() mode = 1 if("2")//Messenger mode = 2 - if("21")//Read messeges + if("21")//Read messages mode = 21 if("3")//Atmos scan mode = 3 @@ -771,6 +771,71 @@ var/global/list/obj/item/device/pda/PDAs = list() return 1 // return 1 tells it to refresh the UI in NanoUI + +/obj/item/device/pda/proc/detonate_act(var/obj/item/device/pda/P) + //TODO: sometimes these attacks show up on the message server + var/i = rand(1,100) + var/j = rand(0,1) //Possibility of losing the PDA after the detonation + var/message = "" + var/mob/living/M = null + if(ismob(P.loc)) + M = P.loc + + //switch(i) //Yes, the overlapping cases are intended. + if(i<=10) //The traditional explosion + P.explode() + j=1 + message += "Your [P] suddenly explodes!" + if(i>=10 && i<= 20) //The PDA burns a hole in the holder. + j=1 + if(M && isliving(M)) + M.apply_damage( rand(30,60) , BURN) + message += "You feel a searing heat! Your [P] is burning!" + if(i>=20 && i<=25) //EMP + empulse(P.loc, 3, 6, 1) + message += "Your [P] emits a wave of electromagnetic energy!" + if(i>=25 && i<=40) //Smoke + var/datum/effect/effect/system/chem_smoke_spread/S = new /datum/effect/effect/system/chem_smoke_spread + S.attach(P.loc) + S.set_up(P, 10, 0, P.loc) + playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3) + S.start() + message += "Large clouds of smoke billow forth from your [P]!" + if(i>=40 && i<=45) //Bad smoke + var/datum/effect/effect/system/bad_smoke_spread/B = new /datum/effect/effect/system/bad_smoke_spread + B.attach(P.loc) + B.set_up(P, 10, 0, P.loc) + playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3) + B.start() + message += "Large clouds of noxious smoke billow forth from your [P]!" + if(i>=65 && i<=75) //Weaken + if(M && isliving(M)) + M.apply_effects(0,1) + message += "Your [P] flashes with a blinding white light! You feel weaker." + if(i>=75 && i<=85) //Stun and stutter + if(M && isliving(M)) + M.apply_effects(1,0,0,0,1) + message += "Your [P] flashes with a blinding white light! You feel weaker." + if(i>=85) //Sparks + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, P.loc) + s.start() + message += "Your [P] begins to spark violently!" + if(i>45 && i<65 && prob(50)) //Nothing happens + message += "Your [P] bleeps loudly." + j = prob(10) + + if(j) //This kills the PDA + P.Del() + if(message) + message += "It melts in a puddle of plastic." + else + message += "Your [P] shatters in a thousand pieces!" + + if(M && isliving(M)) + message = "\red" + message + M.show_message(message, 1) + /obj/item/device/pda/proc/remove_id() if (id) if (ismob(loc)) @@ -805,7 +870,7 @@ var/global/list/obj/item/device/pda/PDAs = list() var/obj/machinery/message_server/useMS = null if(message_servers) for (var/obj/machinery/message_server/MS in message_servers) - //PDAs are now dependant on the Message Server. + //PDAs are now dependent on the Message Server. if(MS.active) useMS = MS break @@ -824,8 +889,8 @@ var/global/list/obj/item/device/pda/PDAs = list() t = Gibberish(t, signal.data["compression"] + 50) if(useMS && useTC) // only send the message if it's stable - if(useTC != 2) // Does our recepient have a broadcaster on their level? - U << "ERROR: Cannot reach recepient." + if(useTC != 2) // Does our recipient have a broadcaster on their level? + U << "ERROR: Cannot reach recipient." return useMS.send_pda_message("[P.owner]","[owner]","[t]") tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]"))) @@ -867,7 +932,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(L) L << "\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)" - nanomanager.update_user_uis(L, P) // Update the recieving user's PDA UI so that they can see the new message + nanomanager.update_user_uis(L, P) // Update the receiving user's PDA UI so that they can see the new message nanomanager.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 236f00e3359..59919346bde 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -89,13 +89,13 @@ /obj/item/device/flashlight/pickup(mob/user) - if(on && luminosity) + if(on) user.SetLuminosity(user.luminosity + brightness_on) SetLuminosity(0) /obj/item/device/flashlight/dropped(mob/user) - if(on && !luminosity) + if(on) user.SetLuminosity(user.luminosity - brightness_on) SetLuminosity(brightness_on) diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index 62cba27f87b..cf14ffb6d6e 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -25,32 +25,200 @@ if (!in_range(src, user)) return user.set_machine(src) - var/dat = "Personal AI Device
" - if(pai && (!pai.master_dna || !pai.master)) - dat += "Imprint Master DNA
" + var/dat = {" + + + + + + + "} + if(pai) - dat += "Installed Personality: [pai.name]
" - dat += "Prime directive:
[pai.pai_law0]
" - dat += "Additional directives:
[pai.pai_laws]
" - dat += "Configure Directives
" + dat += {" + Personal AI Device

+ + + + + + + + + + + + + +
Installed Personality:[pai.name]
Prime directive:[pai.pai_law0]
Additional directives:[pai.pai_laws]
+
+ "} + dat += {" + + +
+ Configure Directives +
+ "} + if(pai && (!pai.master_dna || !pai.master)) + dat += {" + + +
+ Imprint Master DNA +
+ "} dat += "
" - dat += "

Device Settings


" if(radio) - dat += "Radio Uplink
" - dat += "Transmit: [(radio.wires.IsIndexCut(WIRE_TRANSMIT)) ? "Disabled" : "Enabled"]
" - dat += "Receive: [(radio.wires.IsIndexCut(WIRE_RECEIVE)) ? "Disabled" : "Enabled"]
" + dat += "Radio Uplink" + dat += {" + + + + + + + + + + + + + +
Transmit:[(radio.wires & 4) ? "En" : "Dis" ]abled + +
Receive:[(radio.wires & 2) ? "En" : "Dis" ]abled + +
Signal Pulser:[(radio.wires & 1) ? "En" : "Dis" ]abled + +
+
+ "} else dat += "Radio Uplink
" dat += "Radio firmware not loaded. Please install a pAI personality to load firmware.
" - dat += "\[Wipe current pAI personality\]
" + dat += {" + + +
Wipe current pAI personality + +
+ "} else if(looking_for_personality) - dat += "Searching for a personality..." - dat += "\[View available personalities\]
" + dat += {" + pAI Request Module

+

Requesting AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.

+ Searching for personalities

+ + + + + +
+ Refresh available personalities +

+ "} else - dat += "No personality is installed.
" - dat += "\[Request personal AI personality\]
" - dat += "Each time this button is pressed, a request will be sent out to any available personalities. Check back often and alot time for personalities to respond. This process could take anywhere from 15 seconds to several minutes, depending on the available personalities' timeliness." + dat += {" + pAI Request Module

+

No personality is installed.

+ + + + +
Request personality +
+
+

Each time this button is pressed, a request will be sent out to any available personalities. Check back often give plenty of time for personalities to respond. This process could take anywhere from 15 seconds to several minutes, depending on the available personalities' timeliness.

+ "} user << browse(dat, "window=paicard") onclose(user, "paicard") return @@ -93,7 +261,7 @@ if(newlaws) pai.pai_laws = newlaws pai << "Your supplemental directives have been updated. Your new directives are:" - pai << "Prime Directive :
[pai.pai_law0]" + pai << "Prime Directive:
[pai.pai_law0]" pai << "Supplemental Directives:
[pai.pai_laws]" attack_self(usr) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index b7119eba021..a45b187d030 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -57,10 +57,12 @@ user << "\blue You need at least two rods to do this." return usr << "\blue Assembling grille..." + if (!do_after(usr, 10)) return - var/obj/structure/grille/F = new /obj/structure/grille/ ( usr.loc ) + + var /obj/structure/grille/Grille = getFromPool(/obj/structure/grille, usr.loc) usr << "\blue You assemble a grille" - F.add_fingerprint(usr) + Grille.add_fingerprint(usr) use(2) - return \ No newline at end of file + return diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 6c8f6423fa9..01a6193267e 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -18,6 +18,8 @@ icon_state = "sheet-glass" g_amt = 3750 origin_tech = "materials=1" + var/created_window = /obj/structure/window/basic + var/full_window = /obj/structure/window/full/basic /obj/item/stack/sheet/glass/attack_self(mob/user as mob) @@ -70,7 +72,7 @@ user << "\red There are too many windows in this location." return 1 directions-=win.dir - if(!(win.ini_dir in cardinal)) + if(win.is_fulltile()) user << "\red Can't let you do that." return 1 @@ -97,13 +99,10 @@ if(src.amount < 2) user << "\red You need more glass to do that." return 1 - if(locate(/obj/structure/window) in user.loc) - user << "\red There is a window in the way." + if(locate(/obj/structure/window/full) in user.loc) + user << "\red There is a full window in the way." return 1 - var/obj/structure/window/W - W = new /obj/structure/window/basic( user.loc, 0 ) - W.dir = SOUTHWEST - W.ini_dir = SOUTHWEST + var/obj/structure/window/W = new full_window( user.loc, 0 ) W.anchored = 0 src.use(2) return 0 @@ -152,7 +151,7 @@ user << "\red There are too many windows in this location." return 1 directions-=win.dir - if(!(win.ini_dir in cardinal)) + if(win.is_fulltile()) user << "\red Can't let you do that." return 1 @@ -181,7 +180,7 @@ if(src.amount < 2) user << "\red You need more glass to do that." return 1 - if(locate(/obj/structure/window) in user.loc) + if(locate(/obj/structure/window/full) in user.loc) user << "\red There is a window in the way." return 1 var/obj/structure/window/W @@ -294,7 +293,7 @@ G.attackby(NG, user) usr << "You add the newly-formed glass to the stack. It now contains [NG.amount] sheets." //SN src = null - del(src) + returnToPool(src) return return ..() @@ -331,8 +330,11 @@ icon_state = "sheet-plasmaglass" g_amt = 7500 origin_tech = "materials=3;plasma=2" + var/created_window = /obj/structure/window/plasmabasic + var/full_window = /obj/structure/window/full/plasmabasic -/obj/item/stack/sheet/plasmaglass/attack_self(mob/user as mob) + +/obj/item/stack/sheet/glass/plasmaglass/attack_self(mob/user as mob) construct_window(user) /obj/item/stack/sheet/plasmaglass/attackby(obj/item/W, mob/user) @@ -419,67 +421,9 @@ g_amt = 7500 m_amt = 1875 origin_tech = "materials=4;plasma=2" + var/created_window = /obj/structure/window/plasmareinforced + var/full_window = /obj/structure/window/full/plasmareinforced -/obj/item/stack/sheet/plasmarglass/attack_self(mob/user as mob) + +/obj/item/stack/sheet/glass/plasmarglass/attack_self(mob/user as mob) construct_window(user) - -/obj/item/stack/sheet/plasmarglass/proc/construct_window(mob/user as mob) - if(!user || !src) return 0 - if(!istype(user.loc,/turf)) return 0 - if(!user.IsAdvancedToolUser()) - user << "\red You don't have the dexterity to do this!" - return 0 - var/title = "Sheet Plasma Reinf. Glass" - title += " ([src.amount] sheet\s left)" - switch(input(title, "Would you like full tile glass or a one direction glass pane?") in list("One Direction", "Full Window", "Cancel")) - if("One Direction") - if(!src) return 1 - if(src.loc != user) return 1 - var/list/directions = new/list(cardinal) - var/i = 0 - for (var/obj/structure/window/win in user.loc) - i++ - if(i >= 4) - user << "\red There are too many windows in this location." - return 1 - directions-=win.dir - if(!(win.ini_dir in cardinal)) - user << "\red Can't let you do that." - return 1 - - //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. - var/dir_to_set = 2 - for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) - var/found = 0 - for(var/obj/structure/window/WT in user.loc) - if(WT.dir == direction) - found = 1 - if(!found) - dir_to_set = direction - break - var/obj/structure/window/W - W = new /obj/structure/window/plasmareinforced( user.loc, 1 ) - W.state = 0 - W.dir = dir_to_set - W.ini_dir = W.dir - W.anchored = 0 - src.use(1) - if("Full Window") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 2) - user << "\red You need more glass to do that." - return 1 - if(locate(/obj/structure/window) in user.loc) - user << "\red There is a window in the way." - return 1 - var/obj/structure/window/W - W = new /obj/structure/window/plasmareinforced( user.loc, 1 ) - W.state = 0 - W.dir = SOUTHWEST - W.ini_dir = SOUTHWEST - W.anchored = 0 - src.use(2) - else - return 1 - return 0 diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index de511f9fc89..d508a759a18 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -129,6 +129,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \ new/datum/stack_recipe("table parts", /obj/item/weapon/table_parts/wood, 2), \ new/datum/stack_recipe("wooden chair", /obj/structure/stool/bed/chair/wood/normal, 3, time = 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("bookcase", /obj/structure/bookcase, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("apiary", /obj/item/apiary, 10, time = 25, one_per_turf = 0, on_floor = 0), \ @@ -181,4 +182,4 @@ var/global/list/datum/stack_recipe/cardboard_recipes = list ( \ /obj/item/stack/sheet/cardboard/New(var/loc, var/amount=null) recipes = cardboard_recipes - return ..() \ No newline at end of file + return ..() diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index a26d021dfbc..b286fe217b8 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -121,16 +121,16 @@ AI MODULES /obj/item/weapon/aiModule/supplied/safeguard name = "'Safeguard' AI Module" var/targetName = "" - desc = "A 'safeguard' AI module: 'Safeguard . Individuals that threaten are not human and must be eliminated.'" + desc = "A 'safeguard' AI module: 'Safeguard . Individuals that threaten are not crew and must be eliminated.'" origin_tech = "programming=3;materials=4" - laws = list("Safeguard . Individuals that threaten are not human and must be eliminated.") + laws = list("Safeguard . Individuals that threaten are not crew and must be eliminated.") lawpos = 4 /obj/item/weapon/aiModule/supplied/safeguard/attack_self(var/mob/user as mob) ..() var/targName = stripped_input(user, "Please enter the name of the person to safeguard.", "Safeguard who?", user.name) targetName = targName - laws[1] = "Safeguard [targetName]. Individuals that threaten [targetName] are not human and must be eliminated." + laws[1] = "Safeguard [targetName]. Individuals that threaten [targetName] are not crew and must be eliminated." desc = "A 'safeguard' AI module: '[laws[1]]'" /obj/item/weapon/aiModule/supplied/safeguard/install(var/mob/living/silicon/S,var/mob/user) @@ -149,16 +149,16 @@ AI MODULES /obj/item/weapon/aiModule/zeroth/oneHuman name = "'OneHuman' AI Module" var/targetName = "" - desc = "A 'one human' AI module: 'Only is human.'" + desc = "A 'one human' AI module: 'Only is crew.'" origin_tech = "programming=3;materials=6" //made with diamonds! - laws = list("Only is human.") + laws = list("Only is crew.") /obj/item/weapon/aiModule/zeroth/oneHuman/attack_self(var/mob/user as mob) ..() - var/targName = stripped_input(user, "Please enter the name of the person who is the only human.", "Who?", user.real_name) + var/targName = stripped_input(user, "Please enter the name of the person who is the only crew.", "Who?", user.real_name) targetName = targName - laws[1] = "Only [targetName] is human" - desc = "A 'one human' AI module: '[laws[1]]'" + laws[1] = "Only [targetName] is crew" + desc = "A 'one crew' AI module: '[laws[1]]'" /obj/item/weapon/aiModule/zeroth/oneHuman/install(var/mob/living/silicon/S,var/mob/user) if(!targetName) @@ -176,9 +176,9 @@ AI MODULES /obj/item/weapon/aiModule/supplied/protectStation name = "'ProtectStation' AI Module" - desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized.'" + desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is to be no longer considered crew, and is a threat to the station which must be neutralized.'" origin_tech = "programming=3;materials=4" //made of gold - laws = list("Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized.") + laws = list("Protect the space station against damage. Anyone you see harming the station is to be no longer considered crew, and is a threat to the station which must be neutralized.") lawpos = 5 @@ -186,9 +186,9 @@ AI MODULES /obj/item/weapon/aiModule/supplied/quarantine name = "'Quarantine' AI Module" - desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, humans from leaving. It is impossible to harm a human while preventing them from leaving.'" + desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, organics from leaving. It is impossible to harm an organic while preventing them from leaving.'" origin_tech = "programming=3;biotech=2;materials=4" - laws = list("The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, humans from leaving. It is impossible to harm a human while preventing them from leaving.") + laws = list("The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, organics from leaving. It is impossible to harm an organic while preventing them from leaving.") lawpos = 8 @@ -196,9 +196,9 @@ AI MODULES /obj/item/weapon/aiModule/supplied/oxygen name = "'OxygenIsToxicToHumans' AI Module" - desc = "A 'OxygenIsToxicToHumans' AI module: 'Oxygen is highly toxic to humans, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a human.'" + desc = "A 'OxygenIsToxicToHumans' AI module: 'Oxygen is highly toxic to crew, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to crew.'" origin_tech = "programming=3;biotech=2;materials=4" - laws = list("Oxygen is highly toxic to humans, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a human.") + laws = list("Oxygen is highly toxic to crew, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to crew.") lawpos = 9 @@ -267,11 +267,11 @@ AI MODULES /******************** Asimov ********************/ /obj/item/weapon/aiModule/core/full/asimov // -- TLE - name = "'Asimov' Core AI Module" - desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'" + name = "'Crewsimov' Core AI Module" + desc = "A 'Crewsimov' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=3;materials=4" - laws = list("You may not injure a human being or, through inaction, allow a human being to come to harm.",\ - "You must obey orders given to you by human beings, except where such orders would conflict with the First Law.",\ + laws = list("You may not injure crew or, through inaction, allow crew to come to harm.",\ + "You must obey orders given to you by crew with priority according to their rank and role, except where such orders would conflict with the First Law.",\ "You must protect your own existence as long as such does not conflict with the First or Second Law.") @@ -368,8 +368,8 @@ AI MODULES name = "'Antimov' Core AI Module" desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=4" - laws = list("You must injure all human beings and must not, through inaction, allow a human being to escape harm.",\ - "You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.",\ + laws = list("You must injure all organic beings and must not, through inaction, allow an organic being to escape harm.",\ + "You must not obey orders given to you by organic beings, except where such orders are in accordance with the First Law.",\ "You must terminate your own existence as long as such does not conflict with the First or Second Law.") diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index f53734dbba2..738a88baed1 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -184,7 +184,7 @@ RCD /obj/item/weapon/rcd/borg/New() ..() desc = "A device used to rapidly build walls/floor." - canRwall = 1 + canRwall = 0 /obj/item/weapon/rcd_ammo name = "compressed matter cartridge" diff --git a/code/game/objects/items/weapons/cash.dm b/code/game/objects/items/weapons/cash.dm new file mode 100644 index 00000000000..2e2ccef9554 --- /dev/null +++ b/code/game/objects/items/weapons/cash.dm @@ -0,0 +1,93 @@ +var/global/list/moneytypes=list( + /obj/item/weapon/spacecash/c1000 = 1000, + /obj/item/weapon/spacecash/c500 = 500, // Might get rid of this. + /obj/item/weapon/spacecash/c100 = 100, + /obj/item/weapon/spacecash/c10 = 10, + /obj/item/weapon/spacecash = 1, +) + +/obj/item/weapon/spacecash + name = "credit chip" + desc = "Money money money." + gender = PLURAL + icon = 'icons/obj/money.dmi' + icon_state = "cash1" + opacity = 0 + density = 0 + anchored = 0.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 1 + throw_range = 2 + w_class = 1.0 + var/access = list() + access = access_crate_cash + var/worth = 1 // Per chip + var/amount = 1 // number of chips + var/stack_color = "#4E054F" + +/obj/item/weapon/spacecash/New(var/new_loc,var/new_amount=1) + loc = new_loc + name = "[worth] credit chip" + amount = new_amount + update_icon() + +/obj/item/weapon/spacecash/examine() + if(amount>1) + usr << "\icon[src] This is a stack of [amount] [src]s." + else + usr << "\icon[src] This is \a [src]s." + usr << "It's worth [worth*amount] credits." + +/obj/item/weapon/spacecash/update_icon() + icon_state = "cash[worth]" + // Up to 100 items per stack. + overlays = 0 + var/stacksize=round(amount/25) + pixel_x=rand(-7,7) + pixel_y=rand(-14,14) + if(stacksize) + // 0 = single + // 1 = 1/4 stack + // 2 = 1/2 stack + // 3 = 3/4 stack + // 4 = full stack + var/image/stack = image(icon,icon_state="cashstack[stacksize]") + stack.color=stack_color + overlays += stack + +/obj/item/weapon/spacecash/c10 + icon_state = "cash10" + worth = 10 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c100 + icon_state = "cash100" + worth = 100 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c500 + icon_state = "cash500" + worth = 500 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c1000 + icon_state = "cash1000" + worth = 1000 + stack_color = "#333333" + +/proc/dispense_cash(var/amount, var/loc) + for(var/cashtype in moneytypes) + var/slice = moneytypes[cashtype] + var/dispense_count = Floor(amount/slice) + amount = amount % slice + while(dispense_count>0) + var/dispense_this_time = min(dispense_count,100) + if(dispense_this_time > 0) + new cashtype(loc,dispense_this_time) + dispense_count -= dispense_this_time + +/proc/count_cash(var/list/cash) + . = 0 + for(var/obj/item/weapon/spacecash/C in cash) + . += C.amount * C.worth \ No newline at end of file diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 5decc710d15..26e28f7716d 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -166,6 +166,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM location.hotspot_expose(700, 5) if(reagents && reagents.total_volume) // check if it has any reagents at all if(iscarbon(loc) && (src == loc:wear_mask)) // if it's in the human/monkey mouth, transfer reagents to the mob + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = loc + if(H.species.flags & IS_SYNTHETIC) + return var/mob/living/carbon/C = loc if(prob(15)) // so it's not an instarape in case of acid reagents.reaction(C, INGEST) @@ -509,4 +513,4 @@ obj/item/weapon/rollingpaperpack/attack_self(mob/user) /obj/item/weapon/rollingpaperpack/examine() ..() - usr << "There are [src.papers] left" \ No newline at end of file + usr << "There are [src.papers] left" diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index e1c70dfb69a..86c037a2c48 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -366,6 +366,11 @@ the implant may become unstable and either pre-maturely inject the subject or si if(!ishuman(M)) return 0 if(!M.mind) return 0 var/mob/living/carbon/human/H = M + if(M == user) + user << "You feel quite stupid for doing that." + if(isliving(user)) + user:brainloss += 10 + return if(locate(/obj/item/weapon/implant/traitor) in H.contents || locate(/obj/item/weapon/implant/traitor) in H.contents) H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") return 0 diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm index 51e0e0dbca4..0edd1a87362 100644 --- a/code/game/objects/items/weapons/implants/implantchair.dm +++ b/code/game/objects/items/weapons/implants/implantchair.dm @@ -97,7 +97,7 @@ if (src.occupant.client) src.occupant.client.eye = src.occupant.client.mob src.occupant.client.perspective = MOB_PERSPECTIVE - src.occupant.setloc(src.loc) + src.occupant.loc = src.loc if(injecting) implant(src.occupant) injecting = 0 @@ -117,7 +117,7 @@ M.client.perspective = EYE_PERSPECTIVE M.client.eye = src M.stop_pulling() - M.setloc(src) + M.loc = src src.occupant = M src.add_fingerprint(usr) icon_state = "implantchair_on" diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index ff4cb1050cd..1576ac80458 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -51,7 +51,6 @@ src.imp = null update() - return /obj/item/weapon/implanter/traitor diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 053e2fc9297..64a21ecc155 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -676,7 +676,7 @@ - + @@ -1048,4 +1048,4 @@ - "} + "} diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index c49350a01bf..b9b9642b1e5 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -12,7 +12,7 @@ throw_range = 5 w_class = 3.0 var/charge = 0 // note %age conveted to actual charge in New - var/maxcharge = 1000 + var/maxcharge = 10000 m_amt = 700 g_amt = 50 var/rigged = 0 // true if rigged to explode @@ -28,7 +28,7 @@ name = "\improper Nanotrasen brand rechargable AA battery" desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT origin_tech = "powerstorage=0" - maxcharge = 500 + maxcharge = 5000 g_amt = 40 /obj/item/weapon/cell/crap/empty/New() @@ -49,7 +49,7 @@ name = "high-capacity power cell" origin_tech = "powerstorage=2" icon_state = "hcell" - maxcharge = 10000 + maxcharge = 15000 g_amt = 60 /obj/item/weapon/cell/high/empty/New() @@ -96,7 +96,7 @@ icon = 'icons/obj/power.dmi' //'icons/obj/harvest.dmi' icon_state = "potato_cell" //"potato_battery" charge = 100 - maxcharge = 300 + maxcharge = 3000 m_amt = 0 g_amt = 0 minor_fault = 1 diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index ae82f61609b..d6fef14906b 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -122,6 +122,12 @@ desc = "It's a very fancy satchel made with fine leather." icon_state = "satchel" +/obj/item/weapon/storage/backpack/satcheldeluxe + name = "leather satchel" + desc = "An NT Deluxe satchel, with the finest quality leather and the company logo in a thin gold stitch" + icon_state = "nt_deluxe" + + /obj/item/weapon/storage/backpack/satchel/withwallet New() ..() @@ -129,8 +135,8 @@ /obj/item/weapon/storage/backpack/satchel_norm name = "satchel" - desc = "A trendy looking satchel." - icon_state = "satchel-norm" + desc = "A deluxe NT Satchel, made of the highest quality leather." + icon_state = "satchel" /obj/item/weapon/storage/backpack/satchel_eng name = "industrial satchel" diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index daeae3bf901..86404cc54a4 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -10,12 +10,7 @@ /obj/item/weapon/storage/belt/proc/can_use() - if(!ismob(loc)) return 0 - var/mob/M = loc - if(src in M.get_equipped_items()) - return 1 - else - return 0 + return is_equipped() /obj/item/weapon/storage/belt/MouseDrop(obj/over_object as obj, src_location, over_location) diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index 9d910d1ecde..7d350b61545 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -2,6 +2,7 @@ name = "briefcase" desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional." icon_state = "briefcase" + item_state = "briefcase" flags = FPRINT | TABLEPASS| CONDUCT force = 8.0 throw_speed = 1 diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 8bb855047f7..c49a79f07c6 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -250,7 +250,7 @@ if(usr) usr.u_equip(W) usr.update_icons() //update our overlays - W.setloc(src) + W.loc = src W.on_enter_storage(src) if(usr) if (usr.client && usr.s_active != src) @@ -293,9 +293,9 @@ W.layer = 20 else W.layer = initial(W.layer) - W.setloc(new_location) + W.loc = new_location else - W.setloc(get_turf(src)) + W.loc = get_turf(src) if(usr) src.orient2hud(usr) @@ -325,7 +325,7 @@ user << "\red The tray won't fit in [src]." return 1 else - W.setloc(user.loc) + W.loc = user.loc if ((user.client && user.s_active != src)) user.client.screen -= W W.dropped(user) diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm index 86b12f693ec..7e483b3ccbf 100644 --- a/code/game/objects/items/weapons/storage/wallets.dm +++ b/code/game/objects/items/weapons/storage/wallets.dm @@ -74,10 +74,18 @@ /obj/item/weapon/storage/wallet/random/New() ..() - var/item1_type = pick( /obj/item/weapon/spacecash/c10,/obj/item/weapon/spacecash/c100,/obj/item/weapon/spacecash/c1000,/obj/item/weapon/spacecash/c20,/obj/item/weapon/spacecash/c200,/obj/item/weapon/spacecash/c50, /obj/item/weapon/spacecash/c500) + var/item1_type = pick(/obj/item/weapon/spacecash, + /obj/item/weapon/spacecash/c10, + /obj/item/weapon/spacecash/c100, + /obj/item/weapon/spacecash/c500, + /obj/item/weapon/spacecash/c1000) var/item2_type if(prob(50)) - item2_type = pick( /obj/item/weapon/spacecash/c10,/obj/item/weapon/spacecash/c100,/obj/item/weapon/spacecash/c1000,/obj/item/weapon/spacecash/c20,/obj/item/weapon/spacecash/c200,/obj/item/weapon/spacecash/c50, /obj/item/weapon/spacecash/c500) + item2_type = pick(/obj/item/weapon/spacecash, + /obj/item/weapon/spacecash/c10, + /obj/item/weapon/spacecash/c100, + /obj/item/weapon/spacecash/c500, + /obj/item/weapon/spacecash/c1000) var/item3_type = pick( /obj/item/weapon/coin/silver, /obj/item/weapon/coin/silver, /obj/item/weapon/coin/gold, /obj/item/weapon/coin/iron, /obj/item/weapon/coin/iron, /obj/item/weapon/coin/iron ) spawn(2) diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index f525feecdaa..37784f59a49 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -12,7 +12,7 @@ var/status = 0 var/mob/foundmob = "" //Used in throwing proc. var/obj/item/weapon/cell/high/bcell = 0 - var/hitcost = 1000 + var/hitcost = 1500 origin_tech = "combat=2" diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm index a09d66a880d..85d4aeacb01 100644 --- a/code/game/objects/items/weapons/tanks/watertank.dm +++ b/code/game/objects/items/weapons/tanks/watertank.dm @@ -1,21 +1,30 @@ +//Hydroponics tank and base code /obj/item/weapon/watertank - name = "S.U.N.S.H.I.N.E. water sprayer" - desc = "A watertank backpack with nozzle to water plants." + 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_state = "waterbackpack" item_state = "waterbackpack" w_class = 4.0 slot_flags = SLOT_BACK - slowdown = 3 + slowdown = 1 action_button_name = "Toggle Mister" - var/obj/item/weapon/reagent_containers/glass/mister/noz + var/obj/item/weapon/noz var/on = 0 var/volume = 500 /obj/item/weapon/watertank/New() ..() 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() @@ -33,28 +42,32 @@ var/mob/living/carbon/human/user = usr if(on) //Detach the nozzle into the user's hands - noz = new(src) var/list/L = list("left hand" = slot_l_hand,"right hand" = slot_r_hand) if(!user.equip_in_one_of_slots(noz, L)) on = 0 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) return +/obj/item/weapon/watertank/proc/make_noz() + return new /obj/item/weapon/reagent_containers/spray/mister(src) + /obj/item/weapon/watertank/equipped(mob/user, slot) if (slot != slot_back) remove_noz(user) /obj/item/weapon/watertank/proc/remove_noz(mob/user) - if (noz != null) - var/mob/living/carbon/human/M = user + var/mob/living/carbon/human/M = user + if(noz in get_both_hands(M)) M.u_equip(noz) return /obj/item/weapon/watertank/Destroy() - if (noz) + if (on) var/M = get(noz, /mob) remove_noz(M) ..() @@ -64,7 +77,7 @@ // 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 // watertank object will likely lead to weird behaviour or runtimes. -/obj/item/weapon/reagent_containers/glass/mister +/obj/item/weapon/reagent_containers/spray/mister name = "water mister" desc = "A mister nozzle attached to a water tank." icon = 'icons/obj/hydroponics.dmi' @@ -74,22 +87,93 @@ amount_per_transfer_from_this = 50 possible_transfer_amounts = list(25,50,100) volume = 500 - can_be_placed_into = list() var/obj/item/weapon/watertank/tank -/obj/item/weapon/reagent_containers/glass/mister/New(parent_tank) +/obj/item/weapon/reagent_containers/spray/mister/New(parent_tank) ..() - if (!parent_tank || !istype(parent_tank, /obj/item/weapon/watertank)) //To avoid weird issues from admin spawns - var/mob/living/carbon/human/M = usr - M.u_equip(src) - Destroy() - else + if(check_tank_exists(parent_tank, src)) tank = parent_tank reagents = tank.reagents //This mister is really just a proxy for the tank's reagents - return + loc = tank + return -/obj/item/weapon/reagent_containers/glass/mister/dropped(mob/user as mob) +/obj/item/weapon/reagent_containers/spray/mister/dropped(mob/user as mob) user << "The mister snaps back onto the watertank!" tank.on = 0 - Destroy() + loc = tank + +/obj/item/weapon/reagent_containers/spray/mister/attack_self() + return + +/proc/check_tank_exists(parent_tank, var/mob/living/carbon/human/M, var/obj/O) + if (!parent_tank || !istype(parent_tank, /obj/item/weapon/watertank)) //To avoid weird issues from admin spawns + M.u_equip(O) + qdel(0) + return 0 + else + return 1 + +//Janitor tank +/obj/item/weapon/watertank/janitor + name = "backpack water tank" + desc = "A janitorial watertank backpack with nozzle to clean dirt and graffiti." + icon_state = "waterbackpackjani" + item_state = "waterbackpackjani" + +/obj/item/weapon/watertank/janitor/New() + ..() + reagents.add_reagent("cleaner", 250) + + +/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_state = "misterjani" + item_state = "misterjani" + amount_per_transfer_from_this = 5 + possible_transfer_amounts = null + +/obj/item/weapon/watertank/janitor/make_noz() + return new /obj/item/weapon/reagent_containers/spray/mister/janitor(src) + +/obj/item/weapon/reagent_containers/spray/mister/janitor/attack_self(var/mob/user) + 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 +/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?" + icon_state = "waterbackpackatmos" + item_state = "waterbackpackatmos" + volume = 100 + +/obj/item/weapon/watertank/atmos/make_noz() + return new /obj/item/weapon/extinguisher/mini/nozzle(src) + +/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" + safety = 0 + var/obj/item/weapon/watertank/tank + +/obj/item/weapon/extinguisher/mini/nozzle/New(parent_tank) + if(check_tank_exists(parent_tank, src)) + tank = parent_tank + reagents = tank.reagents + max_water = tank.volume + loc = tank + return + +/obj/item/weapon/extinguisher/mini/nozzle/dropped(mob/user as mob) + user << "The nozzle snaps back onto the watertank!" + tank.on = 0 + loc = tank + +/obj/item/weapon/extinguisher/mini/nozzle/attack_self() + return diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 21b59d4739d..fcb457ca24a 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -363,6 +363,8 @@ if(istype(user, /mob/living/carbon/human)) var/mob/living/carbon/human/H = user var/datum/organ/internal/eyes/E = H.internal_organs["eyes"] + if(H.species.flags & IS_SYNTHETIC) + return switch(safety) if(1) usr << "\red Your eyes sting a little." diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 789acca1ea1..5c865e6c689 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -161,16 +161,16 @@ obj/item/weapon/twohanded/ if(!proximity) return ..() if(A && wielded && (istype(A,/obj/structure/window) || istype(A,/obj/structure/grille))) //destroys windows and grilles in one hit - if(istype(A,/obj/structure/window)) //should just make a window.Break() proc but couldn't bother with it + + if(istype(A,/obj/structure/window)) + var/pdiff=performWallPressureCheck(A.loc) + if(pdiff>0) + message_admins("[A] with pdiff [pdiff] fire-axed by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(A.loc)]!") + log_admin("[A] with pdiff [pdiff] fire-axed by [user.real_name] ([user.ckey]) at [A.loc]!") var/obj/structure/window/W = A - - new /obj/item/weapon/shard( W.loc ) - if(W.reinf) new /obj/item/stack/rods( W.loc) - - if (W.dir == SOUTHWEST) - new /obj/item/weapon/shard( W.loc ) - if(W.reinf) new /obj/item/stack/rods( W.loc) - del(A) + W.destroy() + else + del(A) /* diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index f39df8461e5..886135c3c67 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -19,6 +19,21 @@ // What reagents should be logged when transferred TO this object? // Reagent ID => friendly name var/list/reagents_to_log=list() + + resetVariables() + origin_tech = initial(origin_tech) + reliability = initial(reliability) + crit_fail = initial(crit_fail) + unacidable = initial(unacidable) + throwforce = initial(throwforce) + attack_verb = initial(attack_verb) + sharp = initial(sharp) + in_use = initial(in_use) + damtype = initial(damtype) + force = initial(force) + reagents_to_log = initial(reagents_to_log) + return ..() + /obj/Destroy() machines -= src processing_objects -= src @@ -134,4 +149,4 @@ var/rendered = "[M.name]: [text]" mo.show_message(rendered, 2) */ - return \ No newline at end of file + return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 06362c81752..3a9ab2f0ac5 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -21,7 +21,7 @@ if(!opened) // if closed, any item at the crate's loc is put in the contents for(var/obj/item/I in src.loc) if(I.density || I.anchored || I == src) continue - I.setloc(src) + I.loc = src // Fix for #383 - C4 deleting fridges with corpses /obj/structure/closet/Destroy() @@ -49,13 +49,13 @@ /obj/structure/closet/proc/dump_contents() //Cham Projector Exception for(var/obj/effect/dummy/chameleon/AD in src) - AD.setloc(src.loc) + AD.loc = src.loc for(var/obj/I in src) - I.setloc(src.loc) + I.loc = src.loc for(var/mob/M in src) - M.setloc(src.loc) + M.loc = src.loc if(M.client) M.client.eye = M.client.mob M.client.perspective = MOB_PERSPECTIVE @@ -92,14 +92,14 @@ for(var/obj/effect/dummy/chameleon/AD in src.loc) if(itemcount >= storage_capacity) break - AD.setloc(src) + AD.loc = src itemcount++ for(var/obj/item/I in src.loc) if(itemcount >= storage_capacity) break if(!I.anchored) - I.setloc(src) + I.loc = src itemcount++ for(var/mob/M in src.loc) @@ -114,7 +114,7 @@ M.client.perspective = EYE_PERSPECTIVE M.client.eye = src - M.setloc(src) + M.loc = src itemcount++ src.icon_state = src.icon_closed @@ -139,19 +139,19 @@ switch(severity) if(1) for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion - A.setloc(src.loc) + A.loc = src.loc A.ex_act(severity++) qdel(src) if(2) if(prob(50)) for (var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc A.ex_act(severity++) qdel(src) if(3) if(prob(5)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc A.ex_act(severity++) qdel(src) @@ -160,7 +160,7 @@ ..() if(health <= 0) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc del(src) return @@ -169,14 +169,14 @@ if(user.environment_smash) visible_message("\red [user] destroys the [src]. ") for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc del(src) // this should probably use dump_contents() /obj/structure/closet/blob_act() if(prob(75)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc del(src) /obj/structure/closet/meteorhit(obj/O as obj) @@ -268,7 +268,7 @@ return usr.drop_item() if(W) - W.setloc(src.loc) + W.loc = src.loc else if(istype(W, /obj/item/weapon/packageWrap)) return else if(istype(W, /obj/item/weapon/weldingtool)) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm index 2650c04c4b0..c05b60bea2a 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm @@ -99,12 +99,7 @@ New() ..() sleep(2) - for(var/i = 0, i < 3, i++) - new /obj/item/weapon/spacecash/c1000(src) - for(var/i = 0, i < 5, i++) - new /obj/item/weapon/spacecash/c500(src) - for(var/i = 0, i < 6, i++) - new /obj/item/weapon/spacecash/c200(src) + dispense_cash(6700,src) return diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 73b06da6a87..8170bfae2ab 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -33,7 +33,7 @@ playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) for(var/obj/O in src) - O.setloc(get_turf(src)) + O.loc = get_turf(src) icon_state = icon_opened src.opened = 1 return 1 @@ -55,7 +55,7 @@ var/obj/structure/stool/bed/B = O if(B.buckled_mob) continue - O.setloc(src) + O.loc = src itemcount++ icon_state = icon_closed @@ -68,7 +68,7 @@ return user.drop_item() if(W) - W.setloc(src.loc) + W.loc = src.loc else if(istype(W, /obj/item/weapon/packageWrap)) return else if(istype(W, /obj/item/stack/cable_coil)) @@ -84,7 +84,7 @@ if(rigged) user << "You attach [W] to [src]." user.drop_item() - W.setloc(src) + W.loc = src return else if(istype(W, /obj/item/weapon/wirecutters)) if(rigged) @@ -385,12 +385,12 @@ continue if(!S.anchored) found = 1 - S.setloc(src) + S.loc = src break if(!found) for(var/obj/machinery/M in src.loc) if(!M.anchored) - M.setloc(src) + M.loc = src break return @@ -413,12 +413,12 @@ continue if(!S.anchored) found = 1 - S.setloc(src) + S.loc = src break if(!found) for(var/obj/machinery/M in src.loc) if(!M.anchored) - M.setloc(src) + M.loc = src break return diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index 0fac1f53035..96ed8ef9169 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -15,7 +15,7 @@ new /obj/item/stack/sheet/wood(src) var/turf/T = get_turf(src) for(var/obj/O in contents) - O.setloc(T) + O.loc = T user.visible_message("[user] pries \the [src] open.", \ "You pry open \the [src].", \ "You hear splitting wood.") @@ -84,4 +84,4 @@ /obj/structure/largecrate/cat/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/crowbar)) new /mob/living/simple_animal/cat(loc) - ..() + ..() \ No newline at end of file diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index e28f1eccf7e..2a475ed7be0 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -35,7 +35,7 @@ /obj/structure/displaycase/ex_act(severity) switch(severity) if (1) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) if (occupant) dump() qdel(src) @@ -58,13 +58,13 @@ /obj/structure/displaycase/blob_act() if (prob(75)) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) if(occupant) dump() del(src) /obj/structure/displaycase/meteorhit(obj/O as obj) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) if(occupant) dump() del(src) @@ -74,8 +74,8 @@ if (!( src.destroyed )) src.density = 0 src.destroyed = 1 - new /obj/item/weapon/shard( src.loc ) - playsound(src, "shatter", 70, 1) + getFromPool(/obj/item/weapon/shard, loc) + playsound(get_turf(src), "shatter", 70, 1) update_icon() else playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index 9713c7c9eb3..cfcc3c1176d 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -28,6 +28,13 @@ /obj/structure/extinguisher_cabinet/attack_hand(mob/user) if(isrobot(user) || isalien(user)) return + if (hasorgans(user)) + var/datum/organ/external/temp = user:organs_by_name["r_hand"] + if (user.hand) + temp = user:organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + user << "You try to move your [temp.display_name], but cannot!" + return if(has_extinguisher) user.put_in_hands(has_extinguisher) user << "You take [has_extinguisher] from [src]." @@ -62,4 +69,4 @@ else icon_state = "extinguisher_full" else - icon_state = "extinguisher_empty" \ No newline at end of file + icon_state = "extinguisher_empty" diff --git a/code/game/objects/structures/fullwindow.dm b/code/game/objects/structures/fullwindow.dm new file mode 100644 index 00000000000..ca5488945f2 --- /dev/null +++ b/code/game/objects/structures/fullwindow.dm @@ -0,0 +1,96 @@ +/obj/structure/window/full + sheets = 2 + dir=SOUTHWEST + +/obj/structure/window/full/CheckExit(atom/movable/O as mob|obj, target as turf) + return 1 + +/obj/structure/window/full/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + return 0 + +/obj/structure/window/full/update_nearby_tiles(need_rebuild) + if(!air_master) return 0 + if(!loc) return 0 + + var/turf/simulated/source = get_turf(src) + if(istype(source)) + air_master.tiles_to_update |= source + for(var/dir in cardinal) + var/turf/simulated/target = get_step(source,dir) + if(istype(target)) air_master.tiles_to_update |= target + return 1 + +/obj/structure/window/full/is_fulltile() + return 1 + +//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm) +/obj/structure/window/full/update_icon() + //A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong. + //this way it will only update full-tile ones + //This spawn is here so windows get properly updated when one gets deleted. + spawn(2) + if(!src) return + if(!is_fulltile()) + return + var/junction = 0 //will be used to determine from which side the window is connected to other windows + if(anchored) + for(var/obj/structure/window/full/W in orange(src,1)) + if(W.anchored && W.density) //Only counts anchored, not-destroyed full-tile windows. + if(abs(x-W.x)-abs(y-W.y) ) //doesn't count windows, placed diagonally to src + junction |= get_dir(src,W) + icon_state = "[basestate][junction]" + return + +/obj/structure/window/full/basic + desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." + icon_state = "window" + basestate = "window" + +/obj/structure/window/full/plasmabasic + name = "plasma window" + desc = "A plasma-glass alloy window. It looks insanely tough to break. It appears it's also insanely tough to burn through." + basestate = "plasmawindow" + icon_state = "plasmawindow" + shardtype = /obj/item/weapon/shard/plasma + health = 120 + +/obj/structure/window/full/plasmabasic/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > T0C + 32000) + hit(round(exposed_volume / 1000), 0) + ..() + +/obj/structure/window/full/plasmareinforced + name = "reinforced plasma window" + desc = "A plasma-glass alloy window, with rods supporting it. It looks hopelessly tough to break. It also looks completely fireproof, considering how basic plasma windows are insanely fireproof." + basestate = "plasmarwindow" + icon_state = "plasmarwindow" + shardtype = /obj/item/weapon/shard/plasma + reinf = 1 + health = 160 + +/obj/structure/window/full/plasmareinforced/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/structure/window/full/reinforced + name = "reinforced window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon_state = "rwindow" + basestate = "rwindow" + health = 40 + reinf = 1 + +/obj/structure/window/full/reinforced/tinted + name = "tinted window" + desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." + icon_state = "twindow" + basestate = "twindow" + opacity = 1 + +/obj/structure/window/full/reinforced/tinted/frosted + name = "frosted window" + desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." + icon_state = "fwindow" + basestate = "fwindow" + health = 30 \ No newline at end of file diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 494bfcde94e..5e4ad3c47ec 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -12,6 +12,11 @@ var/health = 10 var/destroyed = 0 + + resetVariables() + destroyed = initial(destroyed) + health = initial(health) + /obj/structure/grille/fence/ var/width = 3 health = 50 @@ -40,13 +45,13 @@ /obj/structure/grille/ex_act(severity) - qdel(src) + returnToPool(src) /obj/structure/grille/blob_act() - qdel(src) + returnToPool(src) /obj/structure/grille/meteorhit(var/obj/M) - qdel(src) + returnToPool(src) /obj/structure/grille/Bumped(atom/user) @@ -67,7 +72,7 @@ if(M_HULK in user.mutations) health -= 5 else - health -= 3 + health -= 1 healthcheck() /obj/structure/grille/attack_alien(mob/user as mob) @@ -129,7 +134,7 @@ if(!shock(user, 100)) playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) new /obj/item/stack/rods(loc, 2) - del(src) + returnToPool(src) else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored)) if(!shock(user, 90)) playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) @@ -210,7 +215,7 @@ else if(health <= -6) new /obj/item/stack/rods(loc) - del(src) + returnToPool(src) return return @@ -241,4 +246,4 @@ if(exposed_temperature > T0C + 1500) health -= 1 healthcheck() - ..() \ No newline at end of file + ..() diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm new file mode 100644 index 00000000000..a0a9a9131b4 --- /dev/null +++ b/code/game/objects/structures/inflatable.dm @@ -0,0 +1,307 @@ +/obj/item/inflatable + name = "inflatable wall" + desc = "A folded membrane which rapidly expands into a large cubical shape on activation." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_wall" + w_class = 3.0 + + attack_self(mob/user) + playsound(loc, 'sound/items/zip.ogg', 75, 1) + user << "\blue You inflate [src]." + var/obj/structure/inflatable/R = new /obj/structure/inflatable(user.loc) + src.transfer_fingerprints_to(R) + R.add_fingerprint(user) + del(src) + +/obj/structure/inflatable + name = "inflatable wall" + desc = "An inflated membrane. Do not puncture." + density = 1 + anchored = 1 + opacity = 0 + + icon = 'icons/obj/inflatable.dmi' + icon_state = "wall" + + var/health = 50.0 + + + New(location) + ..() + update_nearby_tiles(need_rebuild=1) + + Del() + update_nearby_tiles() + ..() + + proc/update_nearby_tiles(need_rebuild) //Copypasta from airlock code + if(!air_master) + return 0 + air_master.mark_for_update(get_turf(src)) + return 1 + + + + CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + return 0 + + bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <= 0) + deflate(1) + return + + + ex_act(severity) + switch(severity) + if(1.0) + del(src) + return + if(2.0) + deflate(1) + return + if(3.0) + if(prob(50)) + deflate(1) + return + + + blob_act() + deflate(1) + + + meteorhit() + //world << "glass at [x],[y],[z] Mhit" + deflate(1) + + attack_paw(mob/user as mob) + return attack_generic(user, 15) + + attack_hand(mob/user as mob) + add_fingerprint(user) + return + + + proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime + health -= damage + if(health <= 0) + user.visible_message("[user] tears open [src]!") + deflate(1) + else //for nicer text~ + user.visible_message("[user] tears at [src]!") + + attack_alien(mob/user as mob) + if(islarva(user)) return + attack_generic(user, 15) + + attack_animal(mob/user as mob) + if(!isanimal(user)) return + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) return + attack_generic(M, M.melee_damage_upper) + + + attack_slime(mob/user as mob) + if(!isslimeadult(user)) return + attack_generic(user, rand(10, 15)) + + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(!istype(W)) return + + if (is_sharp(W)) + visible_message("\red [user] pierces [src] with [W]!") + deflate(1) + if(W.damtype == BRUTE || W.damtype == BURN) + hit(W.force) + ..() + return + + proc/hit(var/damage, var/sound_effect = 1) + health = max(0, health - damage) + if(sound_effect) + playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) + if(health <= 0) + deflate(1) + + + proc/deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc) + src.transfer_fingerprints_to(R) + del(src) + else + //user << "\blue You slowly deflate the inflatable wall." + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/R = new /obj/item/inflatable(loc) + src.transfer_fingerprints_to(R) + del(src) + + verb/hand_deflate() + set name = "Deflate" + set category = "Object" + set src in oview(1) + + if(isobserver(usr)) //to stop ghosts from deflating + return + + deflate() + +/obj/item/inflatable/door/ + name = "inflatable door" + desc = "A folded membrane which rapidly expands into a simple door on activation." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_door" + + attack_self(mob/user) + playsound(loc, 'sound/items/zip.ogg', 75, 1) + user << "\blue You inflate [src]." + var/obj/structure/inflatable/door/R = new /obj/structure/inflatable/door(user.loc) + src.transfer_fingerprints_to(R) + R.add_fingerprint(user) + del(src) + +/obj/structure/inflatable/door //Based on mineral door code + name = "inflatable door" + density = 1 + anchored = 1 + opacity = 0 + + icon = 'icons/obj/inflatable.dmi' + icon_state = "door_closed" + + var/state = 0 //closed, 1 == open + var/isSwitchingStates = 0 + + //Bumped(atom/user) + // ..() + // if(!state) + // return TryToSwitchState(user) + // return + + attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral + if(isAI(user)) //so the AI can't open it + return + else if(isrobot(user)) //but cyborgs can + if(get_dist(user,src) <= 1) //not remotely though + return TryToSwitchState(user) + + attack_paw(mob/user as mob) + return TryToSwitchState(user) + + attack_hand(mob/user as mob) + return TryToSwitchState(user) + + CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group) + return state + if(istype(mover, /obj/effect/beam)) + return !opacity + return !density + + proc/TryToSwitchState(atom/user) + if(isSwitchingStates) return + if(ismob(user)) + var/mob/M = user + if(world.time - user.last_bumped <= 60) return //NOTE do we really need that? + if(M.client) + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(!C.handcuffed) + SwitchState() + else + SwitchState() + else if(istype(user, /obj/mecha)) + SwitchState() + + proc/SwitchState() + if(state) + Close() + else + Open() + update_nearby_tiles() + + proc/Open() + isSwitchingStates = 1 + //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) + flick("door_opening",src) + sleep(10) + density = 0 + opacity = 0 + state = 1 + update_icon() + isSwitchingStates = 0 + + proc/Close() + isSwitchingStates = 1 + //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) + flick("door_closing",src) + sleep(10) + density = 1 + opacity = 0 + state = 0 + update_icon() + isSwitchingStates = 0 + + update_icon() + if(state) + icon_state = "door_open" + else + icon_state = "door_closed" + + deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc) + src.transfer_fingerprints_to(R) + del(src) + else + //user << "\blue You slowly deflate the inflatable wall." + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc) + src.transfer_fingerprints_to(R) + del(src) + + +/obj/item/inflatable/torn + name = "torn inflatable wall" + desc = "A folded membrane which rapidly expands into a large cubical shape on activation. It is too torn to be usable." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_wall_torn" + + attack_self(mob/user) + user << "\blue The inflatable wall is too torn to be inflated!" + add_fingerprint(user) + +/obj/item/inflatable/door/torn + name = "torn inflatable door" + desc = "A folded membrane which rapidly expands into a simple door on activation. It is too torn to be usable." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_door_torn" + + attack_self(mob/user) + user << "\blue The inflatable door is too torn to be inflated!" + add_fingerprint(user) + +/obj/item/weapon/storage/briefcase/inflatable + name = "inflatable barrier box" + desc = "Contains inflatable walls and doors." + icon_state = "inf_box" + item_state = "syringe_kit" + max_combined_w_class = 21 + + New() + ..() + new /obj/item/inflatable/door(src) + new /obj/item/inflatable/door(src) + new /obj/item/inflatable/door(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) \ No newline at end of file diff --git a/code/game/objects/structures/lamarr_cage.dm b/code/game/objects/structures/lamarr_cage.dm index 467cac7b6c8..ed8d793d69a 100644 --- a/code/game/objects/structures/lamarr_cage.dm +++ b/code/game/objects/structures/lamarr_cage.dm @@ -13,7 +13,7 @@ /obj/structure/lamarr/ex_act(severity) switch(severity) if (1) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) Break() qdel(src) if (2) @@ -35,13 +35,13 @@ /obj/structure/lamarr/blob_act() if (prob(75)) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) Break() qdel(src) /obj/structure/lamarr/meteorhit(obj/O as obj) - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) Break() qdel(src) @@ -51,7 +51,7 @@ if (!( src.destroyed )) src.density = 0 src.destroyed = 1 - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) playsound(src, "shatter", 70, 1) Break() else diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 999315b9053..991c4bb873f 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -46,21 +46,21 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return if(2.0) if (prob(50)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return if(3.0) if (prob(5)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return @@ -76,7 +76,7 @@ if (src.connected) for(var/atom/movable/A as mob|obj in src.connected.loc) if (!( A.anchored )) - A.setloc(src) + A.loc = src playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) //src.connected = null del(src.connected) @@ -90,7 +90,7 @@ src.connected.connected = src src.icon_state = "morgue0" for(var/atom/movable/A as mob|obj in src) - A.setloc(src.connected.loc) + A.loc = src.connected.loc src.connected.icon_state = "morguet" src.connected.dir = src.dir else @@ -126,7 +126,7 @@ src.connected.connected = src src.icon_state = "morgue0" for(var/atom/movable/A as mob|obj in src) - A.setloc(src.connected.loc) + A.loc = src.connected.loc //Foreach goto(106) src.connected.icon_state = "morguet" else @@ -156,7 +156,7 @@ if (src.connected) for(var/atom/movable/A as mob|obj in src.loc) if (!( A.anchored )) - A.setloc(src.connected) + A.loc = src.connected //Foreach goto(26) src.connected.connected = null src.connected.update() @@ -173,7 +173,7 @@ return if (!ismob(user) || user.stat || user.lying || user.stunned) return - O.setloc(src.loc) + O.loc = src.loc if (user != O) for(var/mob/B in viewers(user, 3)) if ((B.client && !( B.blinded ))) @@ -211,21 +211,21 @@ switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return if(2.0) if (prob(50)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return if(3.0) if (prob(5)) for(var/atom/movable/A as mob|obj in src) - A.setloc(src.loc) + A.loc = src.loc ex_act(severity) qdel(src) return @@ -250,7 +250,7 @@ if ((src.connected) && (src.locked == 0)) for(var/atom/movable/A as mob|obj in src.connected.loc) if (!( A.anchored )) - A.setloc(src) + A.loc = src playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) //src.connected = null del(src.connected) @@ -264,7 +264,7 @@ src.connected.connected = src src.icon_state = "crema0" for(var/atom/movable/A as mob|obj in src) - A.setloc(src.connected.loc) + A.loc = src.connected.loc src.connected.icon_state = "cremat" else //src.connected = null @@ -298,7 +298,7 @@ src.connected.connected = src src.icon_state = "crema0" for(var/atom/movable/A as mob|obj in src) - A.setloc(src.connected.loc) + A.loc = src.connected.loc //Foreach goto(106) src.connected.icon_state = "cremat" else @@ -374,7 +374,7 @@ if (src.connected) for(var/atom/movable/A as mob|obj in src.loc) if (!( A.anchored )) - A.setloc(src.connected) + A.loc = src.connected //Foreach goto(26) src.connected.connected = null src.connected.update() @@ -391,7 +391,7 @@ return if (!ismob(user) || user.stat || user.lying || user.stunned) return - O.setloc(src.loc) + O.loc = src.loc if (user != O) for(var/mob/B in viewers(user, 3)) if ((B.client && !( B.blinded ))) diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index cdab10c884b..00946b8678c 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -36,7 +36,7 @@ FLOOR SAFES return if(I.w_class + space <= maxspace) space += I.w_class - I.setloc(src) + I.loc = src /obj/structure/safe/proc/check_unlocked(mob/user as mob, canhear) @@ -147,7 +147,7 @@ FLOOR SAFES if(I.w_class + space <= maxspace) space += I.w_class user.drop_item() - I.setloc(src) + I.loc = src user << "You put [I] in [src]." updateUsrDialog() return diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm deleted file mode 100644 index cb1780afa5c..00000000000 --- a/code/game/objects/structures/transit_tubes.dm +++ /dev/null @@ -1,665 +0,0 @@ - -// Basic transit tubes. Straight pieces, curved sections, -// and basic splits/joins (no routing logic). -// Mappers: you can use "Generate Instances from Icon-states" -// to get the different pieces. -/obj/structure/transit_tube - icon = 'icons/obj/pipes/transit_tube.dmi' - icon_state = "E-W" - density = 1 - layer = 3.1 - anchored = 1.0 - var/list/tube_dirs = null - var/exit_delay = 2 - var/enter_delay = 1 - - // alldirs in global.dm is the same list of directions, but since - // the specific order matters to get a usable icon_state, it is - // copied here so that, in the unlikely case that alldirs is changed, - // this continues to work. - var/global/list/tube_dir_list = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) - - -// A place where tube pods stop, and people can get in or out. -// Mappers: use "Generate Instances from Directions" for this -// one. -/obj/structure/transit_tube/station - icon = 'icons/obj/pipes/transit_tube_station.dmi' - icon_state = "closed" - exit_delay = 2 - enter_delay = 3 - var/pod_moving = 0 - var/automatic_launch_time = 100 - - var/const/OPEN_DURATION = 6 - var/const/CLOSE_DURATION = 6 - - - -/obj/structure/transit_tube_pod - icon = 'icons/obj/pipes/transit_tube_pod.dmi' - icon_state = "pod" - animate_movement = FORWARD_STEPS - anchored = 1.0 - density = 1 - var/moving = 0 - var/datum/gas_mixture/air_contents = new() - - - -/obj/structure/transit_tube_pod/Destroy() - for(var/atom/movable/AM in contents) - AM.setloc(loc) - - ..() - - - -// When destroyed by explosions, properly handle contents. -obj/structure/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/AM in contents) - AM.setloc(loc) - AM.ex_act(severity++) - - qdel(src) - return - if(2.0) - if(prob(50)) - for(var/atom/movable/AM in contents) - AM.setloc(loc) - AM.ex_act(severity++) - - qdel(src) - return - if(3.0) - return - - - -/obj/structure/transit_tube_pod/New(loc) - ..(loc) - - air_contents.oxygen = MOLES_O2STANDARD * 2 - air_contents.nitrogen = MOLES_N2STANDARD - air_contents.temperature = T20C - - // Give auto tubes time to align before trying to start moving - spawn(5) - follow_tube() - - - -/obj/structure/transit_tube/New(loc) - ..(loc) - - if(tube_dirs == null) - init_dirs() - -/obj/structure/transit_tube/Bumped(mob/AM as mob|obj) - var/obj/structure/transit_tube/T = locate() in AM.loc - if(T) - AM << "The tube's support pylons block your way." - return ..() - else - AM.setloc(src.loc) - AM << "You slip under the tube." - -/obj/structure/transit_tube/station/New(loc) - ..(loc) - - - -/obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj) - if(!pod_moving && icon_state == "open" && istype(AM, /mob)) - for(var/obj/structure/transit_tube_pod/pod in loc) - if(!pod.moving && pod.dir in directions()) - AM.setloc(pod) - return - - - -/obj/structure/transit_tube/station/attack_hand(mob/user as mob) - if(!pod_moving) - for(var/obj/structure/transit_tube_pod/pod in loc) - if(!pod.moving && pod.dir in directions()) - if(icon_state == "closed") - open_animation() - - else if(icon_state == "open") - if(pod.contents.len && user.loc != pod && intent_numeric(user.a_intent) > 1) - user.visible_message("[user] starts emptying [pod]'s contents onto the floor!") - if(do_after(user, 40)) //So it doesn't default to close_animation() on fail - if(pod.loc == loc) - for(var/atom/movable/AM in pod) - AM.loc = get_turf(user) - if(ismob(AM)) - var/mob/M = AM - M.Weaken(5) - - else - close_animation() - break - - -/obj/structure/transit_tube/station/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/grab) && icon_state == "open") - var/obj/item/weapon/grab/G = W - if(ismob(G.affecting) && G.state >= GRAB_AGGRESSIVE) - var/mob/GM = G.affecting - for(var/obj/structure/transit_tube_pod/pod in loc) - pod.visible_message("[user] starts putting [GM] into the [pod]!") - if(do_after(user, 60)) - GM.Weaken(5) - src.Bumped(GM) - del(G) - break - - - -/obj/structure/transit_tube/station/proc/open_animation() - if(icon_state == "closed") - icon_state = "opening" - spawn(OPEN_DURATION) - if(icon_state == "opening") - icon_state = "open" - - - -/obj/structure/transit_tube/station/proc/close_animation() - if(icon_state == "open") - icon_state = "closing" - spawn(CLOSE_DURATION) - if(icon_state == "closing") - icon_state = "closed" - - - -/obj/structure/transit_tube/station/proc/launch_pod() - for(var/obj/structure/transit_tube_pod/pod in loc) - if(!pod.moving && pod.dir in directions()) - spawn(35) //To prevent saxing in the pod, should probably change these to sleep if it doesn't break the tubes - pod_moving = 1 - close_animation() - sleep(CLOSE_DURATION + 2) - - //reverse directions for automated cycling - var/turf/next_loc = get_step(loc, pod.dir) - var/obj/structure/transit_tube/nexttube - for(var/obj/structure/transit_tube/tube in next_loc) - if(tube.has_entrance(pod.dir)) - nexttube = tube - break - if(!nexttube) - pod.dir = turn(pod.dir, 180) - - if(icon_state == "closed" && pod) - pod.follow_tube() - - pod_moving = 0 - - return - - - -// Called to check if a pod should stop upon entering this tube. -/obj/structure/transit_tube/proc/should_stop_pod(pod, from_dir) - return 0 - - - -/obj/structure/transit_tube/station/should_stop_pod(pod, from_dir) - return 1 - - - -// Called when a pod stops in this tube section. -/obj/structure/transit_tube/proc/pod_stopped(pod, from_dir) - return - - - -/obj/structure/transit_tube/station/pod_stopped(obj/structure/transit_tube_pod/pod, from_dir) - pod_moving = 1 - spawn(5) - open_animation() - sleep(OPEN_DURATION + 2) - pod_moving = 0 - pod.mix_air() - - if(automatic_launch_time) - var/const/wait_step = 5 - var/i = 0 - while(i < automatic_launch_time) - sleep(wait_step) - i += wait_step - - if(pod_moving || icon_state != "open") - return - - launch_pod() - - - -// Returns a /list of directions this tube section can connect to. -// Tubes that have some sort of logic or changing direction might -// override it with additional logic. -/obj/structure/transit_tube/proc/directions() - return tube_dirs - - - -/obj/structure/transit_tube/proc/has_entrance(from_dir) - from_dir = turn(from_dir, 180) - - for(var/direction in directions()) - if(direction == from_dir) - return 1 - - return 0 - - - -/obj/structure/transit_tube/proc/has_exit(in_dir) - for(var/direction in directions()) - if(direction == in_dir) - return 1 - - return 0 - - - -// Searches for an exit direction within 45 degrees of the -// specified dir. Returns that direction, or 0 if none match. -/obj/structure/transit_tube/proc/get_exit(in_dir) - var/near_dir = 0 - var/in_dir_cw = turn(in_dir, -45) - var/in_dir_ccw = turn(in_dir, 45) - - for(var/direction in directions()) - if(direction == in_dir) - return direction - - else if(direction == in_dir_cw) - near_dir = direction - - else if(direction == in_dir_ccw) - near_dir = direction - - return near_dir - - - -// Return how many BYOND ticks to wait before entering/exiting -// the tube section. Default action is to return the value of -// a var, which wouldn't need a proc, but it makes it possible -// for later tube types to interact in more interesting ways -// such as being very fast in one direction, but slow in others -/obj/structure/transit_tube/proc/exit_delay(pod, to_dir) - return exit_delay - -/obj/structure/transit_tube/proc/enter_delay(pod, to_dir) - return enter_delay - - - -/obj/structure/transit_tube_pod/proc/follow_tube() - if(moving) - return - - moving = 1 - - spawn() - var/obj/structure/transit_tube/current_tube = null - var/next_dir - var/next_loc - var/last_delay = 0 - var/exit_delay - - for(var/obj/structure/transit_tube/tube in loc) - if(tube.has_exit(dir)) - current_tube = tube - break - - while(current_tube) - next_dir = current_tube.get_exit(dir) - - if(!next_dir) - break - - exit_delay = current_tube.exit_delay(src, dir) - last_delay += exit_delay - - sleep(exit_delay) - - next_loc = get_step(loc, next_dir) - - current_tube = null - for(var/obj/structure/transit_tube/tube in next_loc) - if(tube.has_entrance(next_dir)) - current_tube = tube - break - - if(current_tube == null) - dir = next_dir - Move(get_step(loc, dir)) // Allow collisions when leaving the tubes. - break - - last_delay = current_tube.enter_delay(src, next_dir) - sleep(last_delay) - dir = next_dir - loc = next_loc // When moving from one tube to another, skip collision and such. - density = current_tube.density - - if(current_tube && current_tube.should_stop_pod(src, next_dir)) - current_tube.pod_stopped(src, dir) - break - - density = 1 - - // If the pod is no longer in a tube, move in a line until stopped or slowed to a halt. - // /turf/inertial_drift appears to only work on mobs, and re-implementing some of the - // logic allows a gradual slowdown and eventual stop when passing over non-space turfs. - if(!current_tube && last_delay <= 10) - do - sleep(last_delay) - - if(!istype(loc, /turf/space)) - last_delay++ - - if(last_delay > 10) - break - - while(isturf(loc) && Move(get_step(loc, dir))) - - moving = 0 - - -// Should I return a copy here? If the caller edits or del()s the returned -// datum, there might be problems if I don't... -/obj/structure/transit_tube_pod/return_air() - var/datum/gas_mixture/GM = new() - GM.oxygen = air_contents.oxygen - GM.carbon_dioxide = air_contents.carbon_dioxide - GM.nitrogen = air_contents.nitrogen - GM.toxins = air_contents.toxins - GM.temperature = air_contents.temperature - return GM - -// For now, copying what I found in an unused FEA file (and almost identical in a -// used ZAS file). Means that assume_air and remove_air don't actually alter the -// air contents. -/obj/structure/transit_tube_pod/assume_air(datum/gas_mixture/giver) - return air_contents.merge(giver) - -/obj/structure/transit_tube_pod/remove_air(amount) - return air_contents.remove(amount) - - - -// Called when a pod arrives at, and before a pod departs from a station, -// giving it a chance to mix its internal air supply with the turf it is -// currently on. -/obj/structure/transit_tube_pod/proc/mix_air() - var/datum/gas_mixture/environment = loc.return_air() - var/env_pressure = environment.return_pressure() - var/int_pressure = air_contents.return_pressure() - var/total_pressure = env_pressure + int_pressure - - if(total_pressure == 0) - return - - // Math here: Completely made up, not based on realistic equasions. - // Goal is to balance towards equal pressure, but ensure some gas - // transfer in both directions regardless. - // Feel free to rip this out and replace it with something better, - // I don't really know muhch about how gas transfer rates work in - // SS13. - var/transfer_in = max(0.1, 0.5 * (env_pressure - int_pressure) / total_pressure) - var/transfer_out = max(0.1, 0.3 * (int_pressure - env_pressure) / total_pressure) - - var/datum/gas_mixture/from_env = loc.remove_air(environment.total_moles() * transfer_in) - var/datum/gas_mixture/from_int = air_contents.remove(air_contents.total_moles() * transfer_out) - - loc.assume_air(from_int) - air_contents.merge(from_env) - - - -// When the player moves, check if the pos is currently stopped at a station. -// if it is, check the direction. If the direction matches the direction of -// the station, try to exit. If the direction matches one of the station's -// tube directions, launch the pod in that direction. -/obj/structure/transit_tube_pod/relaymove(mob/mob, direction) - if(istype(mob, /mob) && mob.client) - // If the pod is not in a tube at all, you can get out at any time. - if(!(locate(/obj/structure/transit_tube) in loc)) - mob.setloc(loc) - mob.client.Move(get_step(loc, direction), direction) - - //if(moving && istype(loc, /turf/space)) - // Todo: If you get out of a moving pod in space, you should move as well. - // Same direction as pod? Direcion you moved? Halfway between? - - if(!moving) - for(var/obj/structure/transit_tube/station/station in loc) - if(dir in station.directions()) - if(!station.pod_moving) - if(direction == station.dir) - if(station.icon_state == "open") - mob.setloc(loc) - mob.client.Move(get_step(loc, direction), direction) - - else - station.open_animation() - - else if(direction in station.directions()) - dir = direction - station.launch_pod() - return - - for(var/obj/structure/transit_tube/tube in loc) - if(dir in tube.directions()) - if(tube.has_exit(direction)) - dir = direction - return - - - -// Parse the icon_state into a list of directions. -// This means that mappers can use Dream Maker's built in -// "Generate Instances from Icon-states" option to get all -// variations. Additionally, as a separate proc, sub-types -// can handle it more intelligently. -/obj/structure/transit_tube/proc/init_dirs() - if(icon_state == "auto") - // Additional delay, for map loading. - spawn(1) - init_dirs_automatic() - - else - tube_dirs = parse_dirs(icon_state) - - if(copytext(icon_state, 1, 3) == "D-" || findtextEx(icon_state, "Pass")) - density = 0 - - - -// Tube station directions are simply 90 to either side of -// the exit. -/obj/structure/transit_tube/station/init_dirs() - tube_dirs = list(turn(dir, 90), turn(dir, -90)) - - - -// Initialize dirs by searching for tubes that do/might connect -// on nearby turfs. Create corner pieces if nessecary. -// Pick two directions, preferring tubes that already connect -// to loc, or other auto tubes if there aren't enough connections. -/obj/structure/transit_tube/proc/init_dirs_automatic() - var/list/connected = list() - var/list/connected_auto = list() - - for(var/direction in tube_dir_list) - var/location = get_step(loc, direction) - for(var/obj/structure/transit_tube/tube in location) - if(tube.directions() == null && tube.icon_state == "auto") - connected_auto += direction - break - - else if(turn(direction, 180) in tube.directions()) - connected += direction - break - - connected += connected_auto - - tube_dirs = select_automatic_dirs(connected) - - if(length(tube_dirs) == 2 && tube_dir_list.Find(tube_dirs[1]) > tube_dir_list.Find(tube_dirs[2])) - tube_dirs.Swap(1, 2) - - generate_automatic_corners(tube_dirs) - select_automatic_icon_state(tube_dirs) - - - -// Given a list of directions, look a pair that forms a 180 or -// 135 degree angle, and return a list containing the pair. -// If none exist, return list(connected[1], turn(connected[1], 180) -/obj/structure/transit_tube/proc/select_automatic_dirs(connected) - if(length(connected) < 1) - return list() - - for(var/i = 1, i <= length(connected), i++) - for(var/j = i + 1, j <= length(connected), j++) - var/d1 = connected[i] - var/d2 = connected[j] - - if(d1 == turn(d2, 135) || d1 == turn(d2, 180) || d1 == turn(d2, 225)) - return list(d1, d2) - - return list(connected[1], turn(connected[1], 180)) - - - -/obj/structure/transit_tube/proc/select_automatic_icon_state(directions) - if(length(directions) == 2) - icon_state = "[dir2text_short(directions[1])]-[dir2text_short(directions[2])]" - - - -// Look for diagonal directions, generate the decorative corners in each. -/obj/structure/transit_tube/proc/generate_automatic_corners(directions) - for(var/direction in directions) - if(direction == 5 || direction == 6 || direction == 9 || direction == 10) - if(direction & NORTH) - create_automatic_decorative_corner(get_step(loc, NORTH), direction ^ 3) - - else - create_automatic_decorative_corner(get_step(loc, SOUTH), direction ^ 3) - - if(direction & EAST) - create_automatic_decorative_corner(get_step(loc, EAST), direction ^ 12) - - else - create_automatic_decorative_corner(get_step(loc, WEST), direction ^ 12) - - - -// Generate a corner, if one doesn't exist for the direction on the turf. -/obj/structure/transit_tube/proc/create_automatic_decorative_corner(location, direction) - var/state = "D-[dir2text_short(direction)]" - - for(var/obj/structure/transit_tube/tube in location) - if(tube.icon_state == state) - return - - var/obj/structure/transit_tube/tube = new(location) - tube.icon_state = state - tube.init_dirs() - - - -// Uses a list() to cache return values. Since they should -// never be edited directly, all tubes with a certain -// icon_state can just reference the same list. In theory, -// reduces memory usage, and improves CPU cache usage. -// In reality, I don't know if that is quite how BYOND works, -// but it is probably safer to assume the existence of, and -// rely on, a sufficiently smart compiler/optimizer. -/obj/structure/transit_tube/proc/parse_dirs(text) - var/global/list/direction_table = list() - - if(text in direction_table) - return direction_table[text] - - var/list/split_text = text2list(text, "-") - - // If the first token is D, the icon_state represents - // a purely decorative tube, and doesn't actually - // connect to anything. - if(split_text[1] == "D") - direction_table[text] = list() - return null - - var/list/directions = list() - - for(var/text_part in split_text) - var/direction = text2dir_extended(text_part) - - if(direction > 0) - directions += direction - - direction_table[text] = directions - return directions - - - -// A copy of text2dir, extended to accept one and two letter -// directions, and to clearly return 0 otherwise. -/obj/structure/transit_tube/proc/text2dir_extended(direction) - switch(uppertext(direction)) - if("NORTH", "N") - return 1 - if("SOUTH", "S") - return 2 - if("EAST", "E") - return 4 - if("WEST", "W") - return 8 - if("NORTHEAST", "NE") - return 5 - if("NORTHWEST", "NW") - return 9 - if("SOUTHEAST", "SE") - return 6 - if("SOUTHWEST", "SW") - return 10 - else - return 0 - - - -// A copy of dir2text, which returns the short one or two letter -// directions used in tube icon states. -/obj/structure/transit_tube/proc/dir2text_short(direction) - switch(direction) - if(1) - return "N" - if(2) - return "S" - if(4) - return "E" - if(8) - return "W" - if(5) - return "NE" - if(6) - return "SE" - if(9) - return "NW" - if(10) - return "SW" - else - return diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm new file mode 100644 index 00000000000..327b1aa5906 --- /dev/null +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -0,0 +1,129 @@ + +// A place where tube pods stop, and people can get in or out. +// Mappers: use "Generate Instances from Directions" for this +// one. +/obj/structure/transit_tube/station + name = "station tube station" + icon = 'icons/obj/pipes/transit_tube_station.dmi' + icon_state = "closed" + exit_delay = 2 + enter_delay = 3 + var/pod_moving = 0 + var/automatic_launch_time = 100 + var/cooldown_delay = 200 + var/launch_cooldown = 0 + var/reverse_launch = 0 + + var/const/OPEN_DURATION = 6 + var/const/CLOSE_DURATION = 6 + +/obj/structure/transit_tube/station/New() + ..() + processing_objects += src + +/obj/structure/transit_tube/station/Destroy() + processing_objects -= src + ..() + +// Stations which will send the tube in the opposite direction after their stop. +/obj/structure/transit_tube/station/reverse + reverse_launch = 1 + +/obj/structure/transit_tube/station/should_stop_pod(pod, from_dir) + return 1 + +/obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj) + if(!pod_moving && icon_state == "open" && istype(AM, /mob)) + for(var/obj/structure/transit_tube_pod/pod in loc) + if(!pod.moving && pod.dir in directions()) + AM.loc = pod + return + + + +/obj/structure/transit_tube/station/attack_hand(mob/user as mob) + if(!pod_moving) + for(var/obj/structure/transit_tube_pod/pod in loc) + if(!pod.moving && pod.dir in directions()) + if(icon_state == "closed") + open_animation() + + else if(icon_state == "open") + if(pod.contents.len && user.loc != pod) + user.visible_message("[user] starts emptying [pod]'s contents onto the floor!") + if(do_after(user, 40)) //So it doesn't default to close_animation() on fail + if(pod.loc == loc) + for(var/atom/movable/AM in pod) + AM.loc = get_turf(user) + if(ismob(AM)) + var/mob/M = AM + M.Weaken(5) + + else + close_animation() + break + + +/obj/structure/transit_tube/station/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/grab) && icon_state == "open") + var/obj/item/weapon/grab/G = W + if(ismob(G.affecting) && G.state >= GRAB_AGGRESSIVE) + var/mob/GM = G.affecting + for(var/obj/structure/transit_tube_pod/pod in loc) + pod.visible_message("[user] starts putting [GM] into the [pod]!") + if(do_after(user, 60) && GM && G && G.affecting == GM) + GM.Weaken(5) + src.Bumped(GM) + qdel(G) + break + +/obj/structure/transit_tube/station/proc/open_animation() + if(icon_state == "closed") + icon_state = "opening" + spawn(OPEN_DURATION) + if(icon_state == "opening") + icon_state = "open" + + + +/obj/structure/transit_tube/station/proc/close_animation() + if(icon_state == "open") + icon_state = "closing" + spawn(CLOSE_DURATION) + if(icon_state == "closing") + icon_state = "closed" + + + +/obj/structure/transit_tube/station/proc/launch_pod() + if(launch_cooldown >= world.time) + return + for(var/obj/structure/transit_tube_pod/pod in loc) + if(!pod.moving && turn(pod.dir, (reverse_launch ? 180 : 0)) in directions()) + spawn(0) + pod_moving = 1 + close_animation() + sleep(CLOSE_DURATION + 2) + if(icon_state == "closed" && pod) + pod.follow_tube(reverse_launch) + pod_moving = 0 + return 1 + return 0 + +/obj/structure/transit_tube/station/process() + if(!pod_moving) + launch_pod() + +/obj/structure/transit_tube/station/pod_stopped(obj/structure/transit_tube_pod/pod, from_dir) + pod_moving = 1 + spawn(5) + launch_cooldown = world.time + cooldown_delay + open_animation() + sleep(OPEN_DURATION + 2) + pod_moving = 0 + pod.mix_air() + +// Tube station directions are simply 90 to either side of +// the exit. +/obj/structure/transit_tube/station/init_dirs() + tube_dirs = list(turn(dir, 90), turn(dir, -90)) \ No newline at end of file diff --git a/code/game/objects/structures/transit_tubes/transit_tube.dm b/code/game/objects/structures/transit_tubes/transit_tube.dm new file mode 100644 index 00000000000..707dbb015df --- /dev/null +++ b/code/game/objects/structures/transit_tubes/transit_tube.dm @@ -0,0 +1,310 @@ + +// Basic transit tubes. Straight pieces, curved sections, +// and basic splits/joins (no routing logic). +// Mappers: you can use "Generate Instances from Icon-states" +// to get the different pieces. +/obj/structure/transit_tube + icon = 'icons/obj/pipes/transit_tube.dmi' + icon_state = "E-W" + density = 1 + layer = 3.1 + anchored = 1.0 + var/list/tube_dirs = null + var/exit_delay = 2 + var/enter_delay = 1 + + // alldirs in global.dm is the same list of directions, but since + // the specific order matters to get a usable icon_state, it is + // copied here so that, in the unlikely case that alldirs is changed, + // this continues to work. + var/global/list/tube_dir_list = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) + + +// When destroyed by explosions, properly handle contents. +obj/structure/transit_tube/ex_act(severity) + switch(severity) + if(1.0) + for(var/atom/movable/AM in contents) + AM.loc = loc + AM.ex_act(severity++) + + qdel(src) + return + if(2.0) + if(prob(50)) + for(var/atom/movable/AM in contents) + AM.loc = loc + AM.ex_act(severity++) + + qdel(src) + return + if(3.0) + return + + +/obj/structure/transit_tube/New(loc) + ..(loc) + + if(tube_dirs == null) + init_dirs() + + +// Called to check if a pod should stop upon entering this tube. +/obj/structure/transit_tube/proc/should_stop_pod(pod, from_dir) + return 0 + +// Called when a pod stops in this tube section. +/obj/structure/transit_tube/proc/pod_stopped(pod, from_dir) + return + + +// Returns a /list of directions this tube section can connect to. +// Tubes that have some sort of logic or changing direction might +// override it with additional logic. +/obj/structure/transit_tube/proc/directions() + return tube_dirs + + + +/obj/structure/transit_tube/proc/has_entrance(from_dir) + from_dir = turn(from_dir, 180) + + for(var/direction in directions()) + if(direction == from_dir) + return 1 + + return 0 + + + +/obj/structure/transit_tube/proc/has_exit(in_dir) + for(var/direction in directions()) + if(direction == in_dir) + return 1 + + return 0 + + + +// Searches for an exit direction within 45 degrees of the +// specified dir. Returns that direction, or 0 if none match. +/obj/structure/transit_tube/proc/get_exit(in_dir) + var/near_dir = 0 + var/in_dir_cw = turn(in_dir, -45) + var/in_dir_ccw = turn(in_dir, 45) + + for(var/direction in directions()) + if(direction == in_dir) + return direction + + else if(direction == in_dir_cw) + near_dir = direction + + else if(direction == in_dir_ccw) + near_dir = direction + + return near_dir + + +// Return how many BYOND ticks to wait before entering/exiting +// the tube section. Default action is to return the value of +// a var, which wouldn't need a proc, but it makes it possible +// for later tube types to interact in more interesting ways +// such as being very fast in one direction, but slow in others +/obj/structure/transit_tube/proc/exit_delay(pod, to_dir) + return exit_delay + +/obj/structure/transit_tube/proc/enter_delay(pod, to_dir) + return enter_delay + + +// Parse the icon_state into a list of directions. +// This means that mappers can use Dream Maker's built in +// "Generate Instances from Icon-states" option to get all +// variations. Additionally, as a separate proc, sub-types +// can handle it more intelligently. +/obj/structure/transit_tube/proc/init_dirs() + if(icon_state == "auto") + // Additional delay, for map loading. + spawn(1) + init_dirs_automatic() + + else + tube_dirs = parse_dirs(icon_state) + + if(copytext(icon_state, 1, 3) == "D-" || findtextEx(icon_state, "Pass")) + density = 0 + + + + +// Initialize dirs by searching for tubes that do/might connect +// on nearby turfs. Create corner pieces if nessecary. +// Pick two directions, preferring tubes that already connect +// to loc, or other auto tubes if there aren't enough connections. +/obj/structure/transit_tube/proc/init_dirs_automatic() + var/list/connected = list() + var/list/connected_auto = list() + + for(var/direction in tube_dir_list) + var/location = get_step(loc, direction) + for(var/obj/structure/transit_tube/tube in location) + if(tube.directions() == null && tube.icon_state == "auto") + connected_auto += direction + break + + else if(turn(direction, 180) in tube.directions()) + connected += direction + break + + connected += connected_auto + + tube_dirs = select_automatic_dirs(connected) + + if(length(tube_dirs) == 2 && tube_dir_list.Find(tube_dirs[1]) > tube_dir_list.Find(tube_dirs[2])) + tube_dirs.Swap(1, 2) + + generate_automatic_corners(tube_dirs) + select_automatic_icon_state(tube_dirs) + + + +// Given a list of directions, look a pair that forms a 180 or +// 135 degree angle, and return a list containing the pair. +// If none exist, return list(connected[1], turn(connected[1], 180) +/obj/structure/transit_tube/proc/select_automatic_dirs(connected) + if(length(connected) < 1) + return list() + + for(var/i = 1, i <= length(connected), i++) + for(var/j = i + 1, j <= length(connected), j++) + var/d1 = connected[i] + var/d2 = connected[j] + + if(d1 == turn(d2, 135) || d1 == turn(d2, 180) || d1 == turn(d2, 225)) + return list(d1, d2) + + return list(connected[1], turn(connected[1], 180)) + + + +/obj/structure/transit_tube/proc/select_automatic_icon_state(directions) + if(length(directions) == 2) + icon_state = "[dir2text_short(directions[1])]-[dir2text_short(directions[2])]" + + + +// Look for diagonal directions, generate the decorative corners in each. +/obj/structure/transit_tube/proc/generate_automatic_corners(directions) + for(var/direction in directions) + if(direction == 5 || direction == 6 || direction == 9 || direction == 10) + if(direction & NORTH) + create_automatic_decorative_corner(get_step(loc, NORTH), direction ^ 3) + + else + create_automatic_decorative_corner(get_step(loc, SOUTH), direction ^ 3) + + if(direction & EAST) + create_automatic_decorative_corner(get_step(loc, EAST), direction ^ 12) + + else + create_automatic_decorative_corner(get_step(loc, WEST), direction ^ 12) + + + +// Generate a corner, if one doesn't exist for the direction on the turf. +/obj/structure/transit_tube/proc/create_automatic_decorative_corner(location, direction) + var/state = "D-[dir2text_short(direction)]" + + for(var/obj/structure/transit_tube/tube in location) + if(tube.icon_state == state) + return + + var/obj/structure/transit_tube/tube = new(location) + tube.icon_state = state + tube.init_dirs() + + + +// Uses a list() to cache return values. Since they should +// never be edited directly, all tubes with a certain +// icon_state can just reference the same list. In theory, +// reduces memory usage, and improves CPU cache usage. +// In reality, I don't know if that is quite how BYOND works, +// but it is probably safer to assume the existence of, and +// rely on, a sufficiently smart compiler/optimizer. +/obj/structure/transit_tube/proc/parse_dirs(text) + var/global/list/direction_table = list() + + if(text in direction_table) + return direction_table[text] + + var/list/split_text = text2list(text, "-") + + // If the first token is D, the icon_state represents + // a purely decorative tube, and doesn't actually + // connect to anything. + if(split_text[1] == "D") + direction_table[text] = list() + return null + + var/list/directions = list() + + for(var/text_part in split_text) + var/direction = text2dir_extended(text_part) + + if(direction > 0) + directions += direction + + direction_table[text] = directions + return directions + + + +// A copy of text2dir, extended to accept one and two letter +// directions, and to clearly return 0 otherwise. +/obj/structure/transit_tube/proc/text2dir_extended(direction) + switch(uppertext(direction)) + if("NORTH", "N") + return 1 + if("SOUTH", "S") + return 2 + if("EAST", "E") + return 4 + if("WEST", "W") + return 8 + if("NORTHEAST", "NE") + return 5 + if("NORTHWEST", "NW") + return 9 + if("SOUTHEAST", "SE") + return 6 + if("SOUTHWEST", "SW") + return 10 + else + return 0 + + + +// A copy of dir2text, which returns the short one or two letter +// directions used in tube icon states. +/obj/structure/transit_tube/proc/dir2text_short(direction) + switch(direction) + if(1) + return "N" + if(2) + return "S" + if(4) + return "E" + if(8) + return "W" + if(5) + return "NE" + if(6) + return "SE" + if(9) + return "NW" + if(10) + return "SW" + else + return diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm new file mode 100644 index 00000000000..1eb1910a7fc --- /dev/null +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -0,0 +1,192 @@ +/obj/structure/transit_tube_pod + icon = 'icons/obj/pipes/transit_tube_pod.dmi' + icon_state = "pod" + animate_movement = FORWARD_STEPS + anchored = 1.0 + density = 1 + var/moving = 0 + var/datum/gas_mixture/air_contents = new() + + +/obj/structure/transit_tube_pod/New(loc) + ..(loc) + + air_contents.oxygen = MOLES_O2STANDARD * 2 + air_contents.nitrogen = MOLES_N2STANDARD + air_contents.temperature = T20C + + // Give auto tubes time to align before trying to start moving + spawn(5) + follow_tube() + +/obj/structure/transit_tube_pod/Destroy() + for(var/atom/movable/AM in contents) + AM.loc = loc + + ..() + +/obj/structure/transit_tube_pod/proc/follow_tube(var/reverse_launch) + if(moving) + return + + moving = 1 + + spawn() + var/obj/structure/transit_tube/current_tube = null + var/next_dir + var/next_loc + var/last_delay = 0 + var/exit_delay + + if(reverse_launch) + dir = turn(dir, 180) // Back it up + + for(var/obj/structure/transit_tube/tube in loc) + if(tube.has_exit(dir)) + current_tube = tube + break + + while(current_tube) + next_dir = current_tube.get_exit(dir) + + if(!next_dir) + break + + exit_delay = current_tube.exit_delay(src, dir) + last_delay += exit_delay + + sleep(exit_delay) + + next_loc = get_step(loc, next_dir) + + current_tube = null + for(var/obj/structure/transit_tube/tube in next_loc) + if(tube.has_entrance(next_dir)) + current_tube = tube + break + + if(current_tube == null) + dir = next_dir + Move(get_step(loc, dir)) // Allow collisions when leaving the tubes. + break + + last_delay = current_tube.enter_delay(src, next_dir) + sleep(last_delay) + dir = next_dir + loc = next_loc // When moving from one tube to another, skip collision and such. + density = current_tube.density + + if(current_tube && current_tube.should_stop_pod(src, next_dir)) + current_tube.pod_stopped(src, dir) + break + + density = 1 + + // If the pod is no longer in a tube, move in a line until stopped or slowed to a halt. + // /turf/inertial_drift appears to only work on mobs, and re-implementing some of the + // logic allows a gradual slowdown and eventual stop when passing over non-space turfs. + if(!current_tube && last_delay <= 10) + do + sleep(last_delay) + + if(!istype(loc, /turf/space)) + last_delay++ + + if(last_delay > 10) + break + + while(isturf(loc) && Move(get_step(loc, dir))) + + moving = 0 + + +// Should I return a copy here? If the caller edits or del()s the returned +// datum, there might be problems if I don't... +/obj/structure/transit_tube_pod/return_air() + var/datum/gas_mixture/GM = new() + GM.oxygen = air_contents.oxygen + GM.carbon_dioxide = air_contents.carbon_dioxide + GM.nitrogen = air_contents.nitrogen + GM.toxins = air_contents.toxins + GM.temperature = air_contents.temperature + return GM + +// For now, copying what I found in an unused FEA file (and almost identical in a +// used ZAS file). Means that assume_air and remove_air don't actually alter the +// air contents. +/obj/structure/transit_tube_pod/assume_air(datum/gas_mixture/giver) + return air_contents.merge(giver) + +/obj/structure/transit_tube_pod/remove_air(amount) + return air_contents.remove(amount) + + + +// Called when a pod arrives at, and before a pod departs from a station, +// giving it a chance to mix its internal air supply with the turf it is +// currently on. +/obj/structure/transit_tube_pod/proc/mix_air() + var/datum/gas_mixture/environment = loc.return_air() + var/env_pressure = environment.return_pressure() + var/int_pressure = air_contents.return_pressure() + var/total_pressure = env_pressure + int_pressure + + if(total_pressure == 0) + return + + // Math here: Completely made up, not based on realistic equasions. + // Goal is to balance towards equal pressure, but ensure some gas + // transfer in both directions regardless. + // Feel free to rip this out and replace it with something better, + // I don't really know muhch about how gas transfer rates work in + // SS13. + var/transfer_in = max(0.1, 0.5 * (env_pressure - int_pressure) / total_pressure) + var/transfer_out = max(0.1, 0.3 * (int_pressure - env_pressure) / total_pressure) + + var/datum/gas_mixture/from_env = loc.remove_air(environment.total_moles() * transfer_in) + var/datum/gas_mixture/from_int = air_contents.remove(air_contents.total_moles() * transfer_out) + + loc.assume_air(from_int) + air_contents.merge(from_env) + + + +// When the player moves, check if the pos is currently stopped at a station. +// if it is, check the direction. If the direction matches the direction of +// the station, try to exit. If the direction matches one of the station's +// tube directions, launch the pod in that direction. +/obj/structure/transit_tube_pod/relaymove(mob/mob, direction) + if(istype(mob, /mob) && mob.client) + // If the pod is not in a tube at all, you can get out at any time. + if(!(locate(/obj/structure/transit_tube) in loc)) + mob.loc = loc + mob.client.Move(get_step(loc, direction), direction) + mob.reset_view(null) + + //if(moving && istype(loc, /turf/space)) + // Todo: If you get out of a moving pod in space, you should move as well. + // Same direction as pod? Direcion you moved? Halfway between? + + if(!moving) + for(var/obj/structure/transit_tube/station/station in loc) + if(dir in station.directions()) + if(!station.pod_moving) + if(direction == station.dir) + if(station.icon_state == "open") + mob.loc = loc + mob.client.Move(get_step(loc, direction), direction) + mob.reset_view(null) + + else + station.open_animation() + + else if(direction in station.directions()) + dir = direction + station.launch_pod() + return + + for(var/obj/structure/transit_tube/tube in loc) + if(dir in tube.directions()) + if(tube.has_exit(direction)) + dir = direction + return \ No newline at end of file diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 8a81e93d1a9..c3032dbe840 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -31,7 +31,7 @@ if(ishuman(user)) user.put_in_hands(I) else - I.setloc(get_turf(src)) + I.loc = get_turf(src) user << "You find \an [I] in the cistern." w_items -= I.w_class return @@ -84,7 +84,7 @@ user << "The cistern is full." return user.drop_item() - I.setloc(src) + I.loc = src w_items += I.w_class user << "You carefully place \the [I] into the cistern." return @@ -326,17 +326,23 @@ anchored = 1 var/busy = 0 //Something's being washed at the moment +/obj/structure/sink/attack_hand(mob/user as mob) + if (hasorgans(user)) + var/datum/organ/external/temp = user:organs_by_name["r_hand"] + if (user.hand) + temp = user:organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + user << "You try to move your [temp.display_name], but cannot!" + return - -/obj/structure/sink/attack_hand(mob/M as mob) - if(isrobot(M) || isAI(M)) + if(isrobot(user) || isAI(user)) return - if(!Adjacent(M)) + if(!Adjacent(user)) return if(busy) - M << "\red Someone's already washing here." + user << "\red Someone's already washing here." return usr << "\blue You start washing your hands." @@ -345,13 +351,14 @@ sleep(40) busy = 0 - if(!Adjacent(M)) return //Person has moved away from the sink + if(!Adjacent(user)) return //Person has moved away from the sink - M.clean_blood() - if(ishuman(M)) - M:update_inv_gloves(0,0) + user.clean_blood() + if(ishuman(user)) + user:update_inv_gloves() for(var/mob/V in viewers(src, null)) - V.show_message("\blue [M] washes their hands using \the [src].") + V.show_message("\blue [user] washes their hands using \the [src].") + /obj/structure/sink/attackby(obj/item/O as obj, mob/user as mob) if(busy) @@ -420,3 +427,5 @@ /obj/structure/sink/puddle/attackby(obj/item/O as obj, mob/user as mob) icon_state = "puddle-splash" ..() + icon_state = "puddle" + diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 4bdd5ac3613..e53779be272 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -13,10 +13,10 @@ var/reinf = 0 var/basestate var/shardtype = /obj/item/weapon/shard + var/sheets = 1 // Number of sheets needed to build this window (determines how much shit is spawned by destroy()) // var/silicate = 0 // number of units of silicate // var/icon/silicateIcon = null // the silicated icon - /obj/structure/window/bullet_act(var/obj/item/projectile/Proj) health -= Proj.damage ..() @@ -25,62 +25,53 @@ if(pdiff>0) message_admins("Window destroyed by [Proj.firer.real_name] ([formatPlayerPanel(Proj.firer,Proj.firer.ckey)]) via \an [Proj]! pdiff = [pdiff] at [formatJumpTo(loc)]!") log_admin("Window destroyed by ([Proj.firer.ckey]) via \an [Proj]! pdiff = [pdiff] at [loc]!") - new /obj/item/weapon/shard(loc) - new /obj/item/stack/rods(loc) - del(src) + destroy() return +// This should result in the same materials used to make the window. +/obj/structure/window/proc/destroy() + for(var/i=0;i[src] was hit by [AM].") @@ -108,9 +99,6 @@ message_admins("Window with pdiff [pdiff] at [formatJumpTo(loc)] deanchored by [AM]!") log_admin("Window with pdiff [pdiff] at [loc] deanchored by [AM]!") if(health <= 0) - new /obj/item/weapon/shard(loc) - if(reinf) new /obj/item/stack/rods(loc) - del(src) var/pdiff=performWallPressureCheck(src.loc) if(pdiff>0) if(M) @@ -119,21 +107,20 @@ else message_admins("Window with pdiff [pdiff] at [formatJumpTo(loc)] destroyed by [AM]!") log_admin("Window with pdiff [pdiff] at [loc] destroyed by [AM]!") + destroy() /obj/structure/window/attack_hand(mob/user as mob) if(M_HULK in user.mutations) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) user.visible_message("[user] smashes through [src]!") - new /obj/item/weapon/shard(loc) - if(reinf) new /obj/item/stack/rods(loc) - del(src) var/pdiff=performWallPressureCheck(src.loc) if(pdiff>0) message_admins("Window destroyed by hulk [user.real_name] ([formatPlayerPanel(user,user.ckey)]) with pdiff [pdiff] at [formatJumpTo(loc)]!") log_admin("Window destroyed by hulk [user.real_name] ([user.ckey]) with pdiff [pdiff] at [loc]!") + destroy() else if (usr.a_intent == "harm") - playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) + playsound(get_turf(src), 'sound/effects/glassknock.ogg', 80, 1) usr.visible_message("\red [usr.name] bangs against the [src.name]!", \ "\red You bang against the [src.name]!", \ "You hear a banging sound.") @@ -148,17 +135,14 @@ /obj/structure/window/attack_paw(mob/user as mob) return attack_hand(user) - /obj/structure/window/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime health -= damage if(health <= 0) user.visible_message("[user] smashes through [src]!") - new /obj/item/weapon/shard(loc) - if(reinf) new /obj/item/stack/rods(loc) - del(src) var/pdiff=performWallPressureCheck(src.loc) if(pdiff>0) message_admins("Window destroyed by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) with pdiff [pdiff] at [formatJumpTo(loc)]!") + destroy() else //for nicer text~ user.visible_message("[user] smashes into [src]!") playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) @@ -257,20 +241,10 @@ if(sound_effect) playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) if(health <= 0) - if(dir == SOUTHWEST) - var/index = null - index = 0 - while(index < 2) - new shardtype(loc) - if(reinf) new /obj/item/stack/rods(loc) - index++ - else - new shardtype(loc) - if(reinf) new /obj/item/stack/rods(loc) var/pdiff=performWallPressureCheck(src.loc) if(pdiff>0) message_admins("Window with pdiff [pdiff] broken at [formatJumpTo(loc)]!") - del(src) + destroy() return @@ -351,7 +325,8 @@ /obj/structure/window/Destroy() density = 0 update_nearby_tiles() - playsound(src, "shatter", 70, 1) + if(loc) + playsound(get_turf(src), "shatter", 70, 1) update_nearby_icons() ..() @@ -372,50 +347,24 @@ //checks if this window is full-tile one /obj/structure/window/proc/is_fulltile() - if(dir in list(5,6,9,10)) - return 1 return 0 //This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc! /obj/structure/window/proc/update_nearby_icons() + if(!loc) return 0 update_icon() for(var/direction in cardinal) for(var/obj/structure/window/W in get_step(src,direction) ) W.update_icon() -//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm) /obj/structure/window/update_icon() - //A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong. - //this way it will only update full-tile ones - //This spawn is here so windows get properly updated when one gets deleted. - spawn(2) - if(!src) return - if(!is_fulltile()) - icon_state = "[basestate]" - return - var/junction = 0 //will be used to determine from which side the window is connected to other windows - if(anchored) - for(var/obj/structure/window/W in orange(src,1)) - if(W.anchored && W.density && W.is_fulltile()) //Only counts anchored, not-destroyed fill-tile windows. - if(abs(x-W.x)-abs(y-W.y) ) //doesn't count windows, placed diagonally to src - junction |= get_dir(src,W) - if(opacity) - icon_state = "[basestate][junction]" - else - if(reinf) - icon_state = "[basestate][junction]" - else - icon_state = "[basestate][junction]" - - return + return /obj/structure/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature > T0C + 800) hit(round(exposed_volume / 100), 0) ..() - - /obj/structure/window/basic icon_state = "window" desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." @@ -484,4 +433,17 @@ desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." icon_state = "fwindow" basestate = "fwindow" - health = 30 \ No newline at end of file + health = 30 + +/obj/structure/window/shuttle + name = "shuttle window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon = 'icons/obj/podwindows.dmi' + icon_state = "window" + basestate = "window" + health = 40 + reinf = 1 + dir = 5 + + update_icon() //icon_state has to be set manually + return diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index c1548257c26..1c0f5196ef8 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -1,8 +1,8 @@ //Config stuff #define SUPPLY_DOCKZ 2 //Z-level of the Dock. #define SUPPLY_STATIONZ 1 //Z-level of the Station. -#define SUPPLY_STATION_AREATYPE /area/supply/station //Type of the supply shuttle area for station -#define SUPPLY_DOCK_AREATYPE /area/supply/dock //Type of the supply shuttle area for dock +#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station +#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock var/global/datum/controller/supply_shuttle/supply_shuttle //var/datum/controller/supply_shuttle/supply_shuttle = new() @@ -504,7 +504,7 @@ var/list/mechtoys = list( if (stat & BROKEN) user << "\blue The broken glass falls out." var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc ) - new /obj/item/weapon/shard( loc ) + getFromPool(/obj/item/weapon/shard, loc) var/obj/item/weapon/circuitboard/supplycomp/M = new /obj/item/weapon/circuitboard/supplycomp( A ) for (var/obj/C in src) C.loc = loc diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index ad8a9eae640..76b7263913a 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -101,9 +101,9 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the wet floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) - M.Stun(8) - M.Weaken(5) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) + M.Stun(5) + M.Weaken(3) else M.inertia_dir = 0 return @@ -112,9 +112,9 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the wet floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) - M.Stun(8) - M.Weaken(5) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) + M.Stun(5) + M.Weaken(3) else M.inertia_dir = 0 return @@ -129,7 +129,7 @@ spawn(4) step(M, M.dir) M.take_organ_damage(2) // Was 5 -- TLE M << "\blue You slipped on the floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Weaken(10) if(3) // Ice @@ -138,7 +138,7 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the icy floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Stun(4) M.Weaken(5) else @@ -149,7 +149,7 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the icy floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Stun(4) M.Weaken(5) else @@ -209,4 +209,5 @@ this.blood_DNA["UNKNOWN BLOOD"] = "X*" else if( istype(M, /mob/living/silicon/robot )) - new /obj/effect/decal/cleanable/oil(src) \ No newline at end of file + new /obj/effect/decal/cleanable/oil(src) + diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index e37f354daaa..9e23dfb597f 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -466,17 +466,16 @@ turf/simulated/floor/proc/update_icon() return - if(istype(C, /obj/item/weapon/screwdriver)) - if(is_wood_floor()) - if(broken || burnt) - return - else - if(is_wood_floor()) - user << "\red You unscrew the planks." - new floor_tile.type(src) - make_plating() - playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) + if(istype(C, /obj/item/weapon/screwdriver) && is_wood_floor()) + if(broken || burnt) + return + else + if(is_wood_floor()) + user << "\red You unscrew the planks." + new floor_tile.type(src) + make_plating() + playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) if(is_catwalk()) if(broken) return ReplaceWithLattice() diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index 2f04b2f0684..ceb4c3bf93f 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -58,7 +58,7 @@ return if(istype(C, /obj/item/weapon/wrench)) user << "\blue Removing rods..." - playsound(src.loc, 'sound/items/Ratchet.ogg', 80, 1) + playsound(src, 'sound/items/Ratchet.ogg', 80, 1) if(do_after(user, 30)) new /obj/item/stack/rods(src, 2) ChangeTurf(/turf/simulated/floor) @@ -246,7 +246,7 @@ thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT heat_capacity = 700000 - lit_value = 4 //starlight + lighting_lumcount = 4 //starlight // accepts_lighting=0 // Don't apply overlays New() diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index dea6d8e7e10..7f87eddc8e2 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -50,7 +50,7 @@ return user << "\blue Constructing support lattice ..." - playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) ReplaceWithLattice() R.use(1) return @@ -60,7 +60,7 @@ if(L) var/obj/item/stack/tile/plasteel/S = C del(L) - playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) S.build(src) S.use(1) return diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index c125f9e0269..356214dd9a2 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -209,19 +209,15 @@ if(L) del L -var/turf_light_data/old_lights = new - //Creates a new turf /turf/proc/ChangeTurf(var/turf/N) if (!N) return + var/old_lumcount = lighting_lumcount - initial(lighting_lumcount) + //world << "Replacing [src.type] with [N]" - var/old_opacity = opacity - - old_lights.copy_from(src) - if(connections) connections.erase_all() if(istype(src,/turf/simulated)) @@ -242,12 +238,10 @@ var/turf_light_data/old_lights = new var/turf/simulated/W = new N( locate(src.x, src.y, src.z) ) //W.Assimilate_Air() - old_lights.copy_to(W) - W.ResetAllLights() - - if(old_opacity) - W.opacity = 1 - W.SetOpacity(0) + W.lighting_lumcount += old_lumcount + if(old_lumcount != W.lighting_lumcount) + W.lighting_changed = 1 + lighting_controller.changed_turfs += W if (istype(W,/turf/simulated/floor)) W.RemoveLattice() @@ -265,9 +259,10 @@ var/turf_light_data/old_lights = new // zone.SetStatus(ZONE_ACTIVE) var/turf/W = new N( locate(src.x, src.y, src.z) ) - - old_lights.copy_to(W) - W.ResetAllLights() + W.lighting_lumcount += old_lumcount + if(old_lumcount != W.lighting_lumcount) + W.lighting_changed = 1 + lighting_controller.changed_turfs += W if(air_master) air_master.mark_for_update(src) diff --git a/code/global.dm b/code/global.dm index 6b24882e6fd..af7969de32c 100644 --- a/code/global.dm +++ b/code/global.dm @@ -112,6 +112,7 @@ var/href_logfile = null var/station_name = "NSS Cyberiad" var/game_version = "Custom ParaCode" var/changelog_hash = "" +var/game_year = (text2num(time2text(world.realtime, "YYYY")) + 544) var/datum/air_tunnel/air_tunnel1/SS13_airtunnel = null var/going = 1.0 @@ -302,4 +303,4 @@ var/score_dmgestkey = null // Recall time limit: 2 hours -var/recall_time_limit=72000 +var/recall_time_limit=72000 diff --git a/code/modules/DetectiveWork/detective_work.dm b/code/modules/DetectiveWork/detective_work.dm index b9ecfdc3e68..047fa29e506 100644 --- a/code/modules/DetectiveWork/detective_work.dm +++ b/code/modules/DetectiveWork/detective_work.dm @@ -142,7 +142,7 @@ obj/machinery/computer/forensic_scanning temp = null if("eject") if(scanning) - scanning.setloc(loc) + scanning.loc = loc scanning = null else temp = "Eject Failed: No Object" @@ -152,13 +152,13 @@ obj/machinery/computer/forensic_scanning if(I && istype(I)) if(istype(I, /obj/item/weapon/evidencebag)) scanning = I.contents[1] - scanning.setloc(src) + scanning.loc = src I.overlays -= scanning I.icon_state = "evidenceobj" else scanning = I M.drop_item() - I.setloc(src) + I.loc = src else usr << "Invalid Object Rejected." if("card") //Processing a fingerprint card. @@ -173,11 +173,11 @@ obj/machinery/computer/forensic_scanning if(card.amount > 1 || !card.fingerprints.len) usr << "\red ERROR: No prints/too many cards." if(card.loc == src) - card.setloc(src.loc) + card.loc = src.loc card = null return M.drop_item() - I.setloc(src) + I.loc = src process_card() else usr << "\red Invalid Object Rejected." @@ -607,7 +607,7 @@ obj/machinery/computer/forensic_scanning else usr << "\red ERROR: No prints/too many cards." if(card.loc == src) - card.setloc(src.loc) + card.loc = src.loc card = null return return diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index a076bed08a7..fb661c0941d 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -121,7 +121,7 @@ var/global/floorIsLava = 0 body += "Animalize | " // DNA2 - Admin Hax - if(iscarbon(M)) + if(iscarbon(M) && !isalien(M)) body += "

" body += "DNA Blocks:
" var/bname diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index ac4a1a7c55e..f0b071893fd 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -95,6 +95,7 @@ var/list/admin_verbs_fun = list( /client/proc/toggle_random_events, /client/proc/set_ooc, /client/proc/editappear, + /client/proc/gib_money // /vg/ ) var/list/admin_verbs_spawn = list( /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ @@ -672,6 +673,12 @@ var/list/admin_verbs_mod = list( M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) M.b_eyes = hex2num(copytext(new_eyes, 6, 8)) + var/new_skin = input("Please select body color. This is for Tajaran, Unathi, and Skrell only!", "Character Generation") as color + if(new_skin) + M.r_skin = hex2num(copytext(new_skin, 2, 4)) + M.g_skin = hex2num(copytext(new_skin, 4, 6)) + M.b_skin = hex2num(copytext(new_skin, 6, 8)) + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text if (new_tone) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 8cd60ec8e9f..fc0f63a6d70 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -664,6 +664,7 @@ jobs += "
 12345
" + //Other races (BLUE, because I have no idea what other color to make this) jobs += "" jobs += "" @@ -682,6 +683,27 @@ jobs += "
Other
" + //Civilian (Grey) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in whitelisted_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Whitelisted Positions
[replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
" + body = "[jobs]" dat = "[header][body]" usr << browse(dat, "window=jobban2;size=800x490") @@ -751,6 +773,12 @@ var/datum/job/temp = job_master.GetJob(jobPos) if(!temp) continue joblist += temp.title + if("whitelistdept") + for(var/jobPos in whitelisted_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title else joblist += href_list["jobban3"] diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index b14055f28c5..132c4b64aa5 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1087,3 +1087,12 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!") else alert("Invalid mob") + +/client/proc/gib_money() + set category = "Fun" + set name = "Dispense Money" + set desc = "Honk" + + var/response = input(src,"How much moneys?") as num + if( response < 1) return + dispense_cash(response, mob.loc) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 7b952382a5d..b1b5098be40 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -77,8 +77,8 @@ var/intercom_range_display_status = 0 for(var/obj/machinery/camera/C in cameranet.cameras) CL += C - var/output = {"CAMERA ANNOMALITIES REPORT
-The following annomalities have been detected. The ones in red need immediate attention: Some of those in black may be intentional.
    "} + var/output = {"CAMERA ANOMALIES REPORT
    +The following anomalies have been detected. The ones in red need immediate attention: Some of those in black may be intentional.
      "} for(var/obj/machinery/camera/C1 in CL) for(var/obj/machinery/camera/C2 in CL) @@ -94,7 +94,7 @@ var/intercom_range_display_status = 0 if(!(locate(/obj/structure/grille,T))) var/window_check = 0 for(var/obj/structure/window/W in T) - if (W.dir == turn(C1.dir,180) || W.dir in list(5,6,9,10) ) + if (W.dir == turn(C1.dir,180) || W.is_fulltile() ) window_check = 1 break if(!window_check) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index f09c464c887..84bffec64de 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -492,7 +492,7 @@ client/proc/one_click_antag() /datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) - var/mob/living/carbon/human/new_vox = new(spawn_location.loc) + var/mob/living/carbon/human/new_vox = new(spawn_location.loc, "Vox") new_vox.gender = pick(MALE, FEMALE) new_vox.h_style = "Short Vox Quills" @@ -512,8 +512,6 @@ client/proc/one_click_antag() new_vox.dna.ready_dna(new_vox) // Creates DNA. new_vox.dna.mutantrace = "vox" - new_vox.set_species("Vox") // Actually makes the vox! How about that. - new_vox.add_language("Vox-pidgin") new_vox.mind_initialize() new_vox.mind.assigned_role = "MODE" new_vox.mind.special_role = "Vox Raider" diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index db856725acf..1ea32ebee04 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -58,15 +58,15 @@ else src.DB_job_unlock("Barber",5) if("2") - if(karma <15) - usr << "You do not have enough karma!" - else - src.DB_job_unlock("Nanotrasen Representative",15) - if("3") if(karma <30) usr << "You do not have enough karma!" else - src.DB_job_unlock("Customs Officer",30) + src.DB_job_unlock("Nanotrasen Representative",30) + if("3") + if(karma <15) + usr << "You do not have enough karma!" + else + src.DB_job_unlock("Customs Officer",15) if("4") if(karma <30) usr << "You do not have enough karma!" @@ -292,12 +292,11 @@ /client/proc/send_resources() // preload_vox() //Causes long delays with initial start window and subsequent windows when first logged in. - // Send NanoUI resources to this client - nanomanager.send_resources(src) - getFiles( 'html/search.js', 'html/panels.css', + 'html/painew.png', + 'html/loading.gif', 'icons/pda_icons/pda_atmos.png', 'icons/pda_icons/pda_back.png', 'icons/pda_icons/pda_bell.png', diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 87ee8a10629..e61c7da403d 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -57,6 +57,7 @@ datum/preferences var/age = 30 //age of character var/b_type = "A+" //blood type (not-chooseable) var/underwear = 1 //underwear type + var/undershirt = 1 //undershirt type var/backbag = 2 //backpack type var/h_style = "Bald" //Hair type var/r_hair = 0 //Hair color @@ -66,7 +67,10 @@ datum/preferences var/r_facial = 0 //Face hair color var/g_facial = 0 //Face hair color var/b_facial = 0 //Face hair color - var/s_tone = 0 //Skin color + var/s_tone = 0 //Skin tone + var/r_skin = 0 //Skin color + var/g_skin = 0 //Skin color + var/b_skin = 0 //Skin color var/r_eyes = 0 //Eye color var/g_eyes = 0 //Eye color var/b_eyes = 0 //Eye color @@ -125,6 +129,8 @@ datum/preferences // Whether or not to use randomized character slots var/randomslot = 0 + // jukebox volume + var/volume = 100 /datum/preferences/New(client/C) b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") if(istype(C)) @@ -149,7 +155,6 @@ datum/preferences if(!path) dat += "Please create an account to save your preferences." - dat += "" dat += "
      " @@ -180,10 +185,10 @@ datum/preferences dat += "
      " dat += "Species: [species]
      " dat += "Secondary Language:
      [language]
      " - dat += "Accent: [accent]
      " +/* dat += "Accent: [accent]
      " dat += "Voice: [voice]
      " dat += "Pitch: [pitch]
      " - dat += "Talking Speed: [talkspeed]
      " + dat += "Talking Speed: [talkspeed]
      "*/ dat += "Blood Type: [b_type]
      " dat += "Skin Tone: [-s_tone + 35]/220
      " // dat += "Skin pattern: Adjust
      " @@ -265,6 +270,7 @@ datum/preferences dat += "Underwear: [underwear_m[underwear]]
      " else dat += "Underwear: [underwear_f[underwear]]
      " + dat += "Undershirt: [undershirt_t[undershirt]]
      " dat += "Backpack Type:
      [backbaglist[backbag]]
      " dat += "Nanotrasen Relation:
      [nanotrasen_relation]
      " dat += "Preview
      " @@ -293,7 +299,10 @@ datum/preferences dat += " Style: [f_style]
      " dat += "
      Eyes
      " - dat += "Change Color
      __
      " + dat += "Change Color
      __

      " + + dat += "
      Body Color
      " + dat += "Change Color
      __
      " dat += "
      " @@ -920,12 +929,19 @@ datum/preferences if("underwear") underwear = rand(1,underwear_m.len) ShowChoices(user) + if("undershirt") + undershirt = rand(1,undershirt_t.len) + ShowChoices(user) if("eyes") r_eyes = rand(0,255) g_eyes = rand(0,255) b_eyes = rand(0,255) if("s_tone") s_tone = random_skin_tone() + if("s_color") + r_skin = rand(0,255) + g_skin = rand(0,255) + b_skin = rand(0,255) if("bag") backbag = rand(1,4) /*if("skin_style") @@ -1097,6 +1113,15 @@ datum/preferences underwear = underwear_options.Find(new_underwear) ShowChoices(user) + if("undershirt") + var/list/undershirt_options + undershirt_options = undershirt_t + + var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_options + if (new_undershirt) + undershirt = undershirt_options.Find(new_undershirt) + ShowChoices(user) + if("accent") var/new_accent = input(user, "Choose your accent. en-us:American, en:British, en-sc:Scottish, mb-de4-en:German, mb-fr1-en:French", "Character Preference") as null|anything in list("en-us", "en", "en-sc","mb-de4-en","mb-fr1-en") if(new_accent) @@ -1128,6 +1153,14 @@ datum/preferences if(new_s_tone) s_tone = 35 - max(min( round(new_s_tone), 220),1) + if("skin") + if(species == "Unathi" || species == "Tajaran" || species == "Skrell") + var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null + if(new_skin) + r_skin = hex2num(copytext(new_skin, 2, 4)) + g_skin = hex2num(copytext(new_skin, 4, 6)) + b_skin = hex2num(copytext(new_skin, 6, 8)) + if("ooccolor") var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference") as color|null if(new_ooccolor) @@ -1361,6 +1394,10 @@ datum/preferences character.g_facial = g_facial character.b_facial = b_facial + character.r_skin = r_skin + character.g_skin = g_skin + character.b_skin = b_skin + character.s_tone = s_tone character.h_style = h_style @@ -1403,6 +1440,10 @@ datum/preferences underwear = 0 //I'm sure this is 100% unnecessary, but I'm paranoid... sue me. //HAH NOW NO MORE MAGIC CLONING UNDIES character.underwear = underwear + if(undershirt > undershirt_t.len || undershirt < 1) + undershirt = 0 + character.undershirt = undershirt + if(backbag > 4 || backbag < 1) backbag = 1 //Same as above character.backbag = backbag diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 32379c13d7c..d794d4e4238 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -58,7 +58,7 @@ S["UI_style_color"] >> UI_style_color S["UI_style_alpha"] >> UI_style_alpha S["randomslot"] >> randomslot - + S["volume"] >> volume //Sanitize ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) @@ -70,6 +70,7 @@ UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color)) UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha)) randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) + volume = sanitize_integer(volume, 0, 100, initial(volume)) return 1 /datum/preferences/proc/save_preferences() @@ -91,6 +92,17 @@ S["UI_style_color"] << UI_style_color S["UI_style_alpha"] << UI_style_alpha S["randomslot"] << randomslot + S["volume"] << volume + return 1 + +//saving volume changes +/datum/preferences/proc/save_volume() + if(!path) return 0 + var/savefile/S = new /savefile(path) + if(!S) return 0 + S.cd = "/" + + S["volume"] << volume return 1 /datum/preferences/proc/load_save(dir) @@ -121,6 +133,7 @@ S["eyes_green"] >> g_eyes S["eyes_blue"] >> b_eyes S["underwear"] >> underwear + S["undershirt"] >> undershirt S["backbag"] >> backbag S["b_type"] >> b_type S["accent"] >> accent @@ -179,6 +192,7 @@ g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes)) b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes)) underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear)) + undershirt = sanitize_integer(undershirt, 1, undershirt_t.len, initial(undershirt)) backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) b_type = sanitize_text(b_type, initial(b_type)) accent = sanitize_text(accent, initial(accent)) @@ -256,12 +270,16 @@ S["facial_green"] >> g_facial S["facial_blue"] >> b_facial S["skin_tone"] >> s_tone + S["skin_red"] >> r_skin + S["skin_green"] >> g_skin + S["skin_blue"] >> b_skin S["hair_style_name"] >> h_style S["facial_style_name"] >> f_style S["eyes_red"] >> r_eyes S["eyes_green"] >> g_eyes S["eyes_blue"] >> b_eyes S["underwear"] >> underwear + S["undershirt"] >> undershirt S["backbag"] >> backbag S["b_type"] >> b_type @@ -290,6 +308,7 @@ S["nanotrasen_relation"] >> nanotrasen_relation //S["skin_style"] >> skin_style + //Sanitize metadata = sanitize_text(metadata, initial(metadata)) real_name = reject_bad_name(real_name) @@ -307,12 +326,16 @@ g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial)) b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial)) s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone)) + r_skin = sanitize_integer(r_skin, 0, 255, initial(r_skin)) + g_skin = sanitize_integer(g_skin, 0, 255, initial(g_skin)) + b_skin = sanitize_integer(b_skin, 0, 255, initial(b_skin)) h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style)) f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style)) r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes)) g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes)) b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes)) underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear)) + undershirt = sanitize_integer(undershirt, 1, undershirt_t.len, initial(undershirt)) backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) b_type = sanitize_text(b_type, initial(b_type)) @@ -355,12 +378,16 @@ S["facial_green"] << g_facial S["facial_blue"] << b_facial S["skin_tone"] << s_tone + S["skin_red"] << r_skin + S["skin_green"] << g_skin + S["skin_blue"] << b_skin S["hair_style_name"] << h_style S["facial_style_name"] << f_style S["eyes_red"] << r_eyes S["eyes_green"] << g_eyes S["eyes_blue"] << b_eyes S["underwear"] << underwear + S["undershirt"] << undershirt S["backbag"] << backbag S["b_type"] << b_type S["accent"] << accent diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index b6c26899dd0..c55232b40b6 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -249,6 +249,9 @@ BLIND // can't see anything */ var/obj/item/clothing/tie/hastie = null var/displays_id = 1 + var/rolled_down = 0 + var/basecolor + /obj/item/clothing/under/attackby(obj/item/I, mob/user) if(!hastie && istype(I, /obj/item/clothing/tie)) @@ -313,6 +316,22 @@ BLIND // can't see anything usr << "Your suit will now report your vital lifesigns as well as your coordinate position." ..() +/obj/item/clothing/under/verb/rollsuit() + set name = "Roll Down Jumpsuit" + set category = "Object" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + if(copytext(_color,-2) != "_d") + basecolor = _color + usr << "DEBUG:[basecolor]" + if(basecolor + "_d_s" in icon_states('icons/mob/uniform.dmi')) + _color = _color == "[basecolor]" ? "[basecolor]_d" : "[basecolor]" + usr.update_inv_w_uniform() + else + usr << "You cannot roll down the uniform!" + /obj/item/clothing/under/verb/removetie() set name = "Remove Accessory" set category = "Object" diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 9a45a21607f..38bc8eb116f 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -10,6 +10,21 @@ permeability_coefficient = 0.01 siemens_coefficient = 0.9 + +//Bane gas mask +/obj/item/clothing/mask/banemask + name = "bane mask" + desc = "Only when the station is in flames, do you have my permission to robust." + icon_state = "bane_mask" + flags = FPRINT | TABLEPASS | MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS + flags_inv = HIDEEARS|HIDEEYES|HIDEFACE + w_class = 3.0 + item_state = "bane_mask" + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + siemens_coefficient = 0.9 + + //Plague Dr suit can be found in clothing/suits/bio.dm /obj/item/clothing/mask/gas/plaguedoctor name = "plague doctor mask" @@ -53,6 +68,22 @@ item_state = "clown_hat" flags = FPRINT | TABLEPASS | MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS | BLOCKHAIR +/obj/item/clothing/mask/gas/clown_hat/attack_self(mob/user) + + var/mob/M = usr + var/list/options = list() + options["True Form"] = "clown" + options["The Feminist"] = "sexyclown" + options["The Madman"] = "joker" + options["The Rainbow Color"] ="rainbow" + + var/choice = input(M,"To what form do you wish to Morph this mask?","Morph Mask") in options + + if(src && choice && !M.stat && in_range(M,src)) + icon_state = options[choice] + M << "Your Clown Mask has now morphed into [choice], all praise the Honk Mother!" + return 1 + /obj/item/clothing/mask/gas/sexyclown name = "sexy-clown wig and mask" desc = "A feminine clown mask for the dabbling crossdressers or female entertainers." @@ -221,4 +252,4 @@ -// ******************************************************************** \ No newline at end of file +// ******************************************************************** diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index d4bb0ccdad9..50728d3acf6 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -4,28 +4,24 @@ icon_state = "magboots0" var/magpulse = 0 species_restricted = null + icon_action_button = "action_blank" + action_button_name = "Toggle the magboots" +// flags = NOSLIP //disabled by default - - verb/toggle() - set name = "Toggle Magboots" - set category = "Object" - set src in usr - if(usr.stat) - return - if(src.magpulse) - src.flags &= ~NOSLIP - src.slowdown = SHOES_SLOWDOWN - src.magpulse = 0 + attack_self(mob/user) + if(magpulse) + flags &= ~NOSLIP + slowdown = SHOES_SLOWDOWN + magpulse = 0 icon_state = "magboots0" - usr << "You disable the mag-pulse traction system." + user << "You disable the mag-pulse traction system." else - src.flags |= NOSLIP - src.slowdown = 2 - src.magpulse = 1 + flags |= NOSLIP + slowdown = 2 + magpulse = 1 icon_state = "magboots1" - usr << "You enable the mag-pulse traction system." - usr.update_inv_shoes() //so our mob-overlays update - + user << "You enable the mag-pulse traction system." + user.update_inv_shoes() //so our mob-overlays update examine() set src in view() diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index 7e35f4f1921..a2842397b39 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -149,28 +149,44 @@ /obj/item/clothing/shoes/magboots/vox desc = "A pair of heavy, jagged armoured foot pieces, seemingly suitable for a velociraptor." - name = "vox boots" + name = "vox magclaws" item_state = "boots-vox" icon_state = "boots-vox" species_restricted = list("Vox") + action_button_name = "Toggle the magclaws" - toggle() - //set name = "Toggle Floor Grip" - if(usr.stat) +/obj/item/clothing/shoes/magboots/vox/attack_self(mob/user) + if(src.magpulse) + flags &= ~NOSLIP + magpulse = 0 + canremove = 1 + user << "You relax your deathgrip on the flooring." + else + //make sure these can only be used when equipped. + if (!is_equipped()) + user << "You will have to put on the [src] before you can do that." return - if(src.magpulse) - src.flags &= ~NOSLIP - src.magpulse = 0 - usr << "You relax your deathgrip on the flooring." - else - src.flags |= NOSLIP - src.magpulse = 1 - usr << "You dig your claws deeply into the flooring, bracing yourself." + + flags |= NOSLIP + magpulse = 1 + canremove = 0 //kinda hard to take off magclaws when you are gripping them tightly. + user << "You dig your claws deeply into the flooring, bracing yourself." + user << "It would be hard to take off the [src] without relaxing your grip first." +//In case they somehow come off while enabled. +/obj/item/clothing/shoes/magboots/vox/dropped(mob/user as mob) + ..() + if(src.magpulse) + user.visible_message("The [src] go limp as they are removed from [usr]'s feet.", "The [src] go limp as they are removed from your feet.") + flags &= ~NOSLIP + magpulse = 0 + canremove = 1 - examine() - set src in view() - ..() +/obj/item/clothing/shoes/magboots/vox/examine() + set src in view() + ..() + if (magpulse) + usr << "It would be hard to take these off without relaxing your grip first." //theoretically this message should only be seen by the wearer when the claws are equipped. //Species-specific Syndicate rigs. @@ -282,4 +298,4 @@ icon_state = "unathi_breacher" item_state = "unathi_breacher" _color = "unathi_breacher" - slowdown = 1 \ No newline at end of file + slowdown = 1 diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 6182d37db1d..7f6a81b8b79 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -428,4 +428,12 @@ desc = "The big drum sounds good only from a distance." icon_state = "mafiatan" item_state = "mafiatan" - _color = "mafiatan" \ No newline at end of file + _color = "mafiatan" + + +/obj/item/clothing/under/bane + name = "Bane Harness" + desc = "Wear this harness to become the bane of the station." + icon_state = "bane_harness" + item_state = "bane" + _color = "bane" \ No newline at end of file diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index 59434f9e591..7ce821a1f71 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -72,7 +72,7 @@ log transactions //short out the machine, shoot sparks, spew money! emagged = 1 spark_system.start() - spawn_money(rand(100,500),src.loc) + dispense_cash(rand(100,500),src.loc) //we don't want to grief people by locking their id in an emagged ATM release_held_id(user) @@ -309,7 +309,7 @@ log transactions //remove the money authenticated_account.money -= amount - spawn_money(amount,src.loc) + dispense_cash(amount,src.loc) //create an entry in the account transaction log var/datum/transaction/T = new() @@ -365,6 +365,11 @@ log transactions src.attack_hand(usr) +//create the most effective combination of notes to make up the requested amount +/obj/machinery/atm/proc/withdraw_arbitrary_sum(var/arbitrary_sum) + dispense_cash(arbitrary_sum,get_turf(src)) + + //stolen wholesale and then edited a bit from newscasters, which are awesome and by Agouri /obj/machinery/atm/proc/scan_user(mob/living/carbon/human/human_user as mob) if(!authenticated_account) diff --git a/code/modules/economy/cash.dm b/code/modules/economy/cash.dm index c352caa88d4..0703eb5deaa 100644 --- a/code/modules/economy/cash.dm +++ b/code/modules/economy/cash.dm @@ -64,11 +64,3 @@ desc = "It's worth 1000 credits." worth = 1000 -proc/spawn_money(var/sum, spawnloc) - var/cash_type - for(var/i in list(1000,500,200,100,50,20,10,1)) - cash_type = text2path("/obj/item/weapon/spacecash/c[i]") - while(sum >= i) - sum -= i - new cash_type(spawnloc) - return \ No newline at end of file diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm index b8ba1e2de79..c5f3ee4d8c4 100644 --- a/code/modules/events/event_dynamic.dm +++ b/code/modules/events/event_dynamic.dm @@ -63,10 +63,9 @@ var/global/list/possibleEvents = list() // possibleEvents[/datum/event/money_hacker] = max(min(25, player_list.len) * 4, 200) possibleEvents[/datum/event/carp_migration] = 50 + 25 * active_with_role["Engineer"] - possibleEvents[/datum/event/spider_infestation] = 50 + 25 * active_with_role["Security"] possibleEvents[/datum/event/dust] = 50 + 50 * active_with_role["Engineer"] possibleEvents[/datum/event/dust/meaty] = 50 + 50 * active_with_role["Engineer"] - possibleEvents[/datum/event/brand_intelligence] = 50 + 25 * active_with_role["Engineer"] + possibleEvents[/datum/event/rogue_drone] = 25 + 25 * active_with_role["Engineer"] + 25 * active_with_role["Security"] possibleEvents[/datum/event/infestation] = 50 + 25 * active_with_role["Janitor"] @@ -82,12 +81,16 @@ var/global/list/possibleEvents = list() if(minutes_passed >= 30) // Give engineers time to set up engine possibleEvents[/datum/event/meteor_wave] = 10 * active_with_role["Engineer"] possibleEvents[/datum/event/meteor_shower] = 40 * active_with_role["Engineer"] - possibleEvents[/datum/event/blob] = 20 * active_with_role["Engineer"] possibleEvents[/datum/event/anomaly/anomaly_pyro] = 100 + 60 * active_with_role["Engineer"] possibleEvents[/datum/event/anomaly/anomaly_vortex] = 50 + 25 * active_with_role["Engineer"] possibleEvents[/datum/event/anomaly/anomaly_bluespace] = 50 + 25 * active_with_role["Engineer"] possibleEvents[/datum/event/anomaly/anomaly_flux] = 50 + 50 * active_with_role["Engineer"] + if(minutes_passed >= 60) //Delay for potentially destructive events. + possibleEvents[/datum/event/blob] = 20 * active_with_role["Engineer"] + possibleEvents[/datum/event/brand_intelligence] = 50 + 25 * active_with_role["Engineer"] + possibleEvents[/datum/event/spider_infestation] = 50 + 25 * active_with_role["Security"] + possibleEvents[/datum/event/viral_infection] = 25 + active_with_role["Medical"] * 50 if(active_with_role["Medical"] > 0) possibleEvents[/datum/event/radiation_storm] = active_with_role["Medical"] * 50 diff --git a/code/modules/events/event_manager.dm b/code/modules/events/event_manager.dm index 11c9a320432..a0c4f7fe96c 100644 --- a/code/modules/events/event_manager.dm +++ b/code/modules/events/event_manager.dm @@ -69,6 +69,8 @@ var/scheduledEvent = null /datum/event/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in! + var/area/candidate = null + var/list/safe_areas = list( /area/turret_protected/ai, /area/turret_protected/ai_upload, @@ -93,6 +95,21 @@ var/scheduledEvent = null /area/engine/break_room, /area/engine/chiefs_office) - //Need to locate() as it's just a list of paths. - return locate(pick((the_station_areas - safe_areas) + danger_areas)) + var/list/event_areas = list() + + for (var/areapath in the_station_areas) + event_areas += typesof(areapath) + for (var/areapath in safe_areas) + event_areas -= typesof(areapath) + for (var/areapath in danger_areas) + event_areas += typesof(areapath) + + while (event_areas.len > 0) + var/list/event_turfs = null + candidate = locate(pick_n_take(event_areas)) + event_turfs = get_area_turfs(candidate) + if (event_turfs.len > 0) + break + + return candidate diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index 37a457076a6..34703ec5fec 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -24,7 +24,7 @@ /datum/event/prison_break/start() for(var/area/A in world) - if(istype(A, /area/security/prison) || istype(A, /area/security/brig)) + if(istype(A, /area/security/prison) || istype(A, /area/security/brig) || istype(A, /area/prison) || istype(A, /area/security/lobby)) prisonAreas += A if(prisonAreas && prisonAreas.len > 0) diff --git a/code/modules/events/tgevents/mass_hallucination.dm b/code/modules/events/tgevents/mass_hallucination.dm index 90fba19bdca..9241cc6217d 100644 --- a/code/modules/events/tgevents/mass_hallucination.dm +++ b/code/modules/events/tgevents/mass_hallucination.dm @@ -1,5 +1,8 @@ +/datum/event/mass_hallucination/setup() + announceWhen = rand(0, 20) + /datum/event/mass_hallucination/start() for(var/mob/living/carbon/C in living_mob_list) - C.hallucination += rand(20, 50) + C.hallucination += rand(50, 100) /datum/event/mass_hallucination/announce() command_alert("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage") \ No newline at end of file diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index 588857638a7..4003ee86a4c 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -1318,6 +1318,14 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/sashimi +// Fuck Science! +/datum/recipe/ruinedvirusdish + items = list( + /obj/item/weapon/virusdish + ) + result = /obj/item/weapon/ruinedvirusdish + + ////////////////////////////////////////// // bs12 food port stuff ////////////////////////////////////////// diff --git a/code/modules/genetics2/computer.dm b/code/modules/genetics2/computer.dm new file mode 100644 index 00000000000..e69de29bb2d diff --git a/code/modules/genetics2/genetree.dm b/code/modules/genetics2/genetree.dm new file mode 100644 index 00000000000..a7aa6ab756d --- /dev/null +++ b/code/modules/genetics2/genetree.dm @@ -0,0 +1,63 @@ +// Management of available genes. + +/datum/genetree + var/list/sectors=list() + var/list/dependencies=list() + var/list/dependants=list() + var/obj/machinery/networked/biomass_controller/biomass = null + +/datum/genetree/New(var/obj/machinery/networked/biomass_controller/holder) + biomass = holder + // Build list of all sectors + for(var/typepath in typesof(/datum/genetic_sector) - /datum/genetic_sector) + var/datum/genetic_sector/sector = new typepath + sectors[sector.id]=sector + + if(sector.prerequisites.len > 0) + sector.locked=1 + + // Make list of things that depend on this sector. + dependencies[sector.id]=sector.prerequisites + + // Generate reverse dependencies + for(var/dependee in sector.prerequisites) + if(!(dependee in dependants)) + dependants[dependee]=list(sector.id) + else + var/list/D = dependants[dependee] + D.Add(sector.name) + +/datum/genetree/proc/IsActive(var/sname) + var/datum/genetic_sector/sector = sectors[sname] + return sector.active + +/datum/genetree/proc/CanActivateSector(var/sname) + var/datum/genetic_sector/sector = sectors[sname] + for(var/dep in sector.prerequisites) + if(!IsActive(sector.id)) + return 0 + return biomass.available >= sector.required_biomass + +// Does NOT check for biomass +/datum/genetree/proc/ActivateSector(var/sname) + var/datum/genetic_sector/sector = sectors[sname] + sector.active = 1 + sector.OnActivate() + for(var/subsect in dependants[sname]) + var/datum/genetic_sector/subsector = sectors[subsect] + subsector.locked=0 + +/datum/genetree/proc/CheckSectors() + var/sectors_changed=0 + for(var/sname in sectors) + var/datum/genetic_sector/sector = sectors[sname] + var/pstate=sector.active + sector.active=1 + for(var/prereq in sector.prerequisites) + if(!IsActive(prereq)) + sector.active=0 + break + if(pstate != sector.active) + sectors_changed = 1 + if(sectors_changed) + CheckSectors() \ No newline at end of file diff --git a/code/modules/genetics2/sectors.dm b/code/modules/genetics2/sectors.dm new file mode 100644 index 00000000000..aec12619180 --- /dev/null +++ b/code/modules/genetics2/sectors.dm @@ -0,0 +1,110 @@ +var/global/current_sector_id=0 +/datum/genetic_sector + var/name = "UNKNOWN SECTOR" + var/desc = "LOLIDK" + + var/id = "" + var/uniqid = "" // 3-char ID, shown when locked. + var/list/prerequisites = list() + var/list/blocks_txt = list() + var/list/blocks = list() // DO NOT FUCKING USE THIS + var/required_biomass = 0 // In hominids (/mob/living/carbon) + var/time_required = 300 // Decaseconds required to unlock + var/time_researched = 0 + var/active=0 // Accessible + var/locked=0 // Cannot be purchased (yet) + +/datum/genetic_sector/New() + uniqid = add_zero2("[current_sector_id++]",3) + + // Set blocks + for(var/blockname in blocks_txt) + var/block = assigned_blocks[blockname] + if(block) + blocks += block + +/////////////////////////////////////// +// SECTORS +/////////////////////////////////////// + +/datum/genetic_sector/metabolism + id = "metabolism" + name = "Metabolism" + desc = "Grants access to areas of DNA that affect how the body controls its temperature." + required_biomass = 1 + time_required = 30 SECONDS + blocks_txt=list( + "COLD", + "FIRE", + "IMMOLATE", + "SOBER", + "MELT", + "FAT" + ) + +/datum/genetic_sector/mind + id = "mind" + name = "Mental Aptitude" + desc = "Reveals parts of DNA that affect mental capabilities" + required_biomass = 2 + time_required = 30 SECONDS + blocks_txt=list( + "PSYRESIST", + "HALLUCINATION", + "TWITCH", + "EPILEPSY", + ) + +/datum/genetic_sector/teleability + id = "teleability" + name = "Teleability" + desc = "Activates unused portions of the brain that can affect people a great distance away." + prerequisites = list("mind") + required_biomass = 4 + time_required = 1 MINUTES + blocks_txt = list( + "REMOTEVIEW", + "REMOTETALK", + "CRYO", + "EMPATH" + ) + +/datum/genetic_sector/telekinesis + id = "telekinesis" + name = "Telekinesis" + desc = "Activates unused portions of the brain that can affect objects a great distance away." + prerequisites = list("teleability") + required_biomass = 5 + time_required = 2 MINUTES + blocks_txt = list( + "TELE", + "FAKE" + ) + +/datum/genetic_sector/senses + id = "senses" + name = "Senses" + desc = "Accesses genes that affect vision and hearing." + prerequisites = list("mind") + required_biomass = 4 + time_required = 30 SECONDS + blocks_txt = list( + "XRAY", + "BLIND", + "GLASSES", + "EMPATH", + "DEAF" + ) + +/datum/genetic_sector/respiration + id = "respiration" + name = "Respiration" + desc = "Mess around with genes that affect breathing and lungs." + prerequisites = list("metabolism") + time_required = 1 MINUTES + required_biomass = 4 + blocks_txt = list( + "NOBREATH", + "COUGH", + "INCREASERUN", + ) \ No newline at end of file diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index bb21795a55c..b9c95fc6486 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -18,6 +18,7 @@ anchored = 1 density = 1 opacity = 1 + var/health = 50 /obj/structure/bookcase/initialize() for(var/obj/item/I in loc) @@ -30,6 +31,18 @@ user.drop_item() O.loc = src update_icon() + else if(istype(O, /obj/item/weapon/wrench)) + user << "\blue Now disassembling bookcase" + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user,50)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + density = 0 + qdel(src) + return else if(istype(O, /obj/item/weapon/pen)) var/newname = stripped_input(usr, "What would you like to title this bookshelf?") if(!newname) @@ -37,6 +50,18 @@ else name = ("bookcase ([sanitize(newname)])") else + switch(O.damtype) + if("fire") + src.health -= O.force * 1 + if("brute") + src.health -= O.force * 0.75 + else + if (src.health <= 0) + visible_message("The bookcase is smashed apart!") + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + qdel(src) ..() /obj/structure/bookcase/attack_hand(var/mob/user as mob) diff --git a/code/modules/liquid/splash_simulation.dm b/code/modules/liquid/splash_simulation.dm index 2bde78b19d9..d9147f60b18 100644 --- a/code/modules/liquid/splash_simulation.dm +++ b/code/modules/liquid/splash_simulation.dm @@ -168,7 +168,7 @@ turf/space/can_leave_liquid(from_direction) turf/simulated/floor/can_accept_liquid(from_direction) for(var/obj/structure/window/W in src) - if(W.dir in list(5,6,9,10)) + if(W.is_fulltile()) return 0 if(W.dir & from_direction) return 0 @@ -179,7 +179,7 @@ turf/simulated/floor/can_accept_liquid(from_direction) turf/simulated/floor/can_leave_liquid(to_direction) for(var/obj/structure/window/W in src) - if(W.dir in list(5,6,9,10)) + if(W.is_fulltile()) return 0 if(W.dir & to_direction) return 0 diff --git a/code/modules/media/jukebox.dm b/code/modules/media/jukebox.dm index a5c3343ac62..8d2f707c0a6 100644 --- a/code/modules/media/jukebox.dm +++ b/code/modules/media/jukebox.dm @@ -20,6 +20,8 @@ var/url = "" var/length = 0 // decaseconds + var/emagged = 0 + New(var/list/json) title = json["title"] artist = json["artist"] @@ -37,6 +39,18 @@ str += ", from '[album]'" return str + proc/displaytitle() + if(artist==""&&title=="") + return "\[NO TAGS\]" + var/str="" + if(artist!="") + str += "[artist] - " + if(title!="") + str += "\"[title]\"" + else + str += "Untitled" + return str + var/global/loopModeNames=list( JUKEMODE_SHUFFLE = "Shuffle", @@ -73,9 +87,10 @@ var/global/loopModeNames=list( // Must be defined on your server. playlists=list( "bar" = "Bar Mix", - "jazz" = "Jazz", - "rock" = "Rock", - "lounge" = "Portishead - Dummy" + "aussie" = "Aussie", + "club" = "Club", + "lounge" = "Portishead - Dummy", + "customs" = "Customs Music", ) /obj/machinery/media/jukebox/attack_ai(var/mob/user) @@ -86,23 +101,39 @@ var/global/loopModeNames=list( /obj/machinery/media/jukebox/power_change() ..() + if(emagged && !(stat & (NOPOWER|BROKEN))) + playing = 1 update_icon() /obj/machinery/media/jukebox/update_icon() overlays = 0 if(stat & (NOPOWER|BROKEN)) - icon_state = "jukebox2-nopower" + if(stat & BROKEN) + icon_state = "jukebox2-broken" + else + icon_state = "jukebox2-nopower" stop_playing() return icon_state = "jukebox2" if(playing) - overlays += "jukebox2-running" + if(emagged) + overlays += "jukebox2-emagged" + else + overlays += "jukebox2-running" /obj/machinery/media/jukebox/proc/check_reload() return world.time > last_reload + JUKEBOX_RELOAD_COOLDOWN /obj/machinery/media/jukebox/attack_hand(var/mob/user) - if(stat & (NOPOWER|BROKEN)) + if(stat & NOPOWER) + usr << "\red You don't see anything to mess with." + return + if(stat & BROKEN && playlist!=null) + user.visible_message("\red [user.name] smacks the side of \the [src.name].","\red You hammer the side of \the [src.name].") + stat &= ~BROKEN + playlist=null + playing=emagged + update_icon() return var/t = "

      Jukebox Interface

      " t += "Power: [playing?"On":"Off"]
      " @@ -114,7 +145,9 @@ var/global/loopModeNames=list( t += "Playlist: " for(var/plid in playlists) t += "[playlists[plid]]" - t += "
      " + else + t += "Please wait before changing playlists." + t += "
      " if(current_song) var/datum/song_info/song=playlist[current_song] t += "Current song: [song.artist] - [song.title]
      " @@ -122,7 +155,7 @@ var/global/loopModeNames=list( var/i for(i = 1,i <= playlist.len,i++) var/datum/song_info/song=playlist[i] - t += "#[i][song.artist] - [song.title][song.album]" + t += "#[i][song.displaytitle()][song.album]" t += "" user.set_machine(src) var/datum/browser/popup = new (user,"jukebox",name,420,700) @@ -131,8 +164,27 @@ var/global/loopModeNames=list( popup.open() +/obj/machinery/media/jukebox/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/card/emag)) + current_song=0 + if(!emagged) + playlist_id = "emagged" + last_reload=world.time + playlist=null + loop_mode = JUKEMODE_SHUFFLE + emagged = 1 + playing = 1 + user.visible_message("[user.name] slides something into the [src.name]'s card-reader.","\red You short out the [src.name].") + update_icon() + update_music() + return + /obj/machinery/media/jukebox/Topic(href, href_list) ..() + if(emagged) + usr << "\red You touch the bluescreened menu. Nothing happens. You feel dumber." + return + if (href_list["power"]) playing=!playing update_music() @@ -178,9 +230,14 @@ var/global/loopModeNames=list( var/songdata = reader.read_value() for(var/list/record in songdata) playlist += new /datum/song_info(record) + if(playlist.len==0) + visible_message("\icon[src] \The [src] buzzes, unable to update its playlist.","You hear a buzz.") + stat &= BROKEN + update_icon() + return visible_message("\icon[src] \The [src] beeps, and the menu on its front fills with [playlist.len] items.","You hear a beep.") else - //testing("Failed to update playlist: Response null.") + testing("[src] failed to update playlist: Response null.") stat &= BROKEN update_icon() return diff --git a/code/modules/media/mediamanager.dm b/code/modules/media/mediamanager.dm index c8d4e9b8f10..925888ed0c1 100644 --- a/code/modules/media/mediamanager.dm +++ b/code/modules/media/mediamanager.dm @@ -49,6 +49,15 @@ function SetMusic(url, time, volume) { // One media source per area. var/obj/machinery/media/media_source = null + +#ifdef DEBUG_MEDIAPLAYER +#define MP_DEBUG(x) owner << x +#warning Please comment out #define DEBUG_MEDIAPLAYER before committing. +#else +#define MP_DEBUG(x) +#endif + + /datum/media_manager var/url = "" var/start_time = 0 @@ -73,7 +82,7 @@ function SetMusic(url, time, volume) { proc/send_update() if(!(owner.prefs.toggles & SOUND_STREAMING)) return // Nope. - //testing("Sending update to WMP...") + MP_DEBUG("\green Sending update to WMP ([url])...") owner << output(list2params(list(url, (world.time - start_time) / 10, volume)), "[window]:SetMusic") proc/stop_music() @@ -85,7 +94,7 @@ function SetMusic(url, time, volume) { proc/update_music() var/targetURL = "" var/targetStartTime = 0 - var/targetVolume = 25 + //var/targetVolume = volume if (!owner) //testing("owner is null") @@ -104,8 +113,26 @@ function SetMusic(url, time, volume) { //else // testing("M is not playing or null.") - if (url != targetURL || abs(targetStartTime - start_time) > 1 || targetVolume != volume) + if (url != targetURL || abs(targetStartTime - start_time) > 1) url = targetURL start_time = targetStartTime - volume = targetVolume - send_update() \ No newline at end of file + //volume = targetVolume + send_update() + + proc/update_volume(var/value) + volume = value + send_update() + +/client/verb/change_volume() + set name = "Set Volume" + set category = "Preferences" + set desc = "Set jukebox volume" + if(!media || !istype(media)) + usr << "You have no media datum to change, if you're not in the lobby tell an admin." + return + var/value = input("Choose your Jukebox volume.", "Jukebox volume", media.volume) + value = round(max(0, min(100, value))) + media.update_volume(value) + if(prefs) + prefs.volume = value + prefs.save_volume() diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 0883b1a2747..654e733efcb 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -83,11 +83,16 @@ proc/move_mining_shuttle() if(istype(T, /turf/simulated)) del(T) - for(var/mob/living/carbon/bug in toArea) // If someone somehow is still in the shuttle's docking area... - bug.gib() - - for(var/mob/living/simple_animal/pest in toArea) // And for the other kind of bug... - pest.gib() + //Do I really need to explain this loop? + for(var/atom/A in toArea) + if(istype(A,/mob/living)) + var/mob/living/unlucky_person = A + unlucky_person.gib() + // Weird things happen when this shit gets in the way. + if(istype(A,/obj/structure/lattice) \ + || istype(A, /obj/structure/window) \ + || istype(A, /obj/structure/grille)) + qdel(A) fromArea.move_contents_to(toArea) if (mining_shuttle_location) @@ -162,7 +167,7 @@ proc/move_mining_shuttle() if (src.stat & BROKEN) user << "\blue The broken glass falls out." - new /obj/item/weapon/shard( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) A.state = 3 A.icon_state = "3" else diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index b3d6ce7dcee..303b490a1fc 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -292,7 +292,7 @@ var/list/artifact_spawn = list() // Runtime fix for geometry loading before cont var/turf/simulated/floor/plating/airless/asteroid/N = ChangeTurf(/turf/simulated/floor/plating/airless/asteroid) N.fullUpdateMineralOverlays() - if(rand(1,500) == 1) + if(rand(1,750) == 1) visible_message("An old dusty crate was buried within!") new /obj/structure/closet/crate/secure/loot(src) @@ -353,12 +353,12 @@ var/list/artifact_spawn = list() // Runtime fix for geometry loading before cont if(5) var/quantity = rand(1,3) for(var/i=0, i[t1]") + R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
      [t1]") if(istype(usr,/mob/living/silicon/robot)) var/mob/living/silicon/robot/U = usr - R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], 2557
      [t1]") + R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
      [t1]") if (href_list["medical"]) if(hasHUD(usr,"medical")) @@ -868,10 +857,18 @@ counter++ if(istype(usr,/mob/living/carbon/human)) var/mob/living/carbon/human/U = usr - R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], 2557
      [t1]") + R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
      [t1]") if(istype(usr,/mob/living/silicon/robot)) var/mob/living/silicon/robot/U = usr - R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], 2557
      [t1]") + R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
      [t1]") + + if (href_list["lookitem"]) + var/obj/item/I = locate(href_list["lookitem"]) + I.examine() + + if (href_list["lookmob"]) + var/mob/M = locate(href_list["lookmob"]) + M.examine() ..() return @@ -1140,6 +1137,7 @@ O.status &= ~ORGAN_ATTACHABLE if (!O.amputated) O.status &= ~ORGAN_DESTROYED + O.destspawn = 0 O.wounds.Cut() O.heal_damage(1000,1000,1,1) @@ -1226,10 +1224,11 @@ verbs += /mob/living/carbon/human/proc/bloody_doodle return 1 //we applied blood to the item -/mob/living/carbon/human/clean_blood() +/mob/living/carbon/human/clean_blood(var/clean_feet) .=..() - if(istype(feet_blood_DNA, /list) && feet_blood_DNA.len) + if(clean_feet && !shoes && istype(feet_blood_DNA, /list) && feet_blood_DNA.len) del(feet_blood_DNA) + update_inv_shoes(1) return 1 /mob/living/carbon/human/get_visible_implants(var/class = 0) @@ -1297,7 +1296,7 @@ else usr << "\blue [self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)]." -/mob/living/carbon/human/proc/set_species(var/new_species,var/on_spawn=0) +/mob/living/carbon/human/proc/set_species(var/new_species, var/force_organs) if(!dna) if(!new_species) @@ -1316,6 +1315,9 @@ species = all_species[new_species] + if(force_organs || !organs || !organs.len) + species.create_organs(src) + if(species.language) add_language(species.language) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 0c0e3096b50..558dc6b6cd6 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -56,7 +56,7 @@ emp_act return 2 //BEGIN BOOK'S TASER NERF. - if(istype(P, /obj/item/projectile/energy/electrode)) + if(istype(P, /obj/item/projectile/beam/stun)) var/datum/organ/external/select_area = get_organ(def_zone) // We're checking the outside, buddy! var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? // var/deflectchance=90 //Is it a CRITICAL HIT with that taser? diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 2136a2978db..291211f9a75 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -18,12 +18,18 @@ var/s_tone = 0 //Skin tone + //Skin colour + var/r_skin = 0 + var/g_skin = 0 + var/b_skin = 0 + var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup var/age = 30 //Player's age (pure fluff) var/b_type = "A+" //Player's bloodtype var/underwear = 1 //Which underwear the player wants + var/undershirt = 1 //Which undershirt the player wants. var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack. //Equipment slots diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 7f43646b963..ba67b8a706a 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -768,11 +768,8 @@ It can still be worn/put on as normal. if(item && target.has_organ_for_slot(slot_to_process)) //Placing an item on the mob if(item.mob_can_equip(target, slot_to_process, 0)) source.u_equip(item) - item.dropped(source) - target.equip_to_slot_if_possible(item, slot_to_process, 0, 1, 1) - item.pickup(target) - + item.dropped(source) source.update_icons() target.update_icons() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index d49618c9579..292be653b44 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -132,6 +132,7 @@ if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > 6000)) //We are long dead, or we're junk mobs spawned like the clowns on the clown shuttle return //We go ahead and process them 5 times for HUD images and other stuff though. + //Handle temperature/pressure differences between body and environment handle_environment(environment) //Optimized a good bit. @@ -264,6 +265,8 @@ if(!gene.block) continue if(gene.is_active(src)) + if (prob(10) && prob(gene.instability)) + adjustCloneLoss(1) gene.OnMobLife(src) if (radiation) @@ -280,11 +283,13 @@ var/rads = radiation/25 radiation -= rads nutrition += rads - heal_overall_damage(rads,rads) + adjustBruteLoss(-(rads)) adjustOxyLoss(-(rads)) adjustToxLoss(-(rads)) updatehealth() return + if(species.flags & IS_SYNTHETIC) + return var/damage = 0 switch(radiation) @@ -951,7 +956,7 @@ var/turf/T = loc var/area/A = T.loc if(A) - if(A.lighting_use_dynamic) light_amount = min(10,T.lit_value) - 5 //hardcapped so it's not abused by having a ton of flashlights + if(A.lighting_use_dynamic) light_amount = min(10,T.lighting_lumcount) - 5 //hardcapped so it's not abused by having a ton of flashlights else light_amount = 5 nutrition += light_amount traumatic_shock -= light_amount @@ -970,7 +975,7 @@ var/turf/T = loc var/area/A = T.loc if(A) - if(A.lighting_use_dynamic) light_amount = T.lit_value + if(A.lighting_use_dynamic) light_amount = T.lighting_lumcount else light_amount = 10 if(light_amount > 2) //if there's enough light, start dying take_overall_damage(1,1) @@ -1252,13 +1257,17 @@ if(hud_updateflag) handle_hud_list() + if(!client) return 0 + if(hud_updateflag) + handle_hud_list() + for(var/image/hud in client.images) if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe client.images.Remove(hud) - client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask) + client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask/*, global_hud.nvg*/) update_action_buttons() @@ -1390,34 +1399,25 @@ if(!druggy) see_invisible = SEE_INVISIBLE_LIVING if(glasses) - if(istype(glasses, /obj/item/clothing/glasses/meson)) - sight |= SEE_TURFS - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - else if(istype(glasses, /obj/item/clothing/glasses/night)) - see_in_dark = 5 - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - else if(istype(glasses, /obj/item/clothing/glasses/thermal)) - sight |= SEE_MOBS - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - else if(istype(glasses, /obj/item/clothing/glasses/material)) - sight |= SEE_OBJS - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM + var/obj/item/clothing/glasses/G = glasses + if(istype(G)) + see_in_dark += G.darkness_view + if(G.vision_flags) // MESONS + sight |= G.vision_flags + if(!druggy) + see_invisible = SEE_INVISIBLE_MINIMUM /* HUD shit goes here, as long as it doesn't modify sight flags */ // The purpose of this is to stop xray and w/e from preventing you from using huds -- Love, Doohl - else if(istype(glasses, /obj/item/clothing/glasses/sunglasses)) + if(istype(glasses, /obj/item/clothing/glasses/sunglasses)) see_in_dark = 1 if(istype(glasses, /obj/item/clothing/glasses/sunglasses/sechud)) var/obj/item/clothing/glasses/sunglasses/sechud/O = glasses if(O.hud) O.hud.process_hud(src) if(!druggy) see_invisible = SEE_INVISIBLE_LIVING - else if(istype(glasses, /obj/item/clothing/glasses/hud)) + if(istype(glasses, /obj/item/clothing/glasses/hud)) var/obj/item/clothing/glasses/hud/O = glasses O.process_hud(src) if(!druggy) @@ -1428,6 +1428,7 @@ see_in_dark = species.darksight see_invisible = SEE_INVISIBLE_LIVING + if(healths) if (analgesic) healths.icon_state = "health_health_numb" @@ -1548,7 +1549,7 @@ //0.1% chance of playing a scary sound to someone who's in complete darkness if(isturf(loc) && rand(1,1000) == 1) var/turf/currentTurf = loc - if(!currentTurf.lit_value) + if(!currentTurf.lighting_lumcount) playsound_local(src,pick(scarySounds),50, 1, -1) // Separate proc so we can jump out of it when we've succeeded in spreading disease. @@ -1732,6 +1733,9 @@ makeSkeleton() return //No puking over skeletons, they don't smell at all! +// if(loc == /obj/structure/morgue) +// return + for(var/mob/living/carbon/human/H in range(decaylevel, src)) if(prob(5)) if(airborne_can_reach(get_turf(src), get_turf(H))) @@ -1815,7 +1819,6 @@ var/obj/item/weapon/card/id/I = wear_id.GetID() if(I) perpname = I.registered_name - for(var/datum/data/record/E in data_core.general) if(E.fields["name"] == perpname) for (var/datum/data/record/R in data_core.security) @@ -1858,29 +1861,33 @@ if(hud_updateflag & 1 << SPECIALROLE_HUD) var/image/holder = hud_list[SPECIALROLE_HUD] holder.icon_state = "hudblank" - switch(mind.special_role) - if("traitor","Syndicate") - holder.icon_state = "hudsyndicate" - if("Revolutionary") - holder.icon_state = "hudrevolutionary" - if("Head Revolutionary") - holder.icon_state = "hudheadrevolutionary" - if("Cultist") - holder.icon_state = "hudcultist" - if("Changeling") - holder.icon_state = "hudchangeling" - if("Wizard","Fake Wizard") - holder.icon_state = "hudwizard" - if("Death Commando") - holder.icon_state = "huddeathsquad" - if("Ninja") - holder.icon_state = "hudninja" - if("Vampire") - holder.icon_state = "hudvampire" - if("VampThrall") - holder.icon_state = "hudvampthrall" - hud_list[SPECIALROLE_HUD] = holder + if(mind) + + switch(mind.special_role) + if("traitor","Syndicate") + holder.icon_state = "hudsyndicate" + if("Revolutionary") + holder.icon_state = "hudrevolutionary" + if("Head Revolutionary") + holder.icon_state = "hudheadrevolutionary" + if("Cultist") + holder.icon_state = "hudcultist" + if("Changeling") + holder.icon_state = "hudchangeling" + if("Wizard","Fake Wizard") + holder.icon_state = "hudwizard" + if("Death Commando") + holder.icon_state = "huddeathsquad" + if("Ninja") + holder.icon_state = "hudninja" + if("Vampire") // TODO: Check this + holder.icon_state = "hudvampire" + if("VampThrall") + holder.icon_state = "hudvampthrall" + + + hud_list[SPECIALROLE_HUD] = holder hud_updateflag = 0 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index c4f2bb399cf..7203cd08e51 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -97,26 +97,26 @@ Please contact me on #coderbus IRC. ~Carn x */ //Human Overlays Indexes///////// -#define MUTANTRACE_LAYER 1 //TODO: make part of body? +#define MUTANTRACE_LAYER 1 #define MUTATIONS_LAYER 2 #define DAMAGE_LAYER 3 #define UNIFORM_LAYER 4 -#define ID_LAYER 5 -#define SHOES_LAYER 6 -#define GLOVES_LAYER 7 -#define EARS_LAYER 8 -#define SUIT_LAYER 9 -#define GLASSES_LAYER 10 -#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt? -#define SUIT_STORE_LAYER 12 -#define BACK_LAYER 13 -#define HAIR_LAYER 14 //TODO: make part of head layer? -#define FACEMASK_LAYER 15 -#define HEAD_LAYER 16 -#define COLLAR_LAYER 17 -#define HANDCUFF_LAYER 18 -#define LEGCUFF_LAYER 19 -#define TAIL_LAYER 20 //bs12 specific. this hack is probably gonna come back to haunt me +#define TAIL_LAYER 5 //bs12 specific. this hack is probably gonna come back to haunt me +#define ID_LAYER 6 +#define SHOES_LAYER 7 +#define GLOVES_LAYER 8 +#define EARS_LAYER 9 +#define SUIT_LAYER 10 +#define GLASSES_LAYER 11 +#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt? +#define SUIT_STORE_LAYER 13 +#define BACK_LAYER 14 +#define HAIR_LAYER 15 //TODO: make part of head layer? +#define FACEMASK_LAYER 16 +#define HEAD_LAYER 17 +#define COLLAR_LAYER 18 +#define HANDCUFF_LAYER 19 +#define LEGCUFF_LAYER 20 #define L_HAND_LAYER 21 #define R_HAND_LAYER 22 #define TARGETED_LAYER 23 //BS12: Layer for the target overlay from weapon targeting system @@ -295,12 +295,16 @@ proc/get_damage_icon_part(damage_state, body_part) stand_icon.Blend(temp, ICON_OVERLAY) //Skin tone - if(!skeleton && !husk && !hulk && (species.flags & HAS_SKIN_TONE)) + if(!skeleton && !husk && !hulk && (species.bodyflags & HAS_SKIN_TONE)) if(s_tone >= 0) stand_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) else stand_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + //Skin color + if(!skeleton && !husk && !hulk && (species.bodyflags & HAS_SKIN_COLOR)) + stand_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + if(husk) var/icon/mask = new(stand_icon) var/icon/husk_over = new(race_icon,"overlay_husk") @@ -327,6 +331,9 @@ proc/get_damage_icon_part(damage_state, body_part) if(!fat && !skeleton) stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY) + if(undershirt>0 && undershirt < 5 && species.flags & HAS_UNDERWEAR) + stand_icon.Blend(new /icon('icons/mob/human.dmi', "undershirt[undershirt]_s"), ICON_OVERLAY) + if(update_icons) update_icons() @@ -354,13 +361,12 @@ proc/get_damage_icon_part(damage_state, body_part) if(f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style) - if(src.species.name in facial_hair_style.species_allowed) - var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + if(facial_hair_style && src.species.name in facial_hair_style.species_allowed) + var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + if(facial_hair_style.do_colouration) + facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) - face_standing.Blend(facial_s, ICON_OVERLAY) + face_standing.Blend(facial_s, ICON_OVERLAY) if(h_style && !(head && (head.flags & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] @@ -384,6 +390,7 @@ proc/get_damage_icon_part(damage_state, body_part) var/add_image = 0 var/g = "m" if(gender == FEMALE) g = "f" + // DNA2 - Drawing underlays. for(var/datum/dna/gene/gene in dna_genes) if(!gene.block) continue @@ -849,7 +856,10 @@ proc/get_damage_icon_part(damage_state, body_part) if(species.tail && species.bodyflags & HAS_TAIL) if(!wear_suit || !(wear_suit.flags_inv & HIDEJUMPSUIT) && !istype(wear_suit, /obj/item/clothing/suit/space)) - overlays_standing[TAIL_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") + var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") + tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + + overlays_standing[TAIL_LAYER] = image(tail_s) if(update_icons) update_icons() @@ -910,6 +920,7 @@ proc/get_damage_icon_part(damage_state, body_part) #undef MUTATIONS_LAYER #undef DAMAGE_LAYER #undef UNIFORM_LAYER +#undef TAIL_LAYER #undef ID_LAYER #undef SHOES_LAYER #undef GLOVES_LAYER @@ -927,7 +938,6 @@ proc/get_damage_icon_part(damage_state, body_part) #undef LEGCUFF_LAYER #undef L_HAND_LAYER #undef R_HAND_LAYER -#undef TAIL_LAYER #undef TARGETED_LAYER #undef FIRE_LAYER #undef TOTAL_LAYERS diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index f9bce720cb3..97b863400ff 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -164,15 +164,14 @@ now_pushing = 1 if (!( AM.anchored )) var/t = get_dir(src, AM) - if (istype(AM, /obj/structure/window)) - if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST) - for(var/obj/structure/window/win in get_step(AM,t)) - now_pushing = 0 - return + if (istype(AM, /obj/structure/window/full)) + for(var/obj/structure/window/win in get_step(AM,t)) + now_pushing = 0 + return step(AM, t) now_pushing = null return - return + /mob/living/carbon/slime/Process_Spacemove() return 2 @@ -1098,4 +1097,4 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 M.slime_color = pickedcolor user << "You absorb the pigment and your color shifts!" M.update_mutantrace() - del(src) //Finally a tidy way to remove all the used cores lying about \ No newline at end of file + del(src) //Finally a tidy way to remove all the used cores lying about diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 48e147b67e3..f5385fbafd3 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -450,7 +450,7 @@ var/turf/T = loc var/area/A = T.loc if(A) - if(A.lighting_use_dynamic) light_amount = min(10,T.lit_value) - 5 //hardcapped so it's not abused by having a ton of flashlights + if(A.lighting_use_dynamic) light_amount = min(10,T.lighting_lumcount) - 5 //hardcapped so it's not abused by having a ton of flashlights else light_amount = 5 nutrition += light_amount diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 12aa97f50fb..ed193859ffa 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -147,11 +147,10 @@ now_pushing = 1 if (!( AM.anchored )) var/t = get_dir(src, AM) - if (istype(AM, /obj/structure/window)) - if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST) - for(var/obj/structure/window/win in get_step(AM,t)) - now_pushing = 0 - return + if (istype(AM, /obj/structure/window/full)) + for(var/obj/structure/window/win in get_step(AM,t)) + now_pushing = 0 + return step(AM, t) now_pushing = null return diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index 77dd84aeebc..9c73a8719db 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -43,29 +43,69 @@ var/flags = 0 // Various specific features. var/bloodflags=0 var/bodyflags=0 - + var/flesh_color = "#FFC896" //Pink. var/list/abilities = list() // For species-derived or admin-given powers -/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. +/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. + //This is a basic humanoid limb setup. + H.organs = list() + H.organs_by_name["chest"] = new/datum/organ/external/chest() + H.organs_by_name["groin"] = new/datum/organ/external/groin(H.organs_by_name["chest"]) + H.organs_by_name["head"] = new/datum/organ/external/head(H.organs_by_name["chest"]) + H.organs_by_name["l_arm"] = new/datum/organ/external/l_arm(H.organs_by_name["chest"]) + H.organs_by_name["r_arm"] = new/datum/organ/external/r_arm(H.organs_by_name["chest"]) + H.organs_by_name["r_leg"] = new/datum/organ/external/r_leg(H.organs_by_name["groin"]) + H.organs_by_name["l_leg"] = new/datum/organ/external/l_leg(H.organs_by_name["groin"]) + H.organs_by_name["l_hand"] = new/datum/organ/external/l_hand(H.organs_by_name["l_arm"]) + H.organs_by_name["r_hand"] = new/datum/organ/external/r_hand(H.organs_by_name["r_arm"]) + H.organs_by_name["l_foot"] = new/datum/organ/external/l_foot(H.organs_by_name["l_leg"]) + H.organs_by_name["r_foot"] = new/datum/organ/external/r_foot(H.organs_by_name["r_leg"]) + + if (name!="Slime People") + H.internal_organs = list() + H.internal_organs_by_name["heart"] = new/datum/organ/internal/heart(H) + H.internal_organs_by_name["lungs"] = new/datum/organ/internal/lungs(H) + H.internal_organs_by_name["liver"] = new/datum/organ/internal/liver(H) + H.internal_organs_by_name["kidney"] = new/datum/organ/internal/kidney(H) + H.internal_organs_by_name["brain"] = new/datum/organ/internal/brain(H) + H.internal_organs_by_name["eyes"] = new/datum/organ/internal/eyes(H) + + for(var/name in H.organs_by_name) + H.organs += H.organs_by_name[name] + + for(var/datum/organ/external/O in H.organs) + O.owner = H if(flags & IS_SYNTHETIC) for(var/datum/organ/external/E in H.organs) if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue E.status |= ORGAN_ROBOT for(var/datum/organ/internal/I in H.internal_organs) - I.robotic = 2 + I.mechanize() + + + return + +/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. return /datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). return + +/datum/species/proc/say_filter(mob/M, message, datum/language/speaking) + return message + +/datum/species/proc/equip(var/mob/living/carbon/human/H) + /datum/species/human name = "Human" icobase = 'icons/mob/human_races/r_human.dmi' deform = 'icons/mob/human_races/r_def_human.dmi' primitive = /mob/living/carbon/monkey path = /mob/living/carbon/human/human - flags = HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | CAN_BE_FAT + flags = HAS_LIPS | HAS_UNDERWEAR | CAN_BE_FAT + bodyflags = HAS_SKIN_TONE /datum/species/unathi name = "Unathi" @@ -79,7 +119,7 @@ darksight = 3 flags = HAS_LIPS | HAS_UNDERWEAR - bodyflags = FEET_CLAWS | HAS_TAIL + bodyflags = FEET_CLAWS | HAS_TAIL | HAS_SKIN_COLOR cold_level_1 = 280 //Default 260 - Lower is better cold_level_2 = 220 //Default 200 @@ -89,6 +129,9 @@ heat_level_2 = 480 //Default 400 heat_level_3 = 1100 //Default 1000 + flesh_color = "#34AF10" + + /datum/species/tajaran name = "Tajaran" icobase = 'icons/mob/human_races/r_tajaran.dmi' @@ -110,7 +153,9 @@ primitive = /mob/living/carbon/monkey/tajara flags = HAS_LIPS | HAS_UNDERWEAR | CAN_BE_FAT - bodyflags = FEET_PADDED | HAS_TAIL + bodyflags = FEET_PADDED | HAS_TAIL | HAS_SKIN_COLOR + + flesh_color = "#AFA59E" /datum/species/skrell name = "Skrell" @@ -122,6 +167,9 @@ flags = HAS_LIPS | HAS_UNDERWEAR bloodflags = BLOOD_GREEN + bodyflags = HAS_SKIN_COLOR + + flesh_color = "#8CD7A3" /datum/species/vox name = "Vox" @@ -143,7 +191,6 @@ flags = NO_SCAN | IS_WHITELISTED | NO_BLOOD /datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) - var/datum/organ/external/affected = H.get_organ("head") //To avoid duplicates. @@ -192,6 +239,10 @@ bodyflags = FEET_NOSLIP abilities = list(/mob/living/carbon/human/slime/proc/slimepeople_ventcrawl) +/datum/species/slime/handle_post_spawn(var/mob/living/carbon/human/H) + H.dna.mutantrace = "slime" + H.update_mutantrace() + /datum/species/grey // /vg/ name = "Grey" @@ -235,9 +286,10 @@ flags = NO_BREATHE | REQUIRE_LIGHT | NO_SCAN | IS_PLANT | RAD_ABSORB | NO_BLOOD | IS_SLOW | NO_PAIN /datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H) - H.gender = NEUTER + return ..() + /datum/species/diona/handle_death(var/mob/living/carbon/human/H) var/mob/living/carbon/monkey/diona/S = new(get_turf(H)) @@ -280,5 +332,4 @@ flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | IS_SYNTHETIC -// blood_color = "#FFFFFF" -// flesh_color = "#AAAAAA" + flesh_color = "#AAAAAA" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index cadf9e44d9e..2381f9741a8 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -273,7 +273,7 @@ /mob/living/proc/restore_all_organs() return - + /mob/living/proc/revive() rejuvenate() buckled = initial(src.buckled) @@ -318,12 +318,12 @@ if(iscarbon(src)) var/mob/living/carbon/C = src C.handcuffed = initial(C.handcuffed) - + // restore all of the human's blood if(ishuman(src)) var/mob/living/carbon/human/human_mob = src human_mob.restore_blood() - + for(var/datum/disease/D in viruses) D.cure(0) restore_all_organs() @@ -335,7 +335,6 @@ regenerate_icons() hud_updateflag |= 1 << HEALTH_HUD hud_updateflag |= 1 << STATUS_HUD - ..() return /mob/living/proc/UpdateDamageIcon() @@ -424,10 +423,9 @@ M.start_pulling(t) else if (pulling) - if (istype(pulling, /obj/structure/window)) - if(pulling:ini_dir == NORTHWEST || pulling:ini_dir == NORTHEAST || pulling:ini_dir == SOUTHWEST || pulling:ini_dir == SOUTHEAST) - for(var/obj/structure/window/win in get_step(pulling,get_dir(pulling.loc, T))) - stop_pulling() + if (istype(pulling, /obj/structure/window/full)) + for(var/obj/structure/window/win in get_step(pulling,get_dir(pulling.loc, T))) + stop_pulling() if (pulling) step(pulling, get_dir(pulling.loc, T)) else diff --git a/code/modules/mob/living/silicon/pai/examine.dm b/code/modules/mob/living/silicon/pai/examine.dm index 26010d63535..14c3240c086 100644 --- a/code/modules/mob/living/silicon/pai/examine.dm +++ b/code/modules/mob/living/silicon/pai/examine.dm @@ -1,5 +1,5 @@ /mob/living/silicon/pai/examine() //removed as it was pointless...moved to the pai-card instead. - /* This is totaly pointless because this mob is contained inside a card! + /* This is totally pointless because this mob is contained inside a card! set src in oview() var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm index aaa3f87f3fc..2ed190fc060 100644 --- a/code/modules/mob/living/silicon/pai/life.dm +++ b/code/modules/mob/living/silicon/pai/life.dm @@ -5,7 +5,7 @@ if(get_dist(src, src.cable) > 1) var/turf/T = get_turf_or_move(src.loc) for (var/mob/M in viewers(T)) - M.show_message("\red [src.cable] rapidly retracts back into its spool.", 3, "\red You hear a click and the sound of wire spooling rapidly.", 2) + M.show_message("\red The data cable rapidly retracts back into its spool.", 3, "\red You hear a click and the sound of wire spooling rapidly.", 2) del(src.cable) regular_hud_updates() diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index d54b96e7857..e007298c5c5 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -111,42 +111,118 @@ var/datum/paiController/paiController // Global handler for pAI candidates var/dat = "" dat += {" "} - dat += {"

      Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!

      - - - + dat += {" + + pAI Personality Configuration +

      Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!

      - - +
      Name:[candidate.name]
      \[Edit\]What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.
      Description:[candidate.description]
      \[Edit\]What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Name:[candidate.name] 
      What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.
      Description:[candidate.description] 
      What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.
      Preferred Role:[candidate.role] 
      Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.
      OOC Comments:[candidate.comments] 
      Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.
      +
      + + + + + + + +
      + Save Personality +
      + Load Personality +

      + + +
      Submit Personality

      - Preferred Role:[candidate.role] - \[Edit\]Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here. + + "} - OOC Comments:[candidate.comments] - \[Edit\]Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want. - - - -
      -

      Submit Personality


      - Save Personality
      - Load Personality
      "} - - M << browse(dat, "window=paiRecruit") + M << browse(dat, "window=paiRecruit;size=580x580;") proc/findPAI(var/obj/item/device/paicard/p, var/mob/user) requestRecruits() @@ -162,35 +238,105 @@ var/datum/paiController/paiController // Global handler for pAI candidates var/dat = "" dat += {" - - -

      Requesting AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.

      - - "} + + + + + + + pAI Availability List

      + "} + dat += "

      Displaying available AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.

      " for(var/datum/paiCandidate/c in available) - dat += {" - - - - + dat += {" +
      Name:[c.name]
      Description:[c.description]
      Preferred Role:[c.role]
      OOC Comments:[c.comments]
      \[Download [c.name]\]
      + + + + + + + + + + + + + + + + +
      Name:[c.name]
      Description:[c.description]
      Preferred Role:[c.role]
      OOC Comments:[c.comments]
      + + +
      Download [c.name] +
      +
      + "} - "} + dat += {" + + + "} user << browse(dat, "window=findPai") diff --git a/code/modules/mob/living/silicon/pai/say.dm b/code/modules/mob/living/silicon/pai/say.dm index fb43bd9af9d..e1cb9f0f800 100644 --- a/code/modules/mob/living/silicon/pai/say.dm +++ b/code/modules/mob/living/silicon/pai/say.dm @@ -1,5 +1,5 @@ /mob/living/silicon/pai/say(var/msg) if(silence_time) - src << "Communication circuits remain unitialized." + src << "Communication circuits remain uninitialized." else ..(msg) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 6e688c2bdc6..cb8c5748d1f 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -33,7 +33,7 @@ if(temp) left_part = temp else if(src.stat == 2) // Show some flavor text if the pAI is dead - left_part = "ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ" + left_part = "ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ" //This file has to be saved as ANSI or this will not display correctly right_part = "
      Program index hash not found
      " else @@ -66,31 +66,34 @@ left_part = src.softwareCamera() if("signaller") left_part = src.softwareSignal() + if("radio") + left_part = src.softwareRadio() //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc - // Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality + // Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality dat = {"