Skip to content

Commit

Permalink
Graffiti centers on where you click. (#9255)
Browse files Browse the repository at this point in the history
* Graffiti centers on where you click.

* Oversights, and pixelshifted engravings.

* Better returns
  • Loading branch information
Mechoid authored Dec 28, 2023
1 parent 14c6817 commit e976eab
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 22 deletions.
25 changes: 19 additions & 6 deletions code/game/objects/effects/decals/crayon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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()

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(main,ICON_ADD)
shadeOverlay.Blend(shade,ICON_ADD)
mainOverlay.Blend(art_color,ICON_ADD)
shadeOverlay.Blend(art_shade,ICON_ADD)

add_overlay(mainOverlay)
add_overlay(shadeOverlay)

add_hiddenprint(usr)
return
17 changes: 14 additions & 3 deletions code/game/objects/items/crayons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -209,4 +220,4 @@
..()

/obj/item/pen/crayon/attack_self(var/mob/user)
return
return
4 changes: 2 additions & 2 deletions code/game/turfs/simulated/floor_attackby.dm
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions code/game/turfs/simulated/wall_attacks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -405,4 +405,4 @@
return

else if(!istype(W,/obj/item/rcd) && !istype(W, /obj/item/reagent_containers))
return attack_hand(user)
return attack_hand(user)
14 changes: 13 additions & 1 deletion code/game/turfs/turf.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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, "<span class='notice'>You feel much safer.</span>")

Expand Down
4 changes: 3 additions & 1 deletion code/modules/persistence/datum/persistence_datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@
. += "<tr><td colspan = 4><hr></td></tr>"

for(var/thing in my_tracks)
. += "<tr>[GetAdminDataStringFor(thing, can_modify, user)]</tr>"
var/data = GetAdminDataStringFor(thing, can_modify, user)
if(!isnull(data))
. += "<tr>[GetAdminDataStringFor(thing, can_modify, user)]</tr>"
. += "<tr><td colspan = 4><hr></td></tr>"


Expand Down
57 changes: 53 additions & 4 deletions code/modules/persistence/effects/filth.dm
Original file line number Diff line number Diff line change
@@ -1,22 +1,57 @@
/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 "<td colspan = 3>[thing]</td><td>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]</td><td><a href='byond://?src=\ref[src];caller=\ref[user];remove_entry=\ref[thing]'>Destroy</a></td>"
return "<td colspan = 4>[thing]</td>"
return null

/datum/persistent/filth/IsValidEntry(var/atom/entry)
. = ..() && entry.invisibility == 0

/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
Expand All @@ -28,4 +63,18 @@

/datum/persistent/filth/CompileEntry(var/atom/entry)
. = ..()
LAZYADDASSOC(., "path", "[GetEntryPath(entry)]")
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]")
14 changes: 13 additions & 1 deletion code/modules/persistence/effects/graffiti.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
. = ..()
Expand All @@ -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)
. = "<td colspan = 2>[save_graffiti.message]</td><td>[save_graffiti.author]</td><td><a href='byond://?src=\ref[src];caller=\ref[user];remove_entry=\ref[thing]'>Destroy</a></td>"
else
. = "<td colspan = 3>[save_graffiti.message]</td><td>[save_graffiti.author]</td>"
. = "<td colspan = 3>[save_graffiti.message]</td><td>[save_graffiti.author]</td>"
3 changes: 2 additions & 1 deletion code/modules/persistence/effects/trash.dm
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -14,4 +15,4 @@
return trash.age

/datum/persistent/filth/trash/GetEntryPath(var/atom/entry)
return entry.type
return entry.type
Binary file modified icons/effects/writing.dmi
Binary file not shown.

0 comments on commit e976eab

Please sign in to comment.