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

Alternate tail/body/whatever-can-fit-on-the-tail-layer system #1997

Merged
merged 8 commits into from Sep 15, 2015
1 change: 1 addition & 0 deletions SQL/paradise_schema.sql
Expand Up @@ -79,6 +79,7 @@ CREATE TABLE `characters` (
`nanotrasen_relation` varchar(45) NOT NULL,
`speciesprefs` int(1) NOT NULL,
`socks` mediumtext NOT NULL,
`body_accessory` mediumtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18747 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
Expand Down
43 changes: 34 additions & 9 deletions code/modules/client/preferences.dm
Expand Up @@ -128,6 +128,7 @@ datum/preferences
var/species = "Human"
var/language = "None" //Secondary language

var/body_accessory = null

var/speciesprefs = 0//I hate having to do this, I really do (Using this for oldvox code, making names universal I guess

Expand Down Expand Up @@ -186,17 +187,17 @@ datum/preferences

// jukebox volume
var/volume = 100

// BYOND membership
var/unlock_content = 0

/datum/preferences/New(client/C)
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
if(istype(C))
if(!IsGuestKey(C.key))
unlock_content = C.IsByondMember()
if(unlock_content)
max_save_slots = MAX_SAVE_SLOTS_MEMBER
max_save_slots = MAX_SAVE_SLOTS_MEMBER
var/loaded_preferences_successfully = load_preferences(C)
if(loaded_preferences_successfully)
if(load_character(C))
Expand Down Expand Up @@ -366,10 +367,14 @@ datum/preferences
dat += "<br><b>Eyes</b><br>"
dat += "<a href='?_src_=prefs;preference=eyes;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_eyes, 2)][num2hex(g_eyes, 2)][num2hex(b_eyes, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_eyes, 2)][num2hex(g_eyes, 2)][num2hex(b_eyes)]'><tr><td>__</td></tr></table></font><br>"

if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Vulpkanin")
if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 1, user)) //admins can always fuck with this, because they are admins
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second parameter probably needs to be a 0. It shouldn't notify the user of a lack of rights if that check fails.

dat += "<br><b>Body Color</b><br>"
dat += "<a href='?_src_=prefs;preference=skin;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_skin, 2)][num2hex(g_skin, 2)][num2hex(b_skin, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_skin, 2)][num2hex(g_skin, 2)][num2hex(b_skin)]'><tr><td>__</td></tr></table></font>"

if(body_accessory_by_species[species] || check_rights(R_ADMIN, 1, user))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second parameter probably needs to be a 0. It shouldn't notify the user of a lack of rights if that check fails.

dat += "<br><b>Body Accessory</b><br>"
dat += "Accessory: <a href='?_src_=prefs;preference=body_accessory;task=input'>[body_accessory ? "[body_accessory]" : "None"]</a><br>"

dat += "</td></tr></table><hr><center>"

if (1) // General Preferences
Expand All @@ -387,15 +392,15 @@ datum/preferences
dat += "<b>Ghost radio:</b> <a href='?_src_=prefs;preference=ghost_radio'><b>[(toggles & CHAT_GHOSTRADIO) ? "Nearest Speakers" : "All Chatter"]</b></a><br>"
if(config.allow_Metadata)
dat += "<b>OOC notes:</b> <a href='?_src_=prefs;preference=metadata;task=input'><b>Edit</b></a><br>"

if(user.client)
if(user.client.holder)
dat += "<b>Adminhelp sound:</b> "
dat += "<a href='?_src_=prefs;preference=hear_adminhelps'><b>[(sound & SOUND_ADMINHELP)?"On":"Off"]</b></a><br>"

if(check_rights(R_ADMIN,0))
dat += "<b>OOC:</b> <span style='border: 1px solid #161616; background-color: [ooccolor ? ooccolor : normal_ooc_colour];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=ooccolor;task=input'><b>Change</b></a><br>"

if(unlock_content)
dat += "<b>BYOND Membership Publicity:</b> <a href='?_src_=prefs;preference=publicity'><b>[(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"

Expand Down Expand Up @@ -1165,10 +1170,27 @@ datum/preferences

valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]

var/new_h_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in valid_hairstyles
var/new_h_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in valid_hairstyles
if(new_h_style)
h_style = new_h_style

if("body_accessory")
var/list/possible_body_accessories = list()
if(check_rights(R_ADMIN, 1, user))
possible_body_accessories = body_accessory_by_name.Copy()
else
for(var/B in body_accessory_by_name)
var/datum/body_accessory/accessory = body_accessory_by_name[B]
if(!istype(accessory))
possible_body_accessories += "None" //the only null entry should be the "None" option
continue
if(species in accessory.allowed_species)
possible_body_accessories += B

var/new_body_accessory = input(user, "Choose your body accessory:", "Character Preference") as null|anything in possible_body_accessories
if(new_body_accessory)
body_accessory = new_body_accessory

if("facial")
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference") as color|null
if(new_facial)
Expand Down Expand Up @@ -1246,7 +1268,7 @@ datum/preferences
s_tone = 35 - max(min( round(new_s_tone), 220),1)

if("skin")
if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People"|| species == "Vulpkanin")
if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People"|| species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 1, user))
var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null
if(new_skin)
r_skin = hex2num(copytext(new_skin, 2, 4))
Expand Down Expand Up @@ -1381,7 +1403,7 @@ datum/preferences
if("publicity")
if(unlock_content)
toggles ^= MEMBER_PUBLIC

if("gender")
if(gender == MALE)
gender = FEMALE
Expand Down Expand Up @@ -1571,6 +1593,9 @@ datum/preferences
character.undershirt = undershirt
character.socks = socks

if(body_accessory)
character.body_accessory = body_accessory_by_name["[body_accessory]"]

if(backbag > 4 || backbag < 1)
backbag = 1 //Same as above
character.backbag = backbag
Expand Down
16 changes: 11 additions & 5 deletions code/modules/client/preferences_mysql.dm
Expand Up @@ -151,7 +151,8 @@

//socks
socks = query.item[54]

body_accessory = query.item[55]

//Sanitize
metadata = sanitize_text(metadata, initial(metadata))
real_name = reject_bad_name(real_name)
Expand Down Expand Up @@ -200,7 +201,7 @@
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))

socks = sanitize_text(socks, initial(socks))

body_accessory = sanitize_text(body_accessory, initial(body_accessory))

// if(isnull(disabilities)) disabilities = 0
if(!player_alt_titles) player_alt_titles = new()
Expand Down Expand Up @@ -274,7 +275,8 @@
rlimb_data='[rlimblist]',
nanotrasen_relation='[nanotrasen_relation]',
speciesprefs='[speciesprefs]',
socks='[socks]'
socks='[socks]',
body_accessory='[body_accessory]'
WHERE ckey='[C.ckey]'
AND slot='[default_slot]'"}
)
Expand Down Expand Up @@ -302,7 +304,9 @@
job_karma_high, job_karma_med, job_karma_low,
flavor_text, med_record, sec_record, gen_record,
player_alt_titles, be_special,
disabilities, organ_data, rlimb_data, nanotrasen_relation, speciesprefs, socks)
disabilities, organ_data, rlimb_data, nanotrasen_relation, speciesprefs,
socks, body_accessory)

VALUES
('[C.ckey]', '[default_slot]', '[sql_sanitize_text(metadata)]', '[sql_sanitize_text(real_name)]', '[be_random_name]','[gender]',
'[age]', '[sql_sanitize_text(species)]', '[sql_sanitize_text(language)]',
Expand All @@ -319,7 +323,9 @@
'[job_karma_high]', '[job_karma_med]', '[job_karma_low]',
'[sql_sanitize_text(flavor_text)]', '[sql_sanitize_text(med_record)]', '[sql_sanitize_text(sec_record)]', '[sql_sanitize_text(gen_record)]',
'[playertitlelist]', '[be_special]',
'[disabilities]', '[organlist]', '[rlimblist]', '[nanotrasen_relation]', '[speciesprefs]','[socks]')
'[disabilities]', '[organlist]', '[rlimblist]', '[nanotrasen_relation]', '[speciesprefs]',
'[socks]', '[body_accessory]')

"}
)

Expand Down
133 changes: 133 additions & 0 deletions code/modules/mob/living/carbon/human/body_accessories.dm
@@ -0,0 +1,133 @@
var/global/list/body_accessory_by_name = list("None" = null)

/hook/startup/proc/initalize_body_accessories()

__init_body_accessory(/datum/body_accessory/body)
__init_body_accessory(/datum/body_accessory/tail)

if(body_accessory_by_name.len)
if(initialize_body_accessory_by_species())
return 1

return 0 //fail if no bodies are found

var/global/list/body_accessory_by_species = list("None" = null)

/proc/initialize_body_accessory_by_species()
for(var/B in body_accessory_by_name)
var/datum/body_accessory/accessory = body_accessory_by_name[B]
if(!istype(accessory)) continue

for(var/species in accessory.allowed_species)
if(!body_accessory_by_species["[species]"]) body_accessory_by_species["[species]"] = list()
body_accessory_by_species["[species]"] += accessory

if(body_accessory_by_species.len)
return 1
return 0

/proc/__init_body_accessory(var/ba_path)
if(ispath(ba_path))
var/_added_counter = 0

for(var/A in subtypesof(ba_path))
var/datum/body_accessory/B = new A
if(istype(B))
body_accessory_by_name[B.name] += B
++_added_counter

if(_added_counter)
return 1
return 0


/datum/body_accessory
var/name = "default"

var/icon = null
var/icon_state = ""

var/animated_icon = null
var/animated_icon_state = ""

var/blend_mode = null

var/pixel_x_offset = 0
var/pixel_y_offset = 0

var/list/allowed_species = list()

/datum/body_accessory/proc/try_restrictions(var/mob/living/carbon/human/H)
return 1

/datum/body_accessory/proc/get_pixel_x(var/mob/living/carbon/human/H)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This... doesn't really need to exist.
same for it's Y counterpart, and actually adds a small about of lag to obtaining that var (because of the proccall)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in place for anything that needs special handling depending on the human it's attached to, I suppose I could remove it until something of the sort is actually a thing, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I get -why- it might be needed in the future, but atm it's literally inefficiency personified.

return pixel_x_offset

/datum/body_accessory/proc/get_pixel_y(var/mob/living/carbon/human/H)
return pixel_y_offset

/datum/body_accessory/proc/get_animated_icon() //return animated if it has it, return static if it does not.
if(animated_icon)
return animated_icon

else return icon

/datum/body_accessory/proc/get_animated_icon_state()
if(animated_icon_state)
return animated_icon_state

else return icon_state


//Bodies
/datum/body_accessory/body
blend_mode = ICON_MULTIPLY

/datum/body_accessory/body/snake
name = "Snake"

icon = 'icons/mob/body_accessory_64.dmi'
icon_state = "naga"

pixel_x_offset = -16

//Tails
/datum/body_accessory/tail
icon = 'icons/mob/body_accessory.dmi'
animated_icon = 'icons/mob/body_accessory.dmi'
blend_mode = ICON_ADD

/datum/body_accessory/tail/try_restrictions(var/mob/living/carbon/human/H)
if(!H.wear_suit || !(H.wear_suit.flags_inv & HIDETAIL) && !istype(H.wear_suit, /obj/item/clothing/suit/space))
return 1
return 0


//vulpakin
/datum/body_accessory/tail/vulpkanin_2
name = "Vulpkanin Alt 1 (Bushy)"

icon_state = "vulptail2"
animated_icon_state = "vulptail2_a"
allowed_species = list("Vulpkanin")

/datum/body_accessory/tail/vulpkanin_3
name = "Vulpkanin Alt 2 (Straight)"

icon_state = "vulptail3"
animated_icon_state = "vulptail3_a"
allowed_species = list("Vulpkanin")

/datum/body_accessory/tail/vulpkanin_4
name = "Vulpkanin Alt 3 (Tiny)"

icon_state = "vulptail4"
animated_icon_state = "vulptail4_a"
allowed_species = list("Vulpkanin")

/datum/body_accessory/tail/vulpkanin_5
name = "Vulpkanin Alt 4 (Short)"

icon_state = "vulptail5"
animated_icon_state = "vulptail5_a"
allowed_species = list("Vulpkanin")
9 changes: 7 additions & 2 deletions code/modules/mob/living/carbon/human/emote.dm
Expand Up @@ -116,7 +116,12 @@
m_type = 1

if("wag")
if(species.bodyflags & TAIL_WAGGING)
if(body_accessory)
if(body_accessory.try_restrictions(src))
message = "<B>[src]</B> starts wagging \his tail."
start_tail_wagging(1)

else if(species.bodyflags & TAIL_WAGGING)
if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space))
message = "<B>[src]</B> starts wagging \his tail."
src.start_tail_wagging(1)
Expand All @@ -126,7 +131,7 @@
return

if("swag")
if(species.bodyflags & TAIL_WAGGING)
if(species.bodyflags & TAIL_WAGGING || body_accessory)
message = "<B>[src]</B> stops wagging \his tail."
src.stop_tail_wagging(1)
else
Expand Down
4 changes: 3 additions & 1 deletion code/modules/mob/living/carbon/human/human_defines.dm
Expand Up @@ -82,4 +82,6 @@
var/lastFart = 0 // Toxic fart cooldown.

var/fire_dmi = 'icons/mob/OnFire.dmi'
var/fire_sprite = "Standing"
var/fire_sprite = "Standing"

var/datum/body_accessory/body_accessory = null