Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] Paintings update: Curators get a cut on patronage + zoom in/out buttons on UI #2066

Merged
merged 1 commit into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions code/controllers/subsystem/economy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ SUBSYSTEM_DEF(economy)
* A list of sole account datums can be obtained with flatten_list(), another variable would be redundant rn.
*/
var/list/bank_accounts_by_id = list()
/// A list of bank accounts indexed by their assigned job.
var/list/bank_accounts_by_job = list()
///List of the departmental budget cards in existance.
var/list/dep_cards = list()
/// A var that collects the total amount of credits owned in player accounts on station, reset and recounted on fire()
Expand Down
55 changes: 51 additions & 4 deletions code/modules/art/paintings.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define MAX_PAINTING_ZOOM_OUT 3

///////////
// EASEL //
Expand Down Expand Up @@ -67,10 +68,13 @@
var/framed_offset_y = 10

/**
* How big the grid cells that compose the painting are in the UI.
* How big the grid cells that compose the painting are in the UI (multiplied by zoom).
* This impacts the size of the UI, so smaller values are generally better for bigger canvases and viceversa
*/
var/pixels_per_unit = 24
var/pixels_per_unit = 9

///A list that keeps track of the current zoom value for each current viewer.
var/list/zoom_by_observer

SET_BASE_PIXEL(11, 10)

Expand Down Expand Up @@ -118,10 +122,12 @@
/obj/item/canvas/ui_static_data(mob/user)
. = ..()
.["px_per_unit"] = pixels_per_unit
.["max_zoom"] = MAX_PAINTING_ZOOM_OUT

/obj/item/canvas/ui_data(mob/user)
. = ..()
.["grid"] = grid
.["zoom"] = LAZYACCESS(zoom_by_observer, user.key) || (finalized ? 1 : MAX_PAINTING_ZOOM_OUT)
.["name"] = painting_metadata.title
.["author"] = painting_metadata.creator_name
.["patron"] = painting_metadata.patron_name
Expand Down Expand Up @@ -202,6 +208,24 @@
if("patronage")
. = TRUE
patron(user)
if("zoom_in")
. = TRUE
LAZYINITLIST(zoom_by_observer)
if(!zoom_by_observer[user.key])
zoom_by_observer[user.key] = 2
else
zoom_by_observer[user.key] = min(zoom_by_observer[user.key] + 1, MAX_PAINTING_ZOOM_OUT)
if("zoom_out")
. = TRUE
LAZYINITLIST(zoom_by_observer)
if(!zoom_by_observer[user.key])
zoom_by_observer[user.key] = MAX_PAINTING_ZOOM_OUT - 1
else
zoom_by_observer[user.key] = max(zoom_by_observer[user.key] - 1, 1)

/obj/item/canvas/ui_close(mob/user)
. = ..()
LAZYREMOVE(zoom_by_observer, user.key)

/obj/item/canvas/proc/finalize(mob/user)
if(painting_metadata.loaded_from_json || finalized)
Expand All @@ -218,6 +242,9 @@

SStgui.update_uis(src)

#define CURATOR_PERCENTILE_CUT 0.225
#define SERVICE_PERCENTILE_CUT 0.125

/obj/item/canvas/proc/patron(mob/user)
if(!finalized || !isliving(user))
return
Expand Down Expand Up @@ -245,6 +272,19 @@
if(!account.adjust_money(-offer_amount, "Painting: Patron of [painting_metadata.title]"))
to_chat(user, span_warning("Transaction failure. Please try again."))
return

var/datum/bank_account/service_account = SSeconomy.get_dep_account(ACCOUNT_SRV)
service_account.adjust_money(offer_amount * SERVICE_PERCENTILE_CUT)
///We give the curator(s) a cut (unless they're themselves the patron), as it's their job to curate and promote art among other things.
var/list/curator_accounts = SSeconomy.bank_accounts_by_job[/datum/job/curator] - account
var/curators_length = length(curator_accounts)
if(curators_length)
var/curator_cut = round(offer_amount * CURATOR_PERCENTILE_CUT / curators_length)
if(curator_cut)
for(var/datum/bank_account/curator as anything in curator_accounts)
curator.adjust_money(curator_cut, "Painting: Patronage cut")
curator.bank_card_talk("Cut on patronage received, account now holds [curator.account_balance] cr.")

painting_metadata.patron_ckey = user.ckey
painting_metadata.patron_name = user.real_name
painting_metadata.credit_value = offer_amount
Expand All @@ -260,6 +300,9 @@
SStgui.close_uis(src) // Close the examine ui so that the radial menu doesn't end up covered by it and people don't get confused.
select_new_frame(user, possible_frames)

#undef CURATOR_PERCENTILE_CUT
#undef SERVICE_PERCENTILE_CUT

/obj/item/canvas/proc/select_new_frame(mob/user, list/candidates)
var/possible_frames = candidates || SSpersistent_paintings.get_available_frames(painting_metadata.credit_value)
var/list/radial_options = list()
Expand Down Expand Up @@ -386,6 +429,7 @@
SET_BASE_PIXEL(5, 7)
framed_offset_x = 5
framed_offset_y = 7
pixels_per_unit = 8

/obj/item/canvas/twentythree_twentythree
name = "canvas (23x23)"
Expand All @@ -395,6 +439,7 @@
SET_BASE_PIXEL(5, 5)
framed_offset_x = 5
framed_offset_y = 5
pixels_per_unit = 8

/obj/item/canvas/twentyfour_twentyfour
name = "canvas (24x24) (AI Universal Standard)"
Expand All @@ -405,6 +450,7 @@
SET_BASE_PIXEL(4, 4)
framed_offset_x = 4
framed_offset_y = 4
pixels_per_unit = 8

/obj/item/canvas/thirtysix_twentyfour
name = "canvas (36x24)"
Expand All @@ -415,7 +461,7 @@
SET_BASE_PIXEL(-4, 4)
framed_offset_x = 14
framed_offset_y = 4
pixels_per_unit = 20
pixels_per_unit = 7
w_class = WEIGHT_CLASS_BULKY

custom_price = PAYCHECK_CREW * 1.25
Expand All @@ -435,7 +481,7 @@
SET_BASE_PIXEL(-8, 2)
framed_offset_x = 9
framed_offset_y = 4
pixels_per_unit = 18
pixels_per_unit = 6
w_class = WEIGHT_CLASS_BULKY

custom_price = PAYCHECK_CREW * 1.75
Expand Down Expand Up @@ -798,3 +844,4 @@
current_color = chosen_color

#undef AVAILABLE_PALETTE_SPACE
#undef MAX_PAINTING_ZOOM_OUT
3 changes: 3 additions & 0 deletions code/modules/economy/account.dm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
/datum/bank_account/Destroy()
if(add_to_accounts)
SSeconomy.bank_accounts_by_id -= "[account_id]"
SSeconomy.bank_accounts_by_job[account_job] -= src
QDEL_LIST(redeemed_coupons)
return ..()

Expand All @@ -70,6 +71,8 @@
if(SSeconomy.bank_accounts_by_id["[account_id]"])
stack_trace("Unable to find a unique account ID, substituting currently existing account of id [account_id].")
SSeconomy.bank_accounts_by_id["[account_id]"] = src
if(account_job)
LAZYADD(SSeconomy.bank_accounts_by_job[account_job], src)

/datum/bank_account/vv_edit_var(var_name, var_value) // just so you don't have to do it manually
var/old_id = account_id
Expand Down
1 change: 1 addition & 0 deletions strings/tips.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ As a Cultist, check the alert in the upper-right of your screen for all the deta
As a Cultist, do not cause too much chaos before your objective is completed. If the shuttle gets called too soon, you may not have enough time to win.
As a Cultist, the Blood Boil rune will deal massive amounts of brute damage to non-cultists, and some damage to fellow cultists of Nar'Sie nearby, but will create a fire where the rune stands on use.
As a Cultist, your team starts off very weak, but if necessary can quickly convert everything they have into raw power. Make sure you have the numbers and equipment to support going loud, or the cult will fall flat on its face.
As a Curator, you earn a 22% cut (divided by number of curators) of all credits spent on painting patronages. Turn others' patience and artistry skills into your own income!
As a Cyborg, choose your model carefully, as only cutting and mending your reset wire will let you re-pick it. If possible, refrain from choosing a model until a situation that requires one occurs.
As a Cyborg, you are extremely vulnerable to EMPs as EMPs both stun you and damage you. The ion rifle in the armory or a traitor with an EMP kit can kill you in seconds.
As a Cyborg, you are immune to most forms of stunning, and excel at almost everything far better than humans. However, flashes can easily stunlock you and you cannot do any precision work as you lack hands.
Expand Down
84 changes: 57 additions & 27 deletions tgui/packages/tgui/interfaces/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type PaintCanvasProps = Partial<{
drawing_color: string | null;
has_palette: boolean;
show_grid: boolean;
zoom: number;
}>;

type PointData = {
Expand All @@ -45,13 +46,15 @@ class PaintCanvas extends Component<PaintCanvasProps> {
onCanvasDropper: (x: number, y: number) => void;
drawing: boolean;
drawing_color: string;
zoom: number;

constructor(props) {
super(props);
this.canvasRef = createRef<HTMLCanvasElement>();
this.modifiedElements = [];
this.is_grid_shown = false;
this.drawing = false;
this.zoom = props.zoom;
this.onCanvasModified = props.onCanvasModifiedHandler;
this.onCanvasDropper = props.onCanvasDropperHandler;

Expand All @@ -67,8 +70,12 @@ class PaintCanvas extends Component<PaintCanvasProps> {
}

componentDidUpdate() {
if (this.zoom !== this.props.zoom) {
this.prepareCanvas();
this.syncCanvas();
}
// eslint-disable-next-line max-len
if (
else if (
(this.props.value !== undefined &&
JSON.stringify(this.baseImageData) !==
JSON.stringify(fromDM(this.props.value))) ||
Expand All @@ -79,6 +86,7 @@ class PaintCanvas extends Component<PaintCanvasProps> {
}

prepareCanvas() {
this.zoom = this.props.zoom as number;
const canvas = this.canvasRef.current!;
const ctx = canvas.getContext('2d');
const width = this.props.width || canvas.width || 360;
Expand Down Expand Up @@ -242,22 +250,24 @@ type CanvasData = {
date: string | null;
show_plaque: boolean;
show_grid: boolean;
zoom: number;
max_zoom: number;
};

export const Canvas = (props) => {
const { act, data } = useBackend<CanvasData>();
const [width, height] = getImageSize(data.grid);
const scaled_width = width * data.px_per_unit;
const scaled_height = height * data.px_per_unit;
const scaled_width = width * data.px_per_unit * data.zoom;
const scaled_height = height * data.px_per_unit * data.zoom;
const average_plaque_height = 90;
const palette_height = 44;
const palette_height = 38;
const griddy = !!data.show_grid && !!data.editable && !!data.paint_tool_color;
return (
<Window
width={scaled_width + 72}
width={Math.max(scaled_width + 72, 262)}
height={
scaled_height +
75 +
80 +
(data.show_plaque ? average_plaque_height : 0) +
(data.editable && data.paint_tool_palette ? palette_height : 0)
}
Expand All @@ -269,13 +279,12 @@ export const Canvas = (props) => {
<Tooltip
content={
multiline`
You can Right-Click the canvas to change the color of
the painting tool to that of the clicked pixel.
Right-Click a pixel on the canvas to copy its color.
` +
(data.editable
? multiline`
\n You can also select a color from the
palette at the bottom of the UI,
\n Left-Click the palette at the
bottom of the UI to select a color,
or input a new one with Right-Click.
`
: '')
Expand All @@ -296,26 +305,47 @@ export const Canvas = (props) => {
/>
</Flex.Item>
)}
<Flex.Item>
<Button
tooltip="Zoom Out"
icon="search-minus"
disabled={data.zoom <= 1}
onClick={() => act('zoom_out')}
m={0.5}
/>
</Flex.Item>
<Flex.Item>
<Button
tooltip="Zoom In"
icon="search-plus"
disabled={data.zoom >= data.max_zoom}
onClick={() => act('zoom_in')}
m={0.5}
/>
</Flex.Item>
</Flex>
<Box textAlign="center">
<PaintCanvas
value={data.grid}
imageWidth={width}
imageHeight={height}
width={scaled_width}
height={scaled_height}
drawing_color={data.paint_tool_color}
show_grid={griddy}
onCanvasModifiedHandler={(changed) =>
act('paint', { data: toMassPaintFormat(changed) })
}
onCanvasDropperHandler={(x, y) =>
act('select_color_from_coords', { px: x, py: y })
}
editable={data.editable}
has_palette={!!data.paint_tool_palette}
/>
<Flex align="center" justify="center" direction="column">
<Flex.Item>
<PaintCanvas
value={data.grid}
imageWidth={width}
imageHeight={height}
width={scaled_width}
height={scaled_height}
drawing_color={data.paint_tool_color}
show_grid={griddy}
zoom={data.zoom}
onCanvasModifiedHandler={(changed) =>
act('paint', { data: toMassPaintFormat(changed) })
}
onCanvasDropperHandler={(x, y) =>
act('select_color_from_coords', { px: x, py: y })
}
editable={data.editable}
has_palette={!!data.paint_tool_palette}
/>
</Flex.Item>
{!!data.editable && !!data.paint_tool_palette && (
<Flex.Item>
{data.paint_tool_palette.map((element, index) => (
Expand Down
Loading