diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index bf7afd1e029..bd312dd4ec5 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -68,6 +68,8 @@
#define NOHUNGER 17
#define NOCRITDAMAGE 18
+#define FLYING 65536
+
/*
These defines are used specifically with the atom/movable/languages bitmask.
They are used in atom/movable/Hear() and atom/movable/say() to determine whether hearers can understand a message.
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 1b78d640dbe..a9d31410015 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -23,24 +23,25 @@
#define FRIDAY_13TH "Friday the 13th"
//Human Overlays Indexes/////////
-#define MUTATIONS_LAYER 27 //mutations. Tk headglows, cold resistance glow, etc
-#define SPECIES_LAYER 26 // mutantrace colors... these are on a seperate layer in order to prvent
-#define BODY_BEHIND_LAYER 25 //certain mutantrace features (tail when looking south) that must appear behind the body parts
-#define BODYPARTS_LAYER 24 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag
-#define BODY_ADJ_LAYER 23 //certain mutantrace features (snout, body markings) that must appear above the body parts
-#define BODY_LAYER 22 //underwear, undershirts, socks, eyes, lips(makeup)
-#define FRONT_MUTATIONS_LAYER 21 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes)
-#define DAMAGE_LAYER 20 //damage indicators (cuts and burns)
-#define UNIFORM_LAYER 19
-#define ID_LAYER 18
-#define SHOES_LAYER 17
-#define GLOVES_LAYER 16
-#define EARS_LAYER 15
-#define SUIT_LAYER 14
-#define GLASSES_LAYER 13
-#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt?
-#define SUIT_STORE_LAYER 11
-#define BACK_LAYER 10
+#define MUTATIONS_LAYER 28 //mutations. Tk headglows, cold resistance glow, etc
+#define SPECIES_LAYER 27 // mutantrace colors... these are on a seperate layer in order to prvent
+#define BODY_BEHIND_LAYER 26 //certain mutantrace features (tail when looking south) that must appear behind the body parts
+#define BODYPARTS_LAYER 25 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag
+#define BODY_ADJ_LAYER 24 //certain mutantrace features (snout, body markings) that must appear above the body parts
+#define BODY_LAYER 23 //underwear, undershirts, socks, eyes, lips(makeup)
+#define FRONT_MUTATIONS_LAYER 22 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes)
+#define DAMAGE_LAYER 21 //damage indicators (cuts and burns)
+#define UNIFORM_LAYER 20
+#define ID_LAYER 19
+#define SHOES_LAYER 18
+#define GLOVES_LAYER 17
+#define SUIT_LAYER 16
+#define BELT_LAYER 15 //Possible make this an overlay of somethign required to wear a belt?
+#define SUIT_STORE_LAYER 14
+#define BODY_WING_LAYER 13 //Optimum layer for wing mutant parts. below hair and headgear, and above shit on the body. Can't do better without directional layers
+#define BACK_LAYER 12
+#define EARS_LAYER 11
+#define GLASSES_LAYER 10
#define HAIR_LAYER 9 //TODO: make part of head layer?
#define FACEMASK_LAYER 8
#define HEAD_LAYER 7
@@ -50,7 +51,7 @@
#define R_HAND_LAYER 3 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands
#define BODY_FRONT_LAYER 2
#define FIRE_LAYER 1 //If you're on fire
-#define TOTAL_LAYERS 27 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
+#define TOTAL_LAYERS 28 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
//Human Overlay Index Shortcuts for alternate_worn_layer, layers
//Because I *KNOW* somebody will think layer+1 means "above"
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 7fedc48428d..f77e0cf5300 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -22,9 +22,12 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts, snouts_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, horns_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, ears_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, wings_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/wings_open, wings_open_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, frills_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, spines_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines_animated, animated_spines_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, r_wings_list,roundstart = TRUE)
//Species
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 5fc6b1400d6..41c5a80fe81 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -64,9 +64,11 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, spines_list)
if(!body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, body_markings_list)
+ if(!wings_list.len)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, wings_list)
//For now we will always return none for tail_human and ears.
- return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), "tail_lizard" = pick(tails_list_lizard), "tail_human" = "None", "snout" = pick(snouts_list), "horns" = pick(horns_list), "ears" = "None", "frills" = pick(frills_list), "spines" = pick(spines_list), "body_markings" = pick(body_markings_list)))
+ return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), "tail_lizard" = pick(tails_list_lizard), "tail_human" = "None", "wings" = "None", "snout" = pick(snouts_list), "horns" = pick(horns_list), "ears" = "None", "frills" = pick(frills_list), "spines" = pick(spines_list), "body_markings" = pick(body_markings_list)))
/proc/random_hair_style(gender)
switch(gender)
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 5116c62e83e..9eb72f5b6e6 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -19,16 +19,21 @@ var/global/list/socks_list = list() //stores /datum/sprite_accessory/socks inde
//Lizard Bits (all datum lists indexed by name)
var/global/list/body_markings_list = list()
var/global/list/tails_list_lizard = list()
-var/global/list/tails_list_human = list()
var/global/list/animated_tails_list_lizard = list()
-var/global/list/animated_tails_list_human = list()
var/global/list/snouts_list = list()
var/global/list/horns_list = list()
-var/global/list/ears_list = list()
var/global/list/frills_list = list()
var/global/list/spines_list = list()
var/global/list/animated_spines_list = list()
+ //Mutant Human bits
+var/global/list/tails_list_human = list()
+var/global/list/animated_tails_list_human = list()
+var/global/list/ears_list = list()
+var/global/list/wings_list = list()
+var/global/list/wings_open_list = list()
+var/global/list/r_wings_list = list()
+
var/global/list/ghost_forms_with_directions_list = list("ghost") //stores the ghost forms that support directional sprites
var/global/list/ghost_forms_with_accessories_list = list("ghost") //stores the ghost forms that support hair and other such things
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 1908392d673..8225802a820 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -927,7 +927,7 @@ body
usr << "Mob doesn't exist anymore"
return
- if(H.dna.species.id == "human")
+ if(("tail_human" in H.dna.species.mutant_bodyparts) && ("ears" in H.dna.species.mutant_bodyparts))
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
usr << "Put [H] on purrbation."
H << "Something is nya~t right."
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index bf412453520..064c0e3dd94 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -120,7 +120,7 @@
name = "magic mirror"
desc = "Turn and face the strange... face."
icon_state = "magic_mirror"
- var/list/races_blacklist = list("skeleton", "agent")
+ var/list/races_blacklist = list("skeleton", "agent", "angel")
var/list/choosable_races = list()
/obj/structure/mirror/magic/New()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 22a6805431c..57854738378 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -59,7 +59,7 @@ var/list/preferences_datums = list()
var/skin_tone = "caucasian1" //Skin color
var/eye_color = "000" //Eye color
var/datum/species/pref_species = new /datum/species/human() //Mutant race
- var/list/features = list("mcolor" = "FFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "ears" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
+ var/list/features = list("mcolor" = "FFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
var/list/custom_names = list("clown", "mime", "ai", "cyborg", "religion", "deity")
//Mob preview
@@ -323,6 +323,15 @@ var/list/preferences_datums = list()
dat += ""
+ if("wings" in pref_species.mutant_bodyparts && r_wings_list.len >1)
+ dat += "
"
+
+ dat += "Wings"
+
+ dat += "[features["wings"]] "
+
+ dat += " | "
+
dat += ""
@@ -945,6 +954,12 @@ var/list/preferences_datums = list()
if(new_ears)
features["ears"] = new_ears
+ if("wings")
+ var/new_wings
+ new_wings = input(user, "Choose your character's wings:", "Character Preference") as null|anything in r_wings_list
+ if(new_wings)
+ features["wings"] = new_wings
+
if("frills")
var/new_frills
new_frills = input(user, "Choose your character's frills:", "Character Preference") as null|anything in frills_list
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 8fe9e12e507..0f33a087bd2 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -584,6 +584,8 @@
visible_message("[H] falls into [src]!")
J.chasm_react(H)
return
+ if(H.dna.species && (FLYING in H.dna.species.specflags))
+ return
drop(AM)
@@ -756,4 +758,4 @@
smooth_icon = 'icons/turf/floors/rocky_ash.dmi'
slowdown = 0
smooth = SMOOTH_MORE|SMOOTH_BORDER
- canSmoothWith = list (/turf/open/floor/plating/ash/rocky, /turf/closed)
\ No newline at end of file
+ canSmoothWith = list (/turf/open/floor/plating/ash/rocky, /turf/closed)
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index 5fdfa802698..173bac91986 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -39,4 +39,4 @@ var/const/GALOSHES_DONT_HELP = 4
if(src.m_intent == "run")
src.nutrition -= HUNGER_FACTOR/10
if((src.disabilities & FAT) && src.m_intent == "run" && src.bodytemperature <= 360)
- src.bodytemperature += 2
\ No newline at end of file
+ src.bodytemperature += 2
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 600150027a8..25b62417d9c 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -129,6 +129,21 @@
if (!src.restrained())
message = "[src] flaps \his wings."
m_type = 2
+ if(((dna.features["wings"] != "None") && !("wings" in dna.species.mutant_bodyparts)))
+ OpenWings()
+ spawn(20)
+ CloseWings()
+
+ if ("wings")
+ if (!src.restrained())
+ if(dna && dna.species &&((dna.features["wings"] != "None") && ("wings" in dna.species.mutant_bodyparts)))
+ message = "[src] opens \his wings."
+ OpenWings()
+ else if(dna && dna.species &&((dna.features["wings"] != "None") && ("wingsopen" in dna.species.mutant_bodyparts)))
+ message = "[src] closes \his wings."
+ CloseWings()
+ else
+ src << "Unusable emote '[act]'. Say *help for a list."
if ("gasp","gasps")
if (miming)
@@ -327,7 +342,7 @@
src << "Unusable emote '[act]'. Say *help for a list."
if ("help") //This can stay at the bottom.
- src << "Help for human emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, dance, dap, deathgasp, drool, eyebrow, faint, flap, frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, jump, laugh, look-(none)/mob, me, moan, mumble, nod, pale, point-(atom), raise, salute, scream, shake, shiver, shrug, sigh, signal-#1-10, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tremble, twitch, twitch_s, wave, whimper, wink, wag, yawn"
+ src << "Help for human emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, dance, dap, deathgasp, drool, eyebrow, faint, flap, frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, jump, laugh, look-(none)/mob, me, moan, mumble, nod, pale, point-(atom), raise, salute, scream, shake, shiver, shrug, sigh, signal-#1-10, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tremble, twitch, twitch_s, wave, whimper, wink, wings, wag, yawn"
else
..(act)
@@ -383,4 +398,20 @@
if("waggingtail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_human"
dna.species.mutant_bodyparts |= "tail_human"
+ update_body()
+
+/mob/living/carbon/human/proc/OpenWings()
+ if(!dna || !dna.species)
+ return
+ if("wings" in dna.species.mutant_bodyparts)
+ dna.species.mutant_bodyparts -= "wings"
+ dna.species.mutant_bodyparts |= "wingsopen"
+ update_body()
+
+/mob/living/carbon/human/proc/CloseWings()
+ if(!dna || !dna.species)
+ return
+ if("wingsopen" in dna.species.mutant_bodyparts)
+ dna.species.mutant_bodyparts -= "wingsopen"
+ dna.species.mutant_bodyparts |= "wings"
update_body()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 3a9605fa98d..0614caaf9f0 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1080,3 +1080,7 @@
/mob/living/carbon/human/is_literate()
return 1
+
+/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
+ override = dna.species.override_float
+ ..()
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 84381f3d17b..cf6bbfc765a 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -375,3 +375,7 @@
if(w_uniform)
w_uniform.add_fingerprint(user)
..()
+
+/mob/living/carbon/human/Stun(amount, updating_canmove = 1)
+ amount = dna.species.spec_stun(src,amount)
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index f2723f7bd5c..0bc87b8520a 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -22,7 +22,7 @@
. = 1
/mob/living/carbon/human/mob_negates_gravity()
- return shoes && shoes.negates_gravity()
+ return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity())
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
@@ -54,3 +54,8 @@
S.step_action()
+
+/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
+ if(..())
+ return 1
+ return dna.species.space_move()
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 6276b1fec89..70450bd83ec 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -21,6 +21,7 @@
/datum/species
var/id = null // if the game needs to manually check your race to do something not included in a proc here, it will use this
+ var/limbs_id = null //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
var/name = null // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
var/roundstart = 0 // can this mob be chosen at roundstart? (assuming the config option is checked?)
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
@@ -47,6 +48,7 @@
var/burnmod = 1 // multiplier for burn damage
var/coldmod = 1 // multiplier for cold damage
var/heatmod = 1 // multiplier for heat damage
+ var/stunmod = 1 // multiplier for stun duration
var/punchdamagelow = 0 //lowest possible punch damage
var/punchdamagehigh = 9 //highest possible punch damage
var/punchstunthreshold = 9//damage at which punches from this race will stun //yes it should be to the attacked race but it's not useful that way even if it's logical
@@ -83,11 +85,19 @@
var/tox_breath_dam_min = MIN_PLASMA_DAMAGE
var/tox_breath_dam_max = MAX_PLASMA_DAMAGE
+ //Flight and floating
+ var/override_float = 0
+
///////////
// PROCS //
///////////
+/datum/species/New()
+ if(!limbs_id) //if we havent set a limbs id to use, just use our own id
+ limbs_id = id
+ ..()
+
//Called when admins use the Set Species verb, let's species
//do some init stuff on the mob that got SS'd if necessary
@@ -350,12 +360,13 @@
/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
var/list/bodyparts_to_add = mutant_bodyparts.Copy()
- var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
+ var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER, BODY_WING_LAYER)
var/list/standing = list()
H.remove_overlay(BODY_BEHIND_LAYER)
H.remove_overlay(BODY_ADJ_LAYER)
H.remove_overlay(BODY_FRONT_LAYER)
+ H.remove_overlay(BODY_WING_LAYER)
if(!mutant_bodyparts)
return
@@ -409,6 +420,17 @@
if(!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == ORGAN_ROBOTIC)
bodyparts_to_add -= "ears"
+ if("wings" in mutant_bodyparts)
+ if(!H.dna.features["wings"] || H.dna.features["wings"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)))
+ bodyparts_to_add -= "wings"
+
+ if("wings_open" in mutant_bodyparts)
+ if(H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
+ bodyparts_to_add -= "wings_open"
+ else if ("wings" in mutant_bodyparts)
+ bodyparts_to_add -= "wings_open"
+
+
if(!bodyparts_to_add)
return
@@ -442,6 +464,10 @@
S = ears_list[H.dna.features["ears"]]
if("body_markings")
S = body_markings_list[H.dna.features["body_markings"]]
+ if("wings")
+ S = wings_list[H.dna.features["wings"]]
+ if("wingsopen")
+ S = wings_open_list[H.dna.features["wings"]]
if(!S || S.icon_state == "none")
continue
@@ -460,7 +486,10 @@
else
icon_string = "m_[bodypart]_[S.icon_state]_[layer]"
- I = image("icon" = 'icons/mob/mutant_bodyparts.dmi', "icon_state" = icon_string, "layer" =- layer)
+ I = image("icon" = S.icon, "icon_state" = icon_string, "layer" =- layer)
+
+ if(S.center)
+ I = center_image(I,S.dimension_x,S.dimension_y)
if(!(H.disabilities & HUSK))
if(!forced_colour)
@@ -486,7 +515,10 @@
else
icon_string = "m_[bodypart]inner_[S.icon_state]_[layer]"
- I = image("icon" = 'icons/mob/mutant_bodyparts.dmi', "icon_state" = icon_string, "layer" =- layer)
+ I = image("icon" = S.icon, "icon_state" = icon_string, "layer" =- layer)
+
+ if(S.center)
+ I = center_image(I,S.dimension_x,S.dimension_y)
standing += I
@@ -496,6 +528,7 @@
H.apply_overlay(BODY_BEHIND_LAYER)
H.apply_overlay(BODY_ADJ_LAYER)
H.apply_overlay(BODY_FRONT_LAYER)
+ H.apply_overlay(BODY_WING_LAYER)
/datum/species/proc/spec_life(mob/living/carbon/human/H)
if(NOBREATH in specflags)
@@ -866,6 +899,9 @@
if(!(H.status_flags & IGNORESLOWDOWN))
if(!has_gravity(H))
+ if(specflags & FLYING)
+ . += speedmod
+ return
// If there's no gravity we have the sanic speed of jetpack.
var/obj/item/weapon/tank/jetpack/J = H.back
var/obj/item/clothing/suit/space/hardsuit/C = H.wear_suit
@@ -904,10 +940,11 @@
if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
. += (BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR
- var/leg_amount = H.get_num_legs()
- . += 6 - 3*leg_amount //the fewer the legs, the slower the mob
- if(!leg_amount)
- . += 6 - 3*H.get_num_arms() //crawling is harder with fewer arms
+ if(!(specflags & FLYING))
+ var/leg_amount = H.get_num_legs()
+ . += 6 - 3*leg_amount //the fewer the legs, the slower the mob
+ if(!leg_amount)
+ . += 6 - 3*H.get_num_arms() //crawling is harder with fewer arms
. += speedmod
@@ -1485,6 +1522,25 @@
/datum/species/proc/ExtinguishMob(mob/living/carbon/human/H)
return
+
+////////
+//Stun//
+////////
+
+/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
+ . = stunmod * amount
+
+//////////////
+//Space Move//
+//////////////
+
+/datum/species/proc/space_move()
+ return 0
+
+/datum/species/proc/negates_gravity()
+ return 0
+
+
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm
index eb87e5eae71..3eeb393cdb6 100644
--- a/code/modules/mob/living/carbon/human/species_types.dm
+++ b/code/modules/mob/living/carbon/human/species_types.dm
@@ -7,8 +7,8 @@
id = "human"
default_color = "FFFFFF"
specflags = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
- mutant_bodyparts = list("tail_human", "ears")
- default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None")
+ mutant_bodyparts = list("tail_human", "ears", "wings")
+ default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None")
use_skintones = 1
skinned_type = /obj/item/stack/sheet/animalhide/human
@@ -725,3 +725,148 @@ SYNDICATE BLACK OPS
use_skintones = 0
specflags = list(RADIMMUNE,VIRUSIMMUNE,NOBLOOD,PIERCEIMMUNE,EYECOLOR,NODISMEMBER,NOHUNGER)
sexes = 0
+
+/datum/species/angel
+ name = "Angel"
+ id = "angel"
+ default_color = "FFFFFF"
+ specflags = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
+ mutant_bodyparts = list("tail_human", "ears", "wings")
+ default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "Angel")
+ use_skintones = 1
+ no_equip = list(slot_back)
+ blacklisted = 1
+ limbs_id = "human"
+ skinned_type = /obj/item/stack/sheet/animalhide/human
+
+ var/datum/action/innate/flight/fly
+
+/datum/species/angel/on_species_gain(mob/living/carbon/human/H)
+ ..()
+ if(H.dna && H.dna.species &&((H.dna.features["wings"] != "Angel") && ("wings" in H.dna.species.mutant_bodyparts)))
+ H.dna.features["wings"] = "Angel"
+ H.update_body()
+ if(ishuman(H)&& !fly)
+ fly = new
+ fly.Grant(H)
+
+
+/datum/species/angel/on_species_loss(mob/living/carbon/human/H)
+ if(fly)
+ fly.Remove(H)
+ if(FLYING in specflags)
+ specflags -= FLYING
+ ToggleFlight(H,0)
+ if(H.dna && H.dna.species &&((H.dna.features["wings"] != "None") && ("wings" in H.dna.species.mutant_bodyparts)))
+ H.dna.features["wings"] = "None"
+ H.update_body()
+ ..()
+
+/datum/species/angel/spec_life(mob/living/carbon/human/H)
+ HandleFlight(H)
+
+/datum/species/angel/proc/HandleFlight(mob/living/carbon/human/H)
+ if(FLYING in specflags)
+ if(!CanFly(H))
+ ToggleFlight(H,0)
+ H.float(0)
+ return 0
+ H.float(1)
+ return 1
+ else
+ H.float(0)
+ return 0
+
+/datum/species/angel/proc/CanFly(mob/living/carbon/human/H)
+ if(H.stat || H.stunned || H.weakened)
+ return 0
+ if(H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) //Jumpsuits have tail holes, so it makes sense they have wing holes too
+ H << "Your suit blocks your wings from extending!"
+ return 0
+ var/turf/T = get_turf(H)
+ if(!T)
+ return 0
+
+ var/datum/gas_mixture/environment = T.return_air()
+ if(environment && !(environment.return_pressure() > 30))
+ H << "The atmosphere is too thin for you to fly!"
+ return 0
+ else
+ return 1
+
+/datum/action/innate/flight
+ name = "Toggle Flight"
+ check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUNNED
+ button_icon_state = "slimesplit"
+ background_icon_state = "bg_alien"
+
+/datum/action/innate/flight/Activate()
+ var/mob/living/carbon/human/H = owner
+ var/datum/species/angel/A = H.dna.species
+ if(A.CanFly(H))
+ if(FLYING in A.specflags)
+ H << "You settle gently back onto the ground..."
+ A.specflags -= FLYING
+ A.ToggleFlight(H,0)
+ H.update_canmove()
+ else
+ H << "You beat your wings and begin to hover gently above the ground..."
+ A.specflags += FLYING
+ H.resting = 0
+ A.ToggleFlight(H,1)
+ H.update_canmove()
+
+/datum/species/angel/proc/flyslip(mob/living/carbon/human/H)
+ var/obj/buckled_obj
+ if(H.buckled)
+ buckled_obj = H.buckled
+
+ H << "Your wings spazz out and launch you!"
+
+ playsound(H.loc, 'sound/misc/slip.ogg', 50, 1, -3)
+
+ H.accident(H.l_hand)
+ H.accident(H.r_hand)
+
+ var/olddir = H.dir
+
+ H.stop_pulling()
+ if(buckled_obj)
+ buckled_obj.unbuckle_mob(H)
+ step(buckled_obj, olddir)
+ else
+ for(var/i=1, i<5, i++)
+ spawn (i)
+ step(H, olddir)
+ H.spin(1,1)
+ return 1
+
+
+/datum/species/angel/spec_stun(mob/living/carbon/human/H,amount)
+ if(FLYING in specflags)
+ flyslip(H)
+ . = ..()
+
+/datum/species/angel/negates_gravity()
+ if(FLYING in specflags)
+ return 1
+
+/datum/species/angel/space_move()
+ if(FLYING in specflags)
+ return 1
+
+/datum/species/angel/proc/ToggleFlight(mob/living/carbon/human/H,flight)
+ if(flight && CanFly(H))
+ stunmod = 2
+ speedmod = -1
+ specflags += FLYING
+ override_float = 1
+ H.pass_flags |= PASSTABLE
+ H.OpenWings()
+ else
+ stunmod = 1
+ speedmod = 0
+ specflags -= FLYING
+ override_float = 0
+ H.pass_flags &= ~PASSTABLE
+ H.CloseWings()
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index d0650f6ae05..7ba6b4da8d6 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -585,7 +585,7 @@ var/global/list/limb_icon_cache = list()
//produces a key based on the human's limbs
/mob/living/carbon/human/proc/generate_icon_render_key()
- . = "[dna.species.id]"
+ . = "[dna.species.limbs_id]"
if(dna.check_mutation(HULK))
. += "-coloured-hulk"
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 0209d40b126..97cbc6c99e9 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -690,14 +690,15 @@ Sorry Giacom. Please don't be mad :(
/mob/living/proc/get_visible_name()
return name
-/mob/living/update_gravity(has_gravity)
+/mob/living/update_gravity(has_gravity,override = 0)
if(!ticker || !ticker.mode)
return
if(has_gravity)
clear_alert("weightless")
else
throw_alert("weightless", /obj/screen/alert/weightless)
- float(!has_gravity)
+ if(!override)
+ float(!has_gravity)
/mob/living/proc/float(on)
if(throwing)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 45442b8f7cc..d8fd2af810f 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -61,7 +61,6 @@
//simple_animal access
var/obj/item/weapon/card/id/access_card = null //innate access uses an internal ID card
var/flying = 0 //whether it's flying or touching the ground.
-
var/buffed = 0 //In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to 1, so we have something to check against
var/gold_core_spawnable = 0 //if 1 can be spawned by plasma with gold core, 2 are 'friendlies' spawned with blood
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index d5647ed98dc..f9b5b4b161d 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -661,13 +661,14 @@ var/next_mob_id = 0
var/buckle_lying = !(buckled && !buckled.buckle_lying)
var/has_legs = get_num_legs()
var/has_arms = get_num_arms()
+ var/ignore_legs = get_leg_ignore()
if(ko || resting || stunned || chokehold)
drop_r_hand()
drop_l_hand()
unset_machine()
if(pulling)
stop_pulling()
- else if(has_legs)
+ else if(has_legs || ignore_legs)
lying = 0
if(buckled)
@@ -675,9 +676,9 @@ var/next_mob_id = 0
else if(!lying)
if(resting)
fall()
- else if(ko || !has_legs || chokehold)
+ else if(ko || (!has_legs && !ignore_legs) || chokehold)
fall(forced = 1)
- canmove = !(ko || resting || stunned || chokehold || buckled || (!has_legs && !has_arms))
+ canmove = !(ko || resting || stunned || chokehold || buckled || (!has_legs && !ignore_legs && !has_arms))
density = !lying
if(lying)
if(layer == initial(layer)) //to avoid special cases like hiding larvas.
diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index 930d7a33a15..9da3d6ec762 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -16,7 +16,7 @@
from doing this unless you absolutely know what you are doing, and have defined a
conversion in savefile.dm
*/
-/proc/init_sprite_accessory_subtypes(prototype, list/L, list/male, list/female)
+/proc/init_sprite_accessory_subtypes(prototype, list/L, list/male, list/female,var/roundstart = FALSE)//Roundstart argument builds a specific list for roundstart parts where some parts may be locked
if(!istype(L))
L = list()
if(!istype(male))
@@ -27,6 +27,10 @@
for(var/path in typesof(prototype))
if(path == prototype)
continue
+ if(roundstart)
+ var/datum/sprite_accessory/P = path
+ if(initial(P.locked))
+ continue
var/datum/sprite_accessory/D = new path()
if(D.icon_state)
@@ -52,6 +56,10 @@
var/gender_specific //Something that can be worn by either gender, but looks different on each
var/color_src = MUTCOLORS //Currently only used by mutantparts so don't worry about hair and stuff. This is the source that this accessory will get its color from. Default is MUTCOLOR, but can also be HAIR, FACEHAIR, EYECOLOR and 0 if none.
var/hasinner //Decides if this sprite has an "inner" part, such as the fleshy parts on ears.
+ var/locked = 0 //Is this part locked from roundstart selection? Used for parts that apply effects
+ var/dimension_x = 32
+ var/dimension_y = 32
+ var/center = FALSE //Should we center the sprite?
//////////////////////
// Hair Definitions //
@@ -1285,6 +1293,9 @@
name = "Angeler"
icon_state = "angler"
+/datum/sprite_accessory/ears
+ icon = 'icons/mob/mutant_bodyparts.dmi'
+
/datum/sprite_accessory/ears/none
name = "None"
icon_state = "none"
@@ -1295,6 +1306,33 @@
hasinner = 1
color_src = HAIR
+/datum/sprite_accessory/wings/none
+ name = "None"
+ icon_state = "none"
+
+/datum/sprite_accessory/wings_open
+ icon = 'icons/mob/wings.dmi'
+
+/datum/sprite_accessory/wings_open/angel
+ name = "Angel"
+ icon_state = "angel"
+ color_src = 0
+ dimension_x = 46
+ center = TRUE
+ dimension_y = 34
+
+/datum/sprite_accessory/wings
+ icon = 'icons/mob/wings.dmi'
+
+/datum/sprite_accessory/wings/angel
+ name = "Angel"
+ icon_state = "angel"
+ color_src = 0
+ dimension_x = 46
+ center = TRUE
+ dimension_y = 34
+ locked = TRUE
+
/datum/sprite_accessory/frills
icon = 'icons/mob/mutant_bodyparts.dmi'
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index e92340bee3d..7da8bf4f4b2 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -174,7 +174,7 @@
should_draw_greyscale = FALSE
var/datum/species/S = H.dna.species
- species_id = S.id
+ species_id = S.limbs_id
if(S.use_skintones)
skin_tone = H.skin_tone
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index c1980400a45..28ed730f9af 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -51,6 +51,13 @@
/mob/proc/get_num_legs()
return 2
+/mob/proc/get_leg_ignore()
+ return 0
+
+/mob/living/carbon/human/get_leg_ignore()
+ if(FLYING in dna.species.specflags)
+ return 1
+
/mob/living/carbon/human/get_num_arms()
. = 0
for(var/X in bodyparts)
diff --git a/icons/mob/wings.dmi b/icons/mob/wings.dmi
new file mode 100644
index 00000000000..84cf9bd083b
Binary files /dev/null and b/icons/mob/wings.dmi differ