diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index e6464428e5..8cc0fa3cf9 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -4,25 +4,38 @@ icon = 'icons/obj/rune.dmi' plane = DIRTY_PLANE anchored = 1 + var/art_type + var/art_color + var/art_shade /obj/effect/decal/cleanable/crayon/Initialize(var/ml, main = "#FFFFFF",shade = "#000000",var/type = "rune") . = ..(ml, 0) // mapload, age name = type desc = "A [type] drawn in crayon." + // Persistence vars. + art_type = type + art_color = main + art_shade = shade + switch(type) if("rune") type = "rune[rand(1,6)]" if("graffiti") type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa") - var/icon/mainOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]",2.1) - var/icon/shadeOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]s",2.1) + update_icon() - mainOverlay.Blend(main,ICON_ADD) - shadeOverlay.Blend(shade,ICON_ADD) + add_hiddenprint(usr) + +/obj/effect/decal/cleanable/crayon/update_icon() + cut_overlays() + var/icon/mainOverlay = new/icon('icons/effects/crayondecal.dmi',"[art_type]",2.1) + var/icon/shadeOverlay = new/icon('icons/effects/crayondecal.dmi',"[art_type]s",2.1) + + mainOverlay.Blend(art_color,ICON_ADD) + shadeOverlay.Blend(art_shade,ICON_ADD) add_overlay(mainOverlay) add_overlay(shadeOverlay) - - add_hiddenprint(usr) + return diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 37c80306c6..8671391494 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -65,7 +65,7 @@ shadeColour = input(user, "Please select the shade colour.", "Crayon colour") as color return -/obj/item/pen/crayon/afterattack(atom/target, mob/user as mob, proximity) +/obj/item/pen/crayon/afterattack(atom/target, mob/user as mob, proximity, click_parameters) if(!proximity) return if(istype(target,/turf/simulated/floor)) var/drawtype = input("Choose what you'd like to draw.", "Crayon scribbles") in list("graffiti","rune","letter","arrow") @@ -93,7 +93,18 @@ return to_chat(user, "You start drawing an arrow on the [target.name].") if(instant || do_after(user, 50)) - new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype) + + var/list/mouse_control = params2list(click_parameters) + var/p_x = 0 + var/p_y = 0 + if(mouse_control["icon-x"]) + p_x = text2num(mouse_control["icon-x"]) - 16 + if(mouse_control["icon-y"]) + p_y = text2num(mouse_control["icon-y"]) - 16 + + var/atom/new_graffiti = new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype) + new_graffiti.pixel_x = p_x + new_graffiti.pixel_y = p_y to_chat(user, "You finish drawing.") if(config.log_graffiti) @@ -209,4 +220,4 @@ ..() /obj/item/pen/crayon/attack_self(var/mob/user) - return \ No newline at end of file + return diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm index b0c7851883..7a5221ff84 100644 --- a/code/game/turfs/simulated/floor_attackby.dm +++ b/code/game/turfs/simulated/floor_attackby.dm @@ -1,4 +1,4 @@ -/turf/simulated/floor/attackby(var/obj/item/C, var/mob/user) +/turf/simulated/floor/attackby(var/obj/item/C, var/mob/user, attack_modifier, click_parameters) if(!C || !user) return 0 @@ -29,7 +29,7 @@ if(isliving(user)) var/mob/living/L = user if(L.a_intent == I_HELP && L.is_preference_enabled(/datum/client_preference/engrave_graffiti)) - try_graffiti(L, C) + try_graffiti(L, C, click_parameters) if(istype(C, /obj/item/stack/tile/roofing)) var/expended_tile = FALSE // To track the case. If a ceiling is built in a multiz zlevel, it also necessarily roofs it against weather diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 7b5c87f498..d6302742d9 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -127,12 +127,12 @@ return success_smash(user) return fail_smash(user) -/turf/simulated/wall/attackby(var/obj/item/W, var/mob/user) +/turf/simulated/wall/attackby(var/obj/item/W, var/mob/user, attack_modifier, click_parameters) user.setClickCooldown(user.get_attack_speed(W)) if(!construction_stage && user.a_intent == I_HELP && user.is_preference_enabled(/datum/client_preference/engrave_graffiti)) - if(try_graffiti(user,W)) + if(try_graffiti(user,W,click_parameters)) return if (!user.IsAdvancedToolUser()) @@ -405,4 +405,4 @@ return else if(!istype(W,/obj/item/rcd) && !istype(W, /obj/item/reagent_containers)) - return attack_hand(user) \ No newline at end of file + return attack_hand(user) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 38f812e78e..2b2b91ee7a 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -308,7 +308,7 @@ /turf/proc/can_engrave() return FALSE -/turf/proc/try_graffiti(var/mob/vandal, var/obj/item/tool) +/turf/proc/try_graffiti(var/mob/vandal, var/obj/item/tool, click_parameters) if(!tool.sharp || !can_engrave()) return FALSE @@ -341,6 +341,18 @@ graffiti.message = message graffiti.author = vandal.ckey + if(click_parameters) + var/list/mouse_control = params2list(click_parameters) + var/p_x = 0 + var/p_y = 0 + if(mouse_control["icon-x"]) + p_x = text2num(mouse_control["icon-x"]) - 16 + if(mouse_control["icon-y"]) + p_y = text2num(mouse_control["icon-y"]) - 16 + + graffiti.pixel_x = p_x + graffiti.pixel_y = p_y + if(lowertext(message) == "elbereth") to_chat(vandal, "You feel much safer.") diff --git a/code/modules/persistence/datum/persistence_datum.dm b/code/modules/persistence/datum/persistence_datum.dm index 9ff1598c7c..6a804024bc 100644 --- a/code/modules/persistence/datum/persistence_datum.dm +++ b/code/modules/persistence/datum/persistence_datum.dm @@ -126,7 +126,9 @@ . += "
" for(var/thing in my_tracks) - . += "[GetAdminDataStringFor(thing, can_modify, user)]" + var/data = GetAdminDataStringFor(thing, can_modify, user) + if(!isnull(data)) + . += "[GetAdminDataStringFor(thing, can_modify, user)]" . += "
" diff --git a/code/modules/persistence/effects/filth.dm b/code/modules/persistence/effects/filth.dm index 166c374c02..f315aac816 100644 --- a/code/modules/persistence/effects/filth.dm +++ b/code/modules/persistence/effects/filth.dm @@ -1,6 +1,15 @@ /datum/persistent/filth name = "filth" entries_expire_at = 4 // 4 rounds, 24 hours. + has_admin_data = TRUE + +/datum/persistent/filth/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user) + if(istype(thing, /obj/effect/decal/cleanable/crayon)) + var/obj/effect/decal/cleanable/crayon/CRAY = thing + if(can_modify) + return "[thing]Loc:([CRAY.x],[CRAY.y],[CRAY.z]) P_X: [CRAY.pixel_x] P_Y: [CRAY.pixel_y] Color: [CRAY.art_color] Shading: [CRAY.art_shade] Type: [CRAY.art_type]Destroy" + return "[thing]" + return null /datum/persistent/filth/IsValidEntry(var/atom/entry) . = ..() && entry.invisibility == 0 @@ -8,15 +17,41 @@ /datum/persistent/filth/CheckTokenSanity(var/list/token) // byond's json implementation is "questionable", and uses types as keys and values without quotes sometimes even though they aren't valid json token["path"] = istext(token["path"]) ? text2path(token["path"]) : token["path"] - return ..() && ispath(token["path"]) + token["pixel_x"] = istext(token["pixel_x"]) ? text2num(token["pixel_x"]) : token["pixel_x"] + token["pixel_y"] = istext(token["pixel_y"]) ? text2num(token["pixel_y"]) : token["pixel_y"] + return ..() && ispath(token["path"]) && isnum(token["pixel_x"]) && isnum(token["pixel_y"]) /datum/persistent/filth/CheckTurfContents(var/turf/T, var/list/token) var/_path = token["path"] - return (locate(_path) in T) ? FALSE : TRUE + if(!ispath(_path, /obj/effect/decal/cleanable/crayon)) + return (locate(_path) in T) ? FALSE : TRUE + +// Crayon drawings aren't handled in graffiti, so we need to check if someone made "art" seperately from blood, dirt, etc. + var/too_much_crayon = 0 + for(var/obj/effect/decal/cleanable/crayon/C in T) + too_much_crayon++ + if(too_much_crayon >= 5) + return FALSE + return TRUE /datum/persistent/filth/CreateEntryInstance(var/turf/creating, var/list/token) var/_path = token["path"] - new _path(creating, token["age"]+1) + var/atom/inst = new _path(creating, token["age"]+1) + if(token["pixel_x"]) + inst.pixel_x = token["pixel_x"] + if(token["pixel_y"]) + inst.pixel_y = token["pixel_y"] + + if(istype(inst, /obj/effect/decal/cleanable/crayon)) + var/obj/effect/decal/cleanable/crayon/Crayart = inst + if(token["art_type"]) + Crayart.art_type = token["art_type"] + if(token["art_color"]) + Crayart.art_color = token["art_color"] + if(token["art_shade"]) + Crayart.art_shade = token["art_shade"] + + Crayart.update_icon() /datum/persistent/filth/GetEntryAge(var/atom/entry) var/obj/effect/decal/cleanable/filth = entry @@ -28,4 +63,18 @@ /datum/persistent/filth/CompileEntry(var/atom/entry) . = ..() - LAZYADDASSOC(., "path", "[GetEntryPath(entry)]") \ No newline at end of file + LAZYADDASSOC(., "path", "[GetEntryPath(entry)]") + to_world("path is [GetEntryPath(entry)]") + LAZYADDASSOC(., "pixel_x", "[entry.pixel_x]") + to_world("pixel_x is [entry.pixel_x]") + LAZYADDASSOC(., "pixel_y", "[entry.pixel_y]") + to_world("pixel_y is [entry.pixel_y]") + + if(istype(entry, /obj/effect/decal/cleanable/crayon)) + var/obj/effect/decal/cleanable/crayon/Inst = entry + LAZYADDASSOC(., "art_type", "[Inst.art_type]") + to_world("art type is [Inst.art_type]") + LAZYADDASSOC(., "art_color", "[Inst.art_color]") + to_world("art color is [Inst.art_color]") + LAZYADDASSOC(., "art_shade", "[Inst.art_shade]") + to_world("art shade is [Inst.art_shade]") diff --git a/code/modules/persistence/effects/graffiti.dm b/code/modules/persistence/effects/graffiti.dm index 369f9156b4..aaaeaa9fa2 100644 --- a/code/modules/persistence/effects/graffiti.dm +++ b/code/modules/persistence/effects/graffiti.dm @@ -16,10 +16,20 @@ return FALSE return TRUE +/datum/persistent/graffiti/CheckTokenSanity(var/list/token) + // byond's json implementation is "questionable", and uses types as keys and values without quotes sometimes even though they aren't valid json + token["pixel_x"] = istext(token["pixel_x"]) ? text2num(token["pixel_x"]) : token["pixel_x"] + token["pixel_y"] = istext(token["pixel_y"]) ? text2num(token["pixel_y"]) : token["pixel_y"] + return ..() && isnum(token["pixel_x"]) && isnum(token["pixel_y"]) + /datum/persistent/graffiti/CreateEntryInstance(var/turf/creating, var/list/token) var/obj/effect/decal/writing/inst = new /obj/effect/decal/writing(creating, token["age"]+1, token["message"], token["author"]) if(token["icon_state"]) inst.icon_state = token["icon_state"] + if(token["pixel_x"]) + inst.pixel_x = token["pixel_x"] + if(token["pixel_y"]) + inst.pixel_y = token["pixel_y"] /datum/persistent/graffiti/IsValidEntry(var/atom/entry) . = ..() @@ -37,10 +47,12 @@ LAZYADDASSOC(., "author", "[save_graffiti.author ? save_graffiti.author : "unknown"]") LAZYADDASSOC(., "message", "[save_graffiti.message]") LAZYADDASSOC(., "icon_state", "[save_graffiti.icon_state]") + LAZYADDASSOC(., "pixel_x", "[save_graffiti.pixel_x]") + LAZYADDASSOC(., "pixel_y", "[save_graffiti.pixel_y]") /datum/persistent/graffiti/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user) var/obj/effect/decal/writing/save_graffiti = thing if(can_modify) . = "[save_graffiti.message][save_graffiti.author]Destroy" else - . = "[save_graffiti.message][save_graffiti.author]" \ No newline at end of file + . = "[save_graffiti.message][save_graffiti.author]" diff --git a/code/modules/persistence/effects/trash.dm b/code/modules/persistence/effects/trash.dm index 951e9858af..28c1909f01 100644 --- a/code/modules/persistence/effects/trash.dm +++ b/code/modules/persistence/effects/trash.dm @@ -1,5 +1,6 @@ /datum/persistent/filth/trash name = "trash" + has_admin_data = FALSE /datum/persistent/filth/trash/CheckTurfContents(var/turf/T, var/list/tokens) var/too_much_trash = 0 @@ -14,4 +15,4 @@ return trash.age /datum/persistent/filth/trash/GetEntryPath(var/atom/entry) - return entry.type \ No newline at end of file + return entry.type diff --git a/icons/effects/writing.dmi b/icons/effects/writing.dmi index bbf4055bce..359078eaba 100644 Binary files a/icons/effects/writing.dmi and b/icons/effects/writing.dmi differ