From 02aa2c126c0822f887d1e384dc46ba7602b00984 Mon Sep 17 00:00:00 2001 From: Drexian Date: Thu, 22 Mar 2018 03:39:16 +0300 Subject: [PATCH 1/6] Camera fix --- code/_helpers/icons.dm | 321 ++++++++++++++++++----------------------- 1 file changed, 142 insertions(+), 179 deletions(-) diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index da4385ef6ff..64460aa8895 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -634,211 +634,175 @@ 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. */ -// Creates a single icon from a given /atom or /image. Only the first argument is required. -/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE) - // 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 +proc // Creates a single icon from a given /atom or /image. Only the first argument is required. + getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD)) + // 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 + if(!A) + return flat + if(A.alpha <= 0) + return flat + var/noIcon = FALSE - if(start) - if(!defdir) - defdir = A.dir - if(!deficon) - deficon = A.icon - if(!defstate) - defstate = A.icon_state - if(!defblend) - defblend = A.blend_mode - - 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 = "" + var/curicon + if(A.icon) + curicon = A.icon else + curicon = deficon + + if(!curicon) noIcon = TRUE // Do not render this object. - var/curdir - var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have - - //These should use the parent's direction (most likely) - if(!A.dir || A.dir == SOUTH) - curdir = defdir - else - curdir = A.dir + var/curstate + if(A.icon_state) + curstate = A.icon_state + else + curstate = defstate - //Let's check if the icon actually contains any diagonals, just skip if it's south to save (lot of) time - if(curdir != SOUTH) - var/icon/test_icon - var/directionals_exist = FALSE - var/list/dirs_to_check = cardinal - SOUTH - outer: - for(var/possible_dir in dirs_to_check) - test_icon = icon(curicon,curstate,possible_dir,frame=1) - for(var/x in 1 to world.icon_size) - for(var/y in 1 to world.icon_size) - if(!isnull(test_icon.GetPixel(x,y))) - directionals_exist = TRUE - break outer - if(!directionals_exist) - base_icon_dir = SOUTH - if(!base_icon_dir) - base_icon_dir = curdir + if(!noIcon && !(curstate in icon_states(curicon))) + if("" in icon_states(curicon)) + curstate = "" + else + noIcon = TRUE // Do not render this object. - var/curblend - if(A.blend_mode == BLEND_DEFAULT) - curblend = defblend - else - curblend = A.blend_mode + var/curdir + if(A.dir != 2 && !always_use_defdir) + curdir = A.dir + else + curdir = defdir - // Before processing overlays, make sure any pending overlays are applied - if (isloc(A)) - var/atom/aAtom = A - if(aAtom.flags & OVERLAY_QUEUED) - COMPILE_OVERLAYS(aAtom) + 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() - 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=base_icon_dir) - copy.color = A.color - copy.alpha = A.alpha - copy.blend_mode = curblend - layers[copy] = A.layer + // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed + var/list/layers = list() + 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 + + // 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 + var/curIndex=1 // index of 'current' in list being processed + var/current // Current overlay being sorted + var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) + var/compare // The overlay 'add' is being compared against + var/cmpIndex // The index in the layers list of 'compare' + while(TRUE) + if(curIndex<=process.len) + current = process[curIndex] + if(current) + var/currentPlane = current:plane + if (currentPlane != FLOAT_PLANE && !(currentPlane in picture_planes)) + curIndex++ + continue; + currentLayer = current:layer + if(currentLayer<0) // Special case for FLY_LAYER + if(currentLayer <= -1000) return flat + if(pSet == 0) // Underlay + currentLayer = A.layer+currentLayer/1000 + else // Overlay + currentLayer = A.layer+(1000+currentLayer)/1000 + + // Sort add into layers list + for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++) + compare = layers[cmpIndex] + if(currentLayer < layers[compare]) // Associated value is the calculated layer + layers.Insert(cmpIndex,current) + layers[current] = currentLayer + break + if(cmpIndex>layers.len) // Reached end of list without inserting + layers[current]=currentLayer // Place at end - // 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 - var/curIndex=1 // index of 'current' in list being processed - var/current // Current overlay being sorted - var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) - var/compare // The overlay 'add' is being compared against - var/cmpIndex // The index in the layers list of 'compare' - while(TRUE) - if(curIndex<=process.len) - current = process[curIndex] - if(!current) - curIndex++ //Try the next layer - continue - var/image/I = current - if(I.plane != FLOAT_PLANE && I.plane != A.plane) curIndex++ - continue - currentLayer = I.layer - if(currentLayer<0) // Special case for FLOAT_LAYER - if(currentLayer <= -1000) - return flat - if(pSet == 0) // Underlay - currentLayer = A.layer+currentLayer/1000 - else // Overlay - currentLayer = A.layer+(1000+currentLayer)/1000 - - // Sort add into layers list - for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++) - compare = layers[cmpIndex] - if(currentLayer < layers[compare]) // Associated value is the calculated layer - layers.Insert(cmpIndex,current) - layers[current] = currentLayer - break - if(cmpIndex>layers.len) // Reached end of list without inserting - layers[current]=currentLayer // Place at end - - curIndex++ - - if(curIndex>process.len) - if(pSet == 0) // Switch to overlays + else if(pSet == 0) // Switch to overlays curIndex = 1 pSet = 1 process = A.overlays else // All done break - var/icon/add // Icon of overlay being added + var/icon/add // Icon of overlay being added - // Current dimensions of flattened icon - var/flatX1=1 - var/flatX2=flat.Width() - var/flatY1=1 - var/flatY2=flat.Height() - // Dimensions of overlay being added - var/addX1 - var/addX2 - var/addY1 - var/addY2 + // Current dimensions of flattened icon + var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()} + // Dimensions of overlay being added + var/{addX1;addX2;addY1;addY2} - for(var/V in layers) - var/image/I = V - if(I.alpha == 0) - continue + for(var/I in layers) - if(I == copy) // 'I' is an /image based on the object being flattened. - curblend = BLEND_OVERLAY - add = icon(I.icon, I.icon_state, base_icon_dir) - else // 'I' is an appearance object. - add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, FALSE, no_anim) + if(I:alpha == 0) + continue - // 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()) - addY1 = min(flatY1, I.pixel_y+1) - addY2 = max(flatY2, I.pixel_y+add.Height()) + 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) + // 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. + add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, picture_planes = picture_planes) - if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2) - // Resize the flattened icon so the new icon fits - flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) - flatX1=addX1;flatX2=addX2 - flatY1=addY1;flatY2=addY2 + // 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()) + addY1 = min(flatY1, I:pixel_y+1) + addY2 = max(flatY2, I:pixel_y+add.Height()) - // Blend the overlay into the flattened icon - flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1) + if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2) + // Resize the flattened icon so the new icon fits + flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) + flatX1=addX1;flatX2=addX2 + flatY1=addY1;flatY2=addY2 - if(A.color) - flat.Blend(A.color, ICON_MULTIPLY) - if(A.alpha < 255) - flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) + // Blend the overlay into the flattened icon + flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) + + if(A.color) + flat.Blend(A.color, ICON_MULTIPLY) + if(A.alpha < 255) + flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) - if(no_anim) - //Clean up repeated frames - var/icon/cleaned = new /icon() - cleaned.Insert(flat, "", SOUTH, 1, 0) - return cleaned - else return icon(flat, "", SOUTH) -/proc/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. - for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. - if(I:layer>A.layer) continue//If layer is greater than what we need, skip it. - var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. - //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. - alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. - return alpha_mask//And now return the mask. + 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. + for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. + if(I:layer>A.layer) continue//If layer is greater than what we need, skip it. + var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. + //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. + alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. + return alpha_mask//And now return the mask. //getFlatIcon but generates an icon that can face ALL four directions. The only four. /proc/getCompoundIcon(atom/A) - var/icon/north = getFlatIcon(A,defdir=NORTH) - var/icon/south = getFlatIcon(A,defdir=SOUTH) - var/icon/east = getFlatIcon(A,defdir=EAST) - var/icon/west = getFlatIcon(A,defdir=WEST) + var/icon/north = getFlatIcon(A,defdir=NORTH,always_use_defdir=1) + var/icon/south = getFlatIcon(A,defdir=SOUTH,always_use_defdir=1) + var/icon/east = getFlatIcon(A,defdir=EAST,always_use_defdir=1) + var/icon/west = getFlatIcon(A,defdir=WEST,always_use_defdir=1) //Starts with a blank icon because of byond bugs. var/icon/full = icon('icons/effects/effects.dmi', "icon_state"="nothing") @@ -854,7 +818,7 @@ The _flatIcons list is a cache for generated icon files. return full /proc/downloadImage(atom/A, dir) - var/icon/this_icon = getFlatIcon(A,defdir=dir) + var/icon/this_icon = getFlatIcon(A,defdir=dir||A.dir,always_use_defdir=1) usr << ftp(this_icon,"[A.name].png") @@ -922,8 +886,7 @@ proc/sort_atoms_by_layer(var/list/atoms) /proc/gen_hud_image(var/file, var/person, var/state, var/plane) var/image/img = image(file, person, state) img.plane = plane //Thanks Byond. - img.layer = MOB_LAYER-0.2 - img.appearance_flags = APPEARANCE_UI + img.appearance_flags = APPEARANCE_UI|KEEP_APART return img /** From f1c9193797378b5897e1fe2b8f331c82a2fd1b44 Mon Sep 17 00:00:00 2001 From: Drexian Date: Thu, 22 Mar 2018 03:42:09 +0300 Subject: [PATCH 2/6] adds statue --- code/modules/mob/living/carbon/human/human.dm | 1 + code/modules/mob/living/living.dm | 6 +- code/modules/mob/living/silicon/silicon.dm | 3 + .../mob/living/simple_animal/aliens/statue.dm | 315 ++++++++++++++++++ code/modules/paperwork/photography.dm | 23 +- polaris.dme | 2 + 6 files changed, 348 insertions(+), 2 deletions(-) create mode 100644 code/modules/mob/living/simple_animal/aliens/statue.dm diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b3748ee25c4..315d020dbec 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1562,3 +1562,4 @@ status_flags &= ~HIDING //No hiding for you. Mob layer should be updated naturally, but it actually isn't. else layer = HIDING_LAYER + diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9a7ba9fb0f9..99a86bc9c51 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1015,7 +1015,7 @@ default behaviour is: if(lying != lying_prev) lying_prev = lying update_transform() - + return canmove // Adds overlays for specific modifiers. @@ -1201,3 +1201,7 @@ default behaviour is: /mob/living/proc/make_hud_overlays() return + + +/mob/living/proc/has_vision() + return !(eye_blind || (disabilities & BLIND) || stat || blinded) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 0d88e0c96ff..a142206cf66 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -418,3 +418,6 @@ ghostize(0) qdel(src) + +/mob/living/silicon/has_vision() + return 0 //NOT REAL EYES diff --git a/code/modules/mob/living/simple_animal/aliens/statue.dm b/code/modules/mob/living/simple_animal/aliens/statue.dm new file mode 100644 index 00000000000..cdcb92e23ef --- /dev/null +++ b/code/modules/mob/living/simple_animal/aliens/statue.dm @@ -0,0 +1,315 @@ +// A mob which only moves when it isn't being watched by living beings. +//SCP - 173 hype +//Horrible shitcoding and stolen code adaptations below. You have been warned. + +/mob/living/simple_animal/hostile/statue + name = "statue" // matches the name of the statue with the flesh-to-stone spell + desc = "An incredibly lifelike marble carving. Its eyes seems to follow you..." // same as an ordinary statue with the added "eye following you" description + icon = 'icons/obj/statue.dmi' + icon_state = "human_male" + icon_living = "human_male" + icon_dead = "human_male" + intelligence_level = SA_HUMANOID + var/annoyance = 0 //stop fucking staring you creep + var/last_response = 0 + faction = "statue" + mob_size = MOB_HUGE + response_help = "touches" + response_disarm = "pushes" + environment_smash = 2 + can_be_antagged = 1 + speed = -1 + maxHealth = 50000 + health = 50000 +// investigates = 1 + + + harm_intent_damage = 35 + melee_damage_lower = 30 + melee_damage_upper = 45 + attacktext = "clawed" + attack_sound = 'sound/hallucinations/growl1.ogg' + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + maxbodytemp = 9000 + run_at_them = 0 + + + move_to_delay = 0 // Very fast + + animate_movement = NO_STEPS // Do not animate movement, you jump around as you're a scary statue. + + see_in_dark = 13 + view_range = 35 //So it can run at the victim when out of the view +// supernatural = 1 +/* aggro_vision_range = 12 + idle_vision_range = 12 +*/ + melee_miss_chance = 0 + + + see_invisible = SEE_INVISIBLE_NOLIGHTING + sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS + anchored = 1 + status_flags = GODMODE // Cannot push also + var/last_hit = 0 + var/cannot_be_seen = 1 + var/mob/living/creator = null + mob_swap_flags = null + +// No movement while seen code. + +/mob/living/simple_animal/hostile/statue/New(loc, var/mob/living/creator) + ..() + last_response = world.time + // Give spells + add_spell(new/spell/aoe_turf/flicker_lights) + add_spell(new/spell/aoe_turf/blindness) + add_spell(new/spell/aoe_turf/shatter) + + + // Set creator + if(creator) + src.creator = creator + +/mob/living/simple_animal/hostile/statue/DestroySurroundings() + if(can_be_seen(get_turf(loc))) + if(client) + to_chat(src, "You cannot move, there are eyes on you!") + return 0 + return ..() + +/mob/living/simple_animal/hostile/statue/Move(turf/NewLoc) + if(can_be_seen(NewLoc)) + if(client) + to_chat(src, "You cannot move, there are eyes on you!") + return 0 + return ..() + +/mob/living/simple_animal/hostile/statue/Life() + ..() + handleAnnoyance() + if ((annoyance - 2) > 0) + annoyance -= 2 + if(target_mob) + if((annoyance + 5) < 800) + annoyance += 5 + +/mob/living/simple_animal/hostile/statue/handle_stance() + if(!..()) + return + if(target_mob) // If we have a target and we're AI controlled + var/mob/watching = can_be_seen() + // If they're not our target + if(watching && watching != target_mob) + // This one is closer. + if(get_dist(watching, src) > get_dist(target_mob, src)) + LoseTarget() + target_mob = watching + + +/mob/living/simple_animal/hostile/statue/proc/handleAnnoyance() + if(last_response + 3 SECONDS < world.time) //so it won't blind people 24/7 + return + var/turf/T = get_turf(loc) + if (annoyance > 60) + AI_blind() + annoyance -= 25 + if (prob(50)) + if(T.get_lumcount() * 10 > 1.5) + AI_flash() + annoyance -= 35 + last_response = world.time + return + + +/mob/living/simple_animal/hostile/statue/proc/AI_blind() + for(var/mob/living/L in range(7, src)) + if(L == src) + continue + if (prob(75)) + if(istype(L , /mob/living/carbon/human)) + var/mob/living/carbon/human/H = L + if (H.species == "Diona" || H.species == "Promethean")// can't blink and organic + return + to_chat(L, "Your eyes feel very heavy.") + L.Blind(5) + return + +/mob/living/simple_animal/hostile/statue/proc/AI_flash() + if (prob(60)) + visible_message("The statue slowly points at the light.") + for(var/obj/machinery/light/L in range(10, src)) + L.flicker() + return + + +/mob/living/simple_animal/hostile/statue/proc/AI_mirrorshmash() + for(var/obj/structure/mirror/M in range(10, src)) + if ((!M.shattered )||(!M.glass)) + visible_message("The mirror shatters!") + M.shatter() + return + + + +/mob/living/simple_animal/hostile/statue/AttackTarget() + if(can_be_seen(get_turf(loc))) + if(client) + to_chat(src, "You cannot attack, there are eyes on you!") + return + else if(prob(80)) + spawn(4) + ..() + + + +/mob/living/simple_animal/hostile/statue/face_atom() + if(!can_be_seen(get_turf(loc))) + ..() + +/mob/living/simple_animal/hostile/statue/proc/can_be_seen(turf/destination) + if(!cannot_be_seen) + return null + // Check for darkness + var/turf/T = get_turf(loc) + if(T && destination && T.lighting_overlay) + if(T.get_lumcount() * 10 < 1 && destination.get_lumcount() * 10 < 1) // No one can see us in the darkness, right? + return null + if(T == destination) + destination = null + + // We aren't in darkness, loop for viewers. + var/list/check_list = list(src) + if(destination) + check_list += destination + + // This loop will, at most, loop twice. + for(var/atom/check in check_list) + for(var/mob/living/M in viewers(world.view + 1, check) - src) + if(!(M.sdisabilities & BLIND) || !(M.blinded)) + if(M.has_vision() && !M.isSynthetic()) + return M + for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you + if(M.occupant && M.occupant.client) + if(M.occupant.has_vision() && !M.occupant.isSynthetic()) + return M.occupant + for(var/obj/structure/mirror/M in view(7, check)) //Weeping angels hate mirrors. Probably because they're ugly af + if ((!M.shattered )||(!M.glass)) + annoyance += 2 + if ((annoyance > 200) && (ai_inactive == 0)) + AI_mirrorshmash() + annoyance -= 200 + return src //if it sees the mirror, it sees itself, right? + return null + +// Cannot talk + +/mob/living/simple_animal/hostile/statue/say() + return 0 + +// Turn to dust when gibbed + +/mob/living/simple_animal/hostile/statue/gib() + dust() + + +// Stop attacking clientless mobs + +/mob/living/simple_animal/hostile/statue/proc/CanAttack(atom/the_target) //ignore clientless mobs + if(isliving(the_target)) + var/mob/living/L = the_target + if(!L.client && !L.ckey) + return 0 + return ..() + +// Statue powers + +// Flicker lights +/spell/aoe_turf/flicker_lights + name = "Flicker Lights" + desc = "You will trigger a large amount of lights around you to flicker." + spell_flags = 0 + charge_max = 400 + range = 14 + +/spell/aoe_turf/flicker_lights/cast(list/targets, mob/user = usr) + for(var/turf/T in targets) + for(var/obj/machinery/light/L in T) + L.flicker() + return + +//Blind AOE +/spell/aoe_turf/blindness + name = "Blindness" + desc = "Your prey will be momentarily blind for you to advance on them." + + message = "You glare your eyes." + charge_max = 250 + spell_flags = 0 + range = 10 + +/spell/aoe_turf/blindness/cast(list/targets, mob/user = usr) + for(var/mob/living/L in living_mob_list) + if(L == user) + continue + var/turf/T = get_turf(L.loc) + if(T && T in targets) + L.Blind(7) + return + + +/spell/aoe_turf/shatter + name = "Shatter mirrors!" + desc = "That handsome devil has to wait. You have people to make into corpses." + + message = "You glare your eyes." + charge_max = 2000 + silenced = 500 + spell_flags = 0 + range = 10 + + + + +/spell/aoe_turf/shatter/cast(list/targets, mob/user = usr) + for(var/obj/structure/mirror/M in range(10, src)) + if ((!M.shattered )||(!M.glass)) + M.shatter() + return + + + +/mob/living/simple_animal/hostile/statue/verb/toggle_darkness() + set name = "Toggle Darkness" + set desc = "You ARE the darkness." + set category = "Abilities" + seedarkness = !seedarkness + plane_holder.set_vis(VIS_FULLBRIGHT, !seedarkness) + to_chat(src,"You [seedarkness ? "now" : "no longer"] see darkness.") + + + +/mob/living/simple_animal/hostile/statue/restrained() + . = ..() + if(can_be_seen(loc)) + return 1 + + + +/mob/living/simple_animal/hostile/statue/ListTargets() + . = ..() + + for(var/mob/living/V in mobs_in_xray_view(20, src)) + . += V + + + return . diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index c8b78cfd654..9b0ca19ed56 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -33,11 +33,14 @@ var/global/photo_count = 0 var/icon/img //Big photo image var/scribble //Scribble on the back. var/icon/tiny + var/cursed = 0 var/photo_size = 3 /obj/item/weapon/photo/New() id = photo_count++ + + /obj/item/weapon/photo/attack_self(mob/user as mob) user.examinate(src) @@ -233,6 +236,11 @@ var/global/photo_count = 0 mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " else mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." + + for(var/mob/living/simple_animal/hostile/statue/S in the_turf) + if(S) + mob_detail += "You can see a [S] on the photo. Its stare makes you feel uneasy." //"That which holds the image of an angel, becomes itself an angel." + return mob_detail /obj/item/device/camera/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag) @@ -274,7 +282,16 @@ var/global/photo_count = 0 y_c-- x_c = x_c - size + + + var/obj/item/weapon/photo/p = createpicture(target, user, turfs, mobs, flag) + if(findtext(mobs, "Its stare makes you feel uneasy")) + p.cursed = 1 + visible_message("Something starts to slowly manifest from the picture!") + spawn(150) + new /mob/living/simple_animal/hostile/statue(usr.loc) + printpicture(user, p) /obj/item/device/camera/proc/createpicture(atom/target, mob/user, list/turfs, mobs, flag) @@ -298,7 +315,6 @@ var/global/photo_count = 0 p.pixel_x = rand(-10, 10) p.pixel_y = rand(-10, 10) p.photo_size = size - return p /obj/item/device/camera/proc/printpicture(mob/user, obj/item/weapon/photo/p) @@ -318,6 +334,11 @@ var/global/photo_count = 0 p.pixel_y = pixel_y p.photo_size = photo_size p.scribble = scribble + p.cursed = cursed + if(p.cursed) + visible_message("Something starts to slowly manifest from the picture!") + spawn(150) + new /mob/living/simple_animal/hostile/statue(usr.loc) if(copy_id) p.id = id diff --git a/polaris.dme b/polaris.dme index 0bb899cea27..b3db30781b3 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1877,6 +1877,7 @@ #include "code\modules\mob\living\simple_animal\aliens\hivebot.dm" #include "code\modules\mob\living\simple_animal\aliens\mimic.dm" #include "code\modules\mob\living\simple_animal\aliens\shade.dm" +#include "code\modules\mob\living\simple_animal\aliens\statue.dm" #include "code\modules\mob\living\simple_animal\animals\bat.dm" #include "code\modules\mob\living\simple_animal\animals\bear.dm" #include "code\modules\mob\living\simple_animal\animals\carp.dm" @@ -2428,6 +2429,7 @@ #include "code\ZAS\Zone.dm" #include "interface\interface.dm" #include "interface\skin.dmf" +#include "maps\northern_star\northern_star.dm" #include "maps\southern_cross\southern_cross.dm" #include "maps\submaps\_readme.dm" #include "maps\submaps\space_submaps\space.dm" From a95eb8cebd7a17db8789154e7468bb1332df22e2 Mon Sep 17 00:00:00 2001 From: Drexian Date: Thu, 22 Mar 2018 03:42:09 +0300 Subject: [PATCH 3/6] adds statue --- code/modules/mob/living/carbon/human/human.dm | 1 + code/modules/mob/living/living.dm | 6 +- code/modules/mob/living/silicon/silicon.dm | 3 + .../mob/living/simple_animal/aliens/statue.dm | 315 ++++++++++++++++++ code/modules/paperwork/photography.dm | 23 +- polaris.dme | 2 + 6 files changed, 348 insertions(+), 2 deletions(-) create mode 100644 code/modules/mob/living/simple_animal/aliens/statue.dm diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b3748ee25c4..315d020dbec 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1562,3 +1562,4 @@ status_flags &= ~HIDING //No hiding for you. Mob layer should be updated naturally, but it actually isn't. else layer = HIDING_LAYER + diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9a7ba9fb0f9..99a86bc9c51 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1015,7 +1015,7 @@ default behaviour is: if(lying != lying_prev) lying_prev = lying update_transform() - + return canmove // Adds overlays for specific modifiers. @@ -1201,3 +1201,7 @@ default behaviour is: /mob/living/proc/make_hud_overlays() return + + +/mob/living/proc/has_vision() + return !(eye_blind || (disabilities & BLIND) || stat || blinded) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 0d88e0c96ff..a142206cf66 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -418,3 +418,6 @@ ghostize(0) qdel(src) + +/mob/living/silicon/has_vision() + return 0 //NOT REAL EYES diff --git a/code/modules/mob/living/simple_animal/aliens/statue.dm b/code/modules/mob/living/simple_animal/aliens/statue.dm new file mode 100644 index 00000000000..cdcb92e23ef --- /dev/null +++ b/code/modules/mob/living/simple_animal/aliens/statue.dm @@ -0,0 +1,315 @@ +// A mob which only moves when it isn't being watched by living beings. +//SCP - 173 hype +//Horrible shitcoding and stolen code adaptations below. You have been warned. + +/mob/living/simple_animal/hostile/statue + name = "statue" // matches the name of the statue with the flesh-to-stone spell + desc = "An incredibly lifelike marble carving. Its eyes seems to follow you..." // same as an ordinary statue with the added "eye following you" description + icon = 'icons/obj/statue.dmi' + icon_state = "human_male" + icon_living = "human_male" + icon_dead = "human_male" + intelligence_level = SA_HUMANOID + var/annoyance = 0 //stop fucking staring you creep + var/last_response = 0 + faction = "statue" + mob_size = MOB_HUGE + response_help = "touches" + response_disarm = "pushes" + environment_smash = 2 + can_be_antagged = 1 + speed = -1 + maxHealth = 50000 + health = 50000 +// investigates = 1 + + + harm_intent_damage = 35 + melee_damage_lower = 30 + melee_damage_upper = 45 + attacktext = "clawed" + attack_sound = 'sound/hallucinations/growl1.ogg' + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + maxbodytemp = 9000 + run_at_them = 0 + + + move_to_delay = 0 // Very fast + + animate_movement = NO_STEPS // Do not animate movement, you jump around as you're a scary statue. + + see_in_dark = 13 + view_range = 35 //So it can run at the victim when out of the view +// supernatural = 1 +/* aggro_vision_range = 12 + idle_vision_range = 12 +*/ + melee_miss_chance = 0 + + + see_invisible = SEE_INVISIBLE_NOLIGHTING + sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS + anchored = 1 + status_flags = GODMODE // Cannot push also + var/last_hit = 0 + var/cannot_be_seen = 1 + var/mob/living/creator = null + mob_swap_flags = null + +// No movement while seen code. + +/mob/living/simple_animal/hostile/statue/New(loc, var/mob/living/creator) + ..() + last_response = world.time + // Give spells + add_spell(new/spell/aoe_turf/flicker_lights) + add_spell(new/spell/aoe_turf/blindness) + add_spell(new/spell/aoe_turf/shatter) + + + // Set creator + if(creator) + src.creator = creator + +/mob/living/simple_animal/hostile/statue/DestroySurroundings() + if(can_be_seen(get_turf(loc))) + if(client) + to_chat(src, "You cannot move, there are eyes on you!") + return 0 + return ..() + +/mob/living/simple_animal/hostile/statue/Move(turf/NewLoc) + if(can_be_seen(NewLoc)) + if(client) + to_chat(src, "You cannot move, there are eyes on you!") + return 0 + return ..() + +/mob/living/simple_animal/hostile/statue/Life() + ..() + handleAnnoyance() + if ((annoyance - 2) > 0) + annoyance -= 2 + if(target_mob) + if((annoyance + 5) < 800) + annoyance += 5 + +/mob/living/simple_animal/hostile/statue/handle_stance() + if(!..()) + return + if(target_mob) // If we have a target and we're AI controlled + var/mob/watching = can_be_seen() + // If they're not our target + if(watching && watching != target_mob) + // This one is closer. + if(get_dist(watching, src) > get_dist(target_mob, src)) + LoseTarget() + target_mob = watching + + +/mob/living/simple_animal/hostile/statue/proc/handleAnnoyance() + if(last_response + 3 SECONDS < world.time) //so it won't blind people 24/7 + return + var/turf/T = get_turf(loc) + if (annoyance > 60) + AI_blind() + annoyance -= 25 + if (prob(50)) + if(T.get_lumcount() * 10 > 1.5) + AI_flash() + annoyance -= 35 + last_response = world.time + return + + +/mob/living/simple_animal/hostile/statue/proc/AI_blind() + for(var/mob/living/L in range(7, src)) + if(L == src) + continue + if (prob(75)) + if(istype(L , /mob/living/carbon/human)) + var/mob/living/carbon/human/H = L + if (H.species == "Diona" || H.species == "Promethean")// can't blink and organic + return + to_chat(L, "Your eyes feel very heavy.") + L.Blind(5) + return + +/mob/living/simple_animal/hostile/statue/proc/AI_flash() + if (prob(60)) + visible_message("The statue slowly points at the light.") + for(var/obj/machinery/light/L in range(10, src)) + L.flicker() + return + + +/mob/living/simple_animal/hostile/statue/proc/AI_mirrorshmash() + for(var/obj/structure/mirror/M in range(10, src)) + if ((!M.shattered )||(!M.glass)) + visible_message("The mirror shatters!") + M.shatter() + return + + + +/mob/living/simple_animal/hostile/statue/AttackTarget() + if(can_be_seen(get_turf(loc))) + if(client) + to_chat(src, "You cannot attack, there are eyes on you!") + return + else if(prob(80)) + spawn(4) + ..() + + + +/mob/living/simple_animal/hostile/statue/face_atom() + if(!can_be_seen(get_turf(loc))) + ..() + +/mob/living/simple_animal/hostile/statue/proc/can_be_seen(turf/destination) + if(!cannot_be_seen) + return null + // Check for darkness + var/turf/T = get_turf(loc) + if(T && destination && T.lighting_overlay) + if(T.get_lumcount() * 10 < 1 && destination.get_lumcount() * 10 < 1) // No one can see us in the darkness, right? + return null + if(T == destination) + destination = null + + // We aren't in darkness, loop for viewers. + var/list/check_list = list(src) + if(destination) + check_list += destination + + // This loop will, at most, loop twice. + for(var/atom/check in check_list) + for(var/mob/living/M in viewers(world.view + 1, check) - src) + if(!(M.sdisabilities & BLIND) || !(M.blinded)) + if(M.has_vision() && !M.isSynthetic()) + return M + for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you + if(M.occupant && M.occupant.client) + if(M.occupant.has_vision() && !M.occupant.isSynthetic()) + return M.occupant + for(var/obj/structure/mirror/M in view(7, check)) //Weeping angels hate mirrors. Probably because they're ugly af + if ((!M.shattered )||(!M.glass)) + annoyance += 2 + if ((annoyance > 200) && (ai_inactive == 0)) + AI_mirrorshmash() + annoyance -= 200 + return src //if it sees the mirror, it sees itself, right? + return null + +// Cannot talk + +/mob/living/simple_animal/hostile/statue/say() + return 0 + +// Turn to dust when gibbed + +/mob/living/simple_animal/hostile/statue/gib() + dust() + + +// Stop attacking clientless mobs + +/mob/living/simple_animal/hostile/statue/proc/CanAttack(atom/the_target) //ignore clientless mobs + if(isliving(the_target)) + var/mob/living/L = the_target + if(!L.client && !L.ckey) + return 0 + return ..() + +// Statue powers + +// Flicker lights +/spell/aoe_turf/flicker_lights + name = "Flicker Lights" + desc = "You will trigger a large amount of lights around you to flicker." + spell_flags = 0 + charge_max = 400 + range = 14 + +/spell/aoe_turf/flicker_lights/cast(list/targets, mob/user = usr) + for(var/turf/T in targets) + for(var/obj/machinery/light/L in T) + L.flicker() + return + +//Blind AOE +/spell/aoe_turf/blindness + name = "Blindness" + desc = "Your prey will be momentarily blind for you to advance on them." + + message = "You glare your eyes." + charge_max = 250 + spell_flags = 0 + range = 10 + +/spell/aoe_turf/blindness/cast(list/targets, mob/user = usr) + for(var/mob/living/L in living_mob_list) + if(L == user) + continue + var/turf/T = get_turf(L.loc) + if(T && T in targets) + L.Blind(7) + return + + +/spell/aoe_turf/shatter + name = "Shatter mirrors!" + desc = "That handsome devil has to wait. You have people to make into corpses." + + message = "You glare your eyes." + charge_max = 2000 + silenced = 500 + spell_flags = 0 + range = 10 + + + + +/spell/aoe_turf/shatter/cast(list/targets, mob/user = usr) + for(var/obj/structure/mirror/M in range(10, src)) + if ((!M.shattered )||(!M.glass)) + M.shatter() + return + + + +/mob/living/simple_animal/hostile/statue/verb/toggle_darkness() + set name = "Toggle Darkness" + set desc = "You ARE the darkness." + set category = "Abilities" + seedarkness = !seedarkness + plane_holder.set_vis(VIS_FULLBRIGHT, !seedarkness) + to_chat(src,"You [seedarkness ? "now" : "no longer"] see darkness.") + + + +/mob/living/simple_animal/hostile/statue/restrained() + . = ..() + if(can_be_seen(loc)) + return 1 + + + +/mob/living/simple_animal/hostile/statue/ListTargets() + . = ..() + + for(var/mob/living/V in mobs_in_xray_view(20, src)) + . += V + + + return . diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index c8b78cfd654..9b0ca19ed56 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -33,11 +33,14 @@ var/global/photo_count = 0 var/icon/img //Big photo image var/scribble //Scribble on the back. var/icon/tiny + var/cursed = 0 var/photo_size = 3 /obj/item/weapon/photo/New() id = photo_count++ + + /obj/item/weapon/photo/attack_self(mob/user as mob) user.examinate(src) @@ -233,6 +236,11 @@ var/global/photo_count = 0 mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " else mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." + + for(var/mob/living/simple_animal/hostile/statue/S in the_turf) + if(S) + mob_detail += "You can see a [S] on the photo. Its stare makes you feel uneasy." //"That which holds the image of an angel, becomes itself an angel." + return mob_detail /obj/item/device/camera/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag) @@ -274,7 +282,16 @@ var/global/photo_count = 0 y_c-- x_c = x_c - size + + + var/obj/item/weapon/photo/p = createpicture(target, user, turfs, mobs, flag) + if(findtext(mobs, "Its stare makes you feel uneasy")) + p.cursed = 1 + visible_message("Something starts to slowly manifest from the picture!") + spawn(150) + new /mob/living/simple_animal/hostile/statue(usr.loc) + printpicture(user, p) /obj/item/device/camera/proc/createpicture(atom/target, mob/user, list/turfs, mobs, flag) @@ -298,7 +315,6 @@ var/global/photo_count = 0 p.pixel_x = rand(-10, 10) p.pixel_y = rand(-10, 10) p.photo_size = size - return p /obj/item/device/camera/proc/printpicture(mob/user, obj/item/weapon/photo/p) @@ -318,6 +334,11 @@ var/global/photo_count = 0 p.pixel_y = pixel_y p.photo_size = photo_size p.scribble = scribble + p.cursed = cursed + if(p.cursed) + visible_message("Something starts to slowly manifest from the picture!") + spawn(150) + new /mob/living/simple_animal/hostile/statue(usr.loc) if(copy_id) p.id = id diff --git a/polaris.dme b/polaris.dme index 0bb899cea27..b3db30781b3 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1877,6 +1877,7 @@ #include "code\modules\mob\living\simple_animal\aliens\hivebot.dm" #include "code\modules\mob\living\simple_animal\aliens\mimic.dm" #include "code\modules\mob\living\simple_animal\aliens\shade.dm" +#include "code\modules\mob\living\simple_animal\aliens\statue.dm" #include "code\modules\mob\living\simple_animal\animals\bat.dm" #include "code\modules\mob\living\simple_animal\animals\bear.dm" #include "code\modules\mob\living\simple_animal\animals\carp.dm" @@ -2428,6 +2429,7 @@ #include "code\ZAS\Zone.dm" #include "interface\interface.dm" #include "interface\skin.dmf" +#include "maps\northern_star\northern_star.dm" #include "maps\southern_cross\southern_cross.dm" #include "maps\submaps\_readme.dm" #include "maps\submaps\space_submaps\space.dm" From 4ef959ebc12edb277d32f9607c2de55fdb6ff5b0 Mon Sep 17 00:00:00 2001 From: Drexian Date: Thu, 22 Mar 2018 03:53:29 +0300 Subject: [PATCH 4/6] Revert "adds statue" This reverts commit f1c9193797378b5897e1fe2b8f331c82a2fd1b44. --- code/modules/mob/living/carbon/human/human.dm | 1 - code/modules/mob/living/living.dm | 6 +- code/modules/mob/living/silicon/silicon.dm | 3 - .../mob/living/simple_animal/aliens/statue.dm | 315 ------------------ code/modules/paperwork/photography.dm | 23 +- polaris.dme | 2 - 6 files changed, 2 insertions(+), 348 deletions(-) delete mode 100644 code/modules/mob/living/simple_animal/aliens/statue.dm diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 315d020dbec..b3748ee25c4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1562,4 +1562,3 @@ status_flags &= ~HIDING //No hiding for you. Mob layer should be updated naturally, but it actually isn't. else layer = HIDING_LAYER - diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 99a86bc9c51..9a7ba9fb0f9 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1015,7 +1015,7 @@ default behaviour is: if(lying != lying_prev) lying_prev = lying update_transform() - + return canmove // Adds overlays for specific modifiers. @@ -1201,7 +1201,3 @@ default behaviour is: /mob/living/proc/make_hud_overlays() return - - -/mob/living/proc/has_vision() - return !(eye_blind || (disabilities & BLIND) || stat || blinded) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index a142206cf66..0d88e0c96ff 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -418,6 +418,3 @@ ghostize(0) qdel(src) - -/mob/living/silicon/has_vision() - return 0 //NOT REAL EYES diff --git a/code/modules/mob/living/simple_animal/aliens/statue.dm b/code/modules/mob/living/simple_animal/aliens/statue.dm deleted file mode 100644 index cdcb92e23ef..00000000000 --- a/code/modules/mob/living/simple_animal/aliens/statue.dm +++ /dev/null @@ -1,315 +0,0 @@ -// A mob which only moves when it isn't being watched by living beings. -//SCP - 173 hype -//Horrible shitcoding and stolen code adaptations below. You have been warned. - -/mob/living/simple_animal/hostile/statue - name = "statue" // matches the name of the statue with the flesh-to-stone spell - desc = "An incredibly lifelike marble carving. Its eyes seems to follow you..." // same as an ordinary statue with the added "eye following you" description - icon = 'icons/obj/statue.dmi' - icon_state = "human_male" - icon_living = "human_male" - icon_dead = "human_male" - intelligence_level = SA_HUMANOID - var/annoyance = 0 //stop fucking staring you creep - var/last_response = 0 - faction = "statue" - mob_size = MOB_HUGE - response_help = "touches" - response_disarm = "pushes" - environment_smash = 2 - can_be_antagged = 1 - speed = -1 - maxHealth = 50000 - health = 50000 -// investigates = 1 - - - harm_intent_damage = 35 - melee_damage_lower = 30 - melee_damage_upper = 45 - attacktext = "clawed" - attack_sound = 'sound/hallucinations/growl1.ogg' - - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - maxbodytemp = 9000 - run_at_them = 0 - - - move_to_delay = 0 // Very fast - - animate_movement = NO_STEPS // Do not animate movement, you jump around as you're a scary statue. - - see_in_dark = 13 - view_range = 35 //So it can run at the victim when out of the view -// supernatural = 1 -/* aggro_vision_range = 12 - idle_vision_range = 12 -*/ - melee_miss_chance = 0 - - - see_invisible = SEE_INVISIBLE_NOLIGHTING - sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS - anchored = 1 - status_flags = GODMODE // Cannot push also - var/last_hit = 0 - var/cannot_be_seen = 1 - var/mob/living/creator = null - mob_swap_flags = null - -// No movement while seen code. - -/mob/living/simple_animal/hostile/statue/New(loc, var/mob/living/creator) - ..() - last_response = world.time - // Give spells - add_spell(new/spell/aoe_turf/flicker_lights) - add_spell(new/spell/aoe_turf/blindness) - add_spell(new/spell/aoe_turf/shatter) - - - // Set creator - if(creator) - src.creator = creator - -/mob/living/simple_animal/hostile/statue/DestroySurroundings() - if(can_be_seen(get_turf(loc))) - if(client) - to_chat(src, "You cannot move, there are eyes on you!") - return 0 - return ..() - -/mob/living/simple_animal/hostile/statue/Move(turf/NewLoc) - if(can_be_seen(NewLoc)) - if(client) - to_chat(src, "You cannot move, there are eyes on you!") - return 0 - return ..() - -/mob/living/simple_animal/hostile/statue/Life() - ..() - handleAnnoyance() - if ((annoyance - 2) > 0) - annoyance -= 2 - if(target_mob) - if((annoyance + 5) < 800) - annoyance += 5 - -/mob/living/simple_animal/hostile/statue/handle_stance() - if(!..()) - return - if(target_mob) // If we have a target and we're AI controlled - var/mob/watching = can_be_seen() - // If they're not our target - if(watching && watching != target_mob) - // This one is closer. - if(get_dist(watching, src) > get_dist(target_mob, src)) - LoseTarget() - target_mob = watching - - -/mob/living/simple_animal/hostile/statue/proc/handleAnnoyance() - if(last_response + 3 SECONDS < world.time) //so it won't blind people 24/7 - return - var/turf/T = get_turf(loc) - if (annoyance > 60) - AI_blind() - annoyance -= 25 - if (prob(50)) - if(T.get_lumcount() * 10 > 1.5) - AI_flash() - annoyance -= 35 - last_response = world.time - return - - -/mob/living/simple_animal/hostile/statue/proc/AI_blind() - for(var/mob/living/L in range(7, src)) - if(L == src) - continue - if (prob(75)) - if(istype(L , /mob/living/carbon/human)) - var/mob/living/carbon/human/H = L - if (H.species == "Diona" || H.species == "Promethean")// can't blink and organic - return - to_chat(L, "Your eyes feel very heavy.") - L.Blind(5) - return - -/mob/living/simple_animal/hostile/statue/proc/AI_flash() - if (prob(60)) - visible_message("The statue slowly points at the light.") - for(var/obj/machinery/light/L in range(10, src)) - L.flicker() - return - - -/mob/living/simple_animal/hostile/statue/proc/AI_mirrorshmash() - for(var/obj/structure/mirror/M in range(10, src)) - if ((!M.shattered )||(!M.glass)) - visible_message("The mirror shatters!") - M.shatter() - return - - - -/mob/living/simple_animal/hostile/statue/AttackTarget() - if(can_be_seen(get_turf(loc))) - if(client) - to_chat(src, "You cannot attack, there are eyes on you!") - return - else if(prob(80)) - spawn(4) - ..() - - - -/mob/living/simple_animal/hostile/statue/face_atom() - if(!can_be_seen(get_turf(loc))) - ..() - -/mob/living/simple_animal/hostile/statue/proc/can_be_seen(turf/destination) - if(!cannot_be_seen) - return null - // Check for darkness - var/turf/T = get_turf(loc) - if(T && destination && T.lighting_overlay) - if(T.get_lumcount() * 10 < 1 && destination.get_lumcount() * 10 < 1) // No one can see us in the darkness, right? - return null - if(T == destination) - destination = null - - // We aren't in darkness, loop for viewers. - var/list/check_list = list(src) - if(destination) - check_list += destination - - // This loop will, at most, loop twice. - for(var/atom/check in check_list) - for(var/mob/living/M in viewers(world.view + 1, check) - src) - if(!(M.sdisabilities & BLIND) || !(M.blinded)) - if(M.has_vision() && !M.isSynthetic()) - return M - for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you - if(M.occupant && M.occupant.client) - if(M.occupant.has_vision() && !M.occupant.isSynthetic()) - return M.occupant - for(var/obj/structure/mirror/M in view(7, check)) //Weeping angels hate mirrors. Probably because they're ugly af - if ((!M.shattered )||(!M.glass)) - annoyance += 2 - if ((annoyance > 200) && (ai_inactive == 0)) - AI_mirrorshmash() - annoyance -= 200 - return src //if it sees the mirror, it sees itself, right? - return null - -// Cannot talk - -/mob/living/simple_animal/hostile/statue/say() - return 0 - -// Turn to dust when gibbed - -/mob/living/simple_animal/hostile/statue/gib() - dust() - - -// Stop attacking clientless mobs - -/mob/living/simple_animal/hostile/statue/proc/CanAttack(atom/the_target) //ignore clientless mobs - if(isliving(the_target)) - var/mob/living/L = the_target - if(!L.client && !L.ckey) - return 0 - return ..() - -// Statue powers - -// Flicker lights -/spell/aoe_turf/flicker_lights - name = "Flicker Lights" - desc = "You will trigger a large amount of lights around you to flicker." - spell_flags = 0 - charge_max = 400 - range = 14 - -/spell/aoe_turf/flicker_lights/cast(list/targets, mob/user = usr) - for(var/turf/T in targets) - for(var/obj/machinery/light/L in T) - L.flicker() - return - -//Blind AOE -/spell/aoe_turf/blindness - name = "Blindness" - desc = "Your prey will be momentarily blind for you to advance on them." - - message = "You glare your eyes." - charge_max = 250 - spell_flags = 0 - range = 10 - -/spell/aoe_turf/blindness/cast(list/targets, mob/user = usr) - for(var/mob/living/L in living_mob_list) - if(L == user) - continue - var/turf/T = get_turf(L.loc) - if(T && T in targets) - L.Blind(7) - return - - -/spell/aoe_turf/shatter - name = "Shatter mirrors!" - desc = "That handsome devil has to wait. You have people to make into corpses." - - message = "You glare your eyes." - charge_max = 2000 - silenced = 500 - spell_flags = 0 - range = 10 - - - - -/spell/aoe_turf/shatter/cast(list/targets, mob/user = usr) - for(var/obj/structure/mirror/M in range(10, src)) - if ((!M.shattered )||(!M.glass)) - M.shatter() - return - - - -/mob/living/simple_animal/hostile/statue/verb/toggle_darkness() - set name = "Toggle Darkness" - set desc = "You ARE the darkness." - set category = "Abilities" - seedarkness = !seedarkness - plane_holder.set_vis(VIS_FULLBRIGHT, !seedarkness) - to_chat(src,"You [seedarkness ? "now" : "no longer"] see darkness.") - - - -/mob/living/simple_animal/hostile/statue/restrained() - . = ..() - if(can_be_seen(loc)) - return 1 - - - -/mob/living/simple_animal/hostile/statue/ListTargets() - . = ..() - - for(var/mob/living/V in mobs_in_xray_view(20, src)) - . += V - - - return . diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 9b0ca19ed56..c8b78cfd654 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -33,14 +33,11 @@ var/global/photo_count = 0 var/icon/img //Big photo image var/scribble //Scribble on the back. var/icon/tiny - var/cursed = 0 var/photo_size = 3 /obj/item/weapon/photo/New() id = photo_count++ - - /obj/item/weapon/photo/attack_self(mob/user as mob) user.examinate(src) @@ -236,11 +233,6 @@ var/global/photo_count = 0 mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " else mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." - - for(var/mob/living/simple_animal/hostile/statue/S in the_turf) - if(S) - mob_detail += "You can see a [S] on the photo. Its stare makes you feel uneasy." //"That which holds the image of an angel, becomes itself an angel." - return mob_detail /obj/item/device/camera/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag) @@ -282,16 +274,7 @@ var/global/photo_count = 0 y_c-- x_c = x_c - size - - - var/obj/item/weapon/photo/p = createpicture(target, user, turfs, mobs, flag) - if(findtext(mobs, "Its stare makes you feel uneasy")) - p.cursed = 1 - visible_message("Something starts to slowly manifest from the picture!") - spawn(150) - new /mob/living/simple_animal/hostile/statue(usr.loc) - printpicture(user, p) /obj/item/device/camera/proc/createpicture(atom/target, mob/user, list/turfs, mobs, flag) @@ -315,6 +298,7 @@ var/global/photo_count = 0 p.pixel_x = rand(-10, 10) p.pixel_y = rand(-10, 10) p.photo_size = size + return p /obj/item/device/camera/proc/printpicture(mob/user, obj/item/weapon/photo/p) @@ -334,11 +318,6 @@ var/global/photo_count = 0 p.pixel_y = pixel_y p.photo_size = photo_size p.scribble = scribble - p.cursed = cursed - if(p.cursed) - visible_message("Something starts to slowly manifest from the picture!") - spawn(150) - new /mob/living/simple_animal/hostile/statue(usr.loc) if(copy_id) p.id = id diff --git a/polaris.dme b/polaris.dme index b3db30781b3..0bb899cea27 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1877,7 +1877,6 @@ #include "code\modules\mob\living\simple_animal\aliens\hivebot.dm" #include "code\modules\mob\living\simple_animal\aliens\mimic.dm" #include "code\modules\mob\living\simple_animal\aliens\shade.dm" -#include "code\modules\mob\living\simple_animal\aliens\statue.dm" #include "code\modules\mob\living\simple_animal\animals\bat.dm" #include "code\modules\mob\living\simple_animal\animals\bear.dm" #include "code\modules\mob\living\simple_animal\animals\carp.dm" @@ -2429,7 +2428,6 @@ #include "code\ZAS\Zone.dm" #include "interface\interface.dm" #include "interface\skin.dmf" -#include "maps\northern_star\northern_star.dm" #include "maps\southern_cross\southern_cross.dm" #include "maps\submaps\_readme.dm" #include "maps\submaps\space_submaps\space.dm" From c25fa6dea24a44114579fcefb76baea0d67ba830 Mon Sep 17 00:00:00 2001 From: Drexian Date: Fri, 23 Mar 2018 22:52:05 +0300 Subject: [PATCH 5/6] absolute pathing --- code/_helpers/icons.dm | 280 ++++++++++++++++++++--------------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index 64460aa8895..b3aa7112eba 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -634,168 +634,168 @@ 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 // Creates a single icon from a given /atom or /image. Only the first argument is required. - getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD)) - // 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 - if(!A) - return flat - if(A.alpha <= 0) - return flat - var/noIcon = FALSE + // Creates a single icon from a given /atom or /image. Only the first argument is required. +proc/getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD)) + // 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 + if(!A) + return flat + if(A.alpha <= 0) + return flat + var/noIcon = FALSE - var/curicon - if(A.icon) - curicon = A.icon + 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 - curicon = deficon - - if(!curicon) noIcon = TRUE // Do not render this object. - var/curstate - if(A.icon_state) - curstate = A.icon_state - else - curstate = defstate + var/curdir + if(A.dir != 2 && !always_use_defdir) + curdir = A.dir + else + curdir = defdir - if(!noIcon && !(curstate in icon_states(curicon))) - if("" in icon_states(curicon)) - curstate = "" - else - noIcon = TRUE // Do not render this object. + var/curblend + if(A.blend_mode == BLEND_DEFAULT) + curblend = defblend + else + curblend = A.blend_mode - var/curdir - if(A.dir != 2 && !always_use_defdir) - curdir = A.dir - else - curdir = defdir + // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed + var/list/layers = list() + 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 - var/curblend - if(A.blend_mode == BLEND_DEFAULT) - curblend = defblend - else - curblend = A.blend_mode + // 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 + var/curIndex=1 // index of 'current' in list being processed + var/current // Current overlay being sorted + var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) + var/compare // The overlay 'add' is being compared against + var/cmpIndex // The index in the layers list of 'compare' + while(TRUE) + if(curIndex<=process.len) + current = process[curIndex] + if(current) + var/currentPlane = current:plane + if (currentPlane != FLOAT_PLANE && !(currentPlane in picture_planes)) + curIndex++ + continue; + currentLayer = current:layer + if(currentLayer<0) // Special case for FLY_LAYER + if(currentLayer <= -1000) return flat + if(pSet == 0) // Underlay + currentLayer = A.layer+currentLayer/1000 + else // Overlay + currentLayer = A.layer+(1000+currentLayer)/1000 - // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed - var/list/layers = list() - 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 + // Sort add into layers list + for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++) + compare = layers[cmpIndex] + if(currentLayer < layers[compare]) // Associated value is the calculated layer + layers.Insert(cmpIndex,current) + layers[current] = currentLayer + break + if(cmpIndex>layers.len) // Reached end of list without inserting + layers[current]=currentLayer // Place at end - // 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 - var/curIndex=1 // index of 'current' in list being processed - var/current // Current overlay being sorted - var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) - var/compare // The overlay 'add' is being compared against - var/cmpIndex // The index in the layers list of 'compare' - while(TRUE) - if(curIndex<=process.len) - current = process[curIndex] - if(current) - var/currentPlane = current:plane - if (currentPlane != FLOAT_PLANE && !(currentPlane in picture_planes)) - curIndex++ - continue; - currentLayer = current:layer - if(currentLayer<0) // Special case for FLY_LAYER - if(currentLayer <= -1000) return flat - if(pSet == 0) // Underlay - currentLayer = A.layer+currentLayer/1000 - else // Overlay - currentLayer = A.layer+(1000+currentLayer)/1000 + curIndex++ + else if(pSet == 0) // Switch to overlays + curIndex = 1 + pSet = 1 + process = A.overlays + else // All done + break - // Sort add into layers list - for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++) - compare = layers[cmpIndex] - if(currentLayer < layers[compare]) // Associated value is the calculated layer - layers.Insert(cmpIndex,current) - layers[current] = currentLayer - break - if(cmpIndex>layers.len) // Reached end of list without inserting - layers[current]=currentLayer // Place at end + var/icon/add // Icon of overlay being added - curIndex++ - else if(pSet == 0) // Switch to overlays - curIndex = 1 - pSet = 1 - process = A.overlays - else // All done - break + // Current dimensions of flattened icon + var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()} + // Dimensions of overlay being added + var/{addX1;addX2;addY1;addY2} - var/icon/add // Icon of overlay being added + for(var/I in layers) - // Current dimensions of flattened icon - var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()} - // Dimensions of overlay being added - var/{addX1;addX2;addY1;addY2} + if(I:alpha == 0) + continue - for(var/I in layers) - - 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) - // 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) - // 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(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) + // 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 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. - add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, picture_planes = picture_planes) + 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. + add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, picture_planes = picture_planes) - // 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()) - addY1 = min(flatY1, I:pixel_y+1) - addY2 = max(flatY2, I:pixel_y+add.Height()) + // 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()) + addY1 = min(flatY1, I:pixel_y+1) + addY2 = max(flatY2, I:pixel_y+add.Height()) - if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2) - // Resize the flattened icon so the new icon fits - flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) - flatX1=addX1;flatX2=addX2 - flatY1=addY1;flatY2=addY2 + if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2) + // Resize the flattened icon so the new icon fits + flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) + flatX1=addX1;flatX2=addX2 + flatY1=addY1;flatY2=addY2 - // Blend the overlay into the flattened icon - flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) + // Blend the overlay into the flattened icon + flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) - if(A.color) - flat.Blend(A.color, ICON_MULTIPLY) - if(A.alpha < 255) - flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) + 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) + 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. - for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. - if(I:layer>A.layer) continue//If layer is greater than what we need, skip it. - var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. - //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. - alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. - return alpha_mask//And now return the mask. +proc/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. + for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. + if(I:layer>A.layer) continue//If layer is greater than what we need, skip it. + var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. + //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. + alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. + return alpha_mask//And now return the mask. //getFlatIcon but generates an icon that can face ALL four directions. The only four. /proc/getCompoundIcon(atom/A) From 617aa580d93cdfed5ffbed6ebaf900566906ab7e Mon Sep 17 00:00:00 2001 From: Drexian Date: Fri, 23 Mar 2018 22:54:13 +0300 Subject: [PATCH 6/6] added slashes. No idea for what, but I don't want anyone to ask me to do it because they have OCD --- code/_helpers/icons.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index b3aa7112eba..e537351e4ec 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -635,7 +635,7 @@ The _flatIcons list is a cache for generated icon files. */ // Creates a single icon from a given /atom or /image. Only the first argument is required. -proc/getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD)) +/proc/getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD)) // 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 if(!A) @@ -788,7 +788,7 @@ proc/getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DE return icon(flat, "", SOUTH) -proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N +/proc/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. for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. if(I:layer>A.layer) continue//If layer is greater than what we need, skip it.