[user] caresses [src] with one of it's many apendages.")
+
+ if("harm")
+ var/mob/living/carbon/changelinghorror/CH = user
+ var/datum/dna/attacker_dna = CH.obtain_valid_dna()
+ var/attacker = attacker_dna.real_name
+ var/attack_verb = pick("punches","claws at","swipes at","slices","cuts")
+ var/attacking_body_part = pick("right arm","left arm")
+ var/dam_zone = pick("chest","l_hand", "r_hand", "l_lef", "r_leg","head")
+ var/obj/item/organ/limb/affecting = get_organ(ran_zone(dam_zone))
+ var/DAMAGE = CH.Default_Damage*(CH.mind.changeling.absorbed_dna.len/2)
+ if(affecting)
+ apply_damage(DAMAGE, BRUTE, affecting, run_armor_check(affecting, "melee"))
+ visible_message("[CH] reaches out, [attacker]'s [attacking_body_part] [attack_verb] [src]'s [parse_zone(affecting.name)]!","[CH] reaches out, [attacker]'s [attacking_body_part] [attack_verb] your [parse_zone(affecting.name)]!")
+ else
+ visible_message("[CH] reaches out, [attacker]'s [attacking_body_part] misses [src]!","[CH] reaches out, [attacker]'s [attacking_body_part] misses you!")
+
+ if ("grab")
+ if (user == src || anchored)
+ return
+ var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(user, src )
+
+ user.put_in_active_hand(G)
+
+ G.synch()
+
+ LAssailant = user
+
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ visible_message("[user] has grabbed [name] passively!")
+
+ if ("disarm")
+ playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
+ var/damage = 5
+ if(prob(95))
+ Weaken(15)
+ visible_message("[user] has knocked downn [name]!")
+ else
+ if(drop_item())
+ visible_message("[user] has disarmed [name]!")
+ adjustBruteLoss(damage)
+ updatehealth()
+ return
+
+/mob/living/carbon/changelinghorror/proc/obtain_valid_dna() //Loop to ensure a non null DNA is chosen
+ var/datum/dna/chosen_dna = pick(mind.changeling.absorbed_dna)
+
+ if(!isnull(chosen_dna))
+ return chosen_dna
+
+ return obtain_valid_dna()
+
+/obj/machinery/door/airlock/attack_horror(mob/user as mob)
+ var/delay = 30
+
+ if(!user || user.stat)
+ return
+
+ if(!requiresID() || allowed(user))
+ return
+
+ if(arePowerSystemsOn() && !(stat & NOPOWER))
+ user << "The airlock's motors resist our efforts to force it"
+ return
+
+ else if(locked)
+ user << "The airlock's bolts prevent it from being forced."
+ return
+
+
+ if(!do_after(user,delay))
+ return
+
+ user.visible_message("[user] forces the door open!", "We force the door to open!", "You hear a metal screeching sound.")
+ open(1)
+
+/obj/item/attack_horror(mob/user as mob)
+ attack_hand(user)
+
+/obj/attack_horror(mob/user as mob)
+ attack_alien(user)
+
+/turf/simulated/wall/attack_horror(mob/user as mob)
+
+ if(prob(hardness))
+ user.visible_message("[user] smashes through the wall!","You smash through the wall!","You hear the sound of crunching metal.")
+ dismantle_wall(1)
+ return
+ else
+ user.visible_message("[user]'s claw smashes against the wall, but the wall remains!","Your claw smashes against the wall, but the wall remains!","You hear a metallic clang.")
+ return
diff --git a/code/game/gamemodes/changeling/changeling-horror-mob/life.dm b/code/game/gamemodes/changeling/changeling-horror-mob/life.dm
new file mode 100644
index 0000000000..59dd2460da
--- /dev/null
+++ b/code/game/gamemodes/changeling/changeling-horror-mob/life.dm
@@ -0,0 +1,195 @@
+
+/mob/living/carbon/changelinghorror/Life()
+ set invisibility = 0
+ set background = BACKGROUND_ENABLED
+ if (notransform) return
+ ..()
+
+ var/datum/gas_mixture/environment
+ if(loc)
+ environment = loc.return_air()
+
+ if (stat != DEAD)
+
+ handle_changeling()
+
+ blinded = null
+
+ if(environment)
+ handle_environment(environment)
+
+ handle_fire()
+
+ handle_regular_status_updates()
+ update_canmove()
+
+ if(client)
+ handle_regular_hud_updates()
+
+ for(var/obj/item/weapon/grab/G in src)
+ G.process()
+
+
+/mob/living/carbon/changelinghorror/proc/handle_environment(datum/gas_mixture/environment)
+ if(!environment)
+ return
+ var/environment_heat_capacity = environment.heat_capacity()
+ if(istype(get_turf(src), /turf/space))
+ var/turf/heat_turf = get_turf(src)
+ environment_heat_capacity = heat_turf.heat_capacity
+
+ if(!on_fire)
+ if((environment.temperature > (T0C + 50)) || (environment.temperature < (T0C + 10)))
+ var/transfer_coefficient = 1
+
+ handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient)
+
+ if(stat != 2)
+ bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000)
+
+ var/pressure = environment.return_pressure()
+ var/adjusted_pressure = calculate_affecting_pressure(pressure)
+ switch(adjusted_pressure)
+ if(HAZARD_HIGH_PRESSURE to INFINITY)
+ adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
+ pressure_alert = 2
+ if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
+ pressure_alert = 1
+ if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
+ pressure_alert = 0
+ if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
+ pressure_alert = -1
+ else
+ pressure_alert = -1
+ return
+
+/mob/living/carbon/changelinghorror/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity)
+ if(status_flags & GODMODE) return
+ var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0)
+
+ if(exposed_temperature > bodytemperature)
+ adjustFireLoss(20.0*discomfort)
+
+ else
+ adjustFireLoss(5.0*discomfort)
+
+
+/mob/living/carbon/changelinghorror/proc/handle_regular_status_updates()
+ updatehealth()
+
+ if(stat == DEAD)
+ blinded = 1
+ silent = 0
+ else
+ if(health < 0 || health == 0)
+ death()
+ blinded = 1
+ stat = DEAD
+ silent = 0
+ return 1
+ else
+ stat = CONSCIOUS
+ return 1
+
+ if(stunned)
+ AdjustStunned(-1)
+
+ if(weakened)
+ weakened = max(weakened-1,0)
+
+ return 1
+
+
+/mob/living/carbon/changelinghorror/proc/handle_regular_hud_updates()
+
+ if (stat == 2)
+ sight |= SEE_TURFS
+ sight |= SEE_MOBS
+ sight |= SEE_OBJS
+ see_in_dark = 8
+ see_invisible = SEE_INVISIBLE_LEVEL_TWO
+ else if (stat != 2)
+ sight &= ~SEE_TURFS
+ sight &= ~SEE_MOBS
+ sight &= ~SEE_OBJS
+ see_in_dark = 2
+ see_invisible = SEE_INVISIBLE_LIVING
+ if(see_override)
+ see_invisible = see_override
+
+ if (healths)
+ if (stat != 2)
+ switch(health)
+ if(200 to INFINITY)
+ healths.icon_state = "health0"
+ if(160 to 200)
+ healths.icon_state = "health1"
+ if(120 to 160)
+ healths.icon_state = "health2"
+ if(80 to 120)
+ healths.icon_state = "health3"
+ if(40 to 80)
+ healths.icon_state = "health4"
+ if(0 to 40)
+ healths.icon_state = "health5"
+ else
+ healths.icon_state = "health6"
+ else
+ healths.icon_state = "health7"
+
+ if(pressure)
+ pressure.icon_state = "pressure[pressure_alert]"
+
+ if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]"
+
+ if (toxin) toxin.icon_state = "tox[toxins_alert ? 1 : 0]"
+ if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]"
+ if (fire) fire.icon_state = "fire[fire_alert ? 2 : 0]"
+
+ if(bodytemp)
+ switch(bodytemperature)
+ if(345 to INFINITY)
+ bodytemp.icon_state = "temp4"
+ if(335 to 345)
+ bodytemp.icon_state = "temp3"
+ if(327 to 335)
+ bodytemp.icon_state = "temp2"
+ if(316 to 327)
+ bodytemp.icon_state = "temp1"
+ if(300 to 316)
+ bodytemp.icon_state = "temp0"
+ if(295 to 300)
+ bodytemp.icon_state = "temp-1"
+ if(280 to 295)
+ bodytemp.icon_state = "temp-2"
+ if(260 to 280)
+ bodytemp.icon_state = "temp-3"
+ else
+ bodytemp.icon_state = "temp-4"
+
+ client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired)
+
+ if (stat != 2)
+ if (machine)
+ if (!( machine.check_eye(src) ))
+ reset_view(null)
+ else
+ if(!client.adminobs)
+ reset_view(null)
+
+ return 1
+
+/mob/living/carbon/changelinghorror/proc/handle_changeling()
+ if(mind && mind.changeling)
+ mind.changeling.regenerate()
+ hud_used.lingchemdisplay.invisibility = 0
+ hud_used.lingchemdisplay.maptext = " [src.mind.changeling.chem_charges]
"
+
+
+/mob/living/carbon/changelinghorror/handle_fire()
+ if(..())
+ return
+ adjustFireLoss(20) //changeling horrors do NOT like fire
+ return
+
+
diff --git a/code/game/gamemodes/changeling/changeling-horror-mob/update_icons.dm b/code/game/gamemodes/changeling/changeling-horror-mob/update_icons.dm
new file mode 100644
index 0000000000..bc021cda87
--- /dev/null
+++ b/code/game/gamemodes/changeling/changeling-horror-mob/update_icons.dm
@@ -0,0 +1,61 @@
+//Changeling Horror Overlays/////
+#define CH_FIRE_LAYER 1
+#define CH_TOTAL_LAYERS 1
+/////////////////////////////////
+
+/mob/living/carbon/changelinghorror
+ var/list/overlays_standing[CH_TOTAL_LAYERS]
+
+/mob/living/carbon/changelinghorror/regenerate_icons()
+ ..()
+ update_inv_hands(0)
+ update_fire()
+ update_icons()
+ update_transform()
+ //Hud Stuff
+ update_hud()
+ return
+
+/mob/living/carbon/changelinghorror/update_icons()
+ update_hud()
+ overlays.Cut()
+ for(var/image/I in overlays_standing)
+ overlays += I
+
+/mob/living/carbon/changelinghorror/update_inv_hands(var/update_icons=1)
+ if(handcuffed)
+ drop_r_hand()
+ drop_l_hand()
+ return
+ if(r_hand)
+ r_hand.screen_loc = ui_rhand
+ if(client && hud_used)
+ client.screen += r_hand
+ var/t_state = r_hand.item_state
+ if(!t_state) t_state = r_hand.icon_state
+
+ if(l_hand)
+ l_hand.screen_loc = ui_lhand
+ if(client && hud_used)
+ client.screen += l_hand
+ var/t_state = l_hand.item_state
+ if(!t_state) t_state = l_hand.icon_state
+
+ if(update_icons)
+ update_icons()
+
+/mob/living/carbon/changelinghorror/update_hud()
+ if(client)
+ client.screen |= contents
+
+/mob/living/carbon/changelinghorror/update_fire()
+ overlays -= overlays_standing[CH_FIRE_LAYER]
+ if(on_fire)
+ overlays_standing[CH_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"= -CH_FIRE_LAYER)
+ overlays += overlays_standing[CH_FIRE_LAYER]
+ return
+ else
+ overlays_standing[CH_FIRE_LAYER] = null
+
+#undef CH_FIRE_LAYER
+#undef CH_TOTAL_LAYERS
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 2709071b44..5362c40bf9 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -235,6 +235,11 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/datum/dna/chosen_dna
var/obj/effect/proc_holder/changeling/sting/chosen_sting
var/space_suit_active = 0
+ //Let's HorrorForm's look and be named uniquely
+ var/horror_name
+ var/horror_icon
+ //Used for weak changelings created from the Assimilant Power
+ var/assimilant = 0
/datum/changeling/New(var/gender=FEMALE)
..()
@@ -248,7 +253,18 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
else
changelingID = "[honorific] [rand(1,999)]"
absorbed_dna.len = dna_max
+ UniqueHorror()
+/datum/changeling/proc/UniqueHorror()
+ var/list/prefixHorror = list("Shambling","Crawling","Raging","The","Wretched","Rotting")
+ var/list/suffixHorror = list("Abomination","Horror","Thing","Pile-Of-Flesh") //Yes you can end up as "The Thing" - RR
+
+ if(assimilant)
+ horror_icon = "assimilant_[rand(1,2)]"
+ //Name stuff is handled in Horrorize() for Assimilants
+ else
+ horror_name = "[pick(prefixHorror)] [pick(suffixHorror)]"
+ horror_icon = "horror_[rand(1,4)]"
/datum/changeling/proc/regenerate()
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
@@ -269,6 +285,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
if(NOCLONE in target.mutations || HUSK in target.mutations)
user << "DNA of [target] is ruined beyond usability!"
return
+ if(ishorror(target))
+ return
if(!ishuman(target))//Absorbing monkeys is entirely possible, but it can cause issues with transforming. That's what lesser form is for anyway!
user << "We could gain no benefit from absorbing a lesser creature."
return
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 8307aea0f2..73ae0ea2ca 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -13,6 +13,7 @@
var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1
var/req_human = 0 //if you need to be human to use this ability
var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD
+ var/req_horror = 0 //if you need to be in Horror Form to use this ability
var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
@@ -46,11 +47,14 @@
//Fairly important to remember to return 1 on success >.<
/obj/effect/proc_holder/changeling/proc/can_sting(var/mob/user, var/mob/target)
- if(!ishuman(user) && !ismonkey(user)) //typecast everything from mob to carbon from this point onwards
+ if(!ishuman(user) && !ismonkey(user) && !ishorror(user)) //typecast everything from mob to carbon from this point onwards
return 0
if(req_human && !ishuman(user))
user << "We cannot do that in this form!"
return 0
+ if(req_horror && !ishorror(user))
+ user << "We cannot do that in this form!"
+ return 0
var/datum/changeling/c = user.mind.changeling
if(c.chem_chargesWe require at least [chemical_cost] unit\s of chemicals to do that!"
@@ -71,10 +75,12 @@
//used in /mob/Stat()
/obj/effect/proc_holder/changeling/proc/can_be_used_by(var/mob/user)
- if(!ishuman(user) && !ismonkey(user))
+ if(!ishuman(user) && !ismonkey(user) && !ishorror(user))
return 0
if(req_human && !ishuman(user))
return 0
+ if(req_horror && !ishorror(user))
+ return 0
return 1
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index e1e257b927..1637883ada 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -343,7 +343,7 @@ var/list/sting_paths
/mob/proc/make_changeling()
if(!mind)
return
- if(!ishuman(src) && !ismonkey(src))
+ if(!ishuman(src) && !ismonkey(src) && !ishorror(src))
return
if(!mind.changeling)
mind.changeling = new /datum/changeling(gender)
@@ -373,7 +373,7 @@ var/list/sting_paths
mimicing = ""
/mob/proc/remove_changeling_powers(var/keep_free_powers=0)
- if(ishuman(src) || ismonkey(src))
+ if(ishuman(src) || ismonkey(src) || ishorror(src))
if(mind && mind.changeling)
digitalcamo = 0
mind.changeling.reset()
diff --git a/code/game/gamemodes/changeling/powers/horrorform.dm b/code/game/gamemodes/changeling/powers/horrorform.dm
new file mode 100644
index 0000000000..4fcac57068
--- /dev/null
+++ b/code/game/gamemodes/changeling/powers/horrorform.dm
@@ -0,0 +1,141 @@
+
+/*
+Horror form abilities, By RR
+*/
+
+
+///////////////////////////
+/// Become Horror ///
+///////////////////////////
+
+/obj/effect/proc_holder/changeling/HorrorForm
+ name = "Unleash Horror Form"
+ desc = "Transform into a Shambling Abomination."
+ helptext = "Transform into a Shambling Abomination after a short delay, VERY OBVIOUS."
+ chemical_cost = 40
+ dna_cost = 0
+ req_human = 1
+ req_stat = CONSCIOUS
+
+/obj/effect/proc_holder/changeling/HorrorForm/sting_action(var/mob/living/carbon/user)
+ if(!istype(user))
+ return
+
+ user.visible_message("