Files
2020-02-19 19:48:29 -08:00

1254 lines
34 KiB
Plaintext

/obj/critter/livingobj
name = ""
desc = ""
icon_state = "livingobj"
density = 0
health = 10
aggressive = 0
defensive = 0
wanderer = 1
opensdoors = 0
atkcarbon = 0
atksilicon = 0
generic = 0
butcherable = 1 //Because "toolbox meat" would be hilarious
atk_text = "slams into"
atk_brute_amt = 2
crit_chance = 0
chase_text = "leaps at"
var/stunprob = 0
layer = 5
var/obj/original_object = null
CritterAttack(var/mob/M)
playsound(src.loc, "sound/impact_sounds/Generic_Hit_1.ogg", 50, 1, -1)
..()
attack_hand(mob/user as mob)
if (src.alive && (user.a_intent != INTENT_HARM))
src.visible_message("<span class='combat'><b>[user]</b> pets [src]!</span>")
return
..()
CritterDeath()
src.visible_message("<b>[src]</b> stops moving!")
animate_float(src, 1, 5)
playsound(src.loc, "sound/effects/suck.ogg", 40, 1, -1, 0.6)
SPAWN_DBG (100) //Give time for people to butcher it if they want.
if (!src.disposed && src.loc && original_object)
original_object.loc = src.loc
original_object = null
qdel(src)
return ..()
ChaseAttack(mob/M)
..()
if (prob(stunprob))
M.changeStatus("weakened", 2 SECONDS)
//playsound(src.loc, "sound/impact_sounds/Generic_Hit_1.ogg", 50, 1, -1)
disposing()
if (original_object)
original_object.dispose()
original_object = null
..()
/obj/critter/spore
name = "plasma spore"
desc = "A barely intelligent colony of organisms. Very volatile."
icon_state = "spore"
density = 1
health = 1
aggressive = 0
defensive = 0
wanderer = 1
opensdoors = 0
atkcarbon = 0
atksilicon = 0
firevuln = 2
brutevuln = 2
flying = 1
CritterDeath()
src.visible_message("<b>[src]</b> ruptures and explodes!")
src.alive = 0
var/turf/T = get_turf(src.loc)
if(T)
T.hotspot_expose(700,125)
explosion(src, T, -1, -1, 2, 3)
qdel (src)
ex_act(severity)
CritterDeath()
bullet_act(flag, A as obj)
CritterDeath()
/obj/critter/mimic
name = "mechanical toolbox"
desc = null
icon_state = "mimic_blue1"
health = 20
aggressive = 1
defensive = 1
wanderer = 0
atkcarbon = 1
atksilicon = 1
brutevuln = 0.5
seekrange = 1
angertext = "suddenly comes to life and lunges at"
death_text = "%src% flops closed, dead!"
chase_text = "hurls itself at"
atk_brute_amt = 3
crit_brute_amt = 6
var/toolbox_style = "blue"
var/list/toolbox_list = list("blue", "red", "yellow", "green")
var/switcharoo = 10 // set to 0 for mimics that always are mimics and never toolboxes
New()
..()
src.toolbox_style = pick(src.toolbox_list)
src.update_icon()
if (prob(src.switcharoo))
switch (src.toolbox_style)
if ("blue")
new /obj/item/storage/toolbox/mechanical(src.loc)
if ("red")
new /obj/item/storage/toolbox/emergency(src.loc)
if ("yellow")
new /obj/item/storage/toolbox/electrical(src.loc)
if ("green")
if (prob(1))
new /obj/item/storage/toolbox/memetic(src.loc)
else
new /obj/item/storage/toolbox/artistic(src.loc)
qdel(src)
ai_think()
..()
if (src.alive)
switch (task)
if ("thinking")
src.update_icon()
if ("chasing")
src.update_icon()
if ("attacking")
src.update_icon()
ChaseAttack(mob/M)
..()
if (prob(33)) M.changeStatus("weakened", 4 SECONDS)
CritterAttack(mob/M)
..()
proc/update_icon()
if (!src.toolbox_style)
src.toolbox_style = pick(src.toolbox_list)
src.dead_state = "mimic_[src.toolbox_style]1-dead"
switch (src.task)
if ("thinking")
src.icon_state = "mimic_[src.toolbox_style]1"
if (src.toolbox_style == "blue")
src.name = "mechanical toolbox"
src.desc = "A metal container designed to hold various tools. This variety holds standard construction tools."
if (src.toolbox_style == "red")
src.name = "emergency toolbox"
src.desc = "A metal container designed to hold various tools. This variety holds supplies required for emergencies."
if (src.toolbox_style == "yellow")
src.name = "electrical toolbox"
src.desc = "A metal container designed to hold various tools. This variety holds electrical supplies."
if (src.toolbox_style == "green")
src.name = "artistic toolbox"
src.desc = "It almost hurts to look at that, it's all out of focus."
if ("chasing")
src.icon_state = "mimic_[src.toolbox_style]2"
src.name = "mimic"
src.desc = "Oh shit, that's no toolbox at all!"
if ("attacking")
src.icon_state = "mimic_[src.toolbox_style]2"
src.name = "mimic"
src.desc = "Oh shit, that's no toolbox at all!"
/*
/obj/critter/mimic_old
name = "mechanical toolbox"
desc = null
icon_state = "mimic1"
health = 20
aggressive = 1
defensive = 1
wanderer = 0
atkcarbon = 1
atksilicon = 1
brutevuln = 0.5
seekrange = 1
angertext = "suddenly comes to life and lunges at"
death_text = "%src% crumbles to pieces!"
ai_think()
..()
if (src.alive)
switch(task)
if("thinking")
src.icon_state = "mimic1"
src.name = "mechanical toolbox"
if("chasing")
src.icon_state = "mimic2"
src.name = "mimic"
if("attacking")
src.icon_state = "mimic2"
src.name = "mimic"
ChaseAttack(mob/M)
src.visible_message("<span class='combat'><B>[src]</B> hurls itself at [M]!</span>")
if (prob(33)) M.weakened += rand(3,6)
CritterAttack(mob/M)
src.attacking = 1
src.visible_message("<span class='combat'><B>[src]</B> bites [src.target]!</span>")
random_brute_damage(src.target, rand(2,4))
SPAWN_DBG(2.5 SECONDS)
src.attacking = 0
*/
/obj/critter/wraithskeleton
name = "skeleton"
desc = "It looks rather crumbly."
icon = 'icons/mob/human_decomp.dmi'
icon_state = "decomp4"
health = 1
aggressive = 1
defensive = 1
wanderer = 1
atkcarbon = 1
atksilicon = 1
brutevuln = 1
seekrange = 7
skinresult = /obj/item/material_piece/bone
max_skins = 2
death_text = "%src% vaporizes instantly!"
chase_text = "knocks down"
atk_text = "beats"
atk_brute_amt = 6
crit_chance = 0
ChaseAttack(mob/M)
if (prob(75))
..()
M.changeStatus("weakened", 4 SECONDS)
else
src.visible_message("<span class='combat'><B>[src]</B> tries to knock down [M]!</span>")
CritterAttack(mob/M)
..()
CritterDeath()
..()
particleMaster.SpawnSystem(new /datum/particleSystem/localSmoke("#000000", 5, locate(x, y, z)))
qdel(src)
/obj/critter/mimic2
name = "mechanical toolbox"
desc = null
icon_state = "mimic1"
health = 20
aggressive = 1
defensive = 1
wanderer = 0
atkcarbon = 1
atksilicon = 1
brutevuln = 0.5
seekrange = 1
angertext = "suddenly comes to life and lunges at"
var/objname = "mechanical toolbox" //name when in disguise
generic = 0
death_text = "%src% crumbles to pieces!"
chase_text = "hurls itself at"
atk_brute_amt = 3
crit_brute_amt = 6
ai_think()
..()
if (src.alive)
switch(task)
if("thinking")
src.overlays = null
src.name = objname
if("chasing")
src.overlays += image("icon" = 'icons/misc/critter.dmi', "icon_state" = "mimicface", "layer" = FLOAT_LAYER)
src.name = "mimic"
if("attacking")
src.overlays += image("icon" = 'icons/misc/critter.dmi', "icon_state" = "mimicface", "layer" = FLOAT_LAYER)
src.name = "mimic"
ChaseAttack(mob/M)
..()
if (prob(33)) M.changeStatus("weakened", 4 SECONDS)
CritterAttack(mob/M)
..()
/obj/critter/spirit
name = "spirit"
desc = null
invisibility = 10
icon_state = "spirit"
health = 10
aggressive = 1
defensive = 1
wanderer = 0
atkcarbon = 1
atksilicon = 1
brutevuln = 0.5
opensdoors = 1
seekrange = 5
density = 0
angertext = "suddenly materializes and lunges at"
flying = 1
generic = 0
death_text = "%src% dissipates!"
chase_text = "hurls itself at"
atk_text = "attacks"
atk_brute_amt = 3
crit_chance = 0
ai_think()
..()
if (src.alive)
switch(task)
if("thinking")
src.invisibility = 10
if("chasing")
src.invisibility = 0
if("attacking")
src.invisibility = 0
seek_target()
src.anchored = 0
for (var/mob/living/C in hearers(src.seekrange,src))
if (src.target)
src.task = "chasing"
break
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (iscarbon(C) && !src.atkcarbon) continue
if (issilicon(C) && !src.atksilicon) continue
if (C.health < 0) continue
if (C in src.friends) continue
if (isvampire(C)) continue
if (C.name == src.attacker) src.attack = 1
if (iscarbon(C) && src.atkcarbon) src.attack = 1
if (issilicon(C) && src.atksilicon) src.attack = 1
if (src.attack)
src.target = C
src.oldtarget_name = C.name
src.visible_message("<span class='combat'><b>[src]</b> [src.angertext] [C.name]!</span>")
src.task = "chasing"
break
else
continue
ChaseAttack(mob/M)
..()
if (prob(30)) M.changeStatus("weakened", 3 SECONDS)
CritterAttack(mob/M)
..()
CritterDeath()
if (!src.alive)
return
..()
new /obj/item/reagent_containers/food/snacks/ectoplasm(src.loc)
qdel(src)
bullet_act(var/obj/projectile/P)
if (istype(P, /datum/projectile/energy_bolt_antighost))
src.CritterDeath()
return
else
..()
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if (istype(mover, /obj/projectile))
var/obj/projectile/proj = mover
if (istype(proj.proj_data, /datum/projectile/energy_bolt_antighost))
return 0
return 1
/obj/critter/spacebee
name = "space wasp"
desc = "A wasp in space."
icon_state = "spacebee"
density = 1
health = 10
aggressive = 1
defensive = 1
wanderer = 1
opensdoors = 0
atkcarbon = 1
atksilicon = 1
firevuln = 1
brutevuln = 1
angertext = "buzzes at"
butcherable = 1
flags = NOSPLASH | OPENCONTAINER
flying = 1
//var/neurotoxin = 2
chase_text = "stings"
CritterDeath()
..()
src.reagents.add_reagent("toxin", 50, null)
src.reagents.add_reagent("histamine", 50, null)
return
seek_target()
src.anchored = 0
for (var/mob/living/C in hearers(src.seekrange,src))
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (iscarbon(C) && !src.atkcarbon) continue
if (issilicon(C) && !src.atksilicon) continue
if (C.job == "Botanist") continue
if (C.health < 0) continue
if (C in src.friends) continue
if (iscarbon(C) && src.atkcarbon) src.attack = 1
if (issilicon(C) && src.atksilicon) src.attack = 1
if (src.attack)
src.target = C
src.oldtarget_name = C.name
src.visible_message("<span class='combat'><b>[src]</b> charges at [C.name]!</span>")
src.task = "chasing"
break
else
continue
ChaseAttack(mob/M)
..()
if (M.reagents)
M.reagents.add_reagent("histamine", 12)
M.reagents.add_reagent("toxin", 2)
/obj/item/reagent_containers/food/snacks/ingredient/egg/critter/wasp
name = "space wasp egg"
critter_type = /obj/critter/spacebee
/obj/critter/magiczombie
name = "skeleton"
desc = "Clak clak, motherfucker."
icon_state = "skeleton"
dead_state = "skeleton-dead"
density = 1
health = 20 // too strong
aggressive = 1
defensive = 0
wanderer = 1
opensdoors = 1
atkcarbon = 1
atksilicon = 1
atcritter = 1
firevuln = 0.25
brutevuln = 0.5
chase_text = "bashes"
var/pixel_y_inc = 0
skinresult = /obj/item/material_piece/bone
max_skins = 2
var/revivalChance = 0 // Chance to revive when killed, out of 100. Wizard spell will set to 100, defaults to 0 because skeletons appear in telesci/other sources
var/revivalDecrement = 16 // Decreases revival chance each successful revival. Set to 0 and revivalChance=100 for a permanently reviving skeleton
New()
..()
playsound(src.loc, "sound/items/Scissor.ogg", 50, 0)
Move()
playsound(src.loc, "sound/impact_sounds/Crystal_Hit_1.ogg", 50, 0)
..()
attackby(obj/item/W as obj, mob/living/user as mob)
..()
if (!src.alive) return
if (istype(W, /obj/item/clothing/head))
if (pixel_y_inc > 20) return
var/image/I = image('icons/mob/head.dmi', src, W.icon_state)
I.pixel_y = pixel_y_inc
src.overlays += I
pixel_y_inc += 3
seek_target()
if (!src.alive) return
var/mob/living/Cc
for (var/mob/living/C in hearers(src.seekrange,src))
if (iswizard(C)) continue //do not attack our master
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (iscarbon(C) && !src.atkcarbon) continue
if (issilicon(C) && !src.atksilicon) continue
if (isdead(C)) continue
if (iscarbon(C) && src.atkcarbon) src.attack = 1
if (issilicon(C) && src.atksilicon) src.attack = 1
Cc = C
if (src.attack)
src.target = Cc
src.oldtarget_name = Cc.name
src.visible_message("<span class='combat'><b>[src]</b> charges towards [Cc.name]!</span>")
playsound(src.loc, "sound/items/Scissor.ogg", 50, 0)
src.task = "chasing"
return
proc/CustomizeMagZom(var/NM, var/is_monkey)
src.name = "[capitalize(NM)]'s skeleton"
src.desc = "A horrible skeleton, raised from the corpse of [NM] by a wizard."
src.revivalChance = 100
if (is_monkey)
icon = 'icons/mob/monkey.dmi'
return
ChaseAttack(mob/M)
if (!src.alive) return
..()
playsound(M.loc, "punch", 25, 1, -1)
random_brute_damage(M, rand(5,10))
if(prob(15)) // too mean before
M.visible_message("<span class='combat'><B>[M]</B> staggers!</span>")
M.changeStatus("stunned", 2 SECONDS)
M.changeStatus("weakened", 2 SECONDS)
CritterAttack(mob/M)
if (!src.alive) return
src.attacking = 1
if (ishuman(M))
var/mob/living/carbon/human/H = M
H.was_harmed(src)
if(!M.stat)
M.visible_message("<span class='combat'><B>[src]</B> pummels [src.target] mercilessly!</span>")
playsound(src.loc, "sound/impact_sounds/Generic_Hit_1.ogg", 50, 1, -1)
if(prob(10)) // lowered probability slightly
M.visible_message("<span class='combat'><B>[M]</B> staggers!</span>")
M.changeStatus("stunned", 2 SECONDS)
M.changeStatus("weakened", 2 SECONDS)
random_brute_damage(M, rand(5,10))
else
M.visible_message("<span class='combat'><B>[src]</B> hits [src.target] with a bone!</span>")
playsound(src.loc, "punch", 30, 1, -2)
random_brute_damage(M, rand(10,15))
SPAWN_DBG(1 SECOND)
src.attacking = 0
CritterDeath(mob/M)
if (!src.alive) return
..()
if (rand(100) <= revivalChance)
src.revivalChance -= revivalDecrement
SPAWN_DBG(rand(400,800))
src.alive = 1
src.set_density(1)
src.health = initial(src.health)
src.icon_state = initial(src.icon_state)
for(var/mob/O in viewers(src, null))
O.show_message("<span style=\"color:red\"><b>[src]</b> re-assembles and is ready to fight once more!</span>")
return
/obj/item/reagent_containers/food/snacks/ingredient/egg/critter/skeleton
name = "skeleton egg"
desc = "Uh. What?"
critter_type = /obj/critter/magiczombie
warm_count = 5
critter_reagent = "ash"
/obj/critter/golem
name = "Golem"
desc = "An elemental being, crafted by local artisans using traditional techniques."
icon_state = "golem"
density = 1
health = 25
aggressive = 1
defensive = 0
wanderer = 1
opensdoors = 1
atkcarbon = 1
atksilicon = 1
atcritter = 0 // don't bother!
firevuln = 0.25
brutevuln = 0.5
generic = 0
atk_text = "bashes against"
atk_brute_amt = 7
var/reagent_id = null
New()
..()
var/datum/reagents/R = new/datum/reagents(1000)
reagents = R
R.my_atom = src
SPAWN_DBG(4 SECONDS)
if(!reagents.total_volume)
if (all_functional_reagent_ids.len > 0)
src.reagent_id = pick(all_functional_reagent_ids)
else
src.reagent_id = "water"
R.add_reagent(src.reagent_id, 10)
var/oldcolor = src.reagents.get_master_color()
var/icon/I = new /icon('icons/misc/critter.dmi',"golem")
I.Blend(oldcolor, ICON_ADD)
src.icon = I
src.name = "[capitalize(src.reagents.get_master_reagent_name())]-Golem"
return
seek_target()
src.anchored = 0
var/mob/living/Cc
for (var/mob/living/C in hearers(src.seekrange,src))
if (C.ckey == null) continue //do not attack non-threats ie. NPC monkeys and AFK players
if (iswizard(C)) continue //do not attack our master
var/mob/living/carbon/human/H = C
if (istype(C) && (H.traitHolder.hasTrait("training_chaplain"))) continue
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (iscarbon(C) && !src.atkcarbon) continue
if (issilicon(C) && !src.atksilicon) continue
if (isdead(C)) continue
if (iscarbon(C) && src.atkcarbon) src.attack = 1
if (issilicon(C) && src.atksilicon) src.attack = 1
Cc = C
if (src.attack)
src.target = Cc
src.oldtarget_name = Cc.name
src.visible_message("<span class='combat'><b>[src]</b> charges at [Cc.name]!</span>")
src.task = "chasing"
return
proc/CustomizeGolem(var/datum/reagents/CR) //customise it with the reagents in a container
for(var/current_id in CR.reagent_list)
var/datum/reagent/R = CR.reagent_list[current_id]
src.reagents.add_reagent(current_id, min(R.volume * 5, 50))
var/oldcolor = src.reagents.get_master_color()
var/icon/I = new /icon('icons/misc/critter.dmi',"golem")
I.Blend(oldcolor, ICON_ADD)
src.icon = I
src.name = "[capitalize(src.reagents.get_master_reagent_name())]-Golem"
src.desc = "An elemental entity composed of [src.reagents.get_master_reagent_name()], conjured by a wizard."
return
CritterAttack(mob/M)
var/mob/living/carbon/human/H = M
if (istype(M) && (H.traitHolder.hasTrait("training_chaplain"))) return
..()
playsound(src.loc, "sound/impact_sounds/Generic_Hit_1.ogg", 50, 1, -1)
if(M.reagents)
if(src.reagents && src.reagents.total_volume)
src.reagents.reaction(M, TOUCH)
reagents.trans_to(M, 5)
CritterDeath()
if (!src.alive) return
..()
src.visible_message("<span class='combat'><b>[src]</b> bursts into a puff of smoke!</span>")
var/datum/chemical_reaction/smoke/thesmoke = new
thesmoke.on_reaction(src.reagents, 12)
invisibility = 100
SPAWN_DBG(5 SECONDS)
qdel(src)
/obj/critter/townguard
name = "Town Guard"
desc = "An angry man dressed in medieval armor."
icon_state = "townguard"
density = 1
health = 100
aggressive = 1
defensive = 0
wanderer = 1
opensdoors = 1
atkcarbon = 1
atksilicon = 1
atcritter = 1
firevuln = 0.75
brutevuln = 0.5
death_text = "%src% seizes up and falls limp, his eyes dead and lifeless..."
chase_text = "tackles"
var/sword_damage_max = 12
var/sword_damage_min = 6
passive
sword_damage_max = 0
sword_damage_min = 0
seek_target()
src.anchored = 0
for (var/mob/living/C in hearers(src.seekrange,src))
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (iscarbon(C) && !src.atkcarbon) continue
if (issilicon(C) && !src.atksilicon) continue
if (C.health < 0) continue
if (iscarbon(C) && src.atkcarbon) src.attack = 1
if (issilicon(C) && src.atksilicon) src.attack = 1
if (src.attack)
src.target = C
src.oldtarget_name = C.name
src.visible_message("<span class='combat'><b>[src]</b> points at [C.name]!</span>")
for(var/mob/O in hearers(src, null))
O.show_message("<b>[src]</b> says, \"HALT!\"", 2)
playsound(src.loc, "sound/voice/guard_halt.ogg", 50, 0)
src.task = "chasing"
return
else
continue
if(!src.atcritter) return
for (var/obj/critter/C in view(src.seekrange,src))
if (!C.alive) continue
if (C.health < 0) continue
if (!istype(C, /obj/critter/townguard)) src.attack = 1
if (src.attack)
src.target = C
src.oldtarget_name = C.name
src.visible_message("<span class='combat'><b>[src]</b> points at [C.name]!</span>")
for(var/mob/O in hearers(src, null))
O.show_message("<b>[src]</b> says, \"HALT!\"", 2)
playsound(src.loc, "sound/voice/guard_halt.ogg", 50, 0)
src.task = "chasing"
return
else continue
ChaseAttack(mob/M)
if(iscarbon(M) && prob(15))
..()
playsound(src.loc, "sound/impact_sounds/Generic_Shove_1.ogg", 50, 1, -1)
random_brute_damage(M, rand(0,3))
M.changeStatus("stunned", 2 SECONDS)
M.changeStatus("weakened", 2 SECONDS)
else
src.visible_message("<span class='combat'><B>[src]</B> tries to knock down [src.target] but misses!</span>", 1)
CritterAttack(mob/M)
for(var/mob/O in viewers(src, null))
O.show_message("<b>[src]</b> says, \"HALT!\"", 2)
playsound(src.loc, "sound/voice/guard_halt.ogg", 50, 0)
src.attacking = 1
if(istype(M,/obj/critter))
var/obj/critter/C = M
for(var/mob/O in hearers(src, null))
O.show_message("<b>[src]</b> says, \"HALT!\"", 2)
playsound(C.loc, "swing_hit", 50, 1, -1)
C.health -= 6
if(C.health <= 0)
C.CritterDeath()
SPAWN_DBG(2.5 SECONDS)
src.attacking = 0
return
if (M.health > 40 && !M.getStatusDuration("weakened"))
src.visible_message("<span class='combat'><B>[src]</B> attacks [src.target] with his sword!</span>")
playsound(M.loc, "swing_hit", 50, 1, -1)
var/to_deal = rand(sword_damage_min,sword_damage_max)
random_brute_damage(M, to_deal)
if(iscarbon(M))
if(to_deal > (((sword_damage_max-sword_damage_min)/2)+sword_damage_min) && prob(50))
src.visible_message("<span class='combat'><B>[src] knocks down [M]!</B></span>")
M:changeStatus("weakened", 80)
SPAWN_DBG(2.5 SECONDS)
src.attacking = 0
else
src.visible_message("<span class='combat'><B>[src]</B> kicks [src.target]!</span>")
playsound(src.loc, "swing_hit", 50, 1, -1)
random_brute_damage(src.target, rand(4,8))
SPAWN_DBG(2.5 SECONDS)
src.attacking = 0
if (ishuman(M))
var/mob/living/carbon/human/H = M
H.was_harmed(src)
return
ai_think()
if (prob(20))
if (src.target)
for(var/mob/O in viewers(src, null))
O.show_message("<b>[src]</b> says, \"HALT!\"", 2)
playsound(src.loc, "sound/voice/guard_halt.ogg", 50, 0)
return ..()
/obj/item/reagent_containers/food/snacks/ingredient/egg/critter/townguard
name = "\improper Town Guard egg"
desc = "This is not how humans reproduce. They do not lay eggs. <i>What the hell is this?</i>"
critter_type = /obj/critter/townguard
warm_count = 75
/obj/item/reagent_containers/food/snacks/ingredient/egg/critter/townguard/passive
critter_type = /obj/critter/townguard/passive
/obj/critter/bloodling
name = "Bloodling"
desc = "A force of pure sorrow and evil."
icon_state = "bling"
density = 1
health = 20
aggressive = 1
defensive = 0
wanderer = 1
opensdoors = 1
atkcarbon = 1
atksilicon = 0
atcritter = 0
firevuln = 0
brutevuln = 0
seekrange = 5
invisibility = 1
flying = 1
generic = 0
seek_target()
src.anchored = 0
for (var/mob/living/C in hearers(src.seekrange,src))
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (iscarbon(C) && !src.atkcarbon) continue
if (issilicon(C) && !src.atksilicon) continue
if (C.health < 0) continue
if (iscarbon(C) && src.atkcarbon) src.attack = 1
if (issilicon(C) && src.atksilicon) src.attack = 1
if (src.attack)
src.target = C
src.oldtarget_name = C.name
src.task = "chasing"
return
else
continue
ChaseAttack(mob/M)
src.attacking = 1
if (narrator_mode)
playsound(src.loc, 'sound/vox/ghost.ogg', 50, 1, -1)
else
playsound(src.loc, 'sound/effects/ghost.ogg', 50, 1, -1)
if(iscarbon(M) && prob(50))
if(M.see_invisible < 2)
boutput(M, "<span class='combat'><b>You are forced to the ground by an unseen being!</b></span>")
else
boutput(M, "<span class='combat'><b>You are forced to the ground by the Bloodling!</b></span>")
random_brute_damage(M, rand(0,3))
M.changeStatus("stunned", 2 SECONDS)
M.changeStatus("weakened", 2 SECONDS)
src.attacking = 0
return
CritterAttack(mob/M)
playsound(src.loc, "sound/effects/ghost2.ogg", 50, 1, -1)
attacking = 1
if(iscarbon(M))
if(prob(50))
random_brute_damage(M, rand(3,7))
boutput(M, "<span class='combat'><b>You feel blood getting drawn out through your skin!</b></span>")
else
boutput(M, "<span class='combat'>You feel uncomfortable.</span>")
SPAWN_DBG(5 DECI SECONDS)
attacking = 0
attackby(obj/item/W as obj, mob/living/user as mob)
if (!src.alive)
return
else
if(!W.reagents)
boutput(user, "<span class='combat'>Hitting it with [W] is ineffective!</span>")
return
if(W.reagents.has_reagent("water_holy"))
boutput(user, "[src] screams!")
CritterDeath()
return
else
boutput(user, "<span class='combat'>Hitting it with [W] is ineffective!</span>")
return
ai_think()
if(!locate(/obj/decal/cleanable/blood) in src.loc)
playsound(src.loc, "sound/impact_sounds/Slimy_Splat_1.ogg", 50, 1, -1)
make_cleanable( /obj/decal/cleanable/blood,loc)
return ..()
/obj/critter/blobman
name = "mutant"
desc = "Some sort of horrific, pulsating blob of flesh."
icon_state = "blobman"
density = 1
health = 15
aggressive = 1
defensive = 0
wanderer = 1
opensdoors = 1
atkcarbon = 1
atksilicon = 1
atcritter = 1
firevuln = 0.75
brutevuln = 0.5
death_text = "%src% collapses into viscera."
atk_text = "flails against"
atk_brute_amt = 6
crit_text = "flails heavily against"
crit_brute_amt = 12
chase_text = "headbutts"
CritterAttack(mob/M)
..()
playsound(src.loc, "sound/impact_sounds/Generic_Hit_1.ogg", 50, 1, -1)
ChaseAttack(mob/M)
..()
if(iscarbon(M))
if (prob(5)) M.changeStatus("stunned", 2 SECONDS)
random_brute_damage(M, rand(2,5))
//A terrible post-human cloud of murder.
/obj/critter/aberration
name = "transposed particle field"
desc = "A cloud of particles transposed by some manner of dangerous science, echoing some mannerisms of their previous configuration. In layman's terms, a goddamned science ghost."
icon_state = "aberration"
density = 1
health = 2
aggressive = 1
defensive = 1
wanderer = 1
opensdoors = 1
atkcarbon = 1
atksilicon = 1
atcritter = 1
firevuln = 0.01
brutevuln = 0.25
flying = 1
generic = 0
death_text = "%src% dissipates!"
CritterDeath()
..()
qdel(src)
CritterAttack(mob/M)
src.attacking = 1
src.visible_message("<span class='combat'><B>The [src.name]</B> starts to envelop [M]!</span>")
var/lastloc = M.loc
SPAWN_DBG(6 SECONDS)
if (get_dist(src, M) <= 1 && ((M.loc == lastloc)))
if(isliving(M))
logTheThing("combat", M, null, "was enveloped by [src] (obj) at [log_loc(src)].") // Some logging for instakill critters would be nice (Convair880).
M.ghostize()
if (iscarbon(M))
for(var/obj/item/W in M)
if (isitem(W))
M.u_equip(W)
if (W)
W.set_loc(M.loc)
W.dropped(M)
W.layer = initial(W.layer)
src.visible_message("<span class='combat'><B>The [src.name]</B> completely envelops [M]!</span>")
playsound(src.loc, "sound/impact_sounds/Slimy_Hit_4.ogg", 50, 1)
qdel(M)
src.attacking = 0
attack_hand(var/mob/user as mob)
if (src.alive)
boutput(user, "<span class='combat'><b>Your hand passes right through! It's so cold...</b></span>")
return
attackby(obj/item/W as obj, mob/living/user as mob)
if (!src.alive)
return
else
if (istype(W, /obj/item/baton))
var/obj/item/baton/B = W
if (B.can_stun(1, 1, user) == 1)
user.visible_message("<span class='combat'><b>[user] shocks the [src.name] with [B]!</b></span>", "<span class='combat'><b>While your baton passes through, the [src.name] appears damaged!</b></span>")
B.process_charges(-1, user)
src.health--
if (src.health <= 0)
src.CritterDeath()
return
boutput(user, "<span class='combat'><b>[W] passes right through!</b></span>")
return
seek_target()
src.anchored = 0
for (var/mob/living/C in range(src.seekrange,src))
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (iscarbon(C) && !src.atkcarbon) continue
if (issilicon(C) && !src.atksilicon) continue
if (ishuman(C) && istype(C:head, /obj/item/clothing/head/void_crown)) continue
if (C.health < 0) continue
if (iscarbon(C) && src.atkcarbon) src.attack = 1
if (issilicon(C) && src.atksilicon) src.attack = 1
if (src.attack)
src.target = C
src.oldtarget_name = C.name
src.task = "chasing"
return
else
continue
bullet_act(var/obj/projectile/P)
var/damage = 0
damage = round((P.power*(1-P.proj_data.ks_ratio)), 1.0)
if(P.proj_data.damage_type == D_ENERGY)
src.health -= damage
else
return
if (src.health <= 0)
src.CritterDeath()
ChaseAttack(mob/M)
return
/obj/critter/ancient_thing
name = "???"
desc = "What the hell is that?"
icon_state = "ancientrobot"
invisibility = 10
health = 30
firevuln = 0
brutevuln = 0.5
aggressive = 1
defensive = 1
wanderer = 0
opensdoors = 1
seekrange = 5
density = 1
var/boredom_countdown = 0
CritterDeath()
src.visible_message("<b>[src]</b> fades away.")
src.alive = 0
walk_to(src,0)
flick("ancientrobot-disappear",src)
src.invisibility = 10
critters -= src
src.dispose()
seek_target()
src.anchored = 0
if (src.target)
src.task = "chasing"
return
for (var/mob/living/carbon/C in view(src.seekrange,src))
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (C.stat || C.health < 0) continue
src.boredom_countdown = rand(5,10)
src.target = C
src.oldtarget_name = C.name
src.task = "chasing"
src.appear()
break
attackby(obj/item/W as obj, mob/living/user as mob)
if (!src.alive)
..()
return
switch(W.damtype)
if("fire")
src.health -= W.force * src.firevuln
if("brute")
src.health -= W.force * src.brutevuln
if (src.alive && src.health <= 0) src.CritterDeath()
src.boredom_countdown = rand(5,10)
src.target = user
src.oldtarget_name = user.name
src.task = "chasing"
attack_hand(var/mob/user as mob)
if (!src.alive)
..()
return
if (user.a_intent == "harm")
src.health -= rand(1,2) * src.brutevuln
for(var/mob/O in viewers(src, null))
O.show_message("<span class='combat'><b>[user]</b> punches [src]!</span>", 1)
playsound(src.loc, "punch", 50, 1)
if (src.alive && src.health <= 0) src.CritterDeath()
src.boredom_countdown = rand(5,10)
src.target = user
src.oldtarget_name = user.name
src.task = "chasing"
else
src.visible_message("<span class='combat'><b>[user]</b> pets [src]!<br>For some reason! Not like that's weird or anything!</span>", 1)
ChaseAttack(mob/M)
return
CritterAttack(mob/M)
src.attacking = 1
if (boredom_countdown-- > 0)
src.visible_message("<span class='combat'><B>[src]</B> [pick("measures", "gently pulls at", "examines", "pokes", "gently prods", "feels")] [src.target]'s [pick("head","neck","shoulders","right arm", "left arm","left leg","right leg")]!</span>")
if (prob(50))
boutput(src.target, "<span class='combat'>You feel [pick("very ",null,"rather ","fairly ","remarkably ")]uncomfortable.</span>")
else
var/mob/living/doomedMob = src.target
if (!istype(doomedMob))
return
src.visible_message("<span class='combat'><b>In a whirling flurry of tendrils, [src] rends down [src.target]! Holy shit!</b></span>")
logTheThing("combat", M, null, "was gibbed by [src] at [log_loc(src)].") // Some logging for instakill critters would be nice (Convair880).
playsound(src.loc, "sound/impact_sounds/Flesh_Break_1.ogg", 50, 1)
doomedMob.ghostize()
new /obj/decal/skeleton(doomedMob.loc)
doomedMob.gib()
src.target = null
SPAWN_DBG(4 SECONDS)
src.attacking = 0
proc/appear()
if (!invisibility || (src.icon_state != "ancientrobot"))
return
src.name = pick("something","weird thing","odd thing","whatchamacallit","thing","something weird","old thing")
src.icon_state = "ancientrobot-appear"
src.invisibility = 0
SPAWN_DBG(1.2 SECONDS)
src.icon_state = "ancientrobot"
return
/obj/critter/crunched
name = "transposed scientist"
desc = "A fellow who seems to have been shunted between dimensions. Not a good state to be in."
icon_state = "crunched"
health = 10
brutevuln = 0.5
firevuln = 0
aggressive = 1
generic = 0
attack_hand(var/mob/user as mob)
if (user.a_intent == "help")
return
..()
ChaseAttack(mob/M)
return
CritterAttack(mob/M)
if (!ismob(M))
return
src.attacking = 1
if (M.lying)
src.speak( pick("No! Get up! Please, get up!", "Not again! Not again! I need you!", "Please! Please get up! Please!", "I don't want to be alone again!") )
src.visible_message("<span style=\"color:blue\">[src] shakes [M] trying to wake them up!</span>")
boutput(M, "<span class='combat'><b>It burns!</b></span>")
M.TakeDamage("chest", 0, rand(5,15))
else
src.speak( pick("Please! Help! I need help!", "Please...help me!", "Are you real? You're real! YOU'RE REAL", "Everything hurts! Everything hurts!", "Please, make the pain stop! MAKE IT STOP!") )
src.visible_message("<span class='combat'><B>[src]</B> grabs at [M]'s arm!</span>")
boutput(M, "<span class='combat'><b>It burns!</b></span>")
M.TakeDamage("chest", 0, rand(5,15))
if (ishuman(M))
var/mob/living/carbon/human/H = M
H.was_harmed(src)
SPAWN_DBG(6 SECONDS)
src.attacking = 0
ai_think()
if(task == "thinking" || task == "wandering")
if (prob(5))
src.speak( pick("Cut the power! It's about to go critical, cut the power!","I warned them. I warned them the system wasn't ready.","Shut it down!","It hurts, oh God, oh God.") )
else
if (prob(5))
src.speak( pick("Please...help...it hurts...please", "I'm...sick...help","It went wrong. It all went wrong.","I didn't mean for this to happen!", "I see everything twice!") )
return ..()
CritterDeath()
speak( pick("There...is...nothing...","It's dark. Oh god, oh god, it's dark.","Thank you.","Oh wow. Oh wow. Oh wow.") )
src.icon_state = "crunched-dead"
src.alive = 0
SPAWN_DBG(1.5 SECONDS)
qdel(src)
seek_target()
src.anchored = 0
if (src.target)
src.task = "chasing"
return
for (var/mob/living/carbon/C in view(src.seekrange,src))
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if (C.stat || C.health < 0) continue
src.target = C
src.oldtarget_name = C.name
src.task = "chasing"
src.speak( pick("Hey..you! Help! Help me please!","I need..a doctor...","Someone...new? Help me...please.","Are you real?") )
break
proc/speak(var/message)
if (!message)
return
var/fontSize = 1
var/fontIncreasing = 1
var/fontSizeMax = 3
var/fontSizeMin = -3
var/messageLen = length(message)
var/processedMessage = ""
for (var/i = 1, i <= messageLen, i++)
processedMessage += "<font size=[fontSize]>[copytext(message, i, i+1)]</font>"
if (fontIncreasing)
fontSize = min(fontSize+1, fontSizeMax)
if (fontSize >= fontSizeMax)
fontIncreasing = 0
else
fontSize = max(fontSize-1, fontSizeMin)
if (fontSize <= fontSizeMin)
fontIncreasing = 1
src.visible_message("<b>[src.name]</b> says, \"[processedMessage]\"")
return