diff --git a/baystation12.dme b/baystation12.dme index 9a13707055e..87a5fdaa9fc 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1432,6 +1432,7 @@ #include "code\modules\mob\living\carbon\human\human_organs.dm" #include "code\modules\mob\living\carbon\human\human_powers.dm" #include "code\modules\mob\living\carbon\human\human_species.dm" +#include "code\modules\mob\living\carbon\human\human_tail.dm" #include "code\modules\mob\living\carbon\human\intoxication.dm" #include "code\modules\mob\living\carbon\human\inventory.dm" #include "code\modules\mob\living\carbon\human\life.dm" @@ -1449,6 +1450,7 @@ #include "code\modules\mob\living\carbon\human\species\species_hud.dm" #include "code\modules\mob\living\carbon\human\species\outsider\shadow.dm" #include "code\modules\mob\living\carbon\human\species\outsider\skeleton.dm" +#include "code\modules\mob\living\carbon\human\species\outsider\snake.dm" #include "code\modules\mob\living\carbon\human\species\outsider\vox.dm" #include "code\modules\mob\living\carbon\human\species\station\golem.dm" #include "code\modules\mob\living\carbon\human\species\station\human_subspecies.dm" diff --git a/code/modules/mob/language/outsider.dm b/code/modules/mob/language/outsider.dm index f35d1a841e2..15ed54d5f51 100644 --- a/code/modules/mob/language/outsider.dm +++ b/code/modules/mob/language/outsider.dm @@ -130,4 +130,16 @@ space_chance = 10 /datum/language/terminator/get_random_name() - return "HK [pick(list("Hera","Zeus","Artemis","Athena","Ares","Hades","Poseidon","Demeter","Apollo","Aphrodite","Hermes","Hestia","Dionysus","Persephone","Kronos","Odysseus","Ajax","Agamemnon","Chiron","Charon"))]-[rand(100, 999)]" \ No newline at end of file + return "HK [pick(list("Hera","Zeus","Artemis","Athena","Ares","Hades","Poseidon","Demeter","Apollo","Aphrodite","Hermes","Hestia","Dionysus","Persephone","Kronos","Odysseus","Ajax","Agamemnon","Chiron","Charon"))]-[rand(100, 999)]" + +/datum/language/snake + name = "Snake Language" + desc = "The tongue of the snake people, a lot of hissing." + speech_verb = "hisses" + ask_verb = "hisses" + exclaim_verb = "hisses" + colour = "vox" + key = "&" + flags = RESTRICTED + space_chance = 100 + syllables = list("ssssss", "Hisss", "hSSSSS", "SSSSSSSSSSSSSS", "his!", "ssssSSSssss", "Sssssshshshshs", "S", "Hisss") diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index e9fa53899a0..f0c934df3bc 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -78,6 +78,8 @@ pixel_y = species.icon_y_offset /mob/living/carbon/human/Destroy() + qdel(tail_trail) + tail_trail = null human_mob_list -= src for(var/organ in organs) qdel(organ) @@ -87,7 +89,7 @@ organs_by_name = null bad_internal_organs = null bad_external_organs = null - + QDEL_NULL(DS) // qdel and null out our equipment. QDEL_NULL(shoes) @@ -1210,6 +1212,11 @@ nutrition = (rand(25,100)*0.01)*max_nutrition//Starting nutrition is randomised between 25-100% of max nutrition_loss = HUNGER_FACTOR * species.nutrition_loss_factor + + if(species.tail_stance) + if(!tail_trail) tail_trail = new(src) + tail_trail.sync_to_owner() + if(species) return 1 else diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 23d09be1e95..245757d8221 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -40,18 +40,26 @@ if(shoes) tally += shoes.slowdown - for(var/organ_name in list("l_foot","r_foot","l_leg","r_leg")) - var/obj/item/organ/external/E = get_organ(organ_name) - if(!E || E.is_stump()) - tally += 4 - else if(E.status & ORGAN_SPLINTED) - tally += 0.5 - else if(E.status & ORGAN_BROKEN) + if(species.tail_stance) + // If your groin is missing outright, you are dead, so, whatever. No point tallying stump etc. for it. + var/obj/item/organ/external/E = get_organ("groin") + if(E.status & ORGAN_BROKEN) tally += 1.5 + else + for(var/organ_name in list("l_foot","r_foot","l_leg","r_leg")) + var/obj/item/organ/external/E = get_organ(organ_name) + if(!E || E.is_stump()) + tally += 4 + else if(E.status & ORGAN_SPLINTED) + tally += 0.5 + else if(E.status & ORGAN_BROKEN) + tally += 1.5 + if(shock_stage >= 10) tally += 3 + if(aiming && aiming.aiming_at) tally += 5 // Iron sights make you slower, it's a well-known fact. if (drowsyness) tally += 6 diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 172927cc474..3eb1777473d 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -74,19 +74,32 @@ return for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot")) - var/obj/item/organ/external/E = organs_by_name[limb_tag] - if(!E || (E.status & (ORGAN_MUTATED|ORGAN_DEAD)) || E.is_stump()) //should just be !E.is_usable() here but dislocation screws that up. - stance_damage += 2 // let it fail even if just foot&leg - else if (E.is_malfunctioning()) - //malfunctioning only happens intermittently so treat it as a missing limb when it procs - stance_damage += 2 - if(prob(10)) - visible_message("\The [src]'s [E.name] [pick("twitches", "shudders")] and sparks!") - spark(src, 5) - else if (E.is_broken() || !E.is_usable()) - stance_damage += 1 - else if (E.is_dislocated()) - stance_damage += 0.5 + + if(species.tail_stance) + var/obj/item/organ/external/groin/checkgroin = organs_by_name["groin"] + if(!istype(checkgroin)) + stance_damage = 4 + else + if (checkgroin.is_broken() || !checkgroin.is_usable() || ((checkgroin.status & ORGAN_ROBOT) && checkgroin.is_malfunctioning())) + stance_damage = 2 + else if ((checkgroin.status & (ORGAN_MUTATED|ORGAN_DEAD)) || checkgroin.is_stump()) + stance_damage = 4 + else + for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot")) + var/obj/item/organ/external/E = organs_by_name[limb_tag] + if(!E || (E.status & (ORGAN_MUTATED|ORGAN_DEAD)) || E.is_stump()) //should just be !E.is_usable() here but dislocation screws that up. + stance_damage += 2 // let it fail even if just foot&leg + else if (E.is_malfunctioning()) + //malfunctioning only happens intermittently so treat it as a missing limb when it procs + stance_damage += 2 + if(prob(10)) + visible_message("\The [src]'s [E.name] [pick("twitches", "shudders")] and sparks!") + spark(src, 5) + else if (E.is_broken() || !E.is_usable()) + stance_damage += 1 + else if (E.is_dislocated()) + stance_damage += 0.5 + // Canes and crutches help you stand (if the latter is ever added) // One cane mitigates a broken leg+foot, or a missing foot. diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index b8b2d64e8ad..cf65181de82 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -460,3 +460,37 @@ var/obj/item/weapon/arrow/quill/A = new /obj/item/weapon/arrow/quill(usr.loc) A.throw_at(target, 10, 30, user) msg_admin_attack("[key_name_admin(src)] launched a quill at [key_name_admin(target)] (JMP)") + +/mob/living/carbon/human/proc/venomspit(mob/target as mob in oview()) + set name = "Spit Venom" + set desc = "Spits venom at your target." + set category = "Abilities" + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) + src << "You cannot spit venom in your current state." + return + + visible_message("[src] spits venom at [target]!", "You spit venom at [target].") + + var/turf/T = loc + var/turf/U = (istype(target, /atom/movable) ? target.loc : target) + + if(!U || !T) + return + while(U && !istype(U,/turf)) + U = U.loc + if(!istype(T, /turf)) + return + if (U == T) + usr.bullet_act(new /obj/item/projectile/energy/venom(usr.loc), get_organ_target()) + return + if(!istype(U, /turf)) + return + + last_special = world.time + 25 + + var/obj/item/projectile/energy/venom/A = new /obj/item/projectile/energy/venom(usr.loc) + A.launch(target, get_organ_target()) diff --git a/code/modules/mob/living/carbon/human/human_tail.dm b/code/modules/mob/living/carbon/human/human_tail.dm new file mode 100644 index 00000000000..6db2c65206b --- /dev/null +++ b/code/modules/mob/living/carbon/human/human_tail.dm @@ -0,0 +1,257 @@ +var/list/human_tail_cache = list() + +/mob/living/carbon/human/proc/coil_up() + set name = "Coil Up" + set category = "Abilities" + set desc = "Retract your tail around yourself." + if(stat || paralysis || !tail_trail) + return + src.visible_message("\The [src] coils up!") + tail_trail.update_moved(src) + sleep(-1) + if(istype(src.loc, /turf)) + tail_trail.update_moved(src.loc) + +/mob/living/carbon/human + var/obj/effect/tail/underlay/tail_trail // Tail ref for critters that drag tails behind them. + +/obj/effect/tail + icon = null + icon_state = "" + simulated = 0 + anchored = 1 + density = 0 + opacity = 0 + w_class = 5 + + var/base_colour = "#000000" + var/markings_colour = "#000000" + var/mob/living/carbon/human/owner + var/moved_from + var/tail_type + +/obj/effect/tail/Crossed(var/atom/movable/crossing) + . = ..() + if(crossing == owner || loc == owner.loc || prob(30)) + return . + if(istype(crossing, /mob/living)) + var/mob/living/M = crossing + var/damage_taken + if(istype(crossing, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = crossing + if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.item_flags & NOSLIP)) + damage_taken = rand(5,8) + if(!damage_taken) + damage_taken = rand(1,3) + if(prob(50)) + M.visible_message("\The [M] trips over \the [owner]'s tail!") + M.Weaken(rand(5,8)) + else + M.visible_message("\The [M] treads on \the [owner]'s tail!") + owner << "Your tail is being brutalized!" + owner.apply_damage(damage_taken, BRUTE, "groin") + else if(istype(crossing, /obj/vehicle) || istype(crossing, /obj/mecha)) + crossing.visible_message("\The [crossing] runs over \the [owner]'s tail!") + owner << "Your tail is being brutalized!" + owner.apply_damage(rand(5,8), BRUTE, "groin") + return . + +/obj/effect/tail/Destroy() + owner = null + return ..() + +/obj/effect/tail/underlay/Destroy() + for(var/obj/effect/tail/segment in segments) + qdel(segment) + segments.Cut() + return ..() + +/obj/effect/tail/New(var/mob/living/carbon/human/newowner) + owner = newowner + if(!istype(owner)) + owner = null + qdel(src) + return + ..(get_turf(owner)) + +/obj/effect/tail/proc/sync_to_owner() + name = "[owner]'\s [initial(name)]" + base_colour = rgb(owner.r_skin, owner.g_skin, owner.b_skin) + markings_colour = rgb(owner.r_hair, owner.g_hair, owner.b_hair) + update_icon(1) + +/obj/effect/tail/attack_generic(var/mob/user, var/damage, var/attack_message) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + if(owner.loc == loc) return + return owner.attack_generic(user, damage, attack_message) + +/obj/effect/tail/attackby(var/obj/item/thing, var/mob/user) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + if(owner.loc == loc) return + return owner.attack_hand(user, thing) + +/obj/effect/tail/attack_hand(var/mob/user) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + if(owner.loc == loc) return + return owner.attack_hand(user) + +/obj/effect/tail/bullet_act(var/obj/item/projectile/proj) + if(owner.loc == loc) return + return owner.bullet_act(proj) + +/obj/effect/tail/fire_act(var/datum/gas_mixture/air, var/exposed_temperature, var/exposed_volume) + if(owner.loc == loc) return + return owner.fire_act(air, exposed_temperature, exposed_volume) + +/obj/effect/tail/ex_act(var/severity) + if(owner.loc == loc) return + return owner.ex_act(severity) // Damage to the tail should damage the mob in general. + +/obj/effect/tail/emp_act(var/severity) + if(loc == owner.loc) + return + return owner.ex_act(severity) + +/obj/effect/tail/update_icon(var/force_override) + overlays.Cut() + // Build base. + var/cache_key = "[owner.species.name]-[tail_type]-[base_colour]" + if(!human_tail_cache[cache_key] || force_override) + var/icon/I = icon(icon=owner.species.icobase, icon_state=tail_type) + I.Blend(base_colour, ICON_ADD) + human_tail_cache[cache_key] = I + overlays += human_tail_cache[cache_key] + // Build markings. + cache_key = "[owner.species.name]-[tail_type]_markings-[markings_colour]" + if(!human_tail_cache[cache_key] || force_override) + var/icon/I = icon(icon=owner.species.icobase, icon_state="[tail_type]_markings") + I.Blend(markings_colour, ICON_ADD) + human_tail_cache[cache_key] = I + overlays += human_tail_cache[cache_key] + +/obj/effect/tail/underlay + name = "coils" + var/list/segments = list() + +/obj/effect/tail/underlay/New() + ..() + layer = owner.layer - 0.01 + if(owner && segments) + for(var/i = 1 to owner.species.tail_length) + var/obj/effect/tail/trailing/segment= new (owner, (i == owner.species.tail_length)) + segment.layer = (owner.layer - (0.01 * (i+1))) + segments += segment + +/obj/effect/tail/underlay/sync_to_owner() + ..() + for(var/obj/effect/tail/trailing/segment in segments) + segment.owner = owner + segment.sync_to_owner() + +/obj/effect/tail/trailing + name = "tail" + var/terminating + animate_movement = SYNC_STEPS + +/obj/effect/tail/trailing/New(var/newloc, var/term) + terminating = term + ..(newloc) + +/obj/effect/tail/trailing/update_icon() + if(reverse_dir[moved_from] == dir) + tail_type = "tail_straight[terminating ? "_end" : ""]" + else + // Way, way too tired to work this shit out. + // TODO bug GN or Psi about bit magic. + if(dir == NORTH) + if(moved_from == WEST) + tail_type = "tail_bent_1[terminating ? "_end" : ""]" + else if(moved_from == EAST) + tail_type = "tail_bent_2[terminating ? "_end" : ""]" + else if(dir == SOUTH) + if(moved_from == WEST) + tail_type = "tail_bent_1[terminating ? "_end" : ""]" + else if(moved_from == EAST) + tail_type = "tail_bent_2[terminating ? "_end" : ""]" + else if(dir == EAST) + if(moved_from == NORTH) + tail_type = "tail_bent_1[terminating ? "_end" : ""]" + else if(moved_from == SOUTH) + tail_type = "tail_bent_2[terminating ? "_end" : ""]" + else if(dir == WEST) + if(moved_from == NORTH) + tail_type = "tail_bent_1[terminating ? "_end" : ""]" + else if(moved_from == SOUTH) + tail_type = "tail_bent_2[terminating ? "_end" : ""]" + ..() + +/obj/effect/tail/proc/update_moved(var/turf/newloc, var/turf/predecessor) + if(!newloc || newloc == owner || !istype(owner.loc, /turf)) + forceMove(owner) + return + if(src.loc == owner) + forceMove(get_turf(owner)) + var/turf/oldloc = src.loc + if(!istype(oldloc)) + forceMove(owner) + return + if(newloc == oldloc) + return + forceMove(newloc) + if(predecessor) + moved_from = get_dir(newloc, oldloc) + dir = get_dir(newloc, predecessor) + if(dir in cornerdirs) + forceMove(owner) + return + update_icon() + +/obj/effect/tail/trailing/update_moved(var/turf/newloc, var/turf/predecessor) + ..(newloc, predecessor) + if(loc == owner || owner.loc == loc) + invisibility = 101 + else + invisibility = 0 + +/obj/effect/tail/underlay/update_moved(var/turf/newloc, var/turf/predecessor) + var/oldloc = src.loc + ..(newloc, predecessor) + if(loc == owner) + for(var/obj/effect/tail/T in segments) + T.update_moved(owner) + else + var/obj/effect/lastsegment = src + for(var/obj/effect/tail/segment in segments) + var/segmentloc = segment.loc + segment.update_moved(oldloc, get_turf(lastsegment)) + oldloc = segmentloc + lastsegment = segment + + // Do this here instead of update_icon() because we have to wait for all the other segments to have moved. + dir = owner.dir + tail_type = "tail_underlay" + for(var/obj/effect/tail/trailing/segment in segments) + if(get_turf(segment) != newloc) + return + tail_type = "tail_underlay_static" + update_icon() + +/mob/living/carbon/human/Move() + . = ..() + if(. && species.tail_stance) + if(!tail_trail) tail_trail = new(src) + var/turf/T = get_turf(src) + if(istype(T)) + tail_trail.update_moved(T) + else + tail_trail.update_moved(src) + +/mob/living/carbon/human/forceMove() + . = ..() + if(species.tail_stance) + if(!tail_trail) tail_trail = new(src) + var/turf/T = get_turf(src) + if(istype(T)) + tail_trail.update_moved(T) + else + tail_trail.update_moved(src) diff --git a/code/modules/mob/living/carbon/human/species/outsider/snake.dm b/code/modules/mob/living/carbon/human/species/outsider/snake.dm new file mode 100644 index 00000000000..c58ce9a36f3 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/outsider/snake.dm @@ -0,0 +1,106 @@ +/mob/living/carbon/human/snake/New(var/new_loc) + ..(new_loc, "Snake People") + +/datum/species/snake + name = "Snake People" + short_name = "snek" + name_plural = "Snake Folk" + bodytype = "Snake" + icobase = 'icons/mob/human_races/r_snake.dmi' + deform = 'icons/mob/human_races/r_snake.dmi' + blurb = "A race of snakelike sapients from somewhere beyond the frontier. They are a new threat, arriving in the galaxy as invaders." + eyes = "eyes_snake" + breakcuffs = list(MALE,FEMALE,NEUTER) + + tail_stance = 1 + tail_length = 5 + + mob_size = 15 + gluttonous = 3 + vision_flags = SEE_SELF | SEE_MOBS + rarity_value = 10 + slowdown = -1 // Compensating for a total inability to wear shoes. + + darksight = 8 + brute_mod = 0.5 + ethanol_resistance = 0.7 + + virus_immune = 1 + siemens_coefficient = 0.5 + + cold_level_1 = 280 + cold_level_2 = 220 + cold_level_3 = 130 + heat_level_1 = 420 + heat_level_2 = 480 + heat_level_3 = 1100 + heat_discomfort_level = 295 + + heat_discomfort_strings = list( + "You feel soothingly warm.", + "You feel the heat sink into your bones.", + "You feel warm enough to take a nap." + ) + cold_discomfort_level = 292 + cold_discomfort_strings = list( + "You feel chilly.", + "You feel sluggish and cold.", + "Your scales bristle against the cold." + ) + + hud_type = /datum/hud_data/snake + unarmed_types = list(/datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/sharp) + + default_language = "Snake Language" + language = "Ceti Basic" + num_alternate_languages = 1 + + spawn_flags = CAN_JOIN | IS_WHITELISTED + appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_EYE_COLOR + flags = NO_SLIP + + inherent_verbs = list( + /mob/living/proc/devour, + /mob/living/carbon/human/proc/regurgitate, + /mob/living/carbon/human/proc/venomspit, + /mob/living/carbon/human/proc/coil_up + ) + + flesh_color = "#006600" + blood_color = "#1D2CBF" + base_color = "#006666" + + reagent_tag = IS_UNATHI + + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest/snake), + "groin" = list("path" = /obj/item/organ/external/groin/snake), + "head" = list("path" = /obj/item/organ/external/head/snake), + "l_arm" = list("path" = /obj/item/organ/external/arm), + "r_arm" = list("path" = /obj/item/organ/external/arm/right), + "l_hand" = list("path" = /obj/item/organ/external/hand), + "r_hand" = list("path" = /obj/item/organ/external/hand/right) + ) + + has_organ = list( + "heart" = /obj/item/organ/heart, + "lungs" = /obj/item/organ/lungs, + "liver" = /obj/item/organ/liver, + "kidneys" = /obj/item/organ/kidneys, + "brain" = /obj/item/organ/brain, + "eyes" = /obj/item/organ/eyes, + "venom gland" = /obj/item/organ/venomgland + ) + + stamina = 120 + sprint_speed_factor = 3 + stamina_recovery = 1 + sprint_cost_factor = 1 + +/datum/species/snake + autohiss_basic_map = list( + "s" = list("ssss", "sssss", "ssssss"), + "c" = list("cksss", "ckssss", "cksssss"), + "k" = list("ksss", "kssss", "ksssss"), + "x" = list("ksss", "kssss", "ksssss") + ) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 7a04d4e972e..6c955cdfa8b 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -32,6 +32,8 @@ var/base_color // Used by changelings. Should also be used for icon previes.. var/tail // Name of tail state in species effects icon file. var/tail_animation // If set, the icon to obtain tail animation states from. + var/tail_stance + var/tail_length var/tail_hair var/race_key = 0 // Used for mob icon cache string. var/icon/icon_template // Used for mob icon generation for non-32x32 species. diff --git a/code/modules/mob/living/carbon/human/species/species_hud.dm b/code/modules/mob/living/carbon/human/species/species_hud.dm index 13354058ebb..65137b6001f 100644 --- a/code/modules/mob/living/carbon/human/species/species_hud.dm +++ b/code/modules/mob/living/carbon/human/species/species_hud.dm @@ -73,3 +73,21 @@ "mask" = list("loc" = ui_shoes, "name" = "Mask", "slot" = slot_wear_mask, "state" = "mask", "toggle" = 1), "back" = list("loc" = ui_sstore1, "name" = "Back", "slot" = slot_back, "state" = "back") ) + +/datum/hud_data/snake + gear = list( + "i_clothing" = list("loc" = ui_iclothing, "name" = "Uniform", "slot" = slot_w_uniform, "state" = "center", "toggle" = 1), + "o_clothing" = list("loc" = ui_oclothing, "name" = "Suit", "slot" = slot_wear_suit, "state" = "suit", "toggle" = 1), + "mask" = list("loc" = ui_mask, "name" = "Mask", "slot" = slot_wear_mask, "state" = "mask", "toggle" = 1), + "gloves" = list("loc" = ui_gloves, "name" = "Gloves", "slot" = slot_gloves, "state" = "gloves", "toggle" = 1), + "eyes" = list("loc" = ui_glasses, "name" = "Glasses", "slot" = slot_glasses, "state" = "glasses","toggle" = 1), + "l_ear" = list("loc" = ui_l_ear, "name" = "Left Ear", "slot" = slot_l_ear, "state" = "ears", "toggle" = 1), + "r_ear" = list("loc" = ui_r_ear, "name" = "Right Ear", "slot" = slot_r_ear, "state" = "ears", "toggle" = 1), + "head" = list("loc" = ui_head, "name" = "Hat", "slot" = slot_head, "state" = "hair", "toggle" = 1), + "suit storage" = list("loc" = ui_sstore1, "name" = "Suit Storage", "slot" = slot_s_store, "state" = "suitstore"), + "back" = list("loc" = ui_back, "name" = "Back", "slot" = slot_back, "state" = "back"), + "id" = list("loc" = ui_id, "name" = "ID", "slot" = slot_wear_id, "state" = "id"), + "storage1" = list("loc" = ui_storage1, "name" = "Left Pocket", "slot" = slot_l_store, "state" = "pocket"), + "storage2" = list("loc" = ui_storage2, "name" = "Right Pocket", "slot" = slot_r_store, "state" = "pocket"), + "belt" = list("loc" = ui_belt, "name" = "Belt", "slot" = slot_belt, "state" = "belt") + ) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index dd4c8932cd4..7468be9e678 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -150,6 +150,9 @@ Please contact me on #coderbus IRC. ~Carn x update_hud() //TODO: remove the need for this overlays.Cut() + if(species.tail_stance) + if(!tail_trail) tail_trail = new(src) + tail_trail.sync_to_owner() if(cloaked) icon = 'icons/mob/human.dmi' @@ -393,12 +396,12 @@ var/global/list/damage_icon_parts = list() var/col = species.get_light_color(h_style) if (!col) col = "#FFFFFF" - + set_light(species.light_range, species.light_power, col, uv = 0, angle = LIGHT_WIDE) - + else if (species.light_range) - set_light(FALSE) - + set_light(FALSE) + overlays_standing[HAIR_LAYER] = image(face_standing) if(update_icons) update_icons() diff --git a/code/modules/organs/subtypes/xenos.dm b/code/modules/organs/subtypes/xenos.dm index c4c9bf35625..b0e1d532654 100644 --- a/code/modules/organs/subtypes/xenos.dm +++ b/code/modules/organs/subtypes/xenos.dm @@ -104,3 +104,39 @@ name = "skull" dislocated = -1 vital = 0 + +/obj/item/organ/external/groin/snake + name = "tail" + max_damage = 200 + min_broken_damage = 160 + body_hair = "markings" + +/obj/item/organ/external/head/snake + body_hair = "markings" + +/obj/item/organ/external/chest/snake + body_hair = "markings" + +/obj/item/organ/venomgland + name = "venom gland" + desc = "Oversized glands, filled with a venomous liquid." + parent_organ = "head" + icon = 'icons/effects/blood.dmi' + icon_state = "xgibtorso" + organ_tag = "venom gland" + +/obj/item/organ/venomgland/process() + if (is_broken()) + owner.verbs -= /mob/living/carbon/human/proc/venomspit + owner << " Your fangs dries as the glands are crushed by the violence!" + ..() + +/obj/item/organ/venomgland/replaced(var/mob/living/carbon/human/target) + owner.verbs += /mob/living/carbon/human/proc/venomspit + owner << " Venom runs through your fangs!" + ..() + +/obj/item/organ/venomgland/removed(var/mob/living/carbon/human/target) + target.verbs -= /mob/living/carbon/human/proc/venomspit + target << "Your fangs dries as the glands are torn away from you." + ..() diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index d7893391d9f..1a3b7699669 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -232,3 +232,15 @@ kill_count = 75 embed = 0 incinerate = 10*/ + +/obj/item/projectile/energy/venom + name = "venom spit" + icon_state = "neurotoxin" + damage = 10 + damage_type = TOX + +/obj/item/projectile/energy/venom/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) + var/mob/living/carbon/human/M = target + if(M.reagents) M.reagents.add_reagent("toxin", 5) + ..() diff --git a/html/changelogs/alberky-PR-snektiddies.yml b/html/changelogs/alberky-PR-snektiddies.yml new file mode 100644 index 00000000000..0c478ce2ed8 --- /dev/null +++ b/html/changelogs/alberky-PR-snektiddies.yml @@ -0,0 +1,7 @@ +author: Alberyk + +delete-after: True + +changes: + - rscadd: "Added snake people." + - rscdel: "Removed resomi." diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index d7bc9ad8ba2..0588e1cba95 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/human_races/r_snake.dmi b/icons/mob/human_races/r_snake.dmi new file mode 100644 index 00000000000..8d085c43d71 Binary files /dev/null and b/icons/mob/human_races/r_snake.dmi differ