Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into ninjasarecum
# Conflicts: # icons/mob/clothing/feet.dmi # icons/mob/clothing/feet_digi.dmi # icons/mob/clothing/head.dmi # icons/mob/clothing/mask.dmi # icons/mob/clothing/mask_muzzled.dmi # icons/obj/clothing/hats.dmi # icons/obj/clothing/masks.dmi # icons/obj/items_and_weapons.dmi
This commit is contained in:
@@ -101,6 +101,13 @@
|
||||
matrixed_sections = MATRIX_RED
|
||||
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
|
||||
|
||||
/datum/sprite_accessory/ears/lablight
|
||||
name = "Dog, Floppy (Light)"
|
||||
icon_state = "lablight"
|
||||
color_src = MATRIXED
|
||||
matrixed_sections = MATRIX_RED
|
||||
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
|
||||
|
||||
/datum/sprite_accessory/ears/human/eevee
|
||||
name = "Eevee"
|
||||
icon_state = "eevee"
|
||||
@@ -351,10 +358,15 @@
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/ears/mam_ears/lab
|
||||
name = "Dog, Long"
|
||||
name = "Dog, Floppy"
|
||||
icon_state = "lab"
|
||||
matrixed_sections = MATRIX_RED
|
||||
|
||||
/datum/sprite_accessory/ears/mam_ears/lablight
|
||||
name = "Dog, Floppy (Light)"
|
||||
icon_state = "lablight"
|
||||
matrixed_sections = MATRIX_RED
|
||||
|
||||
/datum/sprite_accessory/ears/mam_ears/murid
|
||||
name = "Murid"
|
||||
icon_state = "murid"
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
|
||||
for (var/_A in mind.antag_datums)
|
||||
var/datum/antagonist/A = _A
|
||||
if (A.show_to_ghosts)
|
||||
var/mob/dead/observer/O = user
|
||||
if (A?.show_to_ghosts || !O?.can_reenter_corpse)
|
||||
was_antagonist = TRUE
|
||||
serialized["antag"] = A.name
|
||||
antagonists += list(serialized)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
if(skipface || get_visible_name() == "Unknown")
|
||||
. += "You can't make out what species they are."
|
||||
else
|
||||
. += "[t_He] [t_is] a [dna.custom_species ? dna.custom_species : dna.species.name]!"
|
||||
. += "[t_He] [t_is] a [spec_trait_examine_font()][dna.custom_species ? dna.custom_species : dna.species.name]</font>!"
|
||||
|
||||
//uniform
|
||||
if(w_uniform && !(SLOT_W_UNIFORM in obscured))
|
||||
|
||||
@@ -1055,6 +1055,30 @@
|
||||
. = ..()
|
||||
set_species(race)
|
||||
|
||||
/**
|
||||
* # `spec_trait_examine_font()`
|
||||
*
|
||||
* This gets a humanoid's special examine font, which is used to color their species name during examine / health analyzing.
|
||||
* The first of these that applies is returned.
|
||||
* Returns:
|
||||
* * Metallic font if robotic
|
||||
* * Cyan if a toxinlover
|
||||
* * Purple if plasmaperson
|
||||
* * Rock / Brownish if a golem
|
||||
* * Green if none of the others apply (aka, generic organic)
|
||||
*/
|
||||
/mob/living/carbon/human/proc/spec_trait_examine_font()
|
||||
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
|
||||
return "<font color='#aaa9ad'>"
|
||||
if(HAS_TRAIT(src, TRAIT_TOXINLOVER))
|
||||
return "<font color='#00ffff'>"
|
||||
if(isplasmaman(src))
|
||||
return "<font color='#800080'"
|
||||
if(isgolem(src))
|
||||
return "<font color='#8b4513'"
|
||||
return "<font color='#18d855'>"
|
||||
|
||||
|
||||
/mob/living/carbon/human/get_tooltip_data()
|
||||
var/t_He = p_they(TRUE)
|
||||
var/t_is = p_are()
|
||||
@@ -1063,7 +1087,7 @@
|
||||
if(skipface || get_visible_name() == "Unknown")
|
||||
. += "You can't make out what species they are."
|
||||
else
|
||||
. += "[t_He] [t_is] a [dna.custom_species ? dna.custom_species : dna.species.name]"
|
||||
. += "[t_He] [t_is] a [spec_trait_examine_font()][dna.custom_species ? dna.custom_species : dna.species.name]</font>"
|
||||
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, usr, .)
|
||||
|
||||
/mob/living/carbon/human/species/abductor
|
||||
|
||||
@@ -2002,6 +2002,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/turf/target_shove_turf = get_step(target.loc, shove_dir)
|
||||
var/mob/living/carbon/human/target_collateral_human
|
||||
var/shove_blocked = FALSE //Used to check if a shove is blocked so that if it is knockdown logic can be applied
|
||||
var/targetatrest = !CHECK_MOBILITY(target, MOBILITY_STAND)
|
||||
|
||||
//Thank you based whoneedsspace
|
||||
target_collateral_human = locate(/mob/living/carbon/human) in target_shove_turf.contents
|
||||
@@ -2016,7 +2017,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/append_message = ""
|
||||
if(shove_blocked && !target.buckled)
|
||||
var/directional_blocked = !target.Adjacent(target_shove_turf)
|
||||
var/targetatrest = !CHECK_MOBILITY(target, MOBILITY_STAND)
|
||||
if((directional_blocked || !(target_collateral_human || target_shove_turf.shove_act(target, user))) && !targetatrest)
|
||||
target.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_SOLID)
|
||||
target.visible_message("<span class='danger'>[user.name] shoves [target.name], knocking them down!</span>",
|
||||
@@ -2045,11 +2045,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
append_message += ", loosening their grip on [target_held_item]"
|
||||
else
|
||||
append_message += ", but couldn't loose their grip on [target_held_item]"
|
||||
else if(target_held_item)
|
||||
if(target.dropItemToGround(target_held_item))
|
||||
target.visible_message("<span class='danger'>[target.name] drops \the [target_held_item]!!</span>",
|
||||
"<span class='danger'>You drop \the [target_held_item]!!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
append_message += ", causing them to drop [target_held_item]"
|
||||
else if(target.has_status_effect(STATUS_EFFECT_OFF_BALANCE))
|
||||
if(target_held_item)
|
||||
if(shove_blocked)
|
||||
if (target.buckled)
|
||||
return
|
||||
else if(target.dropItemToGround(target_held_item))
|
||||
target.visible_message("<span class='danger'>[target.name] drops \the [target_held_item]!!</span>",
|
||||
"<span class='danger'>You drop \the [target_held_item]!!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
append_message += ", causing them to drop [target_held_item]"
|
||||
target.ShoveOffBalance(SHOVE_OFFBALANCE_DURATION)
|
||||
log_combat(user, target, "shoved", append_message)
|
||||
|
||||
|
||||
@@ -231,8 +231,11 @@
|
||||
R.update_module_innate()
|
||||
RM.rebuild_modules()
|
||||
INVOKE_ASYNC(RM, .proc/do_transform_animation)
|
||||
if(RM.dogborg)
|
||||
if(RM.dogborg || R.dogborg)
|
||||
RM.dogborg_equip()
|
||||
R.typing_indicator_state = /obj/effect/overlay/typing_indicator/machine/dogborg
|
||||
else
|
||||
R.typing_indicator_state = /obj/effect/overlay/typing_indicator/machine
|
||||
R.maxHealth = borghealth
|
||||
R.health = min(borghealth, R.health)
|
||||
qdel(src)
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
var/hack_software = FALSE //Will be able to use hacking actions
|
||||
var/interaction_range = 7 //wireless control range
|
||||
|
||||
typing_indicator_state = /obj/effect/overlay/typing_indicator/machine
|
||||
|
||||
/mob/living/silicon/Initialize()
|
||||
. = ..()
|
||||
GLOB.silicon_mobs += src
|
||||
|
||||
@@ -6,37 +6,108 @@
|
||||
icon_living = "cat_butcher"
|
||||
icon_dead = "syndicate_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
projectiletype = /obj/item/projectile/bullet/dart/catranq
|
||||
projectilesound = 'sound/items/syringeproj.ogg'
|
||||
ranged = 1
|
||||
ranged_message = "fires the syringe gun at"
|
||||
ranged_cooldown_time = 30
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
response_help_continuous = "pokes"
|
||||
response_harm_continuous = "hits"
|
||||
speed = 0
|
||||
stat_attack = UNCONSCIOUS
|
||||
robust_searching = 1
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attack_verb_continuous = "slashes at"
|
||||
attack_verb_simple = "slash at"
|
||||
attack_sound = 'sound/weapons/circsawhit.ogg'
|
||||
a_intent = INTENT_HARM
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
loot = list(/obj/effect/mob_spawn/human/corpse/cat_butcher, /obj/item/circular_saw)
|
||||
mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
|
||||
loot = list(/obj/effect/mob_spawn/human/corpse/cat_butcher, /obj/item/circular_saw, /obj/item/gun/syringe)
|
||||
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
|
||||
unsuitable_atmos_damage = 15
|
||||
faction = list("hostile")
|
||||
check_friendly_fire = 1
|
||||
status_flags = CANPUSH
|
||||
del_on_death = 1
|
||||
del_on_death = TRUE
|
||||
var/impatience = 0
|
||||
rapid_melee = 2 //this lets him attack nearly as fast as a normal player, instead of half as fast as one. Without this, due to mood differences, a greytider in melee can actually facetank and beat him to death with only fists
|
||||
dodging = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/cat_butcherer/Life()
|
||||
. = ..()
|
||||
if(prob(10) && health <= maxHealth && !target) //heal himself when not in combat
|
||||
var/healamount = min(maxHealth-health, 20)
|
||||
visible_message("[src] medicates themself.", "<span class='notice'>You medicate yourself.</span>")
|
||||
health += healamount
|
||||
|
||||
/mob/living/simple_animal/hostile/cat_butcherer/CanAttack(atom/the_target)
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/human/C = target
|
||||
if(C.getorgan(/obj/item/organ/ears/cat) && C.getorgan(/obj/item/organ/tail/cat) && C.has_trauma_type(/datum/brain_trauma/severe/pacifism))//he wont attack his creations
|
||||
if(C.stat && !istype(C.dna.species, /datum/species/ipc))//unless they need healing
|
||||
return ..()
|
||||
else
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/cat_butcherer/AttackingTarget()
|
||||
. = ..()
|
||||
if(. && prob(35) && iscarbon(target))
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/human/L = target
|
||||
var/obj/item/organ/tail/cat/tail = L.getorgan(/obj/item/organ/tail/cat)
|
||||
if(!QDELETED(tail))
|
||||
visible_message("[src] severs [L]'s tail in one swift swipe!", "<span class='notice'>You sever [L]'s tail in one swift swipe.</span>")
|
||||
tail.Remove()
|
||||
var/obj/item/organ/tail/cat/dropped_tail = new(target.drop_location())
|
||||
dropped_tail.color = L.hair_color
|
||||
return 1
|
||||
if(!L.getorgan(/obj/item/organ/ears/cat) && L.stat) //target doesnt have cat ears
|
||||
if(L.getorgan(/obj/item/organ/ears)) //slice off the old ears
|
||||
var/obj/item/organ/ears/ears = L.getorgan(/obj/item/organ/ears)
|
||||
visible_message("[src] slices off [L]'s ears!", "<span class='notice'>You slice [L]'s ears off.</span>")
|
||||
ears.Remove(L)
|
||||
ears.forceMove(get_turf(L))
|
||||
else //implant new ears
|
||||
visible_message("[src] attaches a pair of cat ears to [L]!", "<span class='notice'>You attach a pair of cat ears to [L].</span>")
|
||||
var/obj/item/organ/ears/cat/newears = new
|
||||
newears.Insert(L, drop_if_replaced = FALSE)
|
||||
return
|
||||
else if(!L.getorgan(/obj/item/organ/tail/cat) && L.stat)
|
||||
if(L.getorgan(/obj/item/organ/tail)) //cut off the tail if they have one already
|
||||
var/obj/item/organ/tail/tail = L.getorgan(/obj/item/organ/tail)
|
||||
visible_message("[src] severs [L]'s tail in one swift swipe!", "<span class='notice'>You sever [L]'s tail in one swift swipe.</span>")
|
||||
tail.Remove(L)
|
||||
tail.forceMove(get_turf(L))
|
||||
else //put a cat tail on
|
||||
visible_message("[src] attaches a cat tail to [L]!", "<span class='notice'>You attach a tail to [L].</span>")
|
||||
var/obj/item/organ/tail/cat/newtail = new
|
||||
newtail.Insert(L, drop_if_replaced = FALSE)
|
||||
return
|
||||
else if(!L.has_trauma_type(/datum/brain_trauma/severe/pacifism) && L.getorgan(/obj/item/organ/ears/cat) && L.getorgan(/obj/item/organ/tail/cat)) //still does damage. This also lacks a Stat check- felinids beware.
|
||||
visible_message("[src] drills a hole in [L]'s skull!", "<span class='notice'>You pacify [L]. Another successful creation.</span>")
|
||||
if(L.stat == CONSCIOUS)
|
||||
L.emote("scream")
|
||||
L.gain_trauma(/datum/brain_trauma/severe/pacifism, TRAUMA_RESILIENCE_BASIC)
|
||||
say("Such a GOOD KITTY!!")
|
||||
if(L.mind && maxHealth <= 300) //if he robusts a tider, he becomes stronger
|
||||
maxHealth += 20
|
||||
adjustHealth(-(maxHealth)) //he heals whenever he finishes
|
||||
else if(L.stat) //quickly heal them up and move on to our next target!
|
||||
visible_message("[src] injects [L] with an unknown medicine!", "<span class='notice'>You inject [L] with medicine.</span>")
|
||||
L.SetSleeping(0, FALSE)
|
||||
L.SetUnconscious(0, FALSE)
|
||||
L.adjustOxyLoss(-50)// do CPR first
|
||||
if(L.blood_volume <= 500) //bandage them up and give em some blood if they're bleeding
|
||||
L.blood_volume += 30
|
||||
L.bleedsuppress = 0
|
||||
if(L.getBruteLoss() >= 50)// first, did we beat them into crit? if so, heal that
|
||||
var/healing = min(L.getBruteLoss(), 120)
|
||||
L.adjustBruteLoss(-healing)
|
||||
L.bleedsuppress = 0 //bandage their ass
|
||||
return
|
||||
else if(L.getFireLoss() >= 50) // are they still down from other damage? fix it, but not as fast as the burns
|
||||
var/healing = min(L.getFireLoss(), 50)
|
||||
L.adjustFireLoss(-healing)
|
||||
impatience += 50
|
||||
if(prob(impatience))
|
||||
FindTarget()//so we don't focus on some unconscious dude when we could get our eyes on the prize
|
||||
impatience = 0
|
||||
say("Bah!!")
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -0,0 +1,457 @@
|
||||
GLOBAL_VAR_INIT(floor_cluwnes, 0)
|
||||
|
||||
#define STAGE_HAUNT 1
|
||||
#define STAGE_SPOOK 2
|
||||
#define STAGE_TORMENT 3
|
||||
#define STAGE_ATTACK 4
|
||||
#define MANIFEST_DELAY 9
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne
|
||||
name = "???"
|
||||
desc = "...."
|
||||
icon = 'icons/obj/clothing/masks.dmi'
|
||||
icon_state = "cluwne"
|
||||
icon_living = "cluwne"
|
||||
icon_gib = "clown_gib"
|
||||
maxHealth = 250
|
||||
health = 250
|
||||
speed = -1
|
||||
attack_verb_continuous = "attacks"
|
||||
attack_verb_simple = "attack"
|
||||
attack_sound = 'sound/items/bikehorn.ogg'
|
||||
del_on_death = TRUE
|
||||
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB | LETPASSTHROW | PASSGLASS | PASSBLOB//it's practically a ghost when unmanifested (under the floor)
|
||||
loot = list(/obj/item/clothing/mask/gas/cluwne)
|
||||
wander = FALSE
|
||||
minimum_distance = 2
|
||||
move_to_delay = 1
|
||||
movement_type = FLYING
|
||||
environment_smash = FALSE
|
||||
lose_patience_timeout = FALSE
|
||||
pixel_y = 8
|
||||
pressure_resistance = 200
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
var/mob/living/carbon/human/current_victim
|
||||
var/manifested = FALSE
|
||||
var/switch_stage = 60
|
||||
var/stage = STAGE_HAUNT
|
||||
var/interest = 0
|
||||
var/target_area
|
||||
var/invalid_area_typecache = list(/area/space, /area/lavaland, /area/centcom, /area/reebe, /area/shuttle/syndicate)
|
||||
var/eating = FALSE
|
||||
var/dontkill = FALSE //for if we just wanna curse a fucker
|
||||
var/obj/effect/dummy/floorcluwne_orbit/poi
|
||||
var/obj/effect/temp_visual/fcluwne_manifest/cluwnehole
|
||||
move_resist = INFINITY
|
||||
hud_type = /datum/hud/ghost
|
||||
hud_possible = list(ANTAG_HUD)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/Initialize()
|
||||
. = ..()
|
||||
access_card = new /obj/item/card/id(src)
|
||||
var/datum/job/captain/C = new /datum/job/captain
|
||||
access_card.access = C.get_access()
|
||||
invalid_area_typecache = typecacheof(invalid_area_typecache)
|
||||
Manifest()
|
||||
if(!current_victim)
|
||||
Acquire_Victim()
|
||||
poi = new(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/med_hud_set_health()
|
||||
return //we use a different hud
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/med_hud_set_status()
|
||||
return //we use a different hud
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/Destroy()
|
||||
QDEL_NULL(poi)
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/attack_hand(mob/living/carbon/human/M)
|
||||
..()
|
||||
playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/CanPass(atom/A, turf/target)
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/Life()
|
||||
do_jitter_animation(1000)
|
||||
pixel_y = 8
|
||||
|
||||
var/area/A = get_area(src.loc)
|
||||
if(is_type_in_typecache(A, invalid_area_typecache) || !is_station_level(z))
|
||||
var/area = pick(GLOB.teleportlocs)
|
||||
var/area/tp = GLOB.teleportlocs[area]
|
||||
forceMove(pick(get_area_turfs(tp.type)))
|
||||
|
||||
if(!current_victim)
|
||||
Acquire_Victim()
|
||||
|
||||
if(stage && !manifested)
|
||||
INVOKE_ASYNC(src, .proc/On_Stage)
|
||||
|
||||
if(stage == STAGE_ATTACK)
|
||||
playsound(src, 'sound/misc/cluwne_breathing.ogg', 75, 1)
|
||||
|
||||
if(eating)
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(current_victim)
|
||||
A = get_area(T)
|
||||
if(prob(5))//checks roughly every 20 ticks
|
||||
if(current_victim.stat == DEAD || current_victim.dna.check_mutation(CLUWNEMUT) || is_type_in_typecache(A, invalid_area_typecache) || !is_station_level(current_victim.z))
|
||||
if(!Found_You())
|
||||
Acquire_Victim()
|
||||
|
||||
if(get_dist(src, current_victim) > 9 && !manifested && !is_type_in_typecache(A, invalid_area_typecache))//if cluwne gets stuck he just teleports
|
||||
do_teleport(src, T)
|
||||
|
||||
interest++
|
||||
if(interest >= switch_stage * 4 && !dontkill)
|
||||
stage = STAGE_ATTACK
|
||||
|
||||
else if(interest >= switch_stage * 2)
|
||||
stage = STAGE_TORMENT
|
||||
|
||||
else if(interest >= switch_stage)
|
||||
stage = STAGE_SPOOK
|
||||
|
||||
else if(interest < switch_stage)
|
||||
stage = STAGE_HAUNT
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/Goto(target, delay, minimum_distance)
|
||||
var/area/A = get_area(current_victim.loc)
|
||||
if(!manifested && !is_type_in_typecache(A, invalid_area_typecache) && is_station_level(current_victim.z))
|
||||
walk_to(src, target, minimum_distance, delay)
|
||||
else
|
||||
walk_to(src,0)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/FindTarget()
|
||||
return current_victim
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/CanAttack(atom/the_target)//you will not escape
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/AttackingTarget()
|
||||
return
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/LoseTarget()
|
||||
return
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)//prevents runtimes with machine fuckery
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/Found_You()
|
||||
for(var/obj/structure/closet/hiding_spot in orange(7,src))
|
||||
if(current_victim.loc == hiding_spot)
|
||||
hiding_spot.bust_open()
|
||||
current_victim.Paralyze(40)
|
||||
to_chat(current_victim, "<span class='warning'>...edih t'nac uoY</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/Acquire_Victim(specific)
|
||||
for(var/I in GLOB.player_list)//better than a potential recursive loop
|
||||
var/mob/living/carbon/human/H = pick(GLOB.player_list)//so the check is fair
|
||||
var/area/A
|
||||
|
||||
if(specific)
|
||||
H = specific
|
||||
A = get_area(H.loc)
|
||||
if(H.stat != DEAD && H.has_dna() && !H.dna.check_mutation(CLUWNEMUT) && !is_type_in_typecache(A, invalid_area_typecache) && is_station_level(H.z))
|
||||
return target = current_victim
|
||||
|
||||
A = get_area(H.loc)
|
||||
if(H && ishuman(H) && H.stat != DEAD && H != current_victim && H.has_dna() && !H.dna.check_mutation(CLUWNEMUT) && !is_type_in_typecache(A, invalid_area_typecache) && is_station_level(H.z))
|
||||
current_victim = H
|
||||
interest = 0
|
||||
stage = STAGE_HAUNT
|
||||
return target = current_victim
|
||||
|
||||
message_admins("Floor Cluwne was deleted due to a lack of valid targets, if this was a manually targeted instance please re-evaluate your choice.")
|
||||
qdel(src)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/Manifest()//handles disappearing and appearance anim
|
||||
if(manifested)
|
||||
mobility_flags &= ~MOBILITY_MOVE
|
||||
update_mobility()
|
||||
cluwnehole = new(src.loc)
|
||||
addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Appear), MANIFEST_DELAY)
|
||||
else
|
||||
layer = GAME_PLANE
|
||||
invisibility = INVISIBILITY_OBSERVER
|
||||
density = FALSE
|
||||
mobility_flags |= MOBILITY_MOVE
|
||||
update_mobility()
|
||||
if(cluwnehole)
|
||||
qdel(cluwnehole)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/Appear()//handled in a seperate proc so floor cluwne doesn't appear before the animation finishes
|
||||
layer = LYING_MOB_LAYER
|
||||
invisibility = FALSE
|
||||
density = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/Reset_View(screens, colour, mob/living/carbon/human/H)
|
||||
if(screens)
|
||||
for(var/whole_screen in screens)
|
||||
animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
|
||||
if(colour && H)
|
||||
H.client.color = colour
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/On_Stage()
|
||||
var/mob/living/carbon/human/H = current_victim
|
||||
switch(stage)
|
||||
|
||||
if(STAGE_HAUNT)
|
||||
|
||||
if(prob(5))
|
||||
H.blur_eyes(1)
|
||||
|
||||
if(prob(5))
|
||||
H.playsound_local(src,'sound/voice/cluwnelaugh2_reversed.ogg', 1)
|
||||
|
||||
if(prob(5))
|
||||
H.playsound_local(src,'sound/misc/bikehorn_creepy.ogg', 5)
|
||||
|
||||
if(prob(3))
|
||||
var/obj/item/I = locate() in orange(H, 8)
|
||||
if(I && !I.anchored)
|
||||
I.throw_at(H, 4, 3)
|
||||
to_chat(H, "<span class='warning'>What threw that?</span>")
|
||||
|
||||
if(STAGE_SPOOK)
|
||||
|
||||
if(prob(4))
|
||||
var/turf/T = get_turf(H)
|
||||
T.handle_slip(H, 20)
|
||||
to_chat(H, "<span class='warning'>The floor shifts underneath you!</span>")
|
||||
|
||||
if(prob(5))
|
||||
H.playsound_local(src,'sound/voice/cluwnelaugh2.ogg', 2)
|
||||
|
||||
if(prob(5))
|
||||
H.playsound_local(src,'sound/voice/cluwnelaugh2_reversed.ogg', 2)
|
||||
|
||||
if(prob(5))
|
||||
H.playsound_local(src,'sound/misc/bikehorn_creepy.ogg', 10)
|
||||
to_chat(H, "<i>knoh</i>")
|
||||
|
||||
if(prob(5))
|
||||
var/obj/item/I = locate() in orange(H, 8)
|
||||
if(I && !I.anchored)
|
||||
I.throw_at(H, 4, 3)
|
||||
to_chat(H, "<span class='warning'>What threw that?</span>")
|
||||
|
||||
if(prob(2))
|
||||
to_chat(H, "<i>yalp ot tnaw I</i>")
|
||||
Appear()
|
||||
manifested = FALSE
|
||||
addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Manifest), 1)
|
||||
|
||||
if(STAGE_TORMENT)
|
||||
|
||||
if(prob(5))
|
||||
var/turf/T = get_turf(H)
|
||||
T.handle_slip(H, 20)
|
||||
to_chat(H, "<span class='warning'>The floor shifts underneath you!</span>")
|
||||
|
||||
if(prob(3))
|
||||
playsound(src,pick('sound/spookoween/scary_horn.ogg', 'sound/spookoween/scary_horn2.ogg', 'sound/spookoween/scary_horn3.ogg'), 30, 1)
|
||||
|
||||
if(prob(3))
|
||||
playsound(src,'sound/voice/cluwnelaugh1.ogg', 30, 1)
|
||||
|
||||
if(prob(3))
|
||||
playsound(src,'sound/voice/cluwnelaugh2_reversed.ogg', 30, 1)
|
||||
|
||||
if(prob(5))
|
||||
playsound(src,'sound/misc/bikehorn_creepy.ogg', 30, 1)
|
||||
|
||||
if(prob(4))
|
||||
for(var/obj/item/I in orange(8, H))
|
||||
if(!I.anchored)
|
||||
I.throw_at(H, 4, 3)
|
||||
to_chat(H, "<span class='warning'>What the hell?!</span>")
|
||||
|
||||
if(prob(2))
|
||||
to_chat(H, "<span class='warning'>Something feels very wrong...</span>")
|
||||
H.playsound_local(src,'sound/hallucinations/behind_you1.ogg', 25)
|
||||
H.flash_act()
|
||||
|
||||
if(prob(2))
|
||||
to_chat(H, "<i>!?REHTOMKNOH eht esiarp uoy oD</i>")
|
||||
to_chat(H, "<span class='warning'>Something grabs your foot!</span>")
|
||||
H.playsound_local(src,'sound/hallucinations/i_see_you1.ogg', 25)
|
||||
H.Stun(20)
|
||||
|
||||
if(prob(3))
|
||||
to_chat(H, "<i>KNOH ?od nottub siht seod tahW</i>")
|
||||
for(var/turf/open/O in RANGE_TURFS(6, src))
|
||||
O.MakeSlippery(TURF_WET_WATER, 10)
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1)
|
||||
|
||||
if(prob(1))
|
||||
to_chat(H, "<span class='userdanger'>WHAT THE FUCK IS THAT?!</span>")
|
||||
to_chat(H, "<i>.KNOH !nuf hcum os si uoy htiw gniyalP .KNOH KNOH KNOH</i>")
|
||||
H.playsound_local(src,'sound/hallucinations/im_here1.ogg', 25)
|
||||
H.reagents.add_reagent(/datum/reagent/toxin/mindbreaker, 3)
|
||||
H.reagents.add_reagent(/datum/reagent/consumable/laughter, 5)
|
||||
H.reagents.add_reagent(/datum/reagent/mercury, 3)
|
||||
Appear()
|
||||
manifested = FALSE
|
||||
addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Manifest), 2)
|
||||
for(var/obj/machinery/light/L in range(8, H))
|
||||
L.flicker()
|
||||
|
||||
|
||||
if(STAGE_ATTACK)
|
||||
if(dontkill)
|
||||
stage = STAGE_TORMENT
|
||||
return
|
||||
if(!eating)
|
||||
Found_You()
|
||||
for(var/I in getline(src,H))
|
||||
var/turf/T = I
|
||||
if(T.density)
|
||||
forceMove(H.loc)
|
||||
for(var/obj/structure/O in T)
|
||||
if(O.density || istype(O, /obj/machinery/door/airlock))
|
||||
forceMove(H.loc)
|
||||
to_chat(H, "<span class='userdanger'>You feel the floor closing in on your feet!</span>")
|
||||
H.Paralyze(300)
|
||||
INVOKE_ASYNC(H, /mob.proc/emote, "scream")
|
||||
H.adjustBruteLoss(10)
|
||||
manifested = TRUE
|
||||
Manifest()
|
||||
if(!eating)
|
||||
addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Grab, H), 50, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
for(var/turf/open/O in RANGE_TURFS(6, src))
|
||||
O.MakeSlippery(TURF_WET_LUBE, 20)
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1)
|
||||
eating = TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/Grab(mob/living/carbon/human/H)
|
||||
if (H != current_victim)
|
||||
message_admins("Cluwne tried to grab someone who's not the target. Returning to life stage.")
|
||||
return
|
||||
to_chat(H, "<span class='userdanger'>You feel a cold, gloved hand clamp down on your ankle!</span>")
|
||||
for(var/I in 1 to get_dist(src, H))
|
||||
if(do_after(src, 5, target = H))
|
||||
step_towards(H, src)
|
||||
playsound(H, pick('sound/effects/bodyscrape-01.ogg', 'sound/effects/bodyscrape-02.ogg'), 20, 1, -4)
|
||||
if(prob(40))
|
||||
H.emote("scream")
|
||||
else if(prob(25))
|
||||
H.say(pick("HELP ME!!","IT'S GOT ME!!","DON'T LET IT TAKE ME!!",";SOMETHING'S KILLING ME!!","HOLY FUCK!!"))
|
||||
playsound(src, pick('sound/voice/cluwnelaugh1.ogg', 'sound/voice/cluwnelaugh2.ogg', 'sound/voice/cluwnelaugh3.ogg'), 50, 1)
|
||||
|
||||
if(get_dist(src,H) <= 1)
|
||||
visible_message("<span class='danger'>[src] begins dragging [H] under the floor!</span>")
|
||||
if(do_after(src, 50, target = H) && eating)
|
||||
H.become_blind()
|
||||
H.layer = GAME_PLANE
|
||||
H.invisibility = INVISIBILITY_OBSERVER
|
||||
H.density = FALSE
|
||||
H.anchored = TRUE
|
||||
addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Kill, H), 100, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
visible_message("<span class='danger'>[src] pulls [H] under!</span>")
|
||||
to_chat(H, "<span class='userdanger'>[src] drags you underneath the floor!</span>")
|
||||
else
|
||||
eating = FALSE
|
||||
else
|
||||
eating = FALSE
|
||||
manifested = FALSE
|
||||
Manifest()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/floor_cluwne/proc/Kill(mob/living/carbon/human/H)
|
||||
if (H != current_victim)
|
||||
message_admins("Cluwne tried to kill someone who's not the target. Returning to life stage.")
|
||||
H.invisibility = initial(H.invisibility)
|
||||
return
|
||||
if(!istype(H) || !H.client)
|
||||
H.invisibility = initial(H.invisibility)
|
||||
Acquire_Victim()
|
||||
return
|
||||
playsound(H, 'sound/effects/cluwne_feast.ogg', 100, 0, -4)
|
||||
var/old_color = H.client.color
|
||||
var/red_splash = list(1,0,0,0.8,0.2,0, 0.8,0,0.2,0.1,0,0)
|
||||
var/pure_red = list(0,0,0,0,0,0,0,0,0,1,0,0)
|
||||
H.client.color = pure_red
|
||||
animate(H.client,color = red_splash, time = 10, easing = SINE_EASING|EASE_OUT)
|
||||
for(var/turf/T in orange(H, 4))
|
||||
H.add_splatter_floor(T)
|
||||
if(do_after(src, 50, target = H))
|
||||
H.unequip_everything()//more runtime prevention
|
||||
if(prob(75))
|
||||
H.gib(FALSE)
|
||||
else
|
||||
H.cluwneify()
|
||||
H.adjustBruteLoss(30)
|
||||
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100, 100)
|
||||
H.cure_blind()
|
||||
H.layer = initial(H.layer)
|
||||
H.invisibility = initial(H.invisibility)
|
||||
H.density = initial(H.density)
|
||||
H.anchored = initial(H.anchored)
|
||||
H.blur_eyes(10)
|
||||
animate(H.client,color = old_color, time = 20)
|
||||
|
||||
eating = FALSE
|
||||
switch_stage = switch_stage * 0.75 //he gets faster after each feast
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
M.playsound_local(get_turf(M), 'sound/misc/honk_echo_distant.ogg', 50, 1, pressure_affected = FALSE)
|
||||
|
||||
interest = 0
|
||||
stage = STAGE_HAUNT
|
||||
Acquire_Victim()
|
||||
|
||||
//manifestation animation
|
||||
/obj/effect/temp_visual/fcluwne_manifest
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "fcluwne_open"
|
||||
layer = TURF_LAYER
|
||||
duration = 600
|
||||
randomdir = FALSE
|
||||
|
||||
/obj/effect/temp_visual/fcluwne_manifest/Initialize()
|
||||
. = ..()
|
||||
playsound(src, 'sound/misc/floor_cluwne_emerge.ogg', 100, 1)
|
||||
flick("fcluwne_manifest",src)
|
||||
|
||||
/obj/effect/dummy/floorcluwne_orbit
|
||||
name = "floor cluwne"
|
||||
desc = "If you have this, tell a coder or admin!"
|
||||
|
||||
/obj/effect/dummy/floorcluwne_orbit/Initialize()
|
||||
. = ..()
|
||||
GLOB.floor_cluwnes++
|
||||
name += " ([GLOB.floor_cluwnes])"
|
||||
GLOB.poi_list += src
|
||||
|
||||
/obj/effect/dummy/floorcluwne_orbit/Destroy()
|
||||
. = ..()
|
||||
GLOB.poi_list -= src
|
||||
|
||||
#undef STAGE_HAUNT
|
||||
#undef STAGE_SPOOK
|
||||
#undef STAGE_TORMENT
|
||||
#undef STAGE_ATTACK
|
||||
#undef MANIFEST_DELAY
|
||||
@@ -6,6 +6,7 @@
|
||||
var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
|
||||
var/SStun = 0 // stun variable
|
||||
|
||||
typing_indicator_state = /obj/effect/overlay/typing_indicator/slime
|
||||
|
||||
/mob/living/simple_animal/slime/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
|
||||
@@ -55,3 +55,12 @@ GLOBAL_LIST_EMPTY(typing_indicator_overlays)
|
||||
icon_state = "normal_typing"
|
||||
appearance_flags = RESET_COLOR | TILE_BOUND | PIXEL_SCALE
|
||||
layer = ABOVE_FLY_LAYER
|
||||
|
||||
/obj/effect/overlay/typing_indicator/machine
|
||||
icon_state = "machine_typing"
|
||||
|
||||
/obj/effect/overlay/typing_indicator/machine/dogborg
|
||||
icon = 'icons/mob/talk_64x64.dmi'
|
||||
|
||||
/obj/effect/overlay/typing_indicator/slime
|
||||
icon_state = "slime_typing"
|
||||
|
||||
Reference in New Issue
Block a user