Skip to content

[DISCUSSION] Multi-layer markings & Colour linking #135

Description

@staryoshi06

Hello all, sorry for the delay on creating this issue.

Summary

A number of the thousands of markings used on The Den utilise a feature pulled from Floof code called Multi Layer Markings and Colour Linking. This allowed a marking to render multiple sprites on different layers, so that you could, for example, have part of a tail sprite render in front of the character while the rest renders behind. The typical solution to this was have a specially cut-out sprite, but this can limit clothing designs and the like, so the Floof solution is generally better. Colour linking was an accompaniment to this feature, allowing a layer of the marking to inherit the colour of a different layer, so you did not have to input the colours for each individual sprite.

The issue with implementing this in rebase, with the addition of nubody, is that markings are no longer placed into "categories", like before. Instead, they are directly attached to a body part, and that body part is used to determine where the marking renders. While we could still implement layers as they are currently, this is perhaps not the wisest implementation method, because markings are now actually technically attached to the specific body part that they are related to, rather than the character. While this has no functional difference at current time, future implementations of surgery could allow for transplantation of body parts between characters, and this would include transferring markings attached to those body parts. As such, I think we should consider modifying the multi-layer system to account for this.

I propose two features, both including new optional YAML fields in marking definitions. As I've already dug my head into the systems, I plan to implement these myself, but I wanted to put these forward for discussion first because I am still fairly new to SS14 contribution and I'm sure I've missed some important details.

Subordinate markings

A new array field in the marking definition, named "subordinates", which can contain any number of additional markings. These are complete marking definitions, treated as separate markings by the Marking Manager, but in C# they utilise a new Marking class property to indicate that they have a "parent" marking, preventing them from showing separately in the marking selector. Additionally, they can make use of a new LayerColoringType for inheriting the colour of their parent (a non-subordinate marking using this type is considered invalid). When the parent marking is enabled, all subordinates are also enabled.

If it is preferred, the original structure for layering and colour linking can still be used in YAML, but I do think that each individual layer should be considered a separate marking internally, for the purposes of being attached to different body parts and being transferable in that sense. This the best method without needing a massive refactor that could cause trouble with later upstream merges.

Render layers

A new string field, "Render Layer" allows you to select a body part that a marking should be rendered on, that does not change the actual body part that it is attached to mechanically. This is primarily useful for subordinate markings, in cases where you might not want them to be removed, but still disable rendering when a body part is removed, or if a "body part" exists for a technical reason rather than being an actual, well, body part.

For example, if you have a sock or gauze that covers both the leg and foot, you probably want to disable the foot part if the character's foot gets removed, but you might not want them to lose half a sock if their foot gets replaced with a different one (or conversely, someone else GAIN half a sock). In this case, you could set the foot part to have the render layer as "Foot", but the body part as "Leg", so that the whole sock would be transferred as part of the "Leg" part. The existing implementation should handle any issues with displacement rendering or incompatible species by simply not rendering the marking in the instance that it occurs; the error checking appears quite thorough already.

Another example would be the implementation of the Tail Behind layer; removing someone's "Tail Behind" but not their "Tail" doesn't make sense mechanically, so the body part would be "Tail" but you'd utilise the "Tail Behind" render layer.

If the render layer is not specified, then it is considered to be the same as the body part, meaning it won't break any existing markings and is still easy to port markings that don't require multi layer support.

Handling symmetrical markings

One issue that we come across is that some markings are symmetrical (i.e. mirrored across both legs or arms, like socks or arm warmers). In this case, it is rather difficult to pick a parent part of the marking. I have three suggestions for this, each having some pros and cons (and really mostly only affecting the admin marking menu, mechanically):

1: Abstract marking layer

Create an abstract marking layer. This layer is a "body part" that cannot be removed, and for symmetrical markings would be assigned no sprites (unless you want part of the marking to be unremovable).

This option is fairly seamless for most game scenarios, and does not bias a particular part of the marking. However, it does cause a couple issues:

  • It will cause some weirdness with the admin menu; the marking originator will always still technically have the marking enabled since the abstract parent marking is never removed, and if someone else switches body parts and gains part or all of the marking, it would not appear to be enabled in the admin menu.
  • A system and field(s) for sprite-less LayerColoringTypes would need to be added, so that the abstract parent marking could grant colours to the subordinates without actually having any sprites by itself. This might be a useful feature regardless, though.
2: Arbitrary parent marking

Most similar to Floof's current method for colour linking, simply assign a random part of the marking as the parent marking and make every single other part a subordinate. This saves the implementation of sprite-less LayerColoringTypes. However, it still causes admin menu weirdness, except that in this case the marking would arbitrarily be "enabled" by whoever has the parent part of the marking.

3: Separate symmetrical sprites.

Something which will have to be done to an extent anyway (though, thankfully many already appear to support this in terms of spritework), we could separate out markings so that they only cover, at most, one limb (unless they have a logical single parent such as the chest or tail). This does allow for more customisation, and saves most of the weirdness with the admin menu, but it could also bloat the marking menu by a bit.

Sub-suggestion 4: Standardise undergarments.

A lot of the problematic symmetrical markings, from my understanding, are undergarment markings. In current Den, this is already kind of an inconsistent thing; some undergarments are clothes and others are markings. Most non-undergarment markings that do not have this issue, that I am aware of, should probably be separated into left and right markings anyway (e.g. Vulpkanin points). Making all undergarments into clothing would save a lot of the issue with this design, but would obviously create a bunch of new headaches, as we'd need to add multi-colourable clothing and also probably add new inventory slots. So I suspect this one is unlikely, but food for thought.

Symmetrical implementation examples

An example of say, striped thigh-high socks, for each suggestion, because it's probably one of the more complex examples of this implementation. Pseudo-YML included (only important fields):

  1. Abstract parent marking with three abstract colourables (base, stripes and tips). Four subordinates, two each for left and right (leg and foot). All four subordinates have "Body Part" as the respective leg and inherit the base colour. The thigh parts inherit the stripes colour as well. The foot parts have a "Render Layer" as the respective foot and also inherit the tips colour.
- type: marking
	id: UnderwearSocksThighStripes
	coloring:
		base:
			type: !type:SimpleColoring
				color: "#FFFFFF"
		stripes:
			type: !type:SimpleColoring
				color: "#999999"
		tips:
			type: !type:SimpleColoring
				color: "#999999"
	bodyPart: Abstract
	subordinates:
		- type: marking
		id: UnderwearSocksThighStripes-LeftLeg
		coloring:
			base:
				type: !type:InheritParent
					inheritedColor: base
			stripes:
				type: !type:InheritParent
					inheritedColor: stripes
		bodyPart: LLeg
		sprites:
			- sprite: ...
				state: thigh-left
			- sprite: ...
				state: stripes-thigh-left
		- type: marking
		id: UnderwearSocksThighStripes-RightLeg
		coloring:
			base:
				type: !type:InheritParent
					inheritedColor: base
			stripes:
				type: !type:InheritParent
					inheritedColor: stripes
		bodyPart: RLeg
		sprites:
			- sprite: ...
				state: thigh-right
			- sprite: ...
				state: stripes-thigh-right
		- type: marking
		id: UnderwearSocksThighStripes-LeftFoot
		coloring:
			base:
				type: !type:InheritParent
					inheritedColor: base
			tips:
				type: !type:InheritParent
					inheritedColor: tips
		bodyPart: LLeg
		renderLayer: LFoot
		sprites:
			- sprite: ...
				state: base-left
			- sprite: ...
				state: tips-left
		- type: marking
		id: UnderwearSocksThighStripes-RightFoot
		coloring:
			base:
				type: !type:InheritParent
					inheritedColor: base
			tips:
				type: !type:InheritParent
					inheritedColor: tips
		bodyPart: RLeg
		renderLayer: RFoot
		sprites:
			- sprite: ...
				state: base-right
			- sprite: ...
				state: tips-right	
  1. As per above, but instead of the abstract parent, we arbitrarily assign, say, left thigh, as the parent marking, with right thigh and left foot as subordinates. It has the base and stripes colours for its sprites; the base colour is inherited by both other parts, and the stripes colour by right thigh. The left foot has its own tips colour, and the right foot is subordinate to it, inheriting both base and tips colours. The body parts and render layers remain the same as No 1.
- type: marking
	id: UnderwearSocksThighStripes-LeftLeg
	coloring:
		thigh-left:
			type: !type:SimpleColor
				color: "#FFFFFF"
		stripes-thigh-left:
			type: !type:SimpleColor
				color: "#999999"
	bodyPart: LLeg
	sprites:
		- sprite: ...
			state: thigh-left
		- sprite: ...
			state: stripes-thigh-left
	subordinates:
		- type: marking
		id: UnderwearSocksThighStripes-RightLeg
		coloring:
			thigh-right:
				type: !type:InheritParent
					inheritedColor: thigh-left
			stripes-thigh-right:
				type: !type:InheritParent
					inheritedColor: stripes-thigh-left
		bodyPart: RLeg
		sprites:
			- sprite: ...
				state: thigh-right
			- sprite: ...
				state: stripes-thigh-right
		- type: marking
		id: UnderwearSocksThighStripes-LeftFoot
		coloring:
			base-left:
				type: !type:InheritParent
					inheritedColor: thigh-left
			tips-left:
				type: !type:SimpleColor
					color: "#999999"
		bodyPart: LLeg
		renderLayer: LFoot
		sprites:
			- sprite: ...
				state: base-left
			- sprite: ...
				state: tips-left
		subordinates:
			- type: marking
			id: UnderwearSocksThighStripes-RightFoot
			coloring:
				base-right:
					type: !type:InheritParent
						inheritedColor: base-left
				tips-right:
					type: !type:InheritParent
						inheritedColor: tips-left
			bodyPart: RLeg
			renderLayer: RFoot
			sprites:
				- sprite: ...
					state: base-right
				- sprite: ...
					state: tips-right
  1. We separate out the marking into "Left Striped Thigh-High" and "Right Striped Thigh-High". Each marking is 2 parts: leg and foot. The leg is the parent marking with the foot as the subordinate. The leg has two colours (base and stripes), with the foot inheriting the base colour and having the tips colour. Now we also have to implement the ability to independently remove the two, or change the "remove underwear" to remove both at the same time. Woohoo, more things to implement. But, now people can wear two different sock designs, if they want.
- type: marking
	id: UnderwearSocksThighStripesLeft
	coloring:
		thigh-left:
			type: !type:SimpleColor
				color: "#FFFFFF"
		stripes-thigh-left:
			type: !type:SimpleColor
				color: "#999999"
	bodyPart: LLeg
	sprites:
		- sprite: ...
			state: thigh-left
		- sprite: ...
			state: stripes-thigh-left
	subordinates:
		- type: marking
		id: UnderwearSocksThighStripesLeft-Foot
		coloring:
			base-left:
				type: !type:InheritParent
					inheritedColor: thigh-left
			tips-left:
				type: !type:SimpleColor
					color: "#999999"
		bodyPart: LLeg
		renderLayer: LFoot
		sprites:
			- sprite: ...
				state: base-left
			- sprite: ...
				state: tips-left

- type: marking
	id: UnderwearSocksThighStripesRight
	coloring:
		thigh-right:
			type: !type:SimpleColor
				color: "#FFFFFF"
		stripes-thigh-right:
			type: !type:SimpleColor
				color: "#999999"
	bodyPart: RLeg
	sprites:
		- sprite: ...
			state: thigh-right
		- sprite: ...
			state: stripes-thigh-right
	subordinates:
		- type: marking
		id: UnderwearSocksThighStripesRight-Foot
		coloring:
			base-right:
				type: !type:InheritParent
					inheritedColor: thigh-right
			tips-right:
				type: !type:SimpleColor
					color: "#999999"
		bodyPart: RLeg
		renderLayer: RFoot
		sprites:
			- sprite: ...
				state: base-right
			- sprite: ...
				state: tips-right
  1. We turn the socks into an undergarment clothing item, in a new underwear or socks slot. Now we need to implement the ability to add multiple colours to clothing items. We also need to then have a feature to convert this from old character exports.
    No sample YML for this one.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions