TAIL FIX! Squashing all those commits...

- Adds blank icons with standardized timings for species tail wagging,
used in icon generation.
- Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or
WEST.
- Ensures tails will overlap stuff as normal only when facing NORTH so
as to avoid unwanted interference with the base sprite.
- Tails now appear in ID cards, overlaying things correctly.
- Tails now overlay and are overlaid by things correctly in preview
icons.
- Modifies the positioning of tail icon generation in the ID card
preview icon generation file.
- Modifies the positioning of tail icon generation in the player
preferences preview icon generation file.
- Breaks limb generation into its own layer, breaks tail generation into
a second layer that can be overlaid by limbs.
- TAIL_LAYER will now overlay the NORTH direction sprite of a tail now,
while TAIL_UNDERLIMBS_LAYER gets all remaining directions.

**AIMS TO DO THE FOLLOWING:**
- *ELIMINATE THE ISSUE IN #3183 WITH DUPLICATE TAIL ICON GENERATION*
- *ELIMINATE THE ISSUE IN #3183 WITH TAILS WAGGING TOO FAST/INCORRECTLY*
- *ELIMINATE THE ISSUE IN #3183 WITH BODY ICONS NOT RENDERING*

Missed a spot

Occurred when reformatting the code and reducing the number of pointless
variables

Missed a spot 2

Crash Fix

Fixes Spontaneous Tail Overlapping Limbs

Tiny Unathi Sprite Corrections

One pixel on the Unathi right arm east direction sprite was miscoloured
(used left arm west direction as a reference), and the animated Unathi
tails previously did not meet the body while naked-- appearing to float.

Fixes both

Finalizes Changelog

Cleans up Vox puke

Accommodates Admin Overrides to body_accessory Species Checks & Fix

Does the above
Elaborating on accommodation: Species getting body accessories that
wouldn't normally be getting body accessories will inherit the
Vulpkanin's default animation template as those are currently the only
tails we have to worry about right now
Elaborating on Fix: Adds a default animation template for Vulpkanin in
body_accessory as the animation timings for Vulpkanin tails there are
different from those in effects/species.dmi

Unathi Static Tail Fix

Adjusts north-direction Unathi static tail sprite, now attaches to the
body in the correct location.

This PR is now on Sale!

Significantly cheaper.

Now, it will only generate tail icons on a per-direction basis if the
user's species is flagged to have a tail that is overlapped by limbs
(TAIL_OVERLAPPED).

Otherwise, it just uses the traditional cheapo method of icon
generation.

This way, we have fixed wagging Voxtails at a lower cost.

Even Cheaper

If the user's species isn't flagged to have a tail that needs to be
overlapped by limbs, it won't divert limbs into their own layer as it's
unnecessary. Tested by spawning a member of every species, walking
around to see if there was any directional issues, wagging and *swagging
all tails-- all is still working as it should be.
This commit is contained in:
KasparoVy
2016-01-10 23:46:39 -05:00
parent 4941d804fa
commit b6af0dd02b
9 changed files with 206 additions and 53 deletions
@@ -200,7 +200,7 @@
flags = NO_SCAN | IS_WHITELISTED
clothing_flags = HAS_SOCKS
dietflags = DIET_OMNI
bodyflags = HAS_TAIL | TAIL_WAGGING
bodyflags = HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED
blood_color = "#2299FC"
flesh_color = "#808D11"
@@ -106,33 +106,35 @@ Please contact me on #coderbus IRC. ~Carn x
//Human Overlays Indexes/////////
#define MUTANTRACE_LAYER 1
#define MARKINGS_LAYER 2
#define MUTATIONS_LAYER 3
#define DAMAGE_LAYER 4
#define UNIFORM_LAYER 5
#define ID_LAYER 6
#define SHOES_LAYER 7
#define GLOVES_LAYER 8
#define EARS_LAYER 9
#define SUIT_LAYER 10
#define GLASSES_LAYER 11
#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt?
#define TAIL_LAYER 13 //bs12 specific. this hack is probably gonna come back to haunt me
#define SUIT_STORE_LAYER 14
#define BACK_LAYER 15
#define HAIR_LAYER 16 //TODO: make part of head layer?
#define HEAD_ACCESSORY_LAYER 17
#define FHAIR_LAYER 18
#define FACEMASK_LAYER 19
#define HEAD_LAYER 20
#define COLLAR_LAYER 21
#define HANDCUFF_LAYER 22
#define LEGCUFF_LAYER 23
#define L_HAND_LAYER 24
#define R_HAND_LAYER 25
#define TARGETED_LAYER 26 //BS12: Layer for the target overlay from weapon targeting system
#define FIRE_LAYER 27 //If you're on fire
#define TOTAL_LAYERS 27
#define TAIL_UNDERLIMBS_LAYER 2
#define LIMBS_LAYER 3
#define MARKINGS_LAYER 4
#define MUTATIONS_LAYER 5
#define DAMAGE_LAYER 6
#define UNIFORM_LAYER 7
#define ID_LAYER 8
#define SHOES_LAYER 9
#define GLOVES_LAYER 10
#define EARS_LAYER 11
#define SUIT_LAYER 12
#define GLASSES_LAYER 13
#define BELT_LAYER 14 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 15
#define BACK_LAYER 16
#define TAIL_LAYER 17 //bs12 specific. this hack is probably gonna come back to haunt me
#define HAIR_LAYER 18 //TODO: make part of head layer?
#define HEAD_ACCESSORY_LAYER 19
#define FHAIR_LAYER 20
#define FACEMASK_LAYER 21
#define HEAD_LAYER 22
#define COLLAR_LAYER 23
#define HANDCUFF_LAYER 24
#define LEGCUFF_LAYER 25
#define L_HAND_LAYER 26
#define R_HAND_LAYER 27
#define TARGETED_LAYER 28 //BS12: Layer for the target overlay from weapon targeting system
#define FIRE_LAYER 29 //If you're on fire
#define TOTAL_LAYERS 29
@@ -323,6 +325,8 @@ var/global/list/damage_icon_parts = list()
//END CACHED ICON GENERATION.
stand_icon.Blend(base_icon,ICON_OVERLAY)
if(src.species.bodyflags & TAIL_OVERLAPPED) // If the user's species is flagged to have a tail that needs to be overlapped by limbs...
overlays_standing[LIMBS_LAYER] = image(stand_icon) // Diverts limbs to their own layer so they can overlay things (i.e. tails).
//Underwear
if(underwear && species.clothing_flags & HAS_UNDERWEAR)
@@ -1009,46 +1013,145 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/proc/update_tail_layer(var/update_icons=1)
overlays_standing[TAIL_LAYER] = null
overlays_standing[TAIL_UNDERLIMBS_LAYER] = null // SEW direction icons, overlayed by LIMBS_LAYER.
overlays_standing[TAIL_LAYER] = null // This will be one of two things:
// If the species' tail is overlapped by limbs, this will be only the N direction icon so tails can still appear on the outside of uniforms and such.
// Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions.
if(body_accessory)
if(body_accessory.try_restrictions(src))
var/icon/accessory_s = new/icon("icon" = body_accessory.icon, "icon_state" = body_accessory.icon_state)
accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode)
overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs...
// Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway.
var/icon/temp1 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s")
if(src.species.name in body_accessory.allowed_species)
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay")
temp1 = temp
else
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "vulptail_delay")
temp1 = temp
temp1.Insert(new/icon(accessory_s,dir=SOUTH),dir=SOUTH)
temp1.Insert(new/icon(accessory_s,dir=EAST),dir=EAST)
temp1.Insert(new/icon(accessory_s,dir=WEST),dir=WEST)
overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(temp1, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
// Creates a blank icon, and copies accessory_s' north direction sprite into it
// before passing that to the tail layer that overlays uniforms and such.
var/icon/temp2 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s")
if(src.species.name in body_accessory.allowed_species)
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay")
temp2 = temp
else
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "vulptail_delay")
temp2 = temp
temp2.Insert(new/icon(accessory_s,dir=NORTH),dir=NORTH)
overlays_standing[TAIL_LAYER] = image(temp2, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation.
overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
else if(species.tail && species.bodyflags & HAS_TAIL) //no tailless tajaran
if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space))
var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s")
tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
overlays_standing[TAIL_LAYER] = image(tail_s)
if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs...
// Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway.
var/icon/temp1 = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_delay")
temp1.Insert(new/icon(tail_s,dir=SOUTH),dir=SOUTH)
temp1.Insert(new/icon(tail_s,dir=EAST),dir=EAST)
temp1.Insert(new/icon(tail_s,dir=WEST),dir=WEST)
overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(temp1)
// Creates a blank icon, and copies accessory_s' north direction sprite into it
// before passing that to the tail layer that overlays uniforms and such.
var/icon/temp2 = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_delay")
temp2.Insert(new/icon(tail_s,dir=NORTH),dir=NORTH)
overlays_standing[TAIL_LAYER] = image(temp2)
else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation.
overlays_standing[TAIL_LAYER] = image(tail_s)
if(update_icons)
update_icons()
/mob/living/carbon/human/proc/start_tail_wagging(var/update_icons=1)
overlays_standing[TAIL_LAYER] = null
overlays_standing[TAIL_UNDERLIMBS_LAYER] = null // SEW direction icons, overlayed by LIMBS_LAYER.
overlays_standing[TAIL_LAYER] = null // This will be one of two things:
// If the species' tail is overlapped by limbs, this will be only the N direction icon so tails can still appear on the outside of uniforms and such.
// Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions.
if(body_accessory)
var/icon/accessory_s = new/icon("icon" = body_accessory.get_animated_icon(), "icon_state" = body_accessory.get_animated_icon_state())
accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode)
overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs...
// Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway.
var/icon/temp1 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s")
if(body_accessory.allowed_species)
if(src.species.name in body_accessory.allowed_species)
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay")
temp1 = temp
else
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "vulptail_delay")
temp1 = temp
temp1.Insert(accessory_s,dir=SOUTH)
temp1.Insert(accessory_s,dir=EAST)
temp1.Insert(accessory_s,dir=WEST)
overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(temp1, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
// Creates a blank icon, and copies accessory_s' north direction sprite into it
// before passing that to the tail layer that overlays uniforms and such.
var/icon/temp2 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s")
if(src.species.name in body_accessory.allowed_species) // If the user's species is in the list of allowed species for the currently selected body accessory, use the appropriate animation timing blank
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay")
temp2 = temp
else // Else if the user's species is not in the list of allowed species for the currently selected body accessory, this point must have been reached by admin-override. Use vulpkanin timings as default.
var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "vulptail_delay")
temp2 = temp
temp2.Insert(accessory_s,dir=NORTH)
overlays_standing[TAIL_LAYER] = image(temp2, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation.
overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
else if(species.tail && species.bodyflags & HAS_TAIL)
var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]w_s")
tailw_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
overlays_standing[TAIL_LAYER] = image(tailw_s)
if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs...
// Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway.
var/icon/temp1 = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_delay")
temp1.Insert(tailw_s,dir=SOUTH)
temp1.Insert(tailw_s,dir=EAST)
temp1.Insert(tailw_s,dir=WEST)
overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(temp1)
// Creates a blank icon, and copies accessory_s' north direction sprite into it
// before passing that to the tail layer that overlays uniforms and such.
var/icon/temp2 = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_delay")
temp2.Insert(tailw_s,dir=NORTH)
overlays_standing[TAIL_LAYER] = image(temp2)
else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation.
overlays_standing[TAIL_LAYER] = image(tailw_s)
if(update_icons)
update_icons()
/mob/living/carbon/human/proc/stop_tail_wagging(var/update_icons=1)
overlays_standing[TAIL_UNDERLIMBS_LAYER] = null
overlays_standing[TAIL_LAYER] = null
update_tail_layer(update_icons) //just trigger a full update for normal stationary sprites
@@ -1114,11 +1217,12 @@ var/global/list/damage_icon_parts = list()
//Human Overlays Indexes/////////
#undef MUTANTRACE_LAYER
#undef TAIL_UNDERLIMBS_LAYER
#undef LIMBS_LAYER
#undef MARKINGS_LAYER
#undef MUTATIONS_LAYER
#undef DAMAGE_LAYER
#undef UNIFORM_LAYER
#undef TAIL_LAYER
#undef ID_LAYER
#undef SHOES_LAYER
#undef GLOVES_LAYER
@@ -1129,6 +1233,7 @@ var/global/list/damage_icon_parts = list()
#undef BELT_LAYER
#undef SUIT_STORE_LAYER
#undef BACK_LAYER
#undef TAIL_LAYER
#undef HAIR_LAYER
#undef HEAD_LAYER
#undef HEAD_ACCESSORY_LAYER
@@ -211,16 +211,6 @@ datum/preferences
preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY)
preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY)
for(var/name in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand"))
if(organ_data[name] == "amputated") continue
if(organ_data[name] == "cyborg")
var/datum/robolimb/R
if(rlimb_data[name]) R = all_robolimbs[rlimb_data[name]]
if(!R) R = basic_robolimb
preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic.
continue
preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY)
//Tail
if(current_species && (current_species.bodyflags & HAS_TAIL))
var/tail_icon
@@ -237,6 +227,16 @@ datum/preferences
var/icon/temp = new /icon("icon" = tail_icon, "icon_state" = tail_icon_state)
preview_icon.Blend(temp, ICON_OVERLAY)
for(var/name in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand"))
if(organ_data[name] == "amputated") continue
if(organ_data[name] == "cyborg")
var/datum/robolimb/R
if(rlimb_data[name]) R = all_robolimbs[rlimb_data[name]]
if(!R) R = basic_robolimb
preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic.
continue
preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY)
// Skin color
if(current_species && (current_species.bodyflags & HAS_SKIN_COLOR))
preview_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)