Merge remote-tracking branch 'origin/master'

This commit is contained in:
Flint
2020-01-19 19:46:35 -06:00
359 changed files with 4948 additions and 3166 deletions
+190 -79
View File
@@ -35,101 +35,212 @@
else
painting = null
//////////////
// CANVASES //
//////////////
#define AMT_OF_CANVASES 4 //Keep this up to date or shit will break.
//To safe memory on making /icons we cache the blanks..
GLOBAL_LIST_INIT(globalBlankCanvases, new(AMT_OF_CANVASES))
/obj/item/canvas
name = "canvas"
desc = "Draw out your soul on this canvas!"
icon = 'icons/obj/artstuff.dmi'
icon_state = "11x11"
icon_state = "square"
resistance_flags = FLAMMABLE
var/whichGlobalBackup = 1 //List index
var/width = 11
var/height = 11
var/list/grid
var/list/top_colors
var/canvas_color = "#ffffff" //empty canvas color
var/ui_x = 400
var/ui_y = 400
var/painting_name //Painting name, this is set after framing.
var/framed = FALSE //Blocks edits, set on framing
/obj/item/canvas/nineteenXnineteen
icon_state = "19x19"
whichGlobalBackup = 2
/obj/item/canvas/twentythreeXnineteen
icon_state = "23x19"
whichGlobalBackup = 3
/obj/item/canvas/twentythreeXtwentythree
icon_state = "23x23"
whichGlobalBackup = 4
//HEY YOU
//ARE YOU READING THE CODE FOR CANVASES?
//ARE YOU AWARE THEY CRASH HALF THE SERVER WHEN SOMEONE DRAWS ON THEM...
//...AND NOBODY CAN FIGURE OUT WHY?
//THEN GO ON BRAVE TRAVELER
//TRY TO FIX THEM AND REMOVE THIS CODE
/obj/item/canvas/Initialize()
..()
return INITIALIZE_HINT_QDEL //Delete on creation
. = ..()
top_colors = list()
reset_grid()
//Find the right size blank canvas
/obj/item/canvas/proc/getGlobalBackup()
. = null
if(GLOB.globalBlankCanvases[whichGlobalBackup])
. = GLOB.globalBlankCanvases[whichGlobalBackup]
else
var/icon/I = icon(initial(icon),initial(icon_state))
GLOB.globalBlankCanvases[whichGlobalBackup] = I
. = I
/obj/item/canvas/proc/reset_grid()
grid = new/list(width,height)
for(var/x in 1 to width)
for(var/y in 1 to height)
grid[x][y] = canvas_color
/obj/item/canvas/attack_self(mob/user)
. = ..()
ui_interact(user)
/obj/item/canvas/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
//One pixel increments
/obj/item/canvas/attackby(obj/item/I, mob/user, params)
//Click info
var/list/click_params = params2list(params)
var/pixX = text2num(click_params["icon-x"])
var/pixY = text2num(click_params["icon-y"])
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "canvas", name, ui_x, ui_y, master_ui, state)
ui.set_autoupdate(FALSE)
ui.open()
//Should always be true, otherwise you didn't click the object, but let's check because SS13~
if(!click_params || !click_params["icon-x"] || !click_params["icon-y"])
return
//Cleaning one pixel with a soap or rag
if(istype(I, /obj/item/soap) || istype(I, /obj/item/reagent_containers/glass/rag))
//Pixel info created only when needed
var/icon/masterpiece = icon(icon,icon_state)
var/thePix = masterpiece.GetPixel(pixX,pixY)
var/icon/Ico = getGlobalBackup()
if(!Ico)
qdel(masterpiece)
return
var/theOriginalPix = Ico.GetPixel(pixX,pixY)
if(thePix != theOriginalPix) //colour changed
DrawPixelOn(theOriginalPix,pixX,pixY)
qdel(masterpiece)
//Drawing one pixel with a crayon
else if(istype(I, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = I
DrawPixelOn(C.paint_color, pixX, pixY)
/obj/item/canvas/attackby(obj/item/I, mob/living/user, params)
if(user.a_intent == INTENT_HELP)
ui_interact(user)
else
return ..()
/obj/item/canvas/ui_data(mob/user)
. = ..()
.["grid"] = grid
.["name"] = painting_name
//Clean the whole canvas
/obj/item/canvas/attack_self(mob/user)
if(!user)
/obj/item/canvas/examine(mob/user)
. = ..()
ui_interact(user)
/obj/item/canvas/ui_act(action, params)
. = ..()
if(. || framed)
return
var/icon/blank = getGlobalBackup()
if(blank)
//it's basically a giant etch-a-sketch
icon = blank
user.visible_message("<span class='notice'>[user] cleans the canvas.</span>","<span class='notice'>You clean the canvas.</span>")
var/mob/user = usr
switch(action)
if("paint")
var/obj/item/I = user.get_active_held_item()
var/color = get_paint_tool_color(I)
if(!color)
return FALSE
var/x = text2num(params["x"])
var/y = text2num(params["y"])
grid[x][y] = color
top_colors = get_most_common_colors(3)
update_icon()
. = TRUE
/obj/item/canvas/update_overlays()
. = ..()
for(var/i in 2 to top_colors.len) //first is used as base color
var/mutable_appearance/detail = mutable_appearance(icon, "[icon_state]_detail_[i-1]")
detail.appearance_flags |= RESET_COLOR
detail.color = top_colors[i]
. += detail
/obj/item/canvas/update_icon_state()
. = ..()
if(top_colors.len)
color = top_colors[1]
/obj/item/canvas/proc/get_most_common_colors(count)
var/list/tally = list()
for(var/x in 1 to width)
for(var/y in 1 to height)
tally[grid[x][y]] += 1
sortTim(tally,/proc/cmp_numeric_dsc,associative=TRUE)
. = list()
for(var/result in tally)
. += result
if(length(.) >= count)
break
//Todo make this element ?
/obj/item/canvas/proc/get_paint_tool_color(obj/item/I)
if(!I)
return
if(istype(I, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = I
return C.paint_color
else if(istype(I, /obj/item/pen))
var/obj/item/pen/P = I
switch(P.colour)
if("black")
return "#000000"
if("blue")
return "#0000ff"
if("red")
return "#ff0000"
return P.colour
else if(istype(I, /obj/item/soap) || istype(I, /obj/item/reagent_containers/glass/rag))
return canvas_color
/obj/item/canvas/nineteenXnineteen
icon_state = "square"
width = 19
height = 19
ui_x = 600
ui_y = 600
/obj/item/canvas/twentythreeXnineteen
icon_state = "wide"
width = 23
height = 19
ui_x = 800
ui_y = 600
/obj/item/canvas/twentythreeXtwentythree
icon_state = "square"
width = 23
height = 23
ui_x = 800
ui_y = 800
#undef AMT_OF_CANVASES
/obj/item/wallframe/painting
name = "painting frame"
desc = "The perfect showcase for your favorite deathtrap memories."
icon = 'icons/obj/decals.dmi'
custom_materials = null
flags_1 = 0
icon_state = "frame-empty"
result_path = /obj/structure/sign/painting
/obj/structure/sign/painting
name = "Painting"
desc = "Art or \"Art\"? You decide."
icon = 'icons/obj/decals.dmi'
icon_state = "frame-empty"
buildable_sign = FALSE
var/obj/item/canvas/C
/obj/structure/sign/painting/Initialize(mapload, dir, building)
. = ..()
AddComponent(/datum/component/art, 20)
if(dir)
setDir(dir)
if(building)
pixel_x = (dir & 3)? 0 : (dir == 4 ? -30 : 30)
pixel_y = (dir & 3)? (dir ==1 ? -30 : 30) : 0
/obj/structure/sign/painting/attackby(obj/item/I, mob/user, params)
if(!C && istype(I, /obj/item/canvas))
frame_canvas(user,I)
else if(C && !C.painting_name && istype(I,/obj/item/pen))
try_rename(user)
else
return ..()
/obj/structure/sign/painting/examine(mob/user)
. = ..()
if(C)
C.ui_interact(user,state = GLOB.physical_obscured_state)
/obj/structure/sign/painting/wirecutter_act(mob/living/user, obj/item/I)
. = ..()
if(C)
C.framed = FALSE
C.forceMove(drop_location())
C = null
to_chat(user, "<span class='notice'>You remove the painting from the frame.</span>")
update_icon()
return TRUE
/obj/structure/sign/painting/proc/frame_canvas(mob/user,obj/item/canvas/new_canvas)
if(user.transferItemToLoc(new_canvas,src))
C = new_canvas
C.framed = TRUE
to_chat(user,"<span class='notice'>You frame [C].</span>")
update_icon()
/obj/structure/sign/painting/proc/try_rename(mob/user)
var/new_name = stripped_input(user,"What do you want to name the painting?")
if(C && !C.painting_name && new_name && user.canUseTopic(src,BE_CLOSE))
C.painting_name = new_name
SStgui.update_uis(C)
/obj/structure/sign/painting/update_overlays()
. = ..()
if(C && C.top_colors.len)
var/mutable_appearance/MA = mutable_appearance(icon, "frame-content-overlay")
MA.appearance_flags |= RESET_COLOR
MA.color = C.top_colors[1]
. += MA
+11 -4
View File
@@ -7,6 +7,7 @@
var/state = GIRDER_NORMAL
var/girderpasschance = 20 // percentage chance that a projectile passes through the girder.
var/can_displace = TRUE //If the girder can be moved around by wrenching it
var/next_beep = 0 //Prevents spamming of the construction sound
max_integrity = 200
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_VERY_LIGHT_INSULATION
@@ -27,6 +28,12 @@
. += "<span class='notice'>[src] is disassembled! You probably shouldn't be able to see this examine message.</span>"
/obj/structure/girder/attackby(obj/item/W, mob/user, params)
var/platingmodifier = 1
if(HAS_TRAIT(user, TRAIT_QUICK_BUILD))
platingmodifier = 0.7
if(next_beep <= world.time)
next_beep = world.time + 10
playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
add_fingerprint(user)
if(istype(W, /obj/item/gun/energy/plasmacutter))
@@ -89,7 +96,7 @@
to_chat(user, "<span class='warning'>You need two sheets of metal to create a false wall!</span>")
return
to_chat(user, "<span class='notice'>You start building a false wall...</span>")
if(do_after(user, 20, target = src))
if(do_after(user, 20*platingmodifier, target = src))
if(S.get_amount() < 2)
return
S.use(2)
@@ -102,7 +109,7 @@
to_chat(user, "<span class='warning'>You need two sheets of metal to finish a wall!</span>")
return
to_chat(user, "<span class='notice'>You start adding plating...</span>")
if (do_after(user, 40, target = src))
if (do_after(user, 40*platingmodifier, target = src))
if(S.get_amount() < 2)
return
S.use(2)
@@ -132,7 +139,7 @@
if(S.get_amount() < 1)
return
to_chat(user, "<span class='notice'>You start finalizing the reinforced wall...</span>")
if(do_after(user, 50, target = src))
if(do_after(user, 50*platingmodifier, target = src))
if(S.get_amount() < 1)
return
S.use(1)
@@ -146,7 +153,7 @@
if(S.get_amount() < 1)
return
to_chat(user, "<span class='notice'>You start reinforcing the girder...</span>")
if(do_after(user, 60, target = src))
if(do_after(user, 60*platingmodifier, target = src))
if(S.get_amount() < 1)
return
S.use(1)
+3 -2
View File
@@ -41,8 +41,9 @@
if(.)
return
to_chat(user, "<span class='notice'>You take down [src].</span>")
victim.forceMove(drop_location())
victim = null
if(victim)
victim.forceMove(drop_location())
victim = null
spear.forceMove(drop_location())
spear = null
qdel(src)
+28 -1
View File
@@ -74,7 +74,7 @@
number_of_rods = 2
smooth = SMOOTH_TRUE
canSmoothWith = null
obj_flags = CAN_BE_HIT | BLOCK_Z_FALL
obj_flags = CAN_BE_HIT | BLOCK_Z_FALL
/obj/structure/lattice/catwalk/deconstruction_hints(mob/user)
return "<span class='notice'>The supporting rods look like they could be <b>cut</b>.</span>"
@@ -90,3 +90,30 @@
for(var/obj/structure/cable/C in T)
C.deconstruct()
..()
/obj/structure/lattice/lava
name = "heatproof support lattice"
desc = "A specialized support beam for building across lava. Watch your step."
icon = 'icons/obj/smooth_structures/catwalk.dmi'
icon_state = "catwalk"
number_of_rods = 1
color = "#5286b9ff"
smooth = SMOOTH_TRUE
canSmoothWith = null
obj_flags = CAN_BE_HIT | BLOCK_Z_FALL
resistance_flags = FIRE_PROOF | LAVA_PROOF
/obj/structure/lattice/lava/deconstruction_hints(mob/user)
return "<span class='notice'>The rods look like they could be <b>cut</b>, but the <i>heat treatment will shatter off</i>. There's space for a <i>tile</i>.</span>"
/obj/structure/lattice/lava/attackby(obj/item/C, mob/user, params)
. = ..()
if(istype(C, /obj/item/stack/tile/plasteel))
var/obj/item/stack/tile/plasteel/P = C
if(P.use(1))
to_chat(user, "<span class='notice'>You construct a floor plating, as lava settles around the rods.</span>")
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
new /turf/open/floor/plating(locate(x, y, z))
else
to_chat(user, "<span class='warning'>You need one floor tile to build atop [src].</span>")
return
+1 -2
View File
@@ -136,8 +136,7 @@
switch(choice)
if("name")
var/newname = copytext(sanitize_name(reject_bad_text(input(H, "Who are we again?", "Name change", H.name) as null|text)),1,MAX_NAME_LEN)
var/newname = sanitize_name(reject_bad_text(stripped_input(H, "Who are we again?", "Name change", H.name, MAX_NAME_LEN)))
if(!newname)
return
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+1 -1
View File
@@ -181,7 +181,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an
icon_state = "morgue1"
else
icon_state = "morgue2" // Dead, brainded mob.
var/list/compiled = recursive_mob_check(src, 0, 0) // Search for mobs in all contents.
var/list/compiled = GetAllContents(/mob/living) // Search for mobs in all contents.
if(!length(compiled)) // No mobs?
icon_state = "morgue3"
return
+12 -11
View File
@@ -112,8 +112,10 @@
var/cur_note = text2ascii(note) - 96
if(cur_note < 1 || cur_note > 7)
continue
for(var/i=2 to length(note))
var/ni = copytext(note,i,i+1)
var/notelen = length(note)
var/ni = ""
for(var/i = length(note[1]) + 1, i <= notelen, i += length(ni))
ni = note[i]
if(!text2num(ni))
if(ni == "#" || ni == "b" || ni == "n")
cur_acc[cur_note] = ni
@@ -202,9 +204,10 @@
//split into lines
lines = splittext(text, "\n")
if(lines.len)
if(copytext(lines[1],1,6) == "BPM: ")
tempo = sanitize_tempo(600 / text2num(copytext(lines[1],6)))
lines.Cut(1,2)
var/bpm_string = "BPM: "
if(findtext(lines[1], bpm_string, 1, length(bpm_string) + 1))
tempo = sanitize_tempo(600 / text2num(copytext(lines[1], length(bpm_string) + 1)))
lines.Cut(1, 2)
else
tempo = sanitize_tempo(5) // default 120 BPM
if(lines.len > MUSIC_MAXLINES)
@@ -212,7 +215,7 @@
lines.Cut(MUSIC_MAXLINES + 1)
var/linenum = 1
for(var/l in lines)
if(length(l) > MUSIC_MAXLINECHARS)
if(length_char(l) > MUSIC_MAXLINECHARS)
to_chat(usr, "Line [linenum] too long!")
lines.Remove(l)
else
@@ -276,8 +279,8 @@
return
if(lines.len > MUSIC_MAXLINES)
return
if(length(newline) > MUSIC_MAXLINECHARS)
newline = copytext(newline, 1, MUSIC_MAXLINECHARS)
if(length_char(newline) > MUSIC_MAXLINECHARS)
newline = copytext_char(newline, 1, MUSIC_MAXLINECHARS)
lines.Add(newline)
else if(href_list["deleteline"])
@@ -288,11 +291,9 @@
else if(href_list["modifyline"])
var/num = round(text2num(href_list["modifyline"]),1)
var/content = html_encode(input("Enter your line: ", instrumentObj.name, lines[num]) as text|null)
var/content = stripped_input(usr, "Enter your line: ", instrumentObj.name, lines[num], MUSIC_MAXLINECHARS)
if(!content || !usr.canUseTopic(instrumentObj, BE_CLOSE, FALSE, NO_TK))
return
if(length(content) > MUSIC_MAXLINECHARS)
content = copytext(content, 1, MUSIC_MAXLINECHARS)
if(num > lines.len || num < 1)
return
lines[num] = content
+1 -1
View File
@@ -39,7 +39,7 @@
. = ..()
if(!isliving(user))
return
if(user.mind && user.mind in immune_minds)
if(user.mind && (user.mind in immune_minds))
return
if(get_dist(user, src) <= 1)
. += "<span class='notice'>You reveal [src]!</span>"