From edef78a1e4a75eb347237d9408e4a50c7e64aaec Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Fri, 11 Jul 2014 00:17:10 -0600 Subject: [PATCH 01/18] Testing out branch management. Nothing to see here. --- IfImHereDeleteMe.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 IfImHereDeleteMe.txt diff --git a/IfImHereDeleteMe.txt b/IfImHereDeleteMe.txt new file mode 100644 index 00000000000..6268d817ef6 --- /dev/null +++ b/IfImHereDeleteMe.txt @@ -0,0 +1 @@ +This is just because I'm a n00b at git. \ No newline at end of file From 75fb62d1a18c12d5ef06826657b7d7466ab785c4 Mon Sep 17 00:00:00 2001 From: John-Michael O'Brien Date: Fri, 11 Jul 2014 00:29:45 -0600 Subject: [PATCH 02/18] Delete IfImHereDeleteMe.txt --- IfImHereDeleteMe.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 IfImHereDeleteMe.txt diff --git a/IfImHereDeleteMe.txt b/IfImHereDeleteMe.txt deleted file mode 100644 index 6268d817ef6..00000000000 --- a/IfImHereDeleteMe.txt +++ /dev/null @@ -1 +0,0 @@ -This is just because I'm a n00b at git. \ No newline at end of file From 646aad945e67ccfa15df55d3f9eb941eac4dde27 Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Sun, 27 Jul 2014 17:21:19 -0600 Subject: [PATCH 03/18] Merged getFlatIcon rendering from tgstation Based on tgstation #2826. This is not all of it though. --- code/__HELPERS/icons.dm | 96 +++++++++++++++++++++++++------------ code/__HELPERS/type2type.dm | 7 +++ code/datums/datacore.dm | 2 +- 3 files changed, 73 insertions(+), 32 deletions(-) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 0ca515486b4..d193fcb26e4 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -634,20 +634,60 @@ as a single icon. Useful for when you want to manipulate an icon via the above a The _flatIcons list is a cache for generated icon files. */ -proc - getFlatIcon(atom/A, dir) // 1 = use cache, 2 = override cache, 0 = ignore cache +proc // Creates a single icon from a given /atom or /image. Only the first argument is required. + getFlatIcon(image/A, defdir=A.dir, deficon=A.icon, defstate=A.icon_state, defblend=A.blend_mode) + // We start with a blank canvas, otherwise some icon procs crash silently + var/icon/flat = icon('icons/effects/effects.dmi', "nothing") // Final flattened icon + if(!A) + return flat + if(A.alpha <= 0) + return flat + var/noIcon = FALSE + + var/curicon + if(A.icon) + curicon = A.icon + else + curicon = deficon + + if(!curicon) + noIcon = TRUE // Do not render this object. + + var/curstate + if(A.icon_state) + curstate = A.icon_state + else + curstate = defstate + + if(!noIcon && !(curstate in icon_states(curicon))) + if("" in icon_states(curicon)) + curstate = "" + else + noIcon = TRUE // Do not render this object. + + var/curdir + if(A.dir) + curdir = A.dir + else + curdir = defdir + + var/curblend + if(A.blend_mode == BLEND_DEFAULT) + curblend = defblend + else + curblend = A.blend_mode + // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed var/list/layers = list() - - // Add the atom's icon itself - if(A.icon) - // Make a copy without pixel_x/y settings - var/image/copy = image(icon=A.icon,icon_state=A.icon_state,layer=A.layer,dir=A.dir) + var/image/copy + // Add the atom's icon itself, without pixel_x/y offsets. + if(!noIcon) + copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) + copy.color = A.color + copy.alpha = A.alpha + copy.blend_mode = curblend layers[copy] = A.layer - // dir defaults to A's dir - if(!dir) dir = A.dir - // Loop through the underlays, then overlays, sorting them into the layers list var/list/process = A.underlays // Current list being processed var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays @@ -662,7 +702,7 @@ proc if(!current) continue currentLayer = current:layer if(currentLayer<0) // Special case for FLY_LAYER - if(currentLayer <= -1000) return 0 + if(currentLayer <= -1000) return flat if(pSet == 0) // Underlay currentLayer = A.layer+currentLayer/1000 else // Overlay @@ -688,8 +728,6 @@ proc else // All done break - // We start with a blank canvas, otherwise some icon procs crash silently - var/icon/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon var/icon/add // Icon of overlay being added // Current dimensions of flattened icon @@ -699,24 +737,15 @@ proc for(var/I in layers) - if(I:icon) - if(I:icon_state) - // Has icon and state set - add = icon(I:icon, I:icon_state) - else - if(A.icon_state in icon_states(I:icon)) - // Inherits icon_state from atom - add = icon(I:icon, A.icon_state) - else - // Uses default state ("") - add = icon(I:icon) - else if(I:icon_state) - // Inherits icon from atom - add = icon(A.icon, I:icon_state) - else - // Unknown + if(I:alpha == 0) continue + if(I == copy) // 'I' is an /image based on the object being flattened. + curblend = BLEND_OVERLAY + add = icon(I:icon, I:icon_state, I:dir) + else // 'I' is an appearance object. + add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) + // Find the new dimensions of the flat icon to fit the added overlay addX1 = min(flatX1, I:pixel_x+1) addX2 = max(flatX2, I:pixel_x+add.Width()) @@ -730,9 +759,14 @@ proc flatY1=addY1;flatY2=addY2 // Blend the overlay into the flattened icon - flat.Blend(add,ICON_OVERLAY,I:pixel_x+2-flatX1,I:pixel_y+2-flatY1) + flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) - return flat + if(A.color) + flat.Blend(A.color, ICON_MULTIPLY) + if(A.alpha < 255) + flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) + + return icon(flat, "", SOUTH) getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 885de82c44b..8c188d0d180 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -298,6 +298,13 @@ proc/tg_list2text(list/list, glue=",") /proc/angle2text(var/degree) return dir2text(angle2dir(degree)) +//Converts a blend_mode constant to one acceptable to icon.Blend() +/proc/blendMode2iconMode(blend_mode) + switch(blend_mode) + if(BLEND_MULTIPLY) return ICON_MULTIPLY + if(BLEND_ADD) return ICON_ADD + if(BLEND_SUBTRACT) return ICON_SUBTRACT + else return ICON_OVERLAY //Converts a rights bitfield into a string /proc/rights2text(rights,seperator="") diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 98da4a58ded..a1a626313b6 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -119,7 +119,7 @@ L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.SE // Used in respawning L.fields["identity"] = H.dna.UI // " - L.fields["image"] = getFlatIcon(H,0) //This is god-awful + L.fields["image"] = getFlatIcon(H) //This is god-awful locked += L return From 1d7310c49d3febfd14450439cabf9d956ede99fc Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Sun, 27 Jul 2014 22:05:24 -0600 Subject: [PATCH 04/18] Patched display and dealt with lying. --- code/__HELPERS/icons.dm | 6 ++-- code/modules/paperwork/photography.dm | 50 +++++++++++++++------------ 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index d193fcb26e4..65807c05757 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -637,7 +637,7 @@ The _flatIcons list is a cache for generated icon files. proc // Creates a single icon from a given /atom or /image. Only the first argument is required. getFlatIcon(image/A, defdir=A.dir, deficon=A.icon, defstate=A.icon_state, defblend=A.blend_mode) // We start with a blank canvas, otherwise some icon procs crash silently - var/icon/flat = icon('icons/effects/effects.dmi', "nothing") // Final flattened icon + var/icon/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon if(!A) return flat if(A.alpha <= 0) @@ -666,7 +666,7 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu noIcon = TRUE // Do not render this object. var/curdir - if(A.dir) + if(A.dir != 2) curdir = A.dir else curdir = defdir @@ -682,6 +682,7 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu var/image/copy // Add the atom's icon itself, without pixel_x/y offsets. if(!noIcon) + world.log << "***Rendering Icon [A.type] in state '[curstate]' on layer [A.layer] in direction [curdir]" // #JMO copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) copy.color = A.color copy.alpha = A.alpha @@ -744,6 +745,7 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu curblend = BLEND_OVERLAY add = icon(I:icon, I:icon_state, I:dir) else // 'I' is an appearance object. + world.log << "***Recursing to render Icon [I:type] in state '[curstate]' in direction [curdir]" // #JMO add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) // Find the new dimensions of the flat icon to fit the added overlay diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index f0d39337b6f..c2399a3f045 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -157,36 +157,41 @@ //i.e. pretty much all wall-mounted machinery var/icon/res = icon('icons/effects/96x96.dmi', "") - var/icon/turficon = build_composite_icon(the_turf) - res.Blend(turficon, ICON_OVERLAY, 33, 33) + world.log << "***Calling build composite..." //#JMO + //var/icon/turficon = build_composite_icon(the_turf) + res.Blend(getFlatIcon(the_turf), blendMode2iconMode(the_turf.blend_mode),33,33) + world.log << "***Exiting build composite..." //#JMO + //res.Blend(turficon, ICON_OVERLAY, 33, 33) var/atoms[] = list() for(var/atom/A in the_turf) if(A.invisibility) continue atoms.Add(A) - //Sorting icons based on levels - var/gap = atoms.len - var/swapped = 1 - while (gap > 1 || swapped) - swapped = 0 - if(gap > 1) - gap = round(gap / 1.247330950103979) - if(gap < 1) - gap = 1 - for(var/i = 1; gap + i <= atoms.len; i++) - var/atom/l = atoms[i] //Fucking hate - var/atom/r = atoms[gap+i] //how lists work here - if(l.layer > r.layer) //no "atoms[i].layer" for me - atoms.Swap(i, gap + i) - swapped = 1 + //Sorting icons based on levels. + //JMO: I have no idea what they were doing here before, but the magic number alone + // was worth replacing it over. "gap = round(gap / 1.247330950103979)" really? + var/list/sorted = list() + var/j + for(var/i = 1 to atoms.len) + var/atom/c = atoms[i] + for(j = sorted.len, j > 0, --j) + var/atom/c2 = sorted[j] + if(c2.layer <= c.layer) + break + sorted.Insert(j+1, c) - for(var/i; i <= atoms.len; i++) - var/atom/A = atoms[i] + for(var/i; i <= sorted.len; i++) + var/atom/A = sorted[i] if(A) - var/icon/img = getFlatIcon(A, A.dir)//build_composite_icon(A) - if(istype(img, /icon)) - res.Blend(new/icon(img, "", A.dir), ICON_OVERLAY, 33 + A.pixel_x, 33 + A.pixel_y) + world.log << "**Calling getFlatIcon to render [A.type]" //#JMO + var/icon/img = getFlatIcon(A)//build_composite_icon(A) + if(istype(A, /mob/living) && A:lying) + world.log << "[A.type] is lying down. Making it look as such..." // #JMO; + img.BecomeLying() + + //if(istype(img, /icon)) + res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x, 33 + A.pixel_y) return res @@ -220,6 +225,7 @@ var/icon/temp = icon('icons/effects/96x96.dmi',"") var/icon/black = icon('icons/turf/space.dmi', "black") var/mobs = "" + world << "Proof that this thing is alive! 1.0" // #JMO for(var/i = 1; i <= 3; i++) for(var/j = 1; j <= 3; j++) var/turf/T = locate(x_c, y_c, z_c) From bdbc404d07867a5b83f598f60c2d5dc7cbabc5cb Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Mon, 28 Jul 2014 01:04:52 -0600 Subject: [PATCH 05/18] Added workaround for non-directional icons with dir!=2 Several items in the map are set with a dir other than 2 but the icon associated with the item doesn't have directions. As such they misrender. This resolves that specific issue, for the most part. Due to an odd behavior of Byond, when this circumstance occurs the icon proc produces a 32x32 image that is all alpha 0. At least that's what my testing suggests; it may be possible with large icons to encounter this as an issue and cause it to ignore an icon that should be reloaded from the default. However, this can't do any worse than the current software. --- code/__HELPERS/icons.dm | 31 ++++++++++++++++++++++++++- code/modules/paperwork/photography.dm | 15 +++++++------ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 65807c05757..b0bc3091e61 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -684,6 +684,10 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu if(!noIcon) world.log << "***Rendering Icon [A.type] in state '[curstate]' on layer [A.layer] in direction [curdir]" // #JMO copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) + if (isnull(copy)) // #JMO + world.log << "****Created a null!" // #JMO + else // #JMO + world.log << "****Created a thing of type [copy.type]" // #JMO copy.color = A.color copy.alpha = A.alpha copy.blend_mode = curblend @@ -744,6 +748,31 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu if(I == copy) // 'I' is an /image based on the object being flattened. curblend = BLEND_OVERLAY add = icon(I:icon, I:icon_state, I:dir) + // This checks for a silent failure mode of the icon routine. If the requested dir + // doesn't exist in this icon state it returns a 32x32 icon with 0 alpha. + if (I:dir != SOUTH && add.Width() == 32 && add.Height() == 32) + // Since checking every pixel for blank isn't trivial, we make some assumptions about + // the content of the image to determine if it actually is blank. On a rare occassions + // this will cause the software to return a non-directional icon for when a + // directionalized one would be more appropriate. This is rare enough that this + // will suffice in place of a map rework that properly normalizes directions. + var/blankpixel=1; + // Check the four corners... + blankpixel &= isnull(add.GetPixel(1,1)) + blankpixel &= isnull(add.GetPixel(32,1)) + blankpixel &= isnull(add.GetPixel(32,32)) + blankpixel &= isnull(add.GetPixel(32,1)) + // The thirds... + blankpixel &= isnull(add.GetPixel(11,11)) + blankpixel &= isnull(add.GetPixel(11,22)) + blankpixel &= isnull(add.GetPixel(22,22)) + blankpixel &= isnull(add.GetPixel(22,11)) + // and the center... + blankpixel &= isnull(add.GetPixel(16,16)) + // If we ALWAYS returned a null (which happens when GetPixel encounters something with alpha 0) + if (blankpixel) + // Pull the default direction. + add = icon(I:icon, I:icon_state) else // 'I' is an appearance object. world.log << "***Recursing to render Icon [I:type] in state '[curstate]' in direction [curdir]" // #JMO add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) @@ -819,4 +848,4 @@ proc/adjust_brightness(var/color, var/value) RGB[1] = Clamp(RGB[1]+value,0,255) RGB[2] = Clamp(RGB[2]+value,0,255) RGB[3] = Clamp(RGB[3]+value,0,255) - return rgb(RGB[1],RGB[2],RGB[3]) \ No newline at end of file + return rgb(RGB[1],RGB[2],RGB[3]) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index c2399a3f045..67e5eb76e82 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -152,7 +152,7 @@ ..() -/obj/item/device/camera/proc/get_icon(turf/the_turf as turf) +/obj/item/device/camera/proc/get_icon(turf/the_turf as turf,mob/user as mob) //#JMO Added mob/user for debug for debug //Bigger icon base to capture those icons that were shifted to the next tile //i.e. pretty much all wall-mounted machinery var/icon/res = icon('icons/effects/96x96.dmi', "") @@ -184,14 +184,16 @@ for(var/i; i <= sorted.len; i++) var/atom/A = sorted[i] if(A) - world.log << "**Calling getFlatIcon to render [A.type]" //#JMO + world.log << "**Calling getFlatIcon to render [A]" //#JMO var/icon/img = getFlatIcon(A)//build_composite_icon(A) + // Check if we're looking at a mob that's lying down if(istype(A, /mob/living) && A:lying) - world.log << "[A.type] is lying down. Making it look as such..." // #JMO; + world.log << "[A] is lying down. Making it look as such..." // #JMO; + // If they are, apply that effect to their picture. img.BecomeLying() - //if(istype(img, /icon)) - res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x, 33 + A.pixel_y) + if(istype(img, /icon)) + res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x, 33 + A.pixel_y) return res @@ -225,7 +227,6 @@ var/icon/temp = icon('icons/effects/96x96.dmi',"") var/icon/black = icon('icons/turf/space.dmi', "black") var/mobs = "" - world << "Proof that this thing is alive! 1.0" // #JMO for(var/i = 1; i <= 3; i++) for(var/j = 1; j <= 3; j++) var/turf/T = locate(x_c, y_c, z_c) @@ -234,7 +235,7 @@ if(user.client) //To make shooting through security cameras possible viewer = user.client.eye if(dummy in viewers(world.view, viewer)) - temp.Blend(get_icon(T), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1)) + temp.Blend(get_icon(T,user), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1)) else temp.Blend(black, ICON_OVERLAY, 32 * (j-1), 64 - 32 * (i-1)) mobs += get_mobs(T) From 8e4ac0a807e452301b3d7da00deaf2243bbadc92 Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Mon, 28 Jul 2014 01:46:07 -0600 Subject: [PATCH 06/18] Modified to check every pixel Checking only a few pixels had the tendancy to turn my charcter's head inside out when I was pointing directions other than south. Worse case is 1024 tests per object in the image. This test should be uncommon and the CPU usage is constrained by other factors. --- code/__HELPERS/icons.dm | 35 +++++++++------------------ code/modules/paperwork/photography.dm | 10 ++------ 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index b0bc3091e61..8c400df60c1 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -682,12 +682,7 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu var/image/copy // Add the atom's icon itself, without pixel_x/y offsets. if(!noIcon) - world.log << "***Rendering Icon [A.type] in state '[curstate]' on layer [A.layer] in direction [curdir]" // #JMO copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) - if (isnull(copy)) // #JMO - world.log << "****Created a null!" // #JMO - else // #JMO - world.log << "****Created a thing of type [copy.type]" // #JMO copy.color = A.color copy.alpha = A.alpha copy.blend_mode = curblend @@ -751,30 +746,22 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu // This checks for a silent failure mode of the icon routine. If the requested dir // doesn't exist in this icon state it returns a 32x32 icon with 0 alpha. if (I:dir != SOUTH && add.Width() == 32 && add.Height() == 32) - // Since checking every pixel for blank isn't trivial, we make some assumptions about - // the content of the image to determine if it actually is blank. On a rare occassions - // this will cause the software to return a non-directional icon for when a - // directionalized one would be more appropriate. This is rare enough that this - // will suffice in place of a map rework that properly normalizes directions. - var/blankpixel=1; - // Check the four corners... - blankpixel &= isnull(add.GetPixel(1,1)) - blankpixel &= isnull(add.GetPixel(32,1)) - blankpixel &= isnull(add.GetPixel(32,32)) - blankpixel &= isnull(add.GetPixel(32,1)) - // The thirds... - blankpixel &= isnull(add.GetPixel(11,11)) - blankpixel &= isnull(add.GetPixel(11,22)) - blankpixel &= isnull(add.GetPixel(22,22)) - blankpixel &= isnull(add.GetPixel(22,11)) - // and the center... - blankpixel &= isnull(add.GetPixel(16,16)) + // Check every pixel for blank (computationally expensive, but the process is limited + // by the amount of film on the station, only happens when we hit something that's + // turned, and bails at the very first pixel it sees. + var/blankpixel; + for(var/y;y<=32;y++) + for(var/x;x<32;x++) + blankpixel = isnull(add.GetPixel(x,y)) + if(!blankpixel) + break + if(!blankpixel) + break // If we ALWAYS returned a null (which happens when GetPixel encounters something with alpha 0) if (blankpixel) // Pull the default direction. add = icon(I:icon, I:icon_state) else // 'I' is an appearance object. - world.log << "***Recursing to render Icon [I:type] in state '[curstate]' in direction [curdir]" // #JMO add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) // Find the new dimensions of the flat icon to fit the added overlay diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 67e5eb76e82..948b023ac4d 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -152,16 +152,12 @@ ..() -/obj/item/device/camera/proc/get_icon(turf/the_turf as turf,mob/user as mob) //#JMO Added mob/user for debug for debug +/obj/item/device/camera/proc/get_icon(turf/the_turf as turf) //Bigger icon base to capture those icons that were shifted to the next tile //i.e. pretty much all wall-mounted machinery var/icon/res = icon('icons/effects/96x96.dmi', "") - world.log << "***Calling build composite..." //#JMO - //var/icon/turficon = build_composite_icon(the_turf) res.Blend(getFlatIcon(the_turf), blendMode2iconMode(the_turf.blend_mode),33,33) - world.log << "***Exiting build composite..." //#JMO - //res.Blend(turficon, ICON_OVERLAY, 33, 33) var/atoms[] = list() for(var/atom/A in the_turf) @@ -184,11 +180,9 @@ for(var/i; i <= sorted.len; i++) var/atom/A = sorted[i] if(A) - world.log << "**Calling getFlatIcon to render [A]" //#JMO var/icon/img = getFlatIcon(A)//build_composite_icon(A) // Check if we're looking at a mob that's lying down if(istype(A, /mob/living) && A:lying) - world.log << "[A] is lying down. Making it look as such..." // #JMO; // If they are, apply that effect to their picture. img.BecomeLying() @@ -235,7 +229,7 @@ if(user.client) //To make shooting through security cameras possible viewer = user.client.eye if(dummy in viewers(world.view, viewer)) - temp.Blend(get_icon(T,user), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1)) + temp.Blend(get_icon(T), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1)) else temp.Blend(black, ICON_OVERLAY, 32 * (j-1), 64 - 32 * (i-1)) mobs += get_mobs(T) From b935d7a0e09069799aa21501bb238c5b03392d04 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Mon, 28 Jul 2014 10:25:29 +0200 Subject: [PATCH 07/18] An Odysseus with patients now bypass mech movement-overrides. --- code/game/mecha/mech_sensor.dm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/game/mecha/mech_sensor.dm b/code/game/mecha/mech_sensor.dm index ac8bc9a30fa..d7e1937715f 100644 --- a/code/game/mecha/mech_sensor.dm +++ b/code/game/mecha/mech_sensor.dm @@ -25,6 +25,14 @@ return 1 /obj/machinery/mech_sensor/proc/is_blocked(O as obj) + if(istype(O, /obj/mecha/medical/odysseus)) + var/obj/mecha/medical/odysseus/M = O + for(var/obj/item/mecha_parts/mecha_equipment/ME in M.equipment) + if(istype(ME, /obj/item/mecha_parts/mecha_equipment/tool/sleeper)) + var/obj/item/mecha_parts/mecha_equipment/tool/sleeper/S = ME + if(S.occupant != null) + return 0 + return istype(O, /obj/mecha) || istype(O, /obj/vehicle) /obj/machinery/mech_sensor/proc/give_feedback(O as obj) From 5457cee52792fe4995010e1b349c6ce52f96c413 Mon Sep 17 00:00:00 2001 From: Loganbacca Date: Mon, 28 Jul 2014 20:39:42 +1200 Subject: [PATCH 08/18] More train fixes - No passing plastic flaps - Only human based mobs can board trains - Adjacent checks for exiting vehicles - Cleaned up as many direct loc moves as possible - Places removed cells in the removers hand --- code/game/supplyshuttle.dm | 17 ++++++++++------- code/modules/vehicles/cargo_train.dm | 13 +++++++++---- code/modules/vehicles/train.dm | 6 ++---- code/modules/vehicles/vehicle.dm | 16 ++++++++-------- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 0b042eeb7b2..b908d09b664 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -54,7 +54,10 @@ var/list/mechtoys = list( if (istype(A, /obj/structure/stool/bed) && B.buckled_mob)//if it's a bed/chair and someone is buckled, it will not pass return 0 - else if(istype(A, /mob/living)) // You Shall Not Pass! + if(istype(A, /obj/vehicle)) //no vehicles + return 0 + + if(istype(A, /mob/living)) // You Shall Not Pass! var/mob/living/M = A if(!M.lying && !istype(M, /mob/living/carbon/monkey) && !istype(M, /mob/living/carbon/slime) && !istype(M, /mob/living/simple_animal/mouse) && !istype(M, /mob/living/silicon/robot/drone)) //If your not laying down, or a small creature, no pass. return 0 @@ -455,7 +458,7 @@ var/list/mechtoys = list( if ("undocking") dat += "Undocking from station [shuttle.can_force()? "Force Launch" : ""]
" else dat += "Station
" - + if (shuttle.can_launch()) dat += "Send away" else if (shuttle.can_cancel()) @@ -472,14 +475,14 @@ var/list/mechtoys = list( else dat += "*Shuttle is busy*" dat += "
\n
" - - + + dat += {"
\nSupply points: [supply_controller.points]
\n
\nOrder items
\n
\nView requests
\n
\nView orders
\n
\nClose"} - + user << browse(dat, "window=computer;size=575x450") onclose(user, "computer") @@ -520,13 +523,13 @@ var/list/mechtoys = list( shuttle.launch(src) temp = "The supply shuttle has been called and will arrive in approximately [round(supply_controller.movetime/600,1)] minutes.

OK" post_signal("supply") - + if (href_list["force_send"]) shuttle.force_launch(src) if (href_list["cancel_send"]) shuttle.cancel_launch(src) - + else if (href_list["order"]) //if(!shuttle.idle()) return //this shouldn't be necessary it seems if(href_list["order"] == "categories") diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index b6f91feec79..11d0c53fb8e 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -43,6 +43,7 @@ ..() cell = new /obj/item/weapon/cell/high verbs -= /atom/movable/verb/pull + verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine key = new() var/image/I = new(icon = 'icons/obj/vehicles.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs overlays += I @@ -70,8 +71,8 @@ if(istype(W, /obj/item/weapon/key/cargo_train)) if(!key) user.drop_item() + W.forceMove(src) key = W - W.loc = src verbs += /obj/vehicle/train/cargo/engine/verb/remove_key return ..() @@ -97,7 +98,7 @@ var/obj/machinery/door/D = Obstacle var/mob/living/carbon/human/H = load if(istype(D) && istype(H)) - D.Bumped(H) //a little hacky, but hey, it works, and repects access rights + D.Bumped(H) //a little hacky, but hey, it works, and respects access rights ..() @@ -194,6 +195,8 @@ turn_on() if (on) usr << "You start [src]'s engine." + verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine + verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine else if(cell.charge < power_use) usr << "[src] is out of power." @@ -215,6 +218,8 @@ turn_off() if (!on) usr << "You stop [src]'s engine." + verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine + verbs += /obj/vehicle/train/cargo/engine/verb/start_engine /obj/vehicle/train/cargo/engine/verb/remove_key() set name = "Remove key" @@ -243,7 +248,7 @@ /obj/vehicle/train/cargo/trolley/load(var/atom/movable/C) if(ismob(C) && !passenger_allowed) return 0 - if(!istype(C,/obj/machinery) && !istype(C,/obj/structure/closet) && !istype(C,/obj/structure/largecrate) && !istype(C,/obj/structure/reagent_dispensers) && !istype(C,/obj/structure/ore_box) && !ismob(C)) + if(!istype(C,/obj/machinery) && !istype(C,/obj/structure/closet) && !istype(C,/obj/structure/largecrate) && !istype(C,/obj/structure/reagent_dispensers) && !istype(C,/obj/structure/ore_box) && !istype(C, /mob/living/carbon/human)) return 0 ..() @@ -255,7 +260,7 @@ return 1 /obj/vehicle/train/cargo/engine/load(var/atom/movable/C) - if(!ismob(C)) + if(!istype(C, /mob/living/carbon/human)) return 0 return ..() diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm index deaed1130c2..d29933b5ed8 100644 --- a/code/modules/vehicles/train.dm +++ b/code/modules/vehicles/train.dm @@ -68,8 +68,7 @@ if(user != load) if(user in src) //for handling players stuck in src - this shouldn't happen - but just in case it does - user.loc = T - contents -= user + user.forceMove(T) return 1 return 0 @@ -93,8 +92,7 @@ return 0 if(user != load && (user in src)) - user.loc = loc //for handling players stuck in src - contents -= user + user.forceMove(loc) //for handling players stuck in src else if(load) unload(user) //unload if loaded else if(!load && !user.buckled) diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index 5e5affac99a..caec0c896ab 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -50,7 +50,7 @@ anchored = init_anc if(load) - load.loc = loc + load.forceMove(loc)// = loc load.dir = dir return 1 @@ -196,7 +196,7 @@ new /obj/item/weapon/cable_coil/cut(Tsec) if(cell) - cell.loc = Tsec + cell.forceMove(Tsec) cell.update_icon() cell = null @@ -234,8 +234,8 @@ return H.drop_from_inventory(C) + C.forceMove(src) cell = C - C.loc = null //this wont be GC'd since it's referrenced above powercheck() usr << "You install [C] in [src]." @@ -244,7 +244,8 @@ return usr << "You remove [cell] from [src]." - cell.loc = get_turf(H) + cell.forceMove(get_turf(H)) + H.put_in_hands(cell) cell = null powercheck() @@ -271,7 +272,7 @@ if(istype(crate)) crate.close() - C.loc = loc + C.forceMove(loc) C.dir = dir C.anchored = 1 @@ -310,7 +311,7 @@ var/list/options = new() for(var/test_dir in alldirs) var/new_dir = get_step_to(src, get_step(src, test_dir)) - if(new_dir) + if(new_dir && load.Adjacent(new_dir)) options += new_dir if(options.len) dest = pick(options) @@ -320,8 +321,7 @@ if(!isturf(dest)) //if there still is nowhere to unload, cancel out since the vehicle is probably in nullspace return 0 - - load.loc = dest + load.forceMove(dest) load.dir = get_dir(loc, dest) load.anchored = initial(load.anchored) load.pixel_x = initial(load.pixel_x) From f8e50b28f5f56afcf908aaebe9e2438db4843b41 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Tue, 29 Jul 2014 00:20:38 +0930 Subject: [PATCH 09/18] Bevy of newhydro fixes. --- code/_onclick/click.dm | 12 ++- code/game/machinery/vending.dm | 12 ++- code/modules/hydroponics/hydro_tray.dm | 10 ++- code/modules/hydroponics/seed_datums.dm | 31 ++++---- code/modules/hydroponics/seed_machines.dm | 14 +++- code/modules/hydroponics/vines.dm | 4 +- .../projectiles/guns/energy/special.dm | 69 ++++++++++-------- icons/obj/hydroponics.dmi | Bin 163160 -> 163293 bytes 8 files changed, 98 insertions(+), 54 deletions(-) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index c3660d53bd2..a88dd793f12 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -298,7 +298,17 @@ // 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 && !buckled.movable) || !A || !x || !y || !A.x || !A.y ) return + + // Snowflake for space vines. + var/is_buckled = 0 + if(buckled) + if(istype(buckled)) + if(!buckled.movable) + is_buckled = 1 + else + is_buckled = 0 + + if( stat || is_buckled || !A || !x || !y || !A.x || !A.y ) return var/dx = A.x - x var/dy = A.y - y if(!dx && !dy) return diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 28efdb90874..61dfe3d915e 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -16,6 +16,7 @@ anchored = 1 density = 1 var/active = 1 //No sales pitches if off! + var/delay_product_spawn // If set, uses sleep() in product spawn proc (mostly for seeds to retrieve correct names). var/vend_ready = 1 //Are we ready to vend?? Is it time?? var/vend_delay = 10 //How long does it take to vend? var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now. @@ -111,7 +112,7 @@ var/atom/temp = new typepath(null) var/datum/data/vending_product/R = new /datum/data/vending_product() - R.product_name = temp.name + R.product_path = typepath R.amount = amount R.price = price @@ -123,6 +124,13 @@ coin_records += R else product_records += R + + if(delay_product_spawn) + sleep(1) + R.product_name = temp.name + else + R.product_name = temp.name + // world << "Added: [R.product_name]] - [R.amount] - [R.product_path]" return @@ -814,6 +822,8 @@ product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!" product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!" icon_state = "seeds" + delay_product_spawn = 1 + products = list(/obj/item/seeds/bananaseed = 3,/obj/item/seeds/berryseed = 3,/obj/item/seeds/carrotseed = 3,/obj/item/seeds/chantermycelium = 3,/obj/item/seeds/chiliseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/replicapod = 3,/obj/item/seeds/soyaseed = 3, /obj/item/seeds/sunflowerseed = 3,/obj/item/seeds/tomatoseed = 3,/obj/item/seeds/towermycelium = 3,/obj/item/seeds/wheatseed = 3,/obj/item/seeds/appleseed = 3, diff --git a/code/modules/hydroponics/hydro_tray.dm b/code/modules/hydroponics/hydro_tray.dm index 1ead014c2af..085fef94760 100644 --- a/code/modules/hydroponics/hydro_tray.dm +++ b/code/modules/hydroponics/hydro_tray.dm @@ -159,7 +159,7 @@ return // Advance plant age. - age += 1 * HYDRO_SPEED_MULTIPLIER + if(prob(25)) age += 1 * HYDRO_SPEED_MULTIPLIER // Maintain tray nutrient and water levels. if(seed.nutrient_consumption > 0 && nutrilevel > 0 && prob(25)) @@ -380,12 +380,14 @@ /obj/machinery/portable_atmospherics/hydroponics/proc/mutate(var/severity) + world << "Tray mutation proc called with [severity]." + // No seed, no mutations. if(!seed) return // Check if we should even bother working on the current seed datum. - if(seed.mutants.len && severity > 1 && prob(10+mutation_mod)) + if(seed.mutants. && seed.mutants.len && severity > 1 && prob(10+mutation_mod)) mutate_species() return @@ -573,7 +575,7 @@ reagent_value = mutagenic_reagents[R.id]+mutation_mod if(reagent_total >= reagent_value) if(prob(min(reagent_total*reagent_value,100))) - mutate(reagent_value > 10 ? 2 : 1) + mutate(reagent_total > 10 ? 2 : 1) S.reagents.clear_reagents() @@ -622,7 +624,7 @@ update_icon() else - user << "\red The [src] already has seeds in it!" + user << "\red \The [src] already has seeds in it!" else if (istype(O, /obj/item/weapon/reagent_containers/spray/plantbgone)) if(seed) diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index 0c87e6dcdd2..9f7947ccb2e 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -58,9 +58,9 @@ proc/populate_seed_list() //Tolerances. var/requires_nutrients = 1 // The plant can starve. - var/nutrient_consumption = 0.1 // Plant eats this much per tick. - var/requires_water = 1 // The plant can become dehydrated. - var/water_consumption = 1 // Plant drinks this much per tick. + var/nutrient_consumption = 0.25 // Plant eats this much per tick. + var/requires_water = 3 // The plant can become dehydrated. + var/water_consumption = 1 // Plant drinks this much per tick. var/ideal_heat = 293 // Preferred temperature in Kelvin. var/heat_tolerance = 20 // Departure from ideal that is survivable. var/ideal_light = 8 // Preferred light level in luminosity. @@ -104,9 +104,12 @@ proc/populate_seed_list() //Mutates the plant overall (randomly). /datum/seed/proc/mutate(var/degree,var/turf/source_turf) + + world << "Seed mutation proc called with [degree]." + if(!degree || immutable) return - source_turf.visible_message("[display_name] quivers uneasily!") + source_turf.visible_message("\blue \The [display_name] quivers!") //This looks like shit, but it's a lot easier to read/change this way. var/total_mutations = rand(1,1+degree) @@ -115,7 +118,7 @@ proc/populate_seed_list() if(0) //Plant cancer! lifespan = max(0,lifespan-rand(1,5)) endurance = max(0,endurance-rand(10,20)) - source_turf.visible_message("[display_name] withers rapidly!") + source_turf.visible_message("\red \The [display_name] withers rapidly!") if(1) nutrient_consumption = max(0, min(5, nutrient_consumption + rand(-(degree*0.1),(degree*0.1)))) water_consumption = max(0, min(50, water_consumption + rand(-degree,degree))) @@ -134,7 +137,7 @@ proc/populate_seed_list() if(prob(degree*5)) carnivorous = max(0, min(2, carnivorous + rand(-degree,degree))) if(carnivorous) - source_turf.visible_message("[display_name] shudders hungrily.") + source_turf.visible_message("\blue \The [display_name] shudders hungrily.") if(6) weed_tolerance = max(0, min(10, weed_tolerance + (rand(-2,2) * degree))) if(prob(degree*5)) parasite = !parasite @@ -148,7 +151,7 @@ proc/populate_seed_list() potency = max(0, min(200, potency + (rand(-20,20) * degree))) if(prob(degree*5)) spread = max(0, min(2, spread + rand(-1,1))) - source_turf.visible_message("[display_name] spasms visibly, shifting in the tray.") + source_turf.visible_message("\blue \The [display_name] spasms visibly, shifting in the tray.") if(9) maturation = max(0, min(30, maturation + (rand(-1,1) * degree))) if(prob(degree*5)) @@ -157,22 +160,22 @@ proc/populate_seed_list() if(prob(degree*2)) biolum = !biolum if(biolum) - source_turf.visible_message("[display_name] begins to glow!") + source_turf.visible_message("\blue \The [display_name] begins to glow!") if(prob(degree*2)) biolum_colour = "#[pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF"))]" - source_turf.visible_message("[display_name]'s glow changes colour!") + source_turf.visible_message("\blue \The [display_name]'s glow changes colour!") else - source_turf.visible_message("[display_name]'s glow dims...") + source_turf.visible_message("\blue \The [display_name]'s glow dims...") if(11) if(prob(degree*2)) flowers = !flowers if(flowers) - source_turf.visible_message("[display_name] sprouts a bevy of flowers!") + source_turf.visible_message("\blue \The [display_name] sprouts a bevy of flowers!") if(prob(degree*2)) flower_colour = "#[pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF"))]" - source_turf.visible_message("[display_name]'s flowers changes colour!") + source_turf.visible_message("\blue \The [display_name]'s flowers changes colour!") else - source_turf.visible_message("[display_name]'s flowers wither and fall off.") + source_turf.visible_message("\blue \The [display_name]'s flowers wither and fall off.") return //Mutates a specific trait/set of traits. @@ -368,7 +371,7 @@ proc/populate_seed_list() yield_mod = 0 total_yield = yield else - total_yield = max(1,rand(1,((yield_mod+yield)))) + total_yield = max(1,rand(yield_mod,yield_mod+yield)) currently_querying = list() for(var/i = 0;i \The [user] fires \the [src] into \the [tray]!") + Fire(target,user) return + ..() + /obj/item/weapon/gun/energy/meteorgun name = "meteor gun" desc = "For the love of god, make sure you're aiming this the right way!" @@ -224,7 +233,7 @@ obj/item/weapon/gun/energy/staff/focus /* -This is called from +This is called from modules/mob/mob_movement.dm if you move you will be zoomed out modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. */ diff --git a/icons/obj/hydroponics.dmi b/icons/obj/hydroponics.dmi index a0d31db14c8ec0343512864fa660e6a1778571c7..ba381b5bec4265b3378d34c4a971aa4910da394a 100644 GIT binary patch delta 39972 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 RKvjOgNdK~4xsF}<{{eNW0K5PI delta 39835 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 From 7f6b36e1dc9929e8c789012d9af747a95beed161 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Tue, 29 Jul 2014 00:25:46 +0930 Subject: [PATCH 10/18] Fixes some transposed values. --- code/modules/hydroponics/seed_datums.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index 9f7947ccb2e..f8d6e654e24 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -59,8 +59,8 @@ proc/populate_seed_list() //Tolerances. var/requires_nutrients = 1 // The plant can starve. var/nutrient_consumption = 0.25 // Plant eats this much per tick. - var/requires_water = 3 // The plant can become dehydrated. - var/water_consumption = 1 // Plant drinks this much per tick. + var/requires_water = 1 // The plant can become dehydrated. + var/water_consumption = 3 // Plant drinks this much per tick. var/ideal_heat = 293 // Preferred temperature in Kelvin. var/heat_tolerance = 20 // Departure from ideal that is survivable. var/ideal_light = 8 // Preferred light level in luminosity. @@ -1403,4 +1403,4 @@ proc/populate_seed_list() maturation = 1 production = 1 yield = 1 - potency = 1 \ No newline at end of file + potency = 1 From df3fcbc9b23039d6dd81bf32a209f109b16526fa Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Mon, 28 Jul 2014 11:54:01 -0600 Subject: [PATCH 11/18] Ported nearest-neighbor scaling from TG --- code/__HELPERS/icons.dm | 19 +++++++++++++++++++ code/modules/paperwork/photography.dm | 25 +++++++++---------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 8c400df60c1..e7a6bbba964 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -836,3 +836,22 @@ proc/adjust_brightness(var/color, var/value) RGB[2] = Clamp(RGB[2]+value,0,255) RGB[3] = Clamp(RGB[3]+value,0,255) return rgb(RGB[1],RGB[2],RGB[3]) + +proc/sort_atoms_by_layer(var/list/atoms) + // Comb sort icons based on levels + var/list/result = atoms.Copy() + var/gap = result.len + var/swapped = 1 + while (gap > 1 || swapped) + swapped = 0 + if(gap > 1) + gap = round(gap / 1.3) // 1.3 is the emperic comb sort coefficient + if(gap < 1) + gap = 1 + for(var/i = 1; gap + i <= result.len; i++) + var/atom/l = result[i] //Fucking hate + var/atom/r = result[gap+i] //how lists work here + if(l.layer > r.layer) //no "result[i].layer" for me + result.Swap(i, gap + i) + swapped = 1 + return result diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 948b023ac4d..da6edc63ea7 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -53,10 +53,10 @@ /obj/item/weapon/photo/proc/show(mob/user as mob) user << browse_rsc(img, "tmp_photo.png") user << browse("[name]" \ - + "" \ - + "
Written on the back:
[scribble]" : ]"\ - + "", "window=book;size=200x[scribble ? 400 : 200]") + + "" \ + + "" \ + + "[scribble ? "
Written on the back:
[scribble]" : ""]"\ + + "", "window=book;size=192x[scribble ? 400 : 192]") onclose(user, "[name]") return @@ -164,18 +164,8 @@ if(A.invisibility) continue atoms.Add(A) - //Sorting icons based on levels. - //JMO: I have no idea what they were doing here before, but the magic number alone - // was worth replacing it over. "gap = round(gap / 1.247330950103979)" really? - var/list/sorted = list() - var/j - for(var/i = 1 to atoms.len) - var/atom/c = atoms[i] - for(j = sorted.len, j > 0, --j) - var/atom/c2 = sorted[j] - if(c2.layer <= c.layer) - break - sorted.Insert(j+1, c) + // Sort the atoms into their layers + var/list/sorted = sort_atoms_by_layer(atoms) for(var/i; i <= sorted.len; i++) var/atom/A = sorted[i] @@ -220,6 +210,9 @@ var/icon/temp = icon('icons/effects/96x96.dmi',"") var/icon/black = icon('icons/turf/space.dmi', "black") + // Initialize the photograph to black. + temp.Blend("#000", ICON_OVERLAY) + var/mobs = "" for(var/i = 1; i <= 3; i++) for(var/j = 1; j <= 3; j++) From f0594b6e21dc5d9ec7905d819001f61723f0e0a8 Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Mon, 28 Jul 2014 12:10:21 -0600 Subject: [PATCH 12/18] Made camera render turf effects. --- code/modules/paperwork/photography.dm | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index da6edc63ea7..d563c9cc1e2 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -157,9 +157,10 @@ //i.e. pretty much all wall-mounted machinery var/icon/res = icon('icons/effects/96x96.dmi', "") - res.Blend(getFlatIcon(the_turf), blendMode2iconMode(the_turf.blend_mode),33,33) - var/atoms[] = list() + // Add outselves to the list of stuff to draw + atoms.Add(the_turf); + // As well as anything that isn't invisible. for(var/atom/A in the_turf) if(A.invisibility) continue atoms.Add(A) @@ -171,13 +172,18 @@ var/atom/A = sorted[i] if(A) var/icon/img = getFlatIcon(A)//build_composite_icon(A) - // Check if we're looking at a mob that's lying down - if(istype(A, /mob/living) && A:lying) - // If they are, apply that effect to their picture. - img.BecomeLying() + // If what we got back is actually a picture, draw it. if(istype(img, /icon)) + // Check if we're looking at a mob that's lying down + if(istype(A, /mob/living) && A:lying) + // If they are, apply that effect to their picture. + img.BecomeLying() res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x, 33 + A.pixel_y) + + + // Lastly, render any contained effects on top. + res.Blend(getFlatIcon(the_turf.loc), blendMode2iconMode(the_turf.blend_mode),33,33) return res From 6b1f696203415ec65eed8c7616aef7ff713d122c Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Mon, 28 Jul 2014 12:44:42 -0600 Subject: [PATCH 13/18] Ported multi-turf behavior This allows for layering that moves across tiles and enables alternate methods of enumerating the tile list (not used at present.) --- code/modules/paperwork/photography.dm | 47 +++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index d563c9cc1e2..dcc7c9f55e4 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -152,18 +152,22 @@ ..() -/obj/item/device/camera/proc/get_icon(turf/the_turf as turf) +/obj/item/device/camera/proc/get_icon(list/turfs, turf/center) + //Bigger icon base to capture those icons that were shifted to the next tile //i.e. pretty much all wall-mounted machinery var/icon/res = icon('icons/effects/96x96.dmi', "") + // Initialize the photograph to black. + res.Blend("#000", ICON_OVERLAY) var/atoms[] = list() - // Add outselves to the list of stuff to draw - atoms.Add(the_turf); - // As well as anything that isn't invisible. - for(var/atom/A in the_turf) - if(A.invisibility) continue - atoms.Add(A) + for(var/turf/the_turf in turfs) + // Add outselves to the list of stuff to draw + atoms.Add(the_turf); + // As well as anything that isn't invisible. + for(var/atom/A in the_turf) + if(A.invisibility) continue + atoms.Add(A) // Sort the atoms into their layers var/list/sorted = sort_atoms_by_layer(atoms) @@ -179,11 +183,17 @@ if(istype(A, /mob/living) && A:lying) // If they are, apply that effect to their picture. img.BecomeLying() - res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x, 33 + A.pixel_y) - + // Calculate where we are relative to the center of the photo + var/xoff = (A.x - center.x) * 32 + var/yoff = (A.y - center.y) * 32 + res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x + xoff, 33 + A.pixel_y + yoff) // Lastly, render any contained effects on top. - res.Blend(getFlatIcon(the_turf.loc), blendMode2iconMode(the_turf.blend_mode),33,33) + for(var/turf/the_turf in turfs) + // Calculate where we are relative to the center of the photo + var/xoff = (the_turf.x - center.x) * 32 + var/yoff = (the_turf.y - center.y) * 32 + res.Blend(getFlatIcon(the_turf.loc), blendMode2iconMode(the_turf.blend_mode),33 + xoff,33 + yoff) return res @@ -214,11 +224,8 @@ var/y_c = target.y + 1 var/z_c = target.z - var/icon/temp = icon('icons/effects/96x96.dmi',"") - var/icon/black = icon('icons/turf/space.dmi', "black") - // Initialize the photograph to black. - temp.Blend("#000", ICON_OVERLAY) + var/list/turfs = list() var/mobs = "" for(var/i = 1; i <= 3; i++) for(var/j = 1; j <= 3; j++) @@ -228,9 +235,7 @@ if(user.client) //To make shooting through security cameras possible viewer = user.client.eye if(dummy in viewers(world.view, viewer)) - temp.Blend(get_icon(T), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1)) - else - temp.Blend(black, ICON_OVERLAY, 32 * (j-1), 64 - 32 * (i-1)) + turfs.Add(T) mobs += get_mobs(T) dummy.loc = null dummy = null //Alas, nameless creature //garbage collect it instead @@ -238,12 +243,14 @@ y_c-- x_c = x_c - 3 + var/icon/photoimage = get_icon(turfs, target) + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() P.loc = user.loc if(!user.get_inactive_hand()) user.put_in_inactive_hand(P) - var/icon/small_img = icon(temp) - var/icon/tiny_img = icon(temp) + var/icon/small_img = icon(photoimage) + var/icon/tiny_img = icon(photoimage) var/icon/ic = icon('icons/obj/items.dmi',"photo") var/icon/pc = icon('icons/obj/bureaucracy.dmi', "photo") small_img.Scale(8, 8) @@ -252,7 +259,7 @@ pc.Blend(tiny_img,ICON_OVERLAY, 12, 19) P.icon = ic P.tiny = pc - P.img = temp + P.img = photoimage P.desc = mobs P.pixel_x = rand(-10, 10) P.pixel_y = rand(-10, 10) From f5df1acaaa3379ab09c585117f2b5f492fca1643 Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Mon, 28 Jul 2014 13:05:29 -0600 Subject: [PATCH 14/18] Added handler for pixel stepping --- code/modules/paperwork/photography.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index dcc7c9f55e4..cbc119eaf5a 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -186,6 +186,9 @@ // Calculate where we are relative to the center of the photo var/xoff = (A.x - center.x) * 32 var/yoff = (A.y - center.y) * 32 + if (istype(A,/atom/movable)) + xoff+=A:step_x + yoff+=A:step_y res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x + xoff, 33 + A.pixel_y + yoff) // Lastly, render any contained effects on top. From 26c5b9efcd199ddc842270bd950b4f6189a01a16 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Mon, 28 Jul 2014 23:53:34 +0200 Subject: [PATCH 15/18] Fixes #5824 by ensuring consistent ready button placement. --- maps/tgstation2.dmm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maps/tgstation2.dmm b/maps/tgstation2.dmm index 1d6710fffa9..a320e3401c3 100644 --- a/maps/tgstation2.dmm +++ b/maps/tgstation2.dmm @@ -6619,7 +6619,7 @@ "cxo" = (/turf/simulated/floor/beach/sand{tag = "icon-desert1"; icon_state = "desert1"},/area/holodeck/source_beach) "cxp" = (/turf/simulated/floor/beach/sand{tag = "icon-desert4"; icon_state = "desert4"},/area/holodeck/source_beach) "cxq" = (/turf/simulated/floor/beach/sand{tag = "icon-desert0"; icon_state = "desert0"},/area/holodeck/source_beach) -"cxr" = (/obj/structure/table/holotable,/obj/machinery/readybutton{pixel_y = -24},/turf/simulated/floor/holofloor{dir = 9; icon_state = "red"},/area/holodeck/source_thunderdomecourt) +"cxr" = (/obj/structure/table/holotable,/obj/machinery/readybutton{pixel_y = 0},/turf/simulated/floor/holofloor{dir = 9; icon_state = "red"},/area/holodeck/source_thunderdomecourt) "cxs" = (/obj/structure/table/holotable,/obj/item/clothing/head/helmet/thunderdome,/obj/item/clothing/suit/armor/tdome/red,/obj/item/clothing/under/color/red,/obj/item/weapon/holo/esword/red,/turf/simulated/floor/holofloor{dir = 1; icon_state = "red"},/area/holodeck/source_thunderdomecourt) "cxt" = (/obj/structure/table/holotable,/turf/simulated/floor/holofloor{dir = 5; icon_state = "red"},/area/holodeck/source_thunderdomecourt) "cxu" = (/obj/structure/table/holotable,/obj/item/clothing/gloves/boxing/hologlove,/turf/simulated/floor/holofloor{dir = 9; icon_state = "red"},/area/holodeck/source_boxingcourt) @@ -6710,7 +6710,7 @@ "czb" = (/turf/simulated/floor/holofloor{dir = 6; icon_state = "green"},/area/holodeck/source_basketball) "czc" = (/obj/structure/table/holotable,/turf/simulated/floor/holofloor{dir = 10; icon_state = "green"},/area/holodeck/source_thunderdomecourt) "czd" = (/obj/structure/table/holotable,/obj/item/clothing/head/helmet/thunderdome,/obj/item/clothing/suit/armor/tdome/green,/obj/item/clothing/under/color/green,/obj/item/weapon/holo/esword/green,/turf/simulated/floor/holofloor{dir = 2; icon_state = "green"},/area/holodeck/source_thunderdomecourt) -"cze" = (/obj/structure/table/holotable,/obj/machinery/readybutton{pixel_y = -24},/turf/simulated/floor/holofloor{dir = 6; icon_state = "green"},/area/holodeck/source_thunderdomecourt) +"cze" = (/obj/structure/table/holotable,/obj/machinery/readybutton{pixel_y = 0},/turf/simulated/floor/holofloor{dir = 6; icon_state = "green"},/area/holodeck/source_thunderdomecourt) "czf" = (/obj/structure/table/holotable,/obj/item/clothing/gloves/boxing/hologlove{icon_state = "boxinggreen"; item_state = "boxinggreen"},/turf/simulated/floor/holofloor{dir = 10; icon_state = "green"},/area/holodeck/source_boxingcourt) "czg" = (/turf/simulated/floor/holofloor{dir = 2; icon_state = "green"},/area/holodeck/source_boxingcourt) "czh" = (/obj/structure/table/holotable,/obj/item/clothing/gloves/boxing/hologlove{icon_state = "boxinggreen"; item_state = "boxinggreen"},/turf/simulated/floor/holofloor{dir = 6; icon_state = "green"},/area/holodeck/source_boxingcourt) From 9680cd85b740ff96286edc22dbc7be427e6b2617 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 28 Jul 2014 20:51:04 -0400 Subject: [PATCH 16/18] Fixes chest not being coloured by necrosis --- code/modules/mob/living/carbon/human/update_icons.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 1fa7e6349d8..5a06f2cfbea 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -251,7 +251,7 @@ proc/get_damage_icon_part(damage_state, body_part) icon_key = "[icon_key]0" else if(part.status & ORGAN_ROBOT) icon_key = "[icon_key]2" - else if(part.status & ORGAN_DEAD) //Do we even have necrosis in our current code? ~Z + else if(part.status & ORGAN_DEAD) icon_key = "[icon_key]3" else icon_key = "[icon_key]1" @@ -274,6 +274,10 @@ proc/get_damage_icon_part(damage_state, body_part) //No icon stored, so we need to start with a basic one. var/datum/organ/external/chest = get_organ("chest") base_icon = chest.get_icon(g) + + if(chest.status & ORGAN_DEAD) + base_icon.ColorTone(necrosis_color_mod) + base_icon.SetIntensity(0.7) for(var/datum/organ/external/part in organs) From 7b084ed3496fd8203a643a5b3476137d51a7a2f8 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Tue, 29 Jul 2014 12:38:21 +0930 Subject: [PATCH 17/18] Fixed diona pods being mutable, fixed a few other tweaks, added cuttings. --- code/datums/supplypacks.dm | 5 +++- code/modules/hydroponics/hydro_tools.dm | 6 ++++- code/modules/hydroponics/hydro_tray.dm | 32 +++++++++++++++++++---- code/modules/hydroponics/seed_datums.dm | 12 ++++++--- code/modules/hydroponics/seed_machines.dm | 10 ++++--- code/modules/hydroponics/seeds.dm | 8 ++++++ 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 74da3c321fd..1e267e524f3 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -266,7 +266,10 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/minihoe, /obj/item/device/analyzer/plant_analyzer, /obj/item/clothing/gloves/botanic_leather, - /obj/item/clothing/suit/apron) // Updated with new things + /obj/item/clothing/suit/apron, + /obj/item/weapon/minihoe, + /obj/item/weapon/storage/box/botanydisk + ) // Updated with new things cost = 15 containertype = /obj/structure/closet/crate/hydroponics containername = "Hydroponics crate" diff --git a/code/modules/hydroponics/hydro_tools.dm b/code/modules/hydroponics/hydro_tools.dm index 7d2836d1012..e7d0ce3865a 100644 --- a/code/modules/hydroponics/hydro_tools.dm +++ b/code/modules/hydroponics/hydro_tools.dm @@ -1,4 +1,8 @@ -//Analyzer, pestkillers, weedkillers, nutrients, hatchets. +//Analyzer, pestkillers, weedkillers, nutrients, hatchets, cutters. + +/obj/item/weapon/wirecutters/clippers + name = "plant clippers" + desc = "A tool used to take samples from plants." /obj/item/device/analyzer/plant_analyzer name = "plant analyzer" diff --git a/code/modules/hydroponics/hydro_tray.dm b/code/modules/hydroponics/hydro_tray.dm index 085fef94760..5359cd82154 100644 --- a/code/modules/hydroponics/hydro_tray.dm +++ b/code/modules/hydroponics/hydro_tray.dm @@ -30,6 +30,7 @@ var/lastcycle = 0 // Cycle timing/tracking var. var/cycledelay = 150 // Delay per cycle. var/closed_system // If set, the tray will attempt to take atmos from a pipe. + var/force_update // Seed details/line data. var/datum/seed/seed = null // The currently planted seed @@ -117,6 +118,10 @@ /obj/machinery/portable_atmospherics/hydroponics/bullet_act(var/obj/item/projectile/Proj) + //Don't act on seeds like dionaea that shouldn't change. + if(seed && seed.immutable) + return + //Override for somatoray projectiles. if(istype(Proj ,/obj/item/projectile/energy/floramut) && prob(20)) mutate(1) @@ -138,8 +143,11 @@ /obj/machinery/portable_atmospherics/hydroponics/process() // Update values every cycle rather than every process() tick. - if(world.time < (lastcycle + cycledelay)) + if(force_update) + force_update = 0 + else if(world.time < (lastcycle + cycledelay)) return + lastcycle = world.time // Weeds like water and nutrients, there's a chance the weed population will increase. @@ -380,8 +388,6 @@ /obj/machinery/portable_atmospherics/hydroponics/proc/mutate(var/severity) - world << "Tray mutation proc called with [severity]." - // No seed, no mutations. if(!seed) return @@ -439,7 +445,22 @@ /obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) - if (istype(O, /obj/item/weapon/reagent_containers/glass)) + if(istype(O, /obj/item/weapon/wirecutters) || istype(O, /obj/item/weapon/scalpel)) + + if(!seed) + user << "There is nothing to take a sample from in \the [src]." + return + + seed.harvest(user,yield_mod,1) + health -= (rand(1,5)*10) + check_level_sanity() + + force_update = 1 + process() + + return + + else 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) @@ -615,7 +636,8 @@ seed = S.seed //Grab the seed datum. dead = 0 age = 1 - health = seed.endurance + //Snowflakey, maybe move this to the seed datum + health = (istype(S, /obj/item/seeds/cutting) ? round(seed.endurance/rand(2,5)) : seed.endurance) lastcycle = world.time del(O) diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index f8d6e654e24..1a30949ca3a 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -105,8 +105,6 @@ proc/populate_seed_list() //Mutates the plant overall (randomly). /datum/seed/proc/mutate(var/degree,var/turf/source_turf) - world << "Seed mutation proc called with [degree]." - if(!degree || immutable) return source_turf.visible_message("\blue \The [display_name] quivers!") @@ -346,7 +344,7 @@ proc/populate_seed_list() return (P ? P : 0) //Place the plant products at the feet of the user. -/datum/seed/proc/harvest(var/mob/user,var/yield_mod) +/datum/seed/proc/harvest(var/mob/user,var/yield_mod,var/harvest_sample) if(!user) return @@ -358,7 +356,7 @@ proc/populate_seed_list() if(!got_product) user << "\red You fail to harvest anything useful." else - user << "You harvest from the [display_name]." + user << "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name]." //This may be a new line. Update the global if it is. if(name == "new line" || !(name in seed_types)) @@ -366,6 +364,12 @@ proc/populate_seed_list() name = "[uid]" seed_types[name] = src + if(harvest_sample) + var/obj/item/seeds/seeds = new(get_turf(user)) + seeds.seed_type = name + seeds.update_seed() + return + var/total_yield if(isnull(yield_mod) || yield_mod < 1) yield_mod = 0 diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm index 510f1f6f57a..e1cf0dfaccc 100644 --- a/code/modules/hydroponics/seed_machines.dm +++ b/code/modules/hydroponics/seed_machines.dm @@ -85,16 +85,18 @@ /obj/machinery/botany/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W,/obj/item/seeds)) if(seed) - if(seed.seed.immutable) - user << "That seed is not compatible with our genetics technology." - else - user << "There is already a seed loaded." + user << "There is already a seed loaded." + + var/obj/item/seeds/S =W + if(S.seed && S.seed.immutable) + user << "That seed is not compatible with our genetics technology." else user.drop_item(W) W.loc = src seed = W user << "You load [W] into [src]." return + if(istype(W,/obj/item/weapon/screwdriver)) open = !open user << "\blue You [open ? "open" : "close"] the maintenance panel." diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index dbc13158ec3..d0afda2e6fb 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -32,6 +32,14 @@ if(seed && !seed.roundstart) usr << "It's tagged as variety #[seed.uid]." +/obj/item/seeds/cutting + name = "cuttings" + desc = "Some plant cuttings." + +/obj/item/seeds/cutting/update_appearance() + ..() + src.name = "packet of [seed.seed_name] cuttings" + /obj/item/seeds/replicapod seed_type = "diona" From 89be9e5f43db5d1718604a14c7481dd059b7b2a8 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Tue, 29 Jul 2014 13:24:52 +0930 Subject: [PATCH 18/18] More adjustments. Implemented gas exuding/consumption (currently unused). Implemented cuttings, fixed some issues. --- code/modules/hydroponics/hydro_tools.dm | 4 +- code/modules/hydroponics/hydro_tray.dm | 61 ++++++++++++++++++++--- code/modules/hydroponics/seed_datums.dm | 24 ++++----- code/modules/hydroponics/seed_machines.dm | 2 +- 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/code/modules/hydroponics/hydro_tools.dm b/code/modules/hydroponics/hydro_tools.dm index e7d0ce3865a..f39fc0ea868 100644 --- a/code/modules/hydroponics/hydro_tools.dm +++ b/code/modules/hydroponics/hydro_tools.dm @@ -71,7 +71,9 @@ if(grown_seed.harvest_repeat) dat += "This plant can be harvested repeatedly.
" - if(grown_seed.immutable) + if(grown_seed.immutable == -1) + dat += "This plant is highly mutable.
" + else if(grown_seed.immutable > 0) dat += "This plant does not possess genetics that are alterable.
" if(grown_seed.products && grown_seed.products.len) diff --git a/code/modules/hydroponics/hydro_tray.dm b/code/modules/hydroponics/hydro_tray.dm index 5359cd82154..d391e33f524 100644 --- a/code/modules/hydroponics/hydro_tray.dm +++ b/code/modules/hydroponics/hydro_tray.dm @@ -119,7 +119,7 @@ /obj/machinery/portable_atmospherics/hydroponics/bullet_act(var/obj/item/projectile/Proj) //Don't act on seeds like dionaea that shouldn't change. - if(seed && seed.immutable) + if(seed && seed.immutable > 0) return //Override for somatoray projectiles. @@ -169,6 +169,11 @@ // Advance plant age. if(prob(25)) age += 1 * HYDRO_SPEED_MULTIPLIER + //Highly mutable plants have a chance of mutating every tick. + if(seed.immutable == -1) + var/mut_prob = rand(1,100) + if(mut_prob <= 5) mutate(mut_prob == 1 ? 2 : 1) + // Maintain tray nutrient and water levels. if(seed.nutrient_consumption > 0 && nutrilevel > 0 && prob(25)) nutrilevel -= max(0,seed.nutrient_consumption * HYDRO_SPEED_MULTIPLIER) @@ -196,10 +201,23 @@ // If atmos input is not there, grab from turf. if(!environment) if(istype(T)) - environment = T.return_air() - if(!environment) //We're in a crate or nullspace, bail out. + environment = T.air + if(!environment) return + // Handle gas consumption. + if(seed.consume_gasses && seed.consume_gasses.len) + var/missing_gas = 0 + for(var/gas in seed.consume_gasses) + if(environment && environment.gas && environment.gas[gas] && \ + environment.gas[gas] >= seed.consume_gasses[gas]) + environment.adjust_gas(gas,-seed.consume_gasses[gas],1) + else + missing_gas++ + + if(missing_gas > 0) + health -= missing_gas * HYDRO_SPEED_MULTIPLIER + // Process it. var/pressure = environment.return_pressure() if(pressure < seed.lowkpa_tolerance || pressure > seed.highkpa_tolerance) @@ -208,6 +226,13 @@ if(abs(environment.temperature - seed.ideal_heat) > seed.heat_tolerance) health -= healthmod + // Handle gas production. + if(seed.exude_gasses && seed.exude_gasses.len) + var/datum/gas_mixture/exuded = new + for(var/gas in seed.exude_gasses) + exuded.adjust_gas(gas,seed.exude_gasses[gas*seed.potency],1) //This will need adjustment since it produces moles. + loc.assume_air(exuded) + // Handle light requirements. var/area/A = T.loc if(A) @@ -257,13 +282,14 @@ pestlevel = 0 // If enough time (in cycles, not ticks) has passed since the plant was harvested, we're ready to harvest again. - else if(age > seed.production && (age - lastproduce) > seed.production && (!harvest && !dead)) + else if(seed.products && seed.products.len && age > seed.production && \ + (age - lastproduce) > seed.production && (!harvest && !dead)) + harvest = 1 lastproduce = age if(prob(5)) // On each tick, there's a 5 percent chance the pest population will increase pestlevel += 1 * HYDRO_SPEED_MULTIPLIER - check_level_sanity() update_icon() return @@ -757,7 +783,30 @@ usr << "[src] is \red filled with weeds!" if(pestlevel >= 5) usr << "[src] is \red filled with tiny worms!" - usr << text ("") + if(!istype(src,/obj/machinery/portable_atmospherics/hydroponics/soil)) + + var/turf/T = loc + var/datum/gas_mixture/environment + + if(closed_system && (connected_port || holding)) + environment = air_contents + + if(!environment) + if(istype(T)) + environment = T.return_air() + + if(!environment) //We're in a crate or nullspace, bail out. + return + + var/area/A = T.loc + var/light_available + if(A) + if(A.lighting_use_dynamic) + light_available = max(0,min(10,T.lighting_lumcount)-5) + else + light_available = 5 + + usr << "The tray's sensor suite is reporting a light level of [light_available] lumens and a temperature of [environment.temperature]K." /obj/machinery/portable_atmospherics/hydroponics/verb/close_lid() set name = "Toggle Tray Lid" diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index 1a30949ca3a..fa5af7c78c7 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -83,7 +83,7 @@ proc/populate_seed_list() var/spread = 0 // 0 limits plant to tray, 1 = creepers, 2 = vines. var/carnivorous = 0 // 0 = none, 1 = eat pests in tray, 2 = eat living things (when a vine). var/parasite = 0 // 0 = no, 1 = gain health from weed level. - var/immutable // If set, plant will never mutate. + var/immutable = 0 // If set, plant will never mutate. If -1, plant has a chance of mutating during process(). var/alter_temp // If set, the plant will periodically alter local temp by this amount. // Cosmetics. @@ -99,13 +99,13 @@ proc/populate_seed_list() //Returns a key corresponding to an entry in the global seed list. /datum/seed/proc/get_mutant_variant() - if(!mutants || !mutants.len || immutable) return 0 + if(!mutants || !mutants.len || immutable > 0) return 0 return pick(mutants) //Mutates the plant overall (randomly). /datum/seed/proc/mutate(var/degree,var/turf/source_turf) - if(!degree || immutable) return + if(!degree || immutable > 0) return source_turf.visible_message("\blue \The [display_name] quivers!") @@ -179,7 +179,7 @@ proc/populate_seed_list() //Mutates a specific trait/set of traits. /datum/seed/proc/apply_gene(var/datum/plantgene/gene) - if(!gene || !gene.values || immutable) return + if(!gene || !gene.values || immutable > 0) return switch(gene.genetype) @@ -209,11 +209,12 @@ proc/populate_seed_list() else chems[rid] = gene.values[2][rid] - //TODO. - //if(!exude_gasses) exude_gasses = list() - //exude_gasses |= gene.values[3] - //for(var/gas in exude_gasses) - // exude_gasses[gas] = max(1,round(exude_gasses[gas]/2)) + var/list/new_gasses = gene.values[3] + if(istype(new_gasses)) + if(!exude_gasses) exude_gasses = list() + exude_gasses |= new_gasses + for(var/gas in exude_gasses) + exude_gasses[gas] = max(1,round(exude_gasses[gas]*0.8)) alter_temp = gene.values[4] potency = gene.values[5] @@ -348,7 +349,6 @@ proc/populate_seed_list() if(!user) return - //TODO: check for failing to harvest. var/got_product if(!isnull(products) && products.len && yield > 0) got_product = 1 @@ -389,7 +389,6 @@ proc/populate_seed_list() handle_living_product(product) // Make sure the product is inheriting the correct seed type reference. - // TODO: can this be collapsed into one type check since they share vars? else if(istype(product,/obj/item/weapon/reagent_containers/food/snacks/grown)) var/obj/item/weapon/reagent_containers/food/snacks/grown/current_product = product current_product.plantname = name @@ -403,7 +402,7 @@ proc/populate_seed_list() // be put into the global datum list until the product is harvested, though. /datum/seed/proc/diverge(var/modified) - if(immutable) return + if(immutable > 0) return //Set up some basic information. var/datum/seed/new_seed = new @@ -1170,6 +1169,7 @@ proc/populate_seed_list() yield = -1 potency = -1 growth_stages = 4 + immutable = -1 /datum/seed/whitebeets name = "whitebeet" diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm index e1cf0dfaccc..837abe7211a 100644 --- a/code/modules/hydroponics/seed_machines.dm +++ b/code/modules/hydroponics/seed_machines.dm @@ -88,7 +88,7 @@ user << "There is already a seed loaded." var/obj/item/seeds/S =W - if(S.seed && S.seed.immutable) + if(S.seed && S.seed.immutable > 0) user << "That seed is not compatible with our genetics technology." else user.drop_item(W)