mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-08-26 14:46:52 +01:00
Merge pull request #6529 from Meghan-Rossi/animalcleanup
Remove unused simple_animal files
This commit is contained in:
+169
-169
@@ -1,170 +1,170 @@
|
||||
//Meant for simple animals to drop lootable human bodies.
|
||||
|
||||
//If someone can do this in a neater way, be my guest-Kor
|
||||
|
||||
//This has to be seperate from the Away Mission corpses, because New() doesn't work for those, and initialize() doesn't work for these.
|
||||
|
||||
//To do: Allow corpses to appear mangled, bloody, etc. Allow customizing the bodies appearance (they're all bald and white right now).
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse
|
||||
name = "Unknown"
|
||||
var/mobname = "Unknown" //Unused now but it'd fuck up maps to remove it now
|
||||
var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse.
|
||||
var/corpsesuit = null
|
||||
var/corpseshoes = null
|
||||
var/corpsegloves = null
|
||||
var/corpseradio = null
|
||||
var/corpseglasses = null
|
||||
var/corpsemask = null
|
||||
var/corpsehelmet = null
|
||||
var/corpsebelt = null
|
||||
var/corpsepocket1 = null
|
||||
var/corpsepocket2 = null
|
||||
var/corpseback = null
|
||||
var/corpseid = 0 //Just set to 1 if you want them to have an ID
|
||||
var/corpseidjob = null // Needs to be in quotes, such as "Clown" or "Chef." This just determines what the ID reads as, not their access
|
||||
var/corpseidaccess = null //This is for access. See access.dm for which jobs give what access. Again, put in quotes. Use "Captain" if you want it to be all access.
|
||||
var/corpseidicon = null //For setting it to be a gold, silver, CentCom etc ID
|
||||
|
||||
/obj/effect/landmark/mobcorpse/New()
|
||||
createCorpse()
|
||||
|
||||
/obj/effect/landmark/mobcorpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it.
|
||||
var/mob/living/carbon/human/M = new /mob/living/carbon/human (src.loc)
|
||||
M.real_name = src.name
|
||||
M.stat = 2 //Kills the new mob
|
||||
if(src.corpseuniform)
|
||||
M.equip_to_slot_or_del(new src.corpseuniform(M), slot_w_uniform)
|
||||
if(src.corpsesuit)
|
||||
M.equip_to_slot_or_del(new src.corpsesuit(M), slot_wear_suit)
|
||||
if(src.corpseshoes)
|
||||
M.equip_to_slot_or_del(new src.corpseshoes(M), slot_shoes)
|
||||
if(src.corpsegloves)
|
||||
M.equip_to_slot_or_del(new src.corpsegloves(M), slot_gloves)
|
||||
if(src.corpseradio)
|
||||
M.equip_to_slot_or_del(new src.corpseradio(M), slot_l_ear)
|
||||
if(src.corpseglasses)
|
||||
M.equip_to_slot_or_del(new src.corpseglasses(M), slot_glasses)
|
||||
if(src.corpsemask)
|
||||
M.equip_to_slot_or_del(new src.corpsemask(M), slot_wear_mask)
|
||||
if(src.corpsehelmet)
|
||||
M.equip_to_slot_or_del(new src.corpsehelmet(M), slot_head)
|
||||
if(src.corpsebelt)
|
||||
M.equip_to_slot_or_del(new src.corpsebelt(M), slot_belt)
|
||||
if(src.corpsepocket1)
|
||||
M.equip_to_slot_or_del(new src.corpsepocket1(M), slot_r_store)
|
||||
if(src.corpsepocket2)
|
||||
M.equip_to_slot_or_del(new src.corpsepocket2(M), slot_l_store)
|
||||
if(src.corpseback)
|
||||
M.equip_to_slot_or_del(new src.corpseback(M), slot_back)
|
||||
if(src.corpseid == 1)
|
||||
var/obj/item/weapon/card/id/W = new(M)
|
||||
W.name = "[M.real_name]'s ID Card"
|
||||
var/datum/job/jobdatum
|
||||
for(var/jobtype in typesof(/datum/job))
|
||||
var/datum/job/J = new jobtype
|
||||
if(J.title == corpseidaccess)
|
||||
jobdatum = J
|
||||
break
|
||||
if(src.corpseidicon)
|
||||
W.icon_state = corpseidicon
|
||||
if(src.corpseidaccess)
|
||||
if(jobdatum)
|
||||
W.access = jobdatum.get_access()
|
||||
else
|
||||
W.access = list()
|
||||
if(corpseidjob)
|
||||
W.assignment = corpseidjob
|
||||
W.registered_name = M.real_name
|
||||
M.equip_to_slot_or_del(W, slot_wear_id)
|
||||
delete_me = 1
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
//List of different corpse types
|
||||
|
||||
/obj/effect/landmark/mobcorpse/syndicatesoldier
|
||||
name = "Mercenary"
|
||||
corpseuniform = /obj/item/clothing/under/syndicate
|
||||
corpsesuit = /obj/item/clothing/suit/armor/vest
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/swat
|
||||
corpsegloves = /obj/item/clothing/gloves/swat
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas
|
||||
corpsehelmet = /obj/item/clothing/head/helmet/swat
|
||||
corpseback = /obj/item/weapon/storage/backpack
|
||||
corpseid = 1
|
||||
corpseidjob = "Operative"
|
||||
corpseidaccess = "Syndicate"
|
||||
|
||||
/obj/effect/landmark/mobcorpse/solarpeacekeeper
|
||||
name = "Mercenary"
|
||||
corpseuniform = /obj/item/clothing/under/syndicate
|
||||
corpsesuit = /obj/item/clothing/suit/armor/pcarrier/blue/sol
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/swat
|
||||
corpsegloves = /obj/item/clothing/gloves/swat
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas
|
||||
corpsehelmet = /obj/item/clothing/head/helmet/swat
|
||||
corpseback = /obj/item/weapon/storage/backpack
|
||||
corpseid = 1
|
||||
corpseidjob = "Peacekeeper"
|
||||
corpseidaccess = "Syndicate"
|
||||
|
||||
/obj/effect/landmark/mobcorpse/syndicatecommando
|
||||
name = "Syndicate Commando"
|
||||
corpseuniform = /obj/item/clothing/under/syndicate
|
||||
corpsesuit = /obj/item/clothing/suit/space/void/merc
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/swat
|
||||
corpsegloves = /obj/item/clothing/gloves/swat
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas/syndicate
|
||||
corpsehelmet = /obj/item/clothing/head/helmet/space/void/merc
|
||||
corpseback = /obj/item/weapon/tank/jetpack/oxygen
|
||||
corpsepocket1 = /obj/item/weapon/tank/emergency/oxygen
|
||||
corpseid = 1
|
||||
corpseidjob = "Operative"
|
||||
corpseidaccess = "Syndicate"
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/clown
|
||||
name = "Clown"
|
||||
corpseuniform = /obj/item/clothing/under/rank/clown
|
||||
corpseshoes = /obj/item/clothing/shoes/clown_shoes
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas/clown_hat
|
||||
corpsepocket1 = /obj/item/weapon/bikehorn
|
||||
corpseback = /obj/item/weapon/storage/backpack/clown
|
||||
corpseid = 1
|
||||
corpseidjob = "Clown"
|
||||
corpseidaccess = "Clown"
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/pirate
|
||||
name = "Pirate"
|
||||
corpseuniform = /obj/item/clothing/under/pirate
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/jackboots
|
||||
corpseglasses = /obj/item/clothing/glasses/eyepatch
|
||||
corpsehelmet = /obj/item/clothing/head/bandana
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/pirate/ranged
|
||||
name = "Pirate Gunner"
|
||||
corpsesuit = /obj/item/clothing/suit/pirate
|
||||
corpsehelmet = /obj/item/clothing/head/pirate
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/russian
|
||||
name = "Russian"
|
||||
corpseuniform = /obj/item/clothing/under/soviet
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/jackboots
|
||||
corpsehelmet = /obj/item/clothing/head/bearpelt
|
||||
|
||||
/obj/effect/landmark/mobcorpse/russian/ranged
|
||||
//Meant for simple animals to drop lootable human bodies.
|
||||
|
||||
//If someone can do this in a neater way, be my guest-Kor
|
||||
|
||||
//This has to be seperate from the Away Mission corpses, because New() doesn't work for those, and initialize() doesn't work for these.
|
||||
|
||||
//To do: Allow corpses to appear mangled, bloody, etc. Allow customizing the bodies appearance (they're all bald and white right now).
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse
|
||||
name = "Unknown"
|
||||
var/mobname = "Unknown" //Unused now but it'd fuck up maps to remove it now
|
||||
var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse.
|
||||
var/corpsesuit = null
|
||||
var/corpseshoes = null
|
||||
var/corpsegloves = null
|
||||
var/corpseradio = null
|
||||
var/corpseglasses = null
|
||||
var/corpsemask = null
|
||||
var/corpsehelmet = null
|
||||
var/corpsebelt = null
|
||||
var/corpsepocket1 = null
|
||||
var/corpsepocket2 = null
|
||||
var/corpseback = null
|
||||
var/corpseid = 0 //Just set to 1 if you want them to have an ID
|
||||
var/corpseidjob = null // Needs to be in quotes, such as "Clown" or "Chef." This just determines what the ID reads as, not their access
|
||||
var/corpseidaccess = null //This is for access. See access.dm for which jobs give what access. Again, put in quotes. Use "Captain" if you want it to be all access.
|
||||
var/corpseidicon = null //For setting it to be a gold, silver, CentCom etc ID
|
||||
|
||||
/obj/effect/landmark/mobcorpse/New()
|
||||
createCorpse()
|
||||
|
||||
/obj/effect/landmark/mobcorpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it.
|
||||
var/mob/living/carbon/human/M = new /mob/living/carbon/human (src.loc)
|
||||
M.real_name = src.name
|
||||
M.stat = 2 //Kills the new mob
|
||||
if(src.corpseuniform)
|
||||
M.equip_to_slot_or_del(new src.corpseuniform(M), slot_w_uniform)
|
||||
if(src.corpsesuit)
|
||||
M.equip_to_slot_or_del(new src.corpsesuit(M), slot_wear_suit)
|
||||
if(src.corpseshoes)
|
||||
M.equip_to_slot_or_del(new src.corpseshoes(M), slot_shoes)
|
||||
if(src.corpsegloves)
|
||||
M.equip_to_slot_or_del(new src.corpsegloves(M), slot_gloves)
|
||||
if(src.corpseradio)
|
||||
M.equip_to_slot_or_del(new src.corpseradio(M), slot_l_ear)
|
||||
if(src.corpseglasses)
|
||||
M.equip_to_slot_or_del(new src.corpseglasses(M), slot_glasses)
|
||||
if(src.corpsemask)
|
||||
M.equip_to_slot_or_del(new src.corpsemask(M), slot_wear_mask)
|
||||
if(src.corpsehelmet)
|
||||
M.equip_to_slot_or_del(new src.corpsehelmet(M), slot_head)
|
||||
if(src.corpsebelt)
|
||||
M.equip_to_slot_or_del(new src.corpsebelt(M), slot_belt)
|
||||
if(src.corpsepocket1)
|
||||
M.equip_to_slot_or_del(new src.corpsepocket1(M), slot_r_store)
|
||||
if(src.corpsepocket2)
|
||||
M.equip_to_slot_or_del(new src.corpsepocket2(M), slot_l_store)
|
||||
if(src.corpseback)
|
||||
M.equip_to_slot_or_del(new src.corpseback(M), slot_back)
|
||||
if(src.corpseid == 1)
|
||||
var/obj/item/weapon/card/id/W = new(M)
|
||||
W.name = "[M.real_name]'s ID Card"
|
||||
var/datum/job/jobdatum
|
||||
for(var/jobtype in typesof(/datum/job))
|
||||
var/datum/job/J = new jobtype
|
||||
if(J.title == corpseidaccess)
|
||||
jobdatum = J
|
||||
break
|
||||
if(src.corpseidicon)
|
||||
W.icon_state = corpseidicon
|
||||
if(src.corpseidaccess)
|
||||
if(jobdatum)
|
||||
W.access = jobdatum.get_access()
|
||||
else
|
||||
W.access = list()
|
||||
if(corpseidjob)
|
||||
W.assignment = corpseidjob
|
||||
W.registered_name = M.real_name
|
||||
M.equip_to_slot_or_del(W, slot_wear_id)
|
||||
delete_me = 1
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
//List of different corpse types
|
||||
|
||||
/obj/effect/landmark/mobcorpse/syndicatesoldier
|
||||
name = "Mercenary"
|
||||
corpseuniform = /obj/item/clothing/under/syndicate
|
||||
corpsesuit = /obj/item/clothing/suit/armor/vest
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/swat
|
||||
corpsegloves = /obj/item/clothing/gloves/swat
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas
|
||||
corpsehelmet = /obj/item/clothing/head/helmet/swat
|
||||
corpseback = /obj/item/weapon/storage/backpack
|
||||
corpseid = 1
|
||||
corpseidjob = "Operative"
|
||||
corpseidaccess = "Syndicate"
|
||||
|
||||
/obj/effect/landmark/mobcorpse/solarpeacekeeper
|
||||
name = "Mercenary"
|
||||
corpseuniform = /obj/item/clothing/under/syndicate
|
||||
corpsesuit = /obj/item/clothing/suit/armor/pcarrier/blue/sol
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/swat
|
||||
corpsegloves = /obj/item/clothing/gloves/swat
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas
|
||||
corpsehelmet = /obj/item/clothing/head/helmet/swat
|
||||
corpseback = /obj/item/weapon/storage/backpack
|
||||
corpseid = 1
|
||||
corpseidjob = "Peacekeeper"
|
||||
corpseidaccess = "Syndicate"
|
||||
|
||||
/obj/effect/landmark/mobcorpse/syndicatecommando
|
||||
name = "Syndicate Commando"
|
||||
corpseuniform = /obj/item/clothing/under/syndicate
|
||||
corpsesuit = /obj/item/clothing/suit/space/void/merc
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/swat
|
||||
corpsegloves = /obj/item/clothing/gloves/swat
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas/syndicate
|
||||
corpsehelmet = /obj/item/clothing/head/helmet/space/void/merc
|
||||
corpseback = /obj/item/weapon/tank/jetpack/oxygen
|
||||
corpsepocket1 = /obj/item/weapon/tank/emergency/oxygen
|
||||
corpseid = 1
|
||||
corpseidjob = "Operative"
|
||||
corpseidaccess = "Syndicate"
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/clown
|
||||
name = "Clown"
|
||||
corpseuniform = /obj/item/clothing/under/rank/clown
|
||||
corpseshoes = /obj/item/clothing/shoes/clown_shoes
|
||||
corpseradio = /obj/item/device/radio/headset
|
||||
corpsemask = /obj/item/clothing/mask/gas/clown_hat
|
||||
corpsepocket1 = /obj/item/weapon/bikehorn
|
||||
corpseback = /obj/item/weapon/storage/backpack/clown
|
||||
corpseid = 1
|
||||
corpseidjob = "Clown"
|
||||
corpseidaccess = "Clown"
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/pirate
|
||||
name = "Pirate"
|
||||
corpseuniform = /obj/item/clothing/under/pirate
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/jackboots
|
||||
corpseglasses = /obj/item/clothing/glasses/eyepatch
|
||||
corpsehelmet = /obj/item/clothing/head/bandana
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/pirate/ranged
|
||||
name = "Pirate Gunner"
|
||||
corpsesuit = /obj/item/clothing/suit/pirate
|
||||
corpsehelmet = /obj/item/clothing/head/pirate
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/mobcorpse/russian
|
||||
name = "Russian"
|
||||
corpseuniform = /obj/item/clothing/under/soviet
|
||||
corpseshoes = /obj/item/clothing/shoes/boots/jackboots
|
||||
corpsehelmet = /obj/item/clothing/head/bearpelt
|
||||
|
||||
/obj/effect/landmark/mobcorpse/russian/ranged
|
||||
corpsehelmet = /obj/item/clothing/head/ushanka
|
||||
@@ -1,142 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/alien
|
||||
name = "alien hunter"
|
||||
desc = "Hiss!"
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "alienh_running"
|
||||
icon_living = "alienh_running"
|
||||
icon_dead = "alien_l"
|
||||
icon_gib = "syndicate_gib"
|
||||
icon_rest = "alienh_sleep"
|
||||
|
||||
faction = "xeno"
|
||||
intelligence_level = SA_HUMANOID
|
||||
cooperative = 1
|
||||
run_at_them = 0
|
||||
|
||||
response_help = "pokes"
|
||||
response_disarm = "shoves"
|
||||
response_harm = "hits"
|
||||
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
speed = -1
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
attacktext = list("slashed")
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
a_intent = I_HURT
|
||||
|
||||
environment_smash = 2
|
||||
status_flags = CANPUSH
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
heat_damage_per_tick = 20
|
||||
unsuitable_atoms_damage = 15
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/xenomeat
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/drone
|
||||
name = "alien drone"
|
||||
icon_state = "aliend_running"
|
||||
icon_living = "aliend_running"
|
||||
icon_dead = "aliend_l"
|
||||
icon_rest = "aliend_sleep"
|
||||
health = 60
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/sentinel
|
||||
name = "alien sentinel"
|
||||
icon_state = "aliens_running"
|
||||
icon_living = "aliens_running"
|
||||
icon_dead = "aliens_l"
|
||||
icon_rest = "aliens_sleep"
|
||||
health = 120
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
ranged = 1
|
||||
projectiletype = /obj/item/projectile/energy/neurotoxin/toxic
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/sentinel/praetorian
|
||||
name = "alien praetorian"
|
||||
icon = 'icons/mob/64x64.dmi'
|
||||
icon_state = "prat_s"
|
||||
icon_living = "prat_s"
|
||||
icon_dead = "prat_dead"
|
||||
icon_rest = "prat_sleep"
|
||||
move_to_delay = 5
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
|
||||
pixel_x = -16
|
||||
old_x = -16
|
||||
meat_amount = 5
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/queen
|
||||
name = "alien queen"
|
||||
icon_state = "alienq_running"
|
||||
icon_living = "alienq_running"
|
||||
icon_dead = "alienq_l"
|
||||
icon_rest = "alienq_sleep"
|
||||
health = 250
|
||||
maxHealth = 250
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
ranged = 1
|
||||
move_to_delay = 3
|
||||
projectiletype = /obj/item/projectile/energy/neurotoxin/toxic
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
rapid = 1
|
||||
status_flags = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/queen/empress
|
||||
name = "alien empress"
|
||||
icon = 'icons/mob/64x64.dmi'
|
||||
icon_state = "queen_s"
|
||||
icon_living = "queen_s"
|
||||
icon_dead = "queen_dead"
|
||||
icon_rest = "queen_sleep"
|
||||
move_to_delay = 4
|
||||
maxHealth = 400
|
||||
health = 400
|
||||
meat_amount = 5
|
||||
speed = 1
|
||||
|
||||
pixel_x = -16
|
||||
old_x = -16
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/queen/empress/mother
|
||||
name = "alien mother"
|
||||
icon = 'icons/mob/96x96.dmi'
|
||||
icon_state = "empress_s"
|
||||
icon_living = "empress_s"
|
||||
icon_dead = "empress_dead"
|
||||
icon_rest = "empress_rest"
|
||||
maxHealth = 600
|
||||
health = 600
|
||||
meat_amount = 10
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 25
|
||||
speed = 2
|
||||
|
||||
pixel_x = -32
|
||||
old_x = -32
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/death()
|
||||
..()
|
||||
visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...")
|
||||
playsound(src, 'sound/voice/hiss6.ogg', 100, 1)
|
||||
@@ -1,78 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/creature
|
||||
name = "creature"
|
||||
desc = "A sanity-destroying otherthing."
|
||||
icon = 'icons/mob/critter.dmi'
|
||||
icon_state = "otherthing"
|
||||
icon_living = "otherthing"
|
||||
icon_dead = "otherthing-dead"
|
||||
|
||||
faction = "creature"
|
||||
intelligence_level = SA_ANIMAL
|
||||
maxHealth = 40
|
||||
health = 40
|
||||
speed = 8
|
||||
|
||||
harm_intent_damage = 8
|
||||
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 15
|
||||
attack_armor_pen = 5 //It's a horror from beyond, I ain't gotta explain 5 AP
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
attacktext = list("chomped")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
speak_emote = list("gibbers")
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/cult
|
||||
faction = "cult"
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
supernatural = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/cult/cultify()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/cult/Life()
|
||||
..()
|
||||
check_horde()
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/strong
|
||||
maxHealth = 160
|
||||
health = 160
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 13
|
||||
melee_damage_upper = 25
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/strong/cult
|
||||
faction = "cult"
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
supernatural = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/cult/cultify()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/cult/Life()
|
||||
..()
|
||||
check_horde()
|
||||
@@ -1,286 +0,0 @@
|
||||
|
||||
//malfunctioning combat drones
|
||||
/mob/living/simple_animal/hostile/malf_drone
|
||||
name = "combat drone"
|
||||
desc = "An automated combat drone armed with state of the art weaponry and shielding."
|
||||
icon_state = "drone3"
|
||||
icon_living = "drone3"
|
||||
icon_dead = "drone_dead"
|
||||
|
||||
faction = "malf_drone"
|
||||
intelligence_level = SA_ROBOTIC
|
||||
maxHealth = 300
|
||||
health = 300
|
||||
speed = 8
|
||||
stop_when_pulled = 0
|
||||
|
||||
turns_per_move = 3
|
||||
response_help = "pokes"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
|
||||
a_intent = I_HURT
|
||||
ranged = 1
|
||||
rapid = 1
|
||||
projectiletype = /obj/item/projectile/beam/drone
|
||||
projectilesound = 'sound/weapons/laser3.ogg'
|
||||
destroy_surroundings = 0
|
||||
hovering = TRUE
|
||||
|
||||
armor = list(melee = 25, bullet = 25, laser = 25, energy = 10, bomb = 25, bio = 100, rad = 100) // Some level of armor plating makes sense
|
||||
//Drones aren't affected by atmos.
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
speak_chance = 5
|
||||
speak = list("ALERT.","Hostile-ile-ile entities dee-twhoooo-wected.","Threat parameterszzzz- szzet.","Bring sub-sub-sub-systems uuuup to combat alert alpha-a-a.")
|
||||
emote_see = list("beeps menacingly","whirrs threateningly","scans its immediate vicinity")
|
||||
|
||||
|
||||
var/datum/effect/effect/system/ion_trail_follow/ion_trail
|
||||
var/turf/patrol_target
|
||||
var/explode_chance = 1
|
||||
var/disabled = 0
|
||||
var/exploding = 0
|
||||
var/has_loot = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/malf_drone/New()
|
||||
..()
|
||||
if(prob(5))
|
||||
projectiletype = /obj/item/projectile/beam/pulse/drone
|
||||
projectilesound = 'sound/weapons/pulse2.ogg'
|
||||
ion_trail = new
|
||||
ion_trail.set_up(src)
|
||||
ion_trail.start()
|
||||
|
||||
/mob/living/simple_animal/hostile/malf_drone/Process_Spacemove(var/check_drift = 0)
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/hostile/malf_drone/isSynthetic()
|
||||
return TRUE
|
||||
|
||||
//self repair systems have a chance to bring the drone back to life
|
||||
/mob/living/simple_animal/hostile/malf_drone/Life()
|
||||
|
||||
//emps and lots of damage can temporarily shut us down
|
||||
if(disabled > 0)
|
||||
stat = UNCONSCIOUS
|
||||
icon_state = "drone_dead"
|
||||
disabled--
|
||||
wander = 0
|
||||
speak_chance = 0
|
||||
if(disabled <= 0)
|
||||
stat = CONSCIOUS
|
||||
icon_state = "drone0"
|
||||
wander = 1
|
||||
speak_chance = 5
|
||||
|
||||
//repair a bit of damage
|
||||
if(prob(1))
|
||||
src.visible_message("<font color='red'>\icon[src] [src] shudders and shakes as some of it's damaged systems come back online.</font>")
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
health += rand(25,100)
|
||||
|
||||
//spark for no reason
|
||||
if(prob(5))
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
//sometimes our targetting sensors malfunction, and we attack anyone nearby
|
||||
if(prob(disabled ? 0 : 1))
|
||||
if(hostile)
|
||||
src.visible_message("<font color='blue'>\icon[src] [src] retracts several targetting vanes, and dulls it's running lights.</font>")
|
||||
hostile = 0
|
||||
else
|
||||
src.visible_message("<font color='red'>\icon[src] [src] suddenly lights up, and additional targetting vanes slide into place.</font>")
|
||||
hostile = 1
|
||||
|
||||
if(health / getMaxHealth() > 0.9)
|
||||
icon_state = "drone3"
|
||||
explode_chance = 0
|
||||
else if(health / getMaxHealth() > 0.7)
|
||||
icon_state = "drone2"
|
||||
explode_chance = 0
|
||||
else if(health / getMaxHealth() > 0.5)
|
||||
icon_state = "drone1"
|
||||
explode_chance = 0.5
|
||||
else if(health / getMaxHealth() > 0.3)
|
||||
icon_state = "drone0"
|
||||
explode_chance = 5
|
||||
else if(health > 0)
|
||||
//if health gets too low, shut down
|
||||
icon_state = "drone_dead"
|
||||
exploding = 0
|
||||
if(!disabled)
|
||||
if(prob(50))
|
||||
src.visible_message("<font color='blue'>\icon[src] [src] suddenly shuts down!</font>")
|
||||
else
|
||||
src.visible_message("<font color='blue'>\icon[src] [src] suddenly lies still and quiet.</font>")
|
||||
disabled = rand(150, 600)
|
||||
walk(src,0)
|
||||
|
||||
if(exploding && prob(20))
|
||||
if(prob(50))
|
||||
src.visible_message("<font color='red'>\icon[src] [src] begins to spark and shake violenty!</font>")
|
||||
else
|
||||
src.visible_message("<font color='red'>\icon[src] [src] sparks and shakes like it's about to explode!</font>")
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
if(!exploding && !disabled && prob(explode_chance))
|
||||
exploding = 1
|
||||
stat = UNCONSCIOUS
|
||||
wander = 1
|
||||
walk(src,0)
|
||||
spawn(rand(50,150))
|
||||
if(!disabled && exploding)
|
||||
explosion(get_turf(src), 0, 1, 4, 7)
|
||||
//proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1)
|
||||
..()
|
||||
|
||||
//ion rifle!
|
||||
/mob/living/simple_animal/hostile/malf_drone/emp_act(severity)
|
||||
health -= rand(3,15) * (severity + 1)
|
||||
disabled = rand(150, 600)
|
||||
hostile = 0
|
||||
walk(src,0)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/malf_drone/death()
|
||||
..(null,"suddenly breaks apart.")
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/malf_drone/Destroy()
|
||||
//More advanced than the default S_A loot system, for visual effect and random tech levels.
|
||||
if(has_loot)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
var/obj/O
|
||||
|
||||
//shards
|
||||
O = new /obj/item/weapon/material/shard(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(75))
|
||||
O = new /obj/item/weapon/material/shard(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(50))
|
||||
O = new /obj/item/weapon/material/shard(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(25))
|
||||
O = new /obj/item/weapon/material/shard(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
|
||||
//rods
|
||||
O = new /obj/item/stack/rods(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(75))
|
||||
O = new /obj/item/stack/rods(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(50))
|
||||
O = new /obj/item/stack/rods(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(25))
|
||||
O = new /obj/item/stack/rods(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
|
||||
//plasteel
|
||||
O = new /obj/item/stack/material/plasteel(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(75))
|
||||
O = new /obj/item/stack/material/plasteel(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(50))
|
||||
O = new /obj/item/stack/material/plasteel(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
if(prob(25))
|
||||
O = new /obj/item/stack/material/plasteel(src.loc)
|
||||
step_to(O, get_turf(pick(view(7, src))))
|
||||
|
||||
//also drop dummy circuit boards deconstructable for research (loot)
|
||||
var/obj/item/weapon/circuitboard/C
|
||||
|
||||
//spawn 1-4 boards of a random type
|
||||
var/spawnees = 0
|
||||
var/num_boards = rand(1,4)
|
||||
var/list/options = list(1,2,4,8,16,32,64,128,256,512)
|
||||
for(var/i=0, i<num_boards, i++)
|
||||
var/chosen = pick(options)
|
||||
options.Remove(options.Find(chosen))
|
||||
spawnees |= chosen
|
||||
|
||||
if(spawnees & 1)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone CPU motherboard"
|
||||
C.origin_tech = list(TECH_DATA = rand(3, 6))
|
||||
|
||||
if(spawnees & 2)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone neural interface"
|
||||
C.origin_tech = list(TECH_BIO = rand(3,6))
|
||||
|
||||
if(spawnees & 4)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone suspension processor"
|
||||
C.origin_tech = list(TECH_MAGNET = rand(3,6))
|
||||
|
||||
if(spawnees & 8)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone shielding controller"
|
||||
C.origin_tech = list(TECH_BLUESPACE = rand(3,6))
|
||||
|
||||
if(spawnees & 16)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone power capacitor"
|
||||
C.origin_tech = list(TECH_POWER = rand(3,6))
|
||||
|
||||
if(spawnees & 32)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone hull reinforcer"
|
||||
C.origin_tech = list(TECH_MATERIAL = rand(3,6))
|
||||
|
||||
if(spawnees & 64)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone auto-repair system"
|
||||
C.origin_tech = list(TECH_ENGINEERING = rand(3,6))
|
||||
|
||||
if(spawnees & 128)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone phoron overcharge counter"
|
||||
C.origin_tech = list(TECH_PHORON = rand(3,6))
|
||||
|
||||
if(spawnees & 256)
|
||||
C = new(src.loc)
|
||||
C.name = "Drone targetting circuitboard"
|
||||
C.origin_tech = list(TECH_COMBAT = rand(3,6))
|
||||
|
||||
if(spawnees & 512)
|
||||
C = new(src.loc)
|
||||
C.name = "Corrupted drone morality core"
|
||||
C.origin_tech = list(TECH_ILLEGAL = rand(3,6))
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/projectile/beam/drone
|
||||
damage = 15
|
||||
|
||||
/obj/item/projectile/beam/pulse/drone
|
||||
damage = 10
|
||||
|
||||
// A slightly easier drone, for POIs.
|
||||
// Difference is that it should not be faster than you.
|
||||
/mob/living/simple_animal/hostile/malf_drone/lesser
|
||||
desc = "An automated combat drone with an aged apperance."
|
||||
returns_home = TRUE
|
||||
move_to_delay = 6
|
||||
@@ -1,84 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/faithless
|
||||
name = "Faithless"
|
||||
desc = "The Wish Granter's faith in humanity, incarnate"
|
||||
icon_state = "faithless"
|
||||
icon_living = "faithless"
|
||||
icon_dead = "faithless_dead"
|
||||
|
||||
faction = "faithless"
|
||||
intelligence_level = SA_HUMANOID
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
speed = 8
|
||||
|
||||
turns_per_move = 5
|
||||
response_help = "passes through"
|
||||
response_disarm = "shoves"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 10
|
||||
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 18
|
||||
attack_armor_pen = 5 //It's a horror from beyond, I ain't gotta explain 5 AP
|
||||
|
||||
attacktext = list("gripped")
|
||||
attack_sound = 'sound/hallucinations/growl1.ogg'
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
speak_chance = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/Process_Spacemove(var/check_drift = 0)
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/set_target()
|
||||
. = ..()
|
||||
if(.)
|
||||
audible_emote("wails at [target_mob]")
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/PunchTarget()
|
||||
. = ..()
|
||||
var/mob/living/L = .
|
||||
if(istype(L))
|
||||
if(prob(12))
|
||||
L.Weaken(3)
|
||||
L.visible_message("<span class='danger'>\the [src] knocks down \the [L]!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/cult
|
||||
faction = "cult"
|
||||
supernatural = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/cult/cultify()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/cult/Life()
|
||||
..()
|
||||
check_horde()
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/strong
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 13
|
||||
melee_damage_upper = 28
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/strong/cult
|
||||
faction = "cult"
|
||||
supernatural = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/cult/cultify()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/cult/Life()
|
||||
..()
|
||||
check_horde()
|
||||
@@ -1,241 +0,0 @@
|
||||
// Hivebots are tuned towards how many default lasers are needed to kill them.
|
||||
// As such, if laser damage is ever changed, you should change this define.
|
||||
#define LASERS_TO_KILL * 40
|
||||
|
||||
// Default hivebot is melee, and a bit more meaty, so it can meatshield for their ranged friends.
|
||||
/mob/living/simple_animal/hostile/hivebot
|
||||
name = "hivebot"
|
||||
desc = "A robot. It appears to be somewhat resilient, but lacks a true weapon."
|
||||
icon = 'icons/mob/hivebot.dmi'
|
||||
icon_state = "basic"
|
||||
icon_living = "basic"
|
||||
icon_dead = "basic"
|
||||
|
||||
faction = "hivebot"
|
||||
intelligence_level = SA_ROBOTIC
|
||||
maxHealth = 3 LASERS_TO_KILL
|
||||
health = 3 LASERS_TO_KILL
|
||||
speed = 4
|
||||
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
|
||||
attacktext = list("clawed")
|
||||
projectilesound = 'sound/weapons/Gunshot.ogg'
|
||||
projectiletype = /obj/item/projectile/bullet/hivebot
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
cooperative = TRUE
|
||||
firing_lines = TRUE
|
||||
investigates = TRUE
|
||||
|
||||
speak_chance = 1
|
||||
speak = list(
|
||||
"Resuming task: Protect area.",
|
||||
"No threats found.",
|
||||
"Error: No targets found."
|
||||
)
|
||||
emote_hear = list("hums ominously", "whirrs softly", "grinds a gear")
|
||||
emote_see = list("looks around the area", "turns from side to side")
|
||||
say_understood = list("Affirmative.", "Positive.")
|
||||
say_cannot = list("Denied.", "Negative.")
|
||||
say_maybe_target = list("Possible threat detected. Investigating.", "Motion detected.", "Investigating.")
|
||||
say_got_target = list("Threat detected.", "New task: Remove threat.", "Threat removal engaged.", "Engaging target.")
|
||||
|
||||
/mob/living/simple_animal/hostile/hivebot/isSynthetic()
|
||||
return TRUE
|
||||
|
||||
// Subtypes.
|
||||
|
||||
// Melee like the base type, but more fragile.
|
||||
/mob/living/simple_animal/hostile/hivebot/swarm
|
||||
name = "swarm hivebot"
|
||||
desc = "A robot. It looks fragile and weak"
|
||||
maxHealth = 1 LASERS_TO_KILL
|
||||
health = 1 LASERS_TO_KILL
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 8
|
||||
|
||||
// This one has a semi-weak ranged attack.
|
||||
/mob/living/simple_animal/hostile/hivebot/range
|
||||
name = "ranged hivebot"
|
||||
desc = "A robot. It has a simple ballistic weapon."
|
||||
ranged = 1
|
||||
maxHealth = 2 LASERS_TO_KILL
|
||||
health = 2 LASERS_TO_KILL
|
||||
|
||||
// This one shoots a burst of three, and is considerably more dangerous.
|
||||
/mob/living/simple_animal/hostile/hivebot/range/rapid
|
||||
name = "rapid hivebot"
|
||||
desc = "A robot. It has a fast firing ballistic rifle."
|
||||
icon_living = "strong"
|
||||
rapid = 1
|
||||
maxHealth = 2 LASERS_TO_KILL
|
||||
health = 2 LASERS_TO_KILL
|
||||
|
||||
// Shoots EMPs, to screw over other robots.
|
||||
/mob/living/simple_animal/hostile/hivebot/range/ion
|
||||
name = "engineering hivebot"
|
||||
desc = "A robot. It has a tool which emits focused electromagnetic pulses, which are deadly to synthetic adverseries."
|
||||
projectiletype = /obj/item/projectile/ion
|
||||
projectilesound = 'sound/weapons/Laser.ogg'
|
||||
icon_living = "engi"
|
||||
ranged = TRUE
|
||||
maxHealth = 2 LASERS_TO_KILL
|
||||
health = 2 LASERS_TO_KILL
|
||||
|
||||
// Shoots deadly lasers.
|
||||
/mob/living/simple_animal/hostile/hivebot/range/laser
|
||||
name = "laser hivebot"
|
||||
desc = "A robot. It has an energy weapon."
|
||||
projectiletype = /obj/item/projectile/beam/blue
|
||||
projectilesound = 'sound/weapons/Laser.ogg'
|
||||
maxHealth = 2 LASERS_TO_KILL
|
||||
health = 2 LASERS_TO_KILL
|
||||
|
||||
// Beefy and ranged.
|
||||
/mob/living/simple_animal/hostile/hivebot/range/strong
|
||||
name = "strong hivebot"
|
||||
desc = "A robot. This one has reinforced plating, and looks tougher."
|
||||
icon_living = "strong"
|
||||
maxHealth = 4 LASERS_TO_KILL
|
||||
health = 4 LASERS_TO_KILL
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
|
||||
// Also beefy, but tries to stay at their 'home', ideal for base defense.
|
||||
/mob/living/simple_animal/hostile/hivebot/range/guard
|
||||
name = "guard hivebot"
|
||||
desc = "A robot. It seems to be guarding something."
|
||||
returns_home = TRUE
|
||||
maxHealth = 4 LASERS_TO_KILL
|
||||
health = 4 LASERS_TO_KILL
|
||||
|
||||
// This one is intended for players to use. Well rounded and can make other hivebots follow them with verbs.
|
||||
/mob/living/simple_animal/hostile/hivebot/range/player
|
||||
name = "commander hivebot"
|
||||
desc = "A robot. This one seems to direct the others, and it has a laser weapon."
|
||||
icon_living = "commander"
|
||||
maxHealth = 5 LASERS_TO_KILL
|
||||
health = 5 LASERS_TO_KILL
|
||||
projectiletype = /obj/item/projectile/beam/blue
|
||||
projectilesound = 'sound/weapons/Laser.ogg'
|
||||
melee_damage_lower = 15 // Needed to force open airlocks.
|
||||
melee_damage_upper = 15
|
||||
|
||||
// Procs.
|
||||
|
||||
/mob/living/simple_animal/hostile/hivebot/death()
|
||||
..()
|
||||
visible_message("<b>[src]</b> blows apart!")
|
||||
new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/hivebot/speech_bubble_appearance()
|
||||
return "synthetic_evil"
|
||||
|
||||
/mob/living/simple_animal/hostile/hivebot/verb/command_follow()
|
||||
set name = "Command - Follow"
|
||||
set category = "Hivebot"
|
||||
set desc = "This will ask other hivebots to follow you."
|
||||
|
||||
say("Delegating new task: Follow.")
|
||||
|
||||
for(var/mob/living/simple_animal/hostile/hivebot/buddy in hearers(src))
|
||||
if(buddy.faction != faction)
|
||||
continue
|
||||
if(buddy == src)
|
||||
continue
|
||||
buddy.set_follow(src)
|
||||
buddy.FollowTarget()
|
||||
spawn(rand(5, 10))
|
||||
buddy.say( pick(buddy.say_understood) )
|
||||
|
||||
/mob/living/simple_animal/hostile/hivebot/verb/command_stop()
|
||||
set name = "Command - Stop Following"
|
||||
set category = "Hivebot"
|
||||
set desc = "This will ask other hivebots to cease following you."
|
||||
|
||||
say("Delegating new task: Stop following.")
|
||||
|
||||
for(var/mob/living/simple_animal/hostile/hivebot/buddy in hearers(src))
|
||||
if(buddy.faction != faction)
|
||||
continue
|
||||
if(buddy == src)
|
||||
continue
|
||||
buddy.LoseFollow()
|
||||
spawn(rand(5, 10))
|
||||
buddy.say( pick(buddy.say_understood) )
|
||||
|
||||
/mob/living/simple_animal/hostile/hivebot/tele//this still needs work
|
||||
name = "Beacon"
|
||||
desc = "Some odd beacon thing"
|
||||
icon = 'icons/mob/hivebot.dmi'
|
||||
icon_state = "def_radar-off"
|
||||
icon_living = "def_radar-off"
|
||||
|
||||
health = 200
|
||||
maxHealth = 200
|
||||
status_flags = 0
|
||||
|
||||
anchored = 1
|
||||
wander = 0
|
||||
stop_automated_movement = 1
|
||||
|
||||
var/bot_type = "norm"
|
||||
var/bot_amt = 10
|
||||
var/spawn_delay = 600
|
||||
var/turn_on = 0
|
||||
var/auto_spawn = 1
|
||||
proc
|
||||
warpbots()
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(5, 0, src.loc)
|
||||
smoke.start()
|
||||
visible_message("<font color='red'><B>The [src] warps in!</font></B>")
|
||||
playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1)
|
||||
|
||||
warpbots()
|
||||
icon_state = "def_radar"
|
||||
visible_message("<font color='red'>The [src] turns on!</font>")
|
||||
while(bot_amt > 0)
|
||||
bot_amt--
|
||||
switch(bot_type)
|
||||
if("norm")
|
||||
new /mob/living/simple_animal/hostile/hivebot(get_turf(src))
|
||||
if("range")
|
||||
new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src))
|
||||
if("rapid")
|
||||
new /mob/living/simple_animal/hostile/hivebot/range/rapid(get_turf(src))
|
||||
spawn(100)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
|
||||
Life()
|
||||
..()
|
||||
if(stat == 0)
|
||||
if(prob(2))//Might be a bit low, will mess with it likely
|
||||
warpbots()
|
||||
|
||||
/obj/item/projectile/bullet/hivebot
|
||||
damage = 10
|
||||
damage_type = BRUTE
|
||||
|
||||
#undef LASERS_TO_KILL
|
||||
@@ -1,201 +0,0 @@
|
||||
//
|
||||
// Abstract Class
|
||||
//
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic
|
||||
name = "crate"
|
||||
desc = "A rectangular steel crate."
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "crate"
|
||||
icon_living = "crate"
|
||||
|
||||
faction = "mimic"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
maxHealth = 250
|
||||
health = 250
|
||||
speed = 4
|
||||
move_to_delay = 8
|
||||
|
||||
response_help = "touches"
|
||||
response_disarm = "pushes"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 12
|
||||
attacktext = list("attacked")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/set_target()
|
||||
. = ..()
|
||||
if(.)
|
||||
audible_emote("growls at [.]")
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/death()
|
||||
..()
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/will_show_tooltip()
|
||||
return FALSE
|
||||
|
||||
|
||||
//
|
||||
// Crate Mimic
|
||||
//
|
||||
|
||||
// Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies.
|
||||
/mob/living/simple_animal/hostile/mimic/crate
|
||||
|
||||
attacktext = list("bitten")
|
||||
|
||||
stop_automated_movement = 1
|
||||
wander = 0
|
||||
var/attempt_open = 0
|
||||
|
||||
// Pickup loot
|
||||
/mob/living/simple_animal/hostile/mimic/crate/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/item/I in loc)
|
||||
I.forceMove(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/DestroySurroundings()
|
||||
..()
|
||||
if(prob(90))
|
||||
icon_state = "[initial(icon_state)]open"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/ListTargets()
|
||||
if(attempt_open)
|
||||
return ..()
|
||||
else
|
||||
return ..(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/set_target()
|
||||
. = ..()
|
||||
if(.)
|
||||
trigger()
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/PunchTarget()
|
||||
. = ..()
|
||||
if(.)
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/proc/trigger()
|
||||
if(!attempt_open)
|
||||
visible_message("<b>[src]</b> starts to move!")
|
||||
attempt_open = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/adjustBruteLoss(var/damage)
|
||||
trigger()
|
||||
..(damage)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/LoseTarget()
|
||||
..()
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/LostTarget()
|
||||
..()
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/death()
|
||||
var/obj/structure/closet/crate/C = new(get_turf(src))
|
||||
// Put loot in crate
|
||||
for(var/obj/O in src)
|
||||
O.forceMove(C)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/crate/PunchTarget()
|
||||
. =..()
|
||||
var/mob/living/L = .
|
||||
if(istype(L))
|
||||
if(prob(15))
|
||||
L.Weaken(2)
|
||||
L.visible_message("<span class='danger'>\the [src] knocks down \the [L]!</span>")
|
||||
|
||||
//
|
||||
// Copy Mimic
|
||||
//
|
||||
|
||||
var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window, /obj/item/projectile/animate)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy
|
||||
|
||||
health = 100
|
||||
maxHealth = 100
|
||||
var/mob/living/creator = null // the creator
|
||||
var/destroy_objects = 0
|
||||
var/knockdown_people = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/New(loc, var/obj/copy, var/mob/living/creator)
|
||||
..(loc)
|
||||
CopyObject(copy, creator)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/death()
|
||||
|
||||
for(var/atom/movable/M in src)
|
||||
M.forceMove(get_turf(src))
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/ListTargets()
|
||||
// Return a list of targets that isn't the creator
|
||||
. = ..()
|
||||
return . - creator
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(var/obj/O, var/mob/living/creator)
|
||||
|
||||
if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, protected_objects))
|
||||
|
||||
O.forceMove(src)
|
||||
name = O.name
|
||||
desc = O.desc
|
||||
icon = O.icon
|
||||
icon_state = O.icon_state
|
||||
icon_living = icon_state
|
||||
|
||||
if(istype(O, /obj/structure))
|
||||
health = (anchored * 50) + 50
|
||||
destroy_objects = 1
|
||||
if(O.density && O.anchored)
|
||||
knockdown_people = 1
|
||||
melee_damage_lower *= 2
|
||||
melee_damage_upper *= 2
|
||||
else if(istype(O, /obj/item))
|
||||
var/obj/item/I = O
|
||||
health = 15 * I.w_class
|
||||
melee_damage_lower = 2 + I.force
|
||||
melee_damage_upper = 2 + I.force
|
||||
move_to_delay = 2 * I.w_class
|
||||
|
||||
maxHealth = health
|
||||
if(creator)
|
||||
src.creator = creator
|
||||
faction = "\ref[creator]" // very unique
|
||||
return 1
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/DestroySurroundings()
|
||||
if(destroy_objects)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/PunchTarget()
|
||||
. =..()
|
||||
if(knockdown_people)
|
||||
var/mob/living/L = .
|
||||
if(istype(L))
|
||||
if(prob(15))
|
||||
L.Weaken(1)
|
||||
L.visible_message("<span class='danger'>\the [src] knocks down \the [L]!</span>")
|
||||
@@ -1,61 +0,0 @@
|
||||
/mob/living/simple_animal/shade
|
||||
name = "Shade"
|
||||
real_name = "Shade"
|
||||
desc = "A bound spirit"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "shade"
|
||||
icon_living = "shade"
|
||||
icon_dead = "shade_dead"
|
||||
|
||||
faction = "cult"
|
||||
intelligence_level = SA_HUMANOID
|
||||
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
speed = -1
|
||||
|
||||
response_help = "puts their hand through"
|
||||
response_disarm = "flails at"
|
||||
response_harm = "punches"
|
||||
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 15
|
||||
attack_armor_pen = 100 //It's a ghost/horror from beyond, I ain't gotta explain 100 AP
|
||||
attacktext = list("drained the life from")
|
||||
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 4000
|
||||
min_oxy = 0
|
||||
max_co2 = 0
|
||||
max_tox = 0
|
||||
|
||||
stop_automated_movement = 1
|
||||
wander = 0
|
||||
status_flags = 0
|
||||
|
||||
speak_chance = 5
|
||||
universal_speak = 1
|
||||
speak_emote = list("hisses")
|
||||
emote_hear = list("wails","screeches")
|
||||
|
||||
loot_list = list(/obj/item/weapon/ectoplasm = 100)
|
||||
|
||||
/mob/living/simple_animal/shade/cultify()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(istype(O, /obj/item/device/soulstone))
|
||||
var/obj/item/device/soulstone/S = O;
|
||||
S.transfer_soul("SHADE", src, user)
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/shade/death()
|
||||
..()
|
||||
for(var/mob/M in viewers(src, null))
|
||||
if((M.client && !( M.blinded )))
|
||||
M.show_message("<font color='red'>[src] lets out a contented sigh as their form unwinds.</font>")
|
||||
|
||||
ghostize()
|
||||
qdel(src)
|
||||
return
|
||||
@@ -1,457 +0,0 @@
|
||||
// A mob which only moves when it isn't being watched by living beings.
|
||||
//Weeping angels/SCP-173 hype
|
||||
//Horrible shitcoding and stolen code adaptations below. You have been warned.
|
||||
|
||||
/mob/living/simple_animal/hostile/statue
|
||||
name = "statue" // matches the name of the statue with the flesh-to-stone spell
|
||||
desc = "An incredibly lifelike marble carving. Its eyes seems to follow you..." // same as an ordinary statue with the added "eye following you" description
|
||||
icon = 'icons/obj/statue.dmi'
|
||||
tt_desc = "angelum weepicus"
|
||||
icon_state = "human_male"
|
||||
icon_living = "human_male"
|
||||
icon_dead = "human_male"
|
||||
intelligence_level = SA_HUMANOID
|
||||
stop_automated_movement = 1
|
||||
var/annoyance = 30 //stop staring you creep
|
||||
var/respond = 1
|
||||
var/banishable = 0
|
||||
faction = "statue"
|
||||
mob_size = MOB_HUGE
|
||||
response_help = "touches"
|
||||
response_disarm = "pushes"
|
||||
environment_smash = 2
|
||||
can_be_antagged = 1
|
||||
speed = -1
|
||||
maxHealth = 3000
|
||||
health = 3000
|
||||
status_flags = CANPUSH
|
||||
// investigates = 1
|
||||
a_intent = I_HURT
|
||||
density = 1
|
||||
mob_bump_flag = HEAVY
|
||||
mob_push_flags = ~HEAVY
|
||||
mob_swap_flags = ~HEAVY
|
||||
harm_intent_damage = 60
|
||||
melee_damage_lower = 50
|
||||
melee_damage_upper = 70
|
||||
attacktext = "clawed"
|
||||
attack_sound = 'sound/hallucinations/growl1.ogg'
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 9000
|
||||
run_at_them = 0
|
||||
|
||||
move_to_delay = 0 // Very fast
|
||||
|
||||
animate_movement = NO_STEPS // Do not animate movement, you jump around as you're a scary statue.
|
||||
|
||||
see_in_dark = 13
|
||||
view_range = 35 //So it can run at the victim when out of the view
|
||||
|
||||
melee_miss_chance = 0
|
||||
|
||||
armor = list(
|
||||
"melee" = 30,
|
||||
"bullet" = 60,
|
||||
"laser" = 80,
|
||||
"energy" = 30,
|
||||
"bomb" = 30,
|
||||
"bio" = 100,
|
||||
"rad" = 100)
|
||||
|
||||
resistance = 20
|
||||
|
||||
see_invisible = SEE_INVISIBLE_NOLIGHTING
|
||||
sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS
|
||||
var/last_hit = 0
|
||||
var/cannot_be_seen = 1
|
||||
var/mob/living/creator = null
|
||||
var/drilled = FALSE
|
||||
|
||||
|
||||
// No movement while seen code.
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/New(loc)
|
||||
..()
|
||||
// Give spells
|
||||
add_spell(new/spell/aoe_turf/flicker_lights)
|
||||
add_spell(new/spell/aoe_turf/blindness)
|
||||
add_spell(new/spell/aoe_turf/shatter)
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/DestroySurroundings()
|
||||
if(can_be_seen(get_turf(loc)))
|
||||
if(client)
|
||||
to_chat(src, "<span class='warning'>You cannot move, there are eyes on you!</span>")
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/attackby(var/obj/item/O as obj, var/mob/user as mob) //banishing the statue is a risky job
|
||||
if(istype(O, /obj/item/weapon/nullrod))
|
||||
visible_message("<span class='warning'>[user] tries to banish [src] with [O]!</span>")
|
||||
if(do_after(user, 15, src))
|
||||
if(banishable)
|
||||
visible_message("<span class='warning'>[src] crumbles into dust!</span>")
|
||||
gib()
|
||||
else
|
||||
visible_message("<span class='warning'>[src] is too strong to be banished!</span>")
|
||||
Paralyse(rand(8,15))
|
||||
if(istype(O, /obj/item/weapon/pickaxe) || istype(O, /obj/item/weapon/pickaxe/plasmacutter) && !drilled)
|
||||
drilled = TRUE
|
||||
resistance = 0
|
||||
spawn(300)
|
||||
drilled = FALSE
|
||||
resistance = initial(resistance)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/death()
|
||||
var/chunks_to_spawn = rand(2,5)
|
||||
for(var/I = 1 to chunks_to_spawn)
|
||||
new /obj/item/stack/material/marble(get_turf(loc))
|
||||
new /obj/item/cursed_marble(get_turf(loc))
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/Move(turf/NewLoc)
|
||||
if(can_be_seen(NewLoc))
|
||||
if(client)
|
||||
to_chat(src, "<span class='warning'>You cannot move, there are eyes on you!</span>")
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/Life()
|
||||
..()
|
||||
handle_target()
|
||||
handleAnnoyance()
|
||||
if(target_mob) //if there's a victim, statue will use its powers
|
||||
if((annoyance + 4) < 800)
|
||||
annoyance += 4
|
||||
if(drilled && (annoyance + 4) < 800) //Being hit with a drill makes them weaker, and angrier.
|
||||
annoyance += 4
|
||||
else if ((annoyance - 2) > 0)
|
||||
annoyance -= 2
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/proc/handle_target()
|
||||
if(target_mob) // If we have a target and we're AI controlled
|
||||
var/mob/watching = can_be_seen()
|
||||
// If they're not our target
|
||||
if(watching && (watching != target_mob))
|
||||
// This one is closer.
|
||||
if(get_dist(watching, src) > get_dist(target_mob, src))
|
||||
LoseTarget()
|
||||
target_mob = watching
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/proc/handleAnnoyance()
|
||||
if(respond) //so it won't blind people 24/7
|
||||
respond = 0
|
||||
if (annoyance > 30)
|
||||
AI_blind()
|
||||
annoyance -= 30
|
||||
if (prob(30) && annoyance > 30)
|
||||
var/turf/T = get_turf(loc)
|
||||
if(T.get_lumcount() * 10 > 1.5)
|
||||
AI_flash()
|
||||
annoyance -= 30
|
||||
spawn(20)
|
||||
respond = 1
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/proc/AI_blind()
|
||||
for(var/mob/living/L in oviewers(12, src)) //the range is so big, because it tries to keep out of sight and can't reengage if you get too far
|
||||
if (prob(70))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if (H.species == "Diona" || H.species == "Promethean" || H == creator)// can't blink and organic
|
||||
return
|
||||
to_chat(L, pick("<span class='notice'>Your eyes feel very heavy.</span>", "<span class='notice'>You blink suddenly!</span>", "<span class='notice'>Your eyes close involuntarily!</span>"))
|
||||
L.Blind(2)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/proc/AI_flash()
|
||||
if (prob(60))
|
||||
visible_message("The statue slowly points at the light.")
|
||||
for(var/obj/machinery/light/L in oview(12, src))
|
||||
L.flicker()
|
||||
return
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/proc/AI_mirrorshmash()
|
||||
for(var/obj/structure/mirror/M in oview(4, src))
|
||||
if ((!M.shattered )||(!M.glass))
|
||||
visible_message("The statue slowly points at the mirror!")
|
||||
sleep(5)
|
||||
M.shatter()
|
||||
return
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/AttackTarget()
|
||||
if(can_be_seen(get_turf(loc)))
|
||||
if(client)
|
||||
to_chat(src, "<span class='warning'>You cannot attack, there are eyes on you!</span>")
|
||||
return
|
||||
else
|
||||
spawn(3) //a small delay
|
||||
..()
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/DoPunch(var/atom/A) //had to redo that, since it's supposed to target only head and upper body
|
||||
if(!Adjacent(A)) // They could've moved in the meantime.
|
||||
return FALSE
|
||||
|
||||
var/damage_to_do = rand(melee_damage_lower, melee_damage_upper)
|
||||
|
||||
for(var/datum/modifier/M in modifiers)
|
||||
if(!isnull(M.outgoing_melee_damage_percent))
|
||||
damage_to_do *= M.outgoing_melee_damage_percent
|
||||
|
||||
// SA attacks can be blocked with shields.
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
H.adjustBruteLossByPart(damage_to_do*0.9, pick(BP_HEAD, BP_TORSO))
|
||||
playsound(src, attack_sound, 75, 1)
|
||||
|
||||
else if(A.attack_generic(src, damage_to_do, pick(attacktext), attack_armor_type, attack_armor_pen, attack_sharp, attack_edge) && attack_sound)
|
||||
playsound(src, attack_sound, 75, 1)
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/face_atom()
|
||||
if(!can_be_seen(get_turf(loc)))
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/proc/can_be_seen(turf/destination)
|
||||
if(!cannot_be_seen)
|
||||
return null
|
||||
|
||||
var/turf/T = get_turf(loc)
|
||||
/* if(T && destination && T.lighting_overlay)
|
||||
if(T.get_lumcount() * 10 < 0.9 && destination.get_lumcount() * 10 < 0.9) // No one can see us in the darkness, right?
|
||||
return null
|
||||
if(T == destination)
|
||||
destination = null*/
|
||||
|
||||
// loop for viewers.
|
||||
var/list/check_list = list(src)
|
||||
if(destination)
|
||||
check_list += destination
|
||||
//&& (M.see_in_dark > 5)
|
||||
// This loop will, at most, loop twice.
|
||||
for(var/atom/check in check_list)
|
||||
for(var/mob/living/M in viewers(world.view + 1, check) - src)
|
||||
if(M != creator)
|
||||
if(!(M.sdisabilities & BLIND) || !(M.blinded)) //if not blinded
|
||||
if(M.has_vision() && !M.isSynthetic()) //is able to see the statue
|
||||
if(T && destination && T.lighting_overlay) // Check for darkness
|
||||
if(T.get_lumcount() * 10 < 0.9 && destination.get_lumcount() * 10 < 0.9) // No one can see us in the darkness, right? WRONG! Damn cats.
|
||||
if(M.see_in_dark > 5)
|
||||
return M
|
||||
return null
|
||||
return M
|
||||
for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
|
||||
if(M.occupant && M.occupant.client && M.occupant != creator)
|
||||
if(M.occupant.has_vision() && !M.occupant.isSynthetic())
|
||||
return M.occupant
|
||||
for(var/obj/structure/mirror/M in view(3, check)) //Weeping angels hate mirrors. Probably because they're ugly af
|
||||
if ((!M.shattered )||(!M.glass))
|
||||
annoyance += 3
|
||||
if (prob(5) && (ai_inactive == 0))
|
||||
AI_mirrorshmash()
|
||||
annoyance -= 50
|
||||
return src //if it sees the mirror, it sees itself, right?
|
||||
return null
|
||||
|
||||
// Cannot talk
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/say()
|
||||
return 0
|
||||
|
||||
// Turn to dust when gibbed
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/gib()
|
||||
dust()
|
||||
|
||||
|
||||
// Stop attacking clientless mobs
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/proc/CanAttack(atom/the_target) //ignore clientless mobs
|
||||
if(isliving(the_target))
|
||||
var/mob/living/L = the_target
|
||||
if(!L.client && !L.ckey)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
// Statue powers
|
||||
|
||||
// Flicker lights
|
||||
/spell/aoe_turf/flicker_lights
|
||||
name = "Flicker Lights"
|
||||
desc = "You will trigger a large amount of lights around you to flicker."
|
||||
spell_flags = 0
|
||||
charge_max = 400
|
||||
range = 10
|
||||
|
||||
/spell/aoe_turf/flicker_lights/cast(list/targets, mob/user = usr)
|
||||
for(var/turf/T in targets)
|
||||
for(var/obj/machinery/light/L in T)
|
||||
L.flicker()
|
||||
return
|
||||
|
||||
//Blind AOE
|
||||
/spell/aoe_turf/blindness
|
||||
name = "Blindness"
|
||||
desc = "Your prey will be momentarily blind for you to advance on them."
|
||||
|
||||
message = "<span class='notice'>You glare your eyes.</span>"
|
||||
charge_max = 250
|
||||
spell_flags = 0
|
||||
range = 10
|
||||
|
||||
/spell/aoe_turf/blindness/cast(list/targets, mob/living/simple_animal/hostile/statue/user = usr)
|
||||
for(var/mob/living/L in targets)
|
||||
if(L == user || L == user.creator)
|
||||
continue
|
||||
var/turf/T = get_turf(L.loc)
|
||||
if(T && T in targets)
|
||||
L.Blind(4)
|
||||
return
|
||||
|
||||
|
||||
/spell/aoe_turf/shatter
|
||||
name = "Shatter mirrors!"
|
||||
desc = "That handsome devil has to wait. You have people to make into corpses."
|
||||
|
||||
message = "<span class='notice'>You glare your eyes.</span>"
|
||||
charge_max = 300
|
||||
spell_flags = 0
|
||||
range = 8
|
||||
|
||||
|
||||
|
||||
|
||||
/spell/aoe_turf/shatter/cast(list/targets, mob/user = usr)
|
||||
spawn(50)
|
||||
for(var/obj/structure/mirror/M in view(5, src))
|
||||
if ((!M.shattered )||(!M.glass))
|
||||
M.shatter()
|
||||
return
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/verb/toggle_darkness()
|
||||
set name = "Toggle Darkness"
|
||||
set desc = "You ARE the darkness."
|
||||
set category = "Abilities"
|
||||
seedarkness = !seedarkness
|
||||
plane_holder.set_vis(VIS_FULLBRIGHT, !seedarkness)
|
||||
to_chat(src,"You [seedarkness ? "now" : "no longer"] see darkness.")
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/restrained()
|
||||
. = ..()
|
||||
if(can_be_seen(loc))
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/ListTargets(dist = view_range)
|
||||
var/list/L = mobs_in_xray_view(dist, src)
|
||||
|
||||
for(var/obj/mecha/M in mechas_list)
|
||||
if ((M.z == src.z) && (get_dist(src, M) <= dist) && (isInSight(src,M)))
|
||||
L += M
|
||||
if(creator)
|
||||
L -= creator
|
||||
|
||||
return L
|
||||
|
||||
|
||||
|
||||
/obj/item/cursed_marble //slime cube copypaste
|
||||
name = "marble slab"
|
||||
desc = "A peculiar slab of marble, radiating with dark energy."
|
||||
icon = 'icons/obj/stacks.dmi'
|
||||
icon_state = "sheet-marble"
|
||||
description_info = "Summons the Statue - a mysterious powerful creature, that can move only when unsurveyed by living eyes."
|
||||
var/searching = 0
|
||||
|
||||
/obj/item/cursed_marble/attack_self(mob/user as mob)
|
||||
if(!searching)
|
||||
to_chat(user, "<span class='warning'>You rub the slab in hopes a wandering spirit wishes to inhabit it. [src] starts to sparkle!</span>")
|
||||
icon_state = "sheet-snowbrick"
|
||||
searching = 1
|
||||
request_player(user)
|
||||
spawn(60 SECONDS)
|
||||
reset_search()
|
||||
|
||||
|
||||
/obj/item/cursed_marble/proc/request_player(var/mob/user)
|
||||
for(var/mob/observer/dead/O in player_list)
|
||||
if(!O.MayRespawn())
|
||||
continue
|
||||
if(O.client)
|
||||
if(O.client.prefs.be_special & BE_ALIEN)
|
||||
question(O.client, user)
|
||||
|
||||
/obj/item/cursed_marble/proc/question(var/client/C, var/mob/user)
|
||||
spawn(0)
|
||||
if(!C)
|
||||
return
|
||||
var/response = alert(C, "Someone is requesting a soul for the statue. Would you like to play as one?", "Statue request", "Yes", "No", "Never for this round")
|
||||
if(response == "Yes")
|
||||
response = alert(C, "Are you sure you want to play as the statue?", "Statue request", "Yes", "No")
|
||||
if(!C || 2 == searching)
|
||||
return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
|
||||
if(response == "Yes")
|
||||
transfer_personality(C.mob, user)
|
||||
else if(response == "Never for this round")
|
||||
C.prefs.be_special ^= BE_ALIEN
|
||||
|
||||
/obj/item/cursed_marble/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
|
||||
icon_state = "sheet-marble"
|
||||
if(searching == 1)
|
||||
searching = 0
|
||||
var/turf/T = get_turf_or_move(src.loc)
|
||||
for (var/mob/M in viewers(T))
|
||||
M.show_message("<span class='warning'>[src] fades. Maybe it will spark another time.</span>")
|
||||
|
||||
/obj/item/cursed_marble/proc/transfer_personality(var/mob/candidate, var/mob/user)
|
||||
announce_ghost_joinleave(candidate, 0, "They are a statue now.")
|
||||
src.searching = 2
|
||||
var/mob/living/simple_animal/hostile/statue/S = new(get_turf(src))
|
||||
S.client = candidate.client
|
||||
if(user)
|
||||
S.creator = user
|
||||
to_chat(S, "<b>You are \a [S], brought into existence on [station_name()] by [user]! Obey all their orders.</b>")
|
||||
S.mind.assigned_role = "The Statue"
|
||||
visible_message("<span class='warning'>The slab suddenly takes the shape of a humanoid!</span>")
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/cursed_marble/verb/crush() //if there's no ghosts to respond to your request/you want to use the statue for malicious stuff
|
||||
set name = "Crush the marble slab"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
summonmob(usr)
|
||||
|
||||
/obj/item/cursed_marble/proc/summonmob(mob/user as mob)
|
||||
if(searching == 0)
|
||||
var/choice = alert(user, "Are you sure you want to crush the marble? (this will spawn a clientless version of the statue, hostile to everyone, but you)", "Crush it?", "Yes", "No")
|
||||
if(choice)
|
||||
if(choice == "Yes")
|
||||
var/mob/living/simple_animal/hostile/statue/S = new /mob/living/simple_animal/hostile/statue(get_turf(user))
|
||||
visible_message("<span class='warning'>The slab suddenly takes the shape of a humanoid!</span>")
|
||||
S.creator = user
|
||||
qdel(src)
|
||||
@@ -1,85 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/scarybat
|
||||
name = "space bats"
|
||||
desc = "A swarm of cute little blood sucking bats that looks pretty upset."
|
||||
tt_desc = "N Bestia gregaria" //Nispean swarm bats, because of course Nisp has swarm bats
|
||||
icon = 'icons/mob/bats.dmi'
|
||||
icon_state = "bat"
|
||||
icon_living = "bat"
|
||||
icon_dead = "bat_dead"
|
||||
icon_gib = "bat_dead"
|
||||
|
||||
faction = "scarybat"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
turns_per_move = 3
|
||||
speed = 4
|
||||
|
||||
response_help = "pets the"
|
||||
response_disarm = "gently pushes aside the"
|
||||
response_harm = "hits the"
|
||||
|
||||
harm_intent_damage = 10
|
||||
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
attack_sharp = 1
|
||||
|
||||
environment_smash = 1
|
||||
|
||||
attacktext = list("bites")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
has_langs = list("Mouse")
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
var/mob/living/owner
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/New(loc, mob/living/L as mob)
|
||||
..()
|
||||
if(istype(L))
|
||||
owner = L
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/Process_Spacemove(var/check_drift = 0)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/set_target()
|
||||
. = ..()
|
||||
if(.)
|
||||
emote("flutters towards [.]")
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/ListTargets()
|
||||
. = ..()
|
||||
if(owner)
|
||||
return . - owner
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/PunchTarget()
|
||||
. =..()
|
||||
var/mob/living/L = .
|
||||
if(istype(L))
|
||||
if(prob(15))
|
||||
L.Stun(1)
|
||||
L.visible_message("<span class='danger'>\the [src] scares \the [L]!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/cult
|
||||
faction = "cult"
|
||||
supernatural = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/cult/cultify()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/scarybat/cult/Life()
|
||||
..()
|
||||
check_horde()
|
||||
@@ -1,141 +0,0 @@
|
||||
//Space bears!
|
||||
/mob/living/simple_animal/hostile/bear
|
||||
name = "space bear"
|
||||
desc = "A product of Space Russia?"
|
||||
tt_desc = "U Ursinae aetherius" //...bearspace? Maybe.
|
||||
icon_state = "bear"
|
||||
icon_living = "bear"
|
||||
icon_dead = "bear_dead"
|
||||
icon_gib = "bear_gib"
|
||||
|
||||
faction = "russian"
|
||||
intelligence_level = SA_ANIMAL
|
||||
cooperative = 1
|
||||
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
turns_per_move = 5
|
||||
see_in_dark = 6
|
||||
stop_when_pulled = 0
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "pokes"
|
||||
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 30
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
//Space bears aren't affected by atmos.
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
speak_chance = 1
|
||||
speak = list("RAWR!","Rawr!","GRR!","Growl!")
|
||||
speak_emote = list("growls", "roars")
|
||||
emote_hear = list("rawrs","grumbles","grawls")
|
||||
emote_see = list("stares ferociously", "stomps")
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/bearmeat
|
||||
|
||||
// var/stance_step = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/bear/handle_stance(var/new_stance)
|
||||
// Below was a bunch of code that made this specific mob be 'alert' and will hurt you when it gets closer.
|
||||
// It's commented out because it made infinite loops and the AI is going to be moved/rewritten sometime soon (famous last words)
|
||||
// and it would be better if this 'alert before attacking' behaviour was on the parent instead of a specific type of mob anyways.
|
||||
|
||||
// Instead we're just gonna get angry if we're dying.
|
||||
..(new_stance)
|
||||
if(stance == STANCE_ATTACK || stance == STANCE_ATTACKING)
|
||||
if((health / maxHealth) <= 0.5) // At half health, and fighting someone currently.
|
||||
add_modifier(/datum/modifier/berserk, 30 SECONDS)
|
||||
|
||||
/*
|
||||
switch(stance)
|
||||
if(STANCE_TIRED)
|
||||
stop_automated_movement = 1
|
||||
stance_step++
|
||||
if(stance_step >= 10) //rests for 10 ticks
|
||||
if(target_mob && target_mob in ListTargets(10))
|
||||
handle_stance(STANCE_ATTACK) //If the mob he was chasing is still nearby, resume the attack, otherwise go idle.
|
||||
else
|
||||
handle_stance(STANCE_IDLE)
|
||||
|
||||
if(STANCE_ALERT)
|
||||
stop_automated_movement = 1
|
||||
var/found_mob = 0
|
||||
if(target_mob && target_mob in ListTargets(10))
|
||||
if(!(SA_attackable(target_mob)))
|
||||
stance_step = max(0, stance_step) //If we have not seen a mob in a while, the stance_step will be negative, we need to reset it to 0 as soon as we see a mob again.
|
||||
stance_step++
|
||||
found_mob = 1
|
||||
src.set_dir(get_dir(src,target_mob)) //Keep staring at the mob
|
||||
|
||||
if(stance_step in list(1,4,7)) //every 3 ticks
|
||||
var/action = pick( list( "growls at [target_mob]", "stares angrily at [target_mob]", "prepares to attack [target_mob]", "closely watches [target_mob]" ) )
|
||||
if(action)
|
||||
custom_emote(1,action)
|
||||
if(!found_mob)
|
||||
stance_step--
|
||||
|
||||
if(stance_step <= -20) //If we have not found a mob for 20-ish ticks, revert to idle mode
|
||||
handle_stance(STANCE_IDLE)
|
||||
if(stance_step >= 7) //If we have been staring at a mob for 7 ticks,
|
||||
handle_stance(STANCE_ATTACK)
|
||||
|
||||
if(STANCE_ATTACKING)
|
||||
if(stance_step >= 20) //attacks for 20 ticks, then it gets tired and needs to rest
|
||||
custom_emote(1, "is worn out and needs to rest." )
|
||||
handle_stance(STANCE_TIRED)
|
||||
stance_step = 0
|
||||
walk(src, 0) //This stops the bear's walking
|
||||
return
|
||||
else
|
||||
..()
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/bear/update_icons()
|
||||
..()
|
||||
if(!stat)
|
||||
if(loc && istype(loc,/turf/space))
|
||||
icon_state = "bear"
|
||||
else
|
||||
icon_state = "bearfloor"
|
||||
|
||||
/mob/living/simple_animal/hostile/bear/Process_Spacemove(var/check_drift = 0)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/bear/FindTarget()
|
||||
. = ..()
|
||||
if(.)
|
||||
custom_emote(1,"stares alertly at [.]")
|
||||
// handle_stance(STANCE_ALERT)
|
||||
|
||||
/mob/living/simple_animal/hostile/bear/PunchTarget()
|
||||
if(!Adjacent(target_mob))
|
||||
return
|
||||
custom_emote(1, pick( list("slashes at [target_mob]", "bites [target_mob]") ) )
|
||||
|
||||
var/damage = rand(melee_damage_lower, melee_damage_upper)
|
||||
|
||||
if(ishuman(target_mob))
|
||||
var/mob/living/carbon/human/H = target_mob
|
||||
var/dam_zone = pick(BP_TORSO, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG)
|
||||
var/obj/item/organ/external/affecting = H.get_organ(ran_zone(dam_zone))
|
||||
H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee"), H.get_armor_soak(affecting, "melee"), sharp=1, edge=1)
|
||||
return H
|
||||
else if(isliving(target_mob))
|
||||
var/mob/living/L = target_mob
|
||||
L.adjustBruteLoss(damage)
|
||||
return L
|
||||
else
|
||||
..()
|
||||
@@ -1,93 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/carp
|
||||
name = "space carp"
|
||||
desc = "A ferocious, fang-bearing creature that resembles a fish."
|
||||
tt_desc = "U Cyprinus aetherius" //carpspace? maybe
|
||||
icon_state = "carp"
|
||||
icon_living = "carp"
|
||||
icon_dead = "carp_dead"
|
||||
icon_gib = "carp_gib"
|
||||
|
||||
faction = "carp"
|
||||
intelligence_level = SA_ANIMAL
|
||||
hovering = TRUE
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
speed = 4
|
||||
turns_per_move = 5
|
||||
|
||||
response_help = "pets the"
|
||||
response_disarm = "gently pushes aside the"
|
||||
response_harm = "hits the"
|
||||
|
||||
harm_intent_damage = 8
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attacktext = list("bitten")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
//Space carp aren't affected by atmos.
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/large
|
||||
name = "elder carp"
|
||||
desc = "An older, more matured carp. Few survive to this age due to their aggressiveness."
|
||||
icon = 'icons/mob/64x32.dmi'
|
||||
icon_state = "shark"
|
||||
icon_living = "shark"
|
||||
icon_dead = "shark_dead"
|
||||
turns_per_move = 2
|
||||
move_to_delay = 2
|
||||
mob_size = MOB_LARGE
|
||||
|
||||
pixel_x = -16
|
||||
old_x = -16
|
||||
|
||||
health = 50
|
||||
maxHealth = 50
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/large/huge
|
||||
name = "great white carp"
|
||||
desc = "A very rare breed of carp- and a very aggressive one."
|
||||
icon = 'icons/mob/64x64.dmi'
|
||||
icon_dead = "megacarp_dead"
|
||||
icon_living = "megacarp"
|
||||
icon_state = "megacarp"
|
||||
maxHealth = 230
|
||||
health = 230
|
||||
attack_same = 1
|
||||
speed = 1
|
||||
|
||||
meat_amount = 10
|
||||
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 25
|
||||
old_y = -16
|
||||
pixel_y = -16
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/Process_Spacemove(var/check_drift = 0)
|
||||
return 1 //No drifting in space for space carp! //original comments do not steal
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/set_target()
|
||||
. = ..()
|
||||
if(.)
|
||||
custom_emote(1,"nashes at [.]")
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/PunchTarget()
|
||||
. =..()
|
||||
var/mob/living/L = .
|
||||
if(istype(L))
|
||||
if(prob(15))
|
||||
L.Weaken(3)
|
||||
L.visible_message("<span class='danger'>\the [src] knocks down \the [L]!</span>")
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
//Cat
|
||||
/mob/living/simple_animal/cat
|
||||
name = "cat"
|
||||
desc = "A domesticated, feline pet. Has a tendency to adopt crewmembers."
|
||||
tt_desc = "E Felis silvestris catus"
|
||||
intelligence_level = SA_ANIMAL
|
||||
icon_state = "cat2"
|
||||
item_state = "cat2"
|
||||
icon_living = "[initial(icon_state)]"
|
||||
icon_dead = "[initial(icon_state)]_dead"
|
||||
icon_rest = "[initial(icon_state)]_rest"
|
||||
|
||||
investigates = 1
|
||||
specific_targets = 1 //Only targets with Found()
|
||||
run_at_them = 0 //DOMESTICATED
|
||||
view_range = 5
|
||||
|
||||
turns_per_move = 5
|
||||
see_in_dark = 6
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
|
||||
min_oxy = 16 //Require atleast 16kPA oxygen
|
||||
minbodytemp = 223 //Below -50 Degrees Celcius
|
||||
maxbodytemp = 323 //Above 50 Degrees Celcius
|
||||
|
||||
holder_type = /obj/item/weapon/holder/cat
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
has_langs = list("Cat")
|
||||
speak_chance = 1
|
||||
speak = list("Meow!","Esp!","Purr!","HSSSSS")
|
||||
speak_emote = list("purrs", "meows")
|
||||
emote_hear = list("meows","mews")
|
||||
emote_see = list("shakes their head", "shivers")
|
||||
say_maybe_target = list("Meow?","Mew?","Mao?")
|
||||
say_got_target = list("MEOW!","HSSSS!","REEER!")
|
||||
|
||||
meat_amount = 1
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
var/turns_since_scan = 0
|
||||
var/mob/flee_target
|
||||
|
||||
/mob/living/simple_animal/cat/Life()
|
||||
. = ..()
|
||||
if(!.) return
|
||||
|
||||
if(prob(2)) //spooky
|
||||
var/mob/observer/dead/spook = locate() in range(src,5)
|
||||
if(spook)
|
||||
var/turf/T = spook.loc
|
||||
var/list/visible = list()
|
||||
for(var/obj/O in T.contents)
|
||||
if(!O.invisibility && O.name)
|
||||
visible += O
|
||||
if(visible.len)
|
||||
var/atom/A = pick(visible)
|
||||
visible_emote("suddenly stops and stares at something unseen[istype(A) ? " near [A]":""].")
|
||||
|
||||
handle_flee_target()
|
||||
|
||||
/mob/living/simple_animal/cat/PunchTarget()
|
||||
if(ismouse(target_mob))
|
||||
var/mob/living/simple_mob/animal/passive/mouse/mouse = target_mob
|
||||
mouse.splat()
|
||||
visible_emote(pick("bites \the [mouse]!","toys with \the [mouse].","chomps on \the [mouse]!"))
|
||||
return mouse
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/cat/Found(var/atom/found_atom)
|
||||
if(ismouse(found_atom) && SA_attackable(found_atom))
|
||||
return found_atom
|
||||
|
||||
/mob/living/simple_animal/cat/proc/handle_flee_target()
|
||||
//see if we should stop fleeing
|
||||
if (flee_target && !(flee_target in ListTargets(view_range)))
|
||||
flee_target = null
|
||||
GiveUpMoving()
|
||||
|
||||
if (flee_target && !stat && !buckled)
|
||||
if (resting)
|
||||
lay_down()
|
||||
if(prob(25)) say("HSSSSS")
|
||||
stop_automated_movement = 1
|
||||
walk_away(src, flee_target, 7, 2)
|
||||
|
||||
/mob/living/simple_animal/cat/react_to_attack(var/atom/A)
|
||||
if(A == src) return
|
||||
flee_target = A
|
||||
turns_since_scan = 5
|
||||
|
||||
/mob/living/simple_animal/cat/ex_act()
|
||||
. = ..()
|
||||
react_to_attack(src.loc)
|
||||
|
||||
//Basic friend AI
|
||||
/mob/living/simple_animal/cat/fluff
|
||||
var/mob/living/carbon/human/friend
|
||||
var/befriend_job = null
|
||||
var/friend_name = null
|
||||
|
||||
/mob/living/simple_animal/cat/fluff/Life()
|
||||
. = ..()
|
||||
if(!. || ai_inactive || !friend) return
|
||||
|
||||
var/friend_dist = get_dist(src,friend)
|
||||
|
||||
if (friend_dist <= 4)
|
||||
if(stance == STANCE_IDLE)
|
||||
if(set_follow(friend))
|
||||
handle_stance(STANCE_FOLLOW)
|
||||
|
||||
if (friend_dist <= 1)
|
||||
if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit)
|
||||
if (prob((friend.stat < DEAD)? 50 : 15))
|
||||
var/verb = pick("meows", "mews", "mrowls")
|
||||
audible_emote(pick("[verb] in distress.", "[verb] anxiously."))
|
||||
else
|
||||
if (prob(5))
|
||||
visible_emote(pick("nuzzles [friend].",
|
||||
"brushes against [friend].",
|
||||
"rubs against [friend].",
|
||||
"purrs."))
|
||||
else if (friend.health <= 50)
|
||||
if (prob(10))
|
||||
var/verb = pick("meows", "mews", "mrowls")
|
||||
audible_emote("[verb] anxiously.")
|
||||
|
||||
/mob/living/simple_animal/cat/fluff/verb/become_friends()
|
||||
set name = "Become Friends"
|
||||
set category = "IC"
|
||||
set src in view(1)
|
||||
|
||||
if(!friend)
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H) && (!befriend_job || H.job == befriend_job) && (!friend_name || H.real_name == friend_name))
|
||||
friend = usr
|
||||
. = 1
|
||||
else if(usr == friend)
|
||||
. = 1 //already friends, but show success anyways
|
||||
|
||||
if(.)
|
||||
set_dir(get_dir(src, friend))
|
||||
visible_emote(pick("nuzzles [friend].",
|
||||
"brushes against [friend].",
|
||||
"rubs against [friend].",
|
||||
"purrs."))
|
||||
else
|
||||
usr << "<span class='notice'>[src] ignores you.</span>"
|
||||
return
|
||||
|
||||
//RUNTIME IS ALIVE! SQUEEEEEEEE~
|
||||
/mob/living/simple_animal/cat/fluff/Runtime
|
||||
name = "Runtime"
|
||||
desc = "Her fur has the look and feel of velvet, and her tail quivers occasionally."
|
||||
tt_desc = "E Felis silvestris medicalis" //a hypoallergenic breed produced by NT for... medical purposes? Sure.
|
||||
gender = FEMALE
|
||||
icon_state = "cat"
|
||||
item_state = "cat"
|
||||
befriend_job = "Chief Medical Officer"
|
||||
|
||||
/mob/living/simple_animal/cat/kitten
|
||||
name = "kitten"
|
||||
desc = "D'aaawwww"
|
||||
icon_state = "kitten"
|
||||
item_state = "kitten"
|
||||
icon_living = "kitten"
|
||||
icon_dead = "kitten_dead"
|
||||
gender = NEUTER
|
||||
|
||||
// Leaving this here for now.
|
||||
/obj/item/weapon/holder/cat/fluff/bones
|
||||
name = "Bones"
|
||||
desc = "It's Bones! Meow."
|
||||
gender = MALE
|
||||
icon_state = "cat3"
|
||||
|
||||
/mob/living/simple_animal/cat/fluff/bones
|
||||
name = "Bones"
|
||||
desc = "That's Bones the cat. He's a laid back, black cat. Meow."
|
||||
gender = MALE
|
||||
icon_state = "cat3"
|
||||
item_state = "cat3"
|
||||
holder_type = /obj/item/weapon/holder/cat/fluff/bones
|
||||
friend_name = "Erstatz Vryroxes"
|
||||
|
||||
/mob/living/simple_animal/cat/kitten/New()
|
||||
gender = pick(MALE, FEMALE)
|
||||
..()
|
||||
@@ -1,231 +0,0 @@
|
||||
//Corgi
|
||||
/mob/living/simple_animal/corgi
|
||||
name = "corgi"
|
||||
real_name = "corgi"
|
||||
desc = "It's a corgi."
|
||||
tt_desc = "E Canis lupus familiaris"
|
||||
intelligence_level = SA_ANIMAL
|
||||
icon_state = "corgi"
|
||||
icon_living = "corgi"
|
||||
icon_dead = "corgi_dead"
|
||||
|
||||
run_at_them = 0
|
||||
turns_per_move = 10
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "bops"
|
||||
response_harm = "kicks"
|
||||
|
||||
see_in_dark = 5
|
||||
mob_size = 8
|
||||
|
||||
has_langs = list("Dog")
|
||||
speak_chance = 1
|
||||
speak = list("YAP", "Woof!", "Bark!", "AUUUUUU")
|
||||
speak_emote = list("barks", "woofs")
|
||||
emote_hear = list("barks", "woofs", "yaps","pants")
|
||||
emote_see = list("shakes its head", "shivers")
|
||||
|
||||
meat_amount = 3
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/corgi
|
||||
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_back
|
||||
|
||||
//IAN! SQUEEEEEEEEE~
|
||||
/mob/living/simple_animal/corgi/Ian
|
||||
name = "Ian"
|
||||
real_name = "Ian" //Intended to hold the name without altering it.
|
||||
gender = MALE
|
||||
desc = "It's a corgi."
|
||||
var/turns_since_scan = 0
|
||||
var/obj/movement_target
|
||||
response_help = "pets"
|
||||
response_disarm = "bops"
|
||||
response_harm = "kicks"
|
||||
|
||||
/mob/living/simple_animal/corgi/Ian/Life()
|
||||
..()
|
||||
|
||||
//Not replacing with SA FollowTarget mechanics because Ian behaves... very... specifically.
|
||||
|
||||
//Feeding, chasing food, FOOOOODDDD
|
||||
if(!stat && !resting && !buckled)
|
||||
turns_since_scan++
|
||||
if(turns_since_scan > 5)
|
||||
turns_since_scan = 0
|
||||
if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) ))
|
||||
movement_target = null
|
||||
stop_automated_movement = 0
|
||||
if( !movement_target || !(movement_target.loc in oview(src, 3)) )
|
||||
movement_target = null
|
||||
stop_automated_movement = 0
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3))
|
||||
if(isturf(S.loc) || ishuman(S.loc))
|
||||
movement_target = S
|
||||
break
|
||||
if(movement_target)
|
||||
stop_automated_movement = 1
|
||||
step_to(src,movement_target,1)
|
||||
sleep(3)
|
||||
step_to(src,movement_target,1)
|
||||
sleep(3)
|
||||
step_to(src,movement_target,1)
|
||||
|
||||
if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
|
||||
if (movement_target.loc.x < src.x)
|
||||
set_dir(WEST)
|
||||
else if (movement_target.loc.x > src.x)
|
||||
set_dir(EAST)
|
||||
else if (movement_target.loc.y < src.y)
|
||||
set_dir(SOUTH)
|
||||
else if (movement_target.loc.y > src.y)
|
||||
set_dir(NORTH)
|
||||
else
|
||||
set_dir(SOUTH)
|
||||
|
||||
if(isturf(movement_target.loc) )
|
||||
UnarmedAttack(movement_target)
|
||||
else if(ishuman(movement_target.loc) && prob(20))
|
||||
visible_emote("stares at the [movement_target] that [movement_target.loc] has with sad puppy eyes.")
|
||||
|
||||
if(prob(1))
|
||||
visible_emote(pick("dances around","chases their tail"))
|
||||
spawn(0)
|
||||
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
|
||||
set_dir(i)
|
||||
sleep(1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
|
||||
name = "corgi meat"
|
||||
desc = "Tastes like... well, you know..."
|
||||
|
||||
/mob/living/simple_animal/corgi/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
|
||||
if(istype(O, /obj/item/weapon/newspaper))
|
||||
if(!stat)
|
||||
for(var/mob/M in viewers(user, null))
|
||||
if ((M.client && !( M.blinded )))
|
||||
M.show_message("<font color='blue'>[user] baps [name] on the nose with the rolled up [O]</font>")
|
||||
spawn(0)
|
||||
for(var/i in list(1,2,4,8,4,2,1,2))
|
||||
set_dir(i)
|
||||
sleep(1)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/corgi/regenerate_icons()
|
||||
overlays = list()
|
||||
|
||||
if(inventory_head)
|
||||
var/head_icon_state = inventory_head.icon_state
|
||||
if(health <= 0)
|
||||
head_icon_state += "2"
|
||||
|
||||
var/icon/head_icon = image('icons/mob/corgi_head.dmi',head_icon_state)
|
||||
if(head_icon)
|
||||
overlays += head_icon
|
||||
|
||||
if(inventory_back)
|
||||
var/back_icon_state = inventory_back.icon_state
|
||||
if(health <= 0)
|
||||
back_icon_state += "2"
|
||||
|
||||
var/icon/back_icon = image('icons/mob/corgi_back.dmi',back_icon_state)
|
||||
if(back_icon)
|
||||
overlays += back_icon
|
||||
|
||||
return
|
||||
|
||||
|
||||
/mob/living/simple_animal/corgi/puppy
|
||||
name = "corgi puppy"
|
||||
real_name = "corgi"
|
||||
desc = "It's a corgi puppy."
|
||||
icon_state = "puppy"
|
||||
icon_living = "puppy"
|
||||
icon_dead = "puppy_dead"
|
||||
|
||||
//pupplies cannot wear anything.
|
||||
/mob/living/simple_animal/corgi/puppy/Topic(href, href_list)
|
||||
if(href_list["remove_inv"] || href_list["add_inv"])
|
||||
usr << "<font color='red'>You can't fit this on [src]</font>"
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
//LISA! SQUEEEEEEEEE~
|
||||
/mob/living/simple_animal/corgi/Lisa
|
||||
name = "Lisa"
|
||||
real_name = "Lisa"
|
||||
gender = FEMALE
|
||||
desc = "It's a corgi with a cute pink bow."
|
||||
icon_state = "lisa"
|
||||
icon_living = "lisa"
|
||||
icon_dead = "lisa_dead"
|
||||
response_help = "pets"
|
||||
response_disarm = "bops"
|
||||
response_harm = "kicks"
|
||||
var/turns_since_scan = 0
|
||||
var/puppies = 0
|
||||
|
||||
//Lisa already has a cute bow!
|
||||
/mob/living/simple_animal/corgi/Lisa/Topic(href, href_list)
|
||||
if(href_list["remove_inv"] || href_list["add_inv"])
|
||||
to_chat(usr, "<font color='red'>[src] already has a cute bow!</font>")
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/corgi/Lisa/Life()
|
||||
..()
|
||||
|
||||
if(!stat && !resting && !buckled)
|
||||
turns_since_scan++
|
||||
if(turns_since_scan > 15)
|
||||
turns_since_scan = 0
|
||||
var/alone = 1
|
||||
var/ian = 0
|
||||
for(var/mob/M in oviewers(7, src))
|
||||
if(istype(M, /mob/living/simple_animal/corgi/Ian))
|
||||
if(M.client)
|
||||
alone = 0
|
||||
break
|
||||
else
|
||||
ian = M
|
||||
else
|
||||
alone = 0
|
||||
break
|
||||
if(alone && ian && puppies < 4)
|
||||
if(near_camera(src) || near_camera(ian))
|
||||
return
|
||||
new /mob/living/simple_animal/corgi/puppy(loc)
|
||||
|
||||
|
||||
if(prob(1))
|
||||
visible_emote(pick("dances around","chases her tail"))
|
||||
spawn(0)
|
||||
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
|
||||
set_dir(i)
|
||||
sleep(1)
|
||||
|
||||
|
||||
//Technically this should be like, its own file or something or a subset of dog but whatever. Not a coder.
|
||||
/mob/living/simple_animal/corgi/tamaskan
|
||||
name = "tamaskan"
|
||||
real_name = "tamaskan"
|
||||
desc = "It's a tamaskan."
|
||||
icon_state = "tamaskan"
|
||||
icon_living = "tamaskan"
|
||||
icon_dead = "tamaskan_dead"
|
||||
|
||||
retaliate = 1 //Tamaskans are bigass dogs, okay?
|
||||
|
||||
/mob/living/simple_animal/corgi/tamaskan/spice
|
||||
name = "Spice"
|
||||
real_name = "Spice" //Intended to hold the name without altering it.
|
||||
gender = FEMALE
|
||||
desc = "It's a tamaskan, the name Spice can be found on its collar."
|
||||
var/turns_since_scan = 0
|
||||
var/obj/movement_target
|
||||
response_help = "pets"
|
||||
response_disarm = "bops"
|
||||
response_harm = "kicks"
|
||||
@@ -1,87 +0,0 @@
|
||||
//Look Sir, free crabs!
|
||||
/mob/living/simple_animal/crab
|
||||
name = "crab"
|
||||
desc = "A hard-shelled crustacean. Seems quite content to lounge around all the time."
|
||||
tt_desc = "E Cancer bellianus"
|
||||
icon_state = "crab"
|
||||
icon_living = "crab"
|
||||
icon_dead = "crab_dead"
|
||||
faction = "crabs"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
wander = 0
|
||||
stop_automated_movement = 1
|
||||
turns_per_move = 5
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "stomps"
|
||||
friendly = "pinches"
|
||||
|
||||
speak_chance = 1
|
||||
speak_emote = list("clicks")
|
||||
emote_hear = list("clicks")
|
||||
emote_see = list("clacks")
|
||||
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_mask
|
||||
|
||||
/mob/living/simple_animal/crab/Life()
|
||||
..()
|
||||
//CRAB movement, I'm not porting this up to SA because... "sideways-only movement" var nothanks
|
||||
if(!ckey && !stat)
|
||||
if(isturf(src.loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc.
|
||||
lifes_since_move++
|
||||
if(lifes_since_move >= turns_per_move)
|
||||
Move(get_step(src,pick(4,8)))
|
||||
lifes_since_move = 0
|
||||
regenerate_icons()
|
||||
|
||||
//COFFEE! SQUEEEEEEEEE!
|
||||
/mob/living/simple_animal/crab/Coffee
|
||||
name = "Coffee"
|
||||
real_name = "Coffee"
|
||||
desc = "It's Coffee, the other pet!"
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "stomps"
|
||||
|
||||
//Sif Crabs
|
||||
/mob/living/simple_animal/giant_crab
|
||||
name = "giant crab"
|
||||
desc = "A large, hard-shelled crustacean. This one is mostly grey."
|
||||
tt_desc = "S Cancer holligus"
|
||||
icon_state = "sif_crab"
|
||||
icon_living = "sif_crab"
|
||||
icon_dead = "sif_crab_dead"
|
||||
faction = "crabs"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
|
||||
mob_size = MOB_LARGE
|
||||
cooperative = 1
|
||||
retaliate = 1
|
||||
turns_per_move = 3
|
||||
|
||||
minbodytemp = 175
|
||||
|
||||
melee_damage_lower = 22
|
||||
melee_damage_upper = 35
|
||||
attack_armor_pen = 35
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "stomps"
|
||||
friendly = "pinches"
|
||||
|
||||
speak_chance = 1
|
||||
speak_emote = list("clicks")
|
||||
emote_hear = list("clicks")
|
||||
emote_see = list("clacks")
|
||||
@@ -1,292 +0,0 @@
|
||||
//goat
|
||||
/mob/living/simple_animal/retaliate/goat
|
||||
name = "goat"
|
||||
desc = "Not known for their pleasant disposition."
|
||||
tt_desc = "E Oreamnos americanus"
|
||||
icon_state = "goat"
|
||||
icon_living = "goat"
|
||||
icon_dead = "goat_dead"
|
||||
|
||||
faction = "goat"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
health = 40
|
||||
turns_per_move = 5
|
||||
see_in_dark = 6
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
|
||||
melee_damage_lower = 1
|
||||
melee_damage_upper = 5
|
||||
attacktext = list("kicked")
|
||||
|
||||
speak_chance = 1
|
||||
speak = list("EHEHEHEHEH","eh?")
|
||||
speak_emote = list("brays")
|
||||
emote_hear = list("brays")
|
||||
emote_see = list("shakes its head", "stamps a foot", "glares around")
|
||||
|
||||
meat_amount = 4
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
var/datum/reagents/udder = null
|
||||
|
||||
/mob/living/simple_animal/retaliate/goat/New()
|
||||
udder = new(50)
|
||||
udder.my_atom = src
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/retaliate/goat/Life()
|
||||
. = ..()
|
||||
if(.)
|
||||
if(stat == CONSCIOUS)
|
||||
if(udder && prob(5))
|
||||
udder.add_reagent("milk", rand(5, 10))
|
||||
|
||||
if(locate(/obj/effect/plant) in loc)
|
||||
var/obj/effect/plant/SV = locate() in loc
|
||||
SV.die_off(1)
|
||||
|
||||
if(locate(/obj/machinery/portable_atmospherics/hydroponics/soil/invisible) in loc)
|
||||
var/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/SP = locate() in loc
|
||||
qdel(SP)
|
||||
|
||||
if(!pulledby)
|
||||
var/obj/effect/plant/food
|
||||
food = locate(/obj/effect/plant) in oview(5,loc)
|
||||
if(food)
|
||||
var/step = get_step_to(src, food, 0)
|
||||
Move(step)
|
||||
|
||||
/mob/living/simple_animal/retaliate/goat/react_to_attack()
|
||||
. = ..()
|
||||
if(.)
|
||||
visible_message("<span class='warning'>[src] gets an evil-looking gleam in their eye.</span>")
|
||||
|
||||
/mob/living/simple_animal/retaliate/goat/Move()
|
||||
..()
|
||||
if(!stat)
|
||||
for(var/obj/effect/plant/SV in loc)
|
||||
SV.die_off(1)
|
||||
|
||||
/mob/living/simple_animal/retaliate/goat/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
var/obj/item/weapon/reagent_containers/glass/G = O
|
||||
if(stat == CONSCIOUS && istype(G) && G.is_open_container())
|
||||
user.visible_message("<span class='notice'>[user] milks [src] using \the [O].</span>")
|
||||
var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
|
||||
if(G.reagents.total_volume >= G.volume)
|
||||
user << "<font color='red'>The [O] is full.</font>"
|
||||
if(!transfered)
|
||||
user << "<font color='red'>The udder is dry. Wait a bit longer...</font>"
|
||||
else
|
||||
..()
|
||||
//cow
|
||||
/mob/living/simple_animal/cow
|
||||
name = "cow"
|
||||
desc = "Known for their milk, just don't tip them over."
|
||||
tt_desc = "E Bos taurus"
|
||||
icon_state = "cow"
|
||||
icon_living = "cow"
|
||||
icon_dead = "cow_dead"
|
||||
icon_gib = "cow_gib"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
health = 50
|
||||
turns_per_move = 5
|
||||
see_in_dark = 6
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
attacktext = list("kicked")
|
||||
|
||||
speak_chance = 1
|
||||
speak = list("moo?","moo","MOOOOOO")
|
||||
speak_emote = list("moos","moos hauntingly")
|
||||
emote_hear = list("brays")
|
||||
emote_see = list("shakes its head")
|
||||
|
||||
meat_amount = 6
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
var/datum/reagents/udder = null
|
||||
|
||||
/mob/living/simple_animal/cow/New()
|
||||
udder = new(50)
|
||||
udder.my_atom = src
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/cow/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
var/obj/item/weapon/reagent_containers/glass/G = O
|
||||
if(stat == CONSCIOUS && istype(G) && G.is_open_container())
|
||||
user.visible_message("<span class='notice'>[user] milks [src] using \the [O].</span>")
|
||||
var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
|
||||
if(G.reagents.total_volume >= G.volume)
|
||||
user << "<font color='red'>The [O] is full.</font>"
|
||||
if(!transfered)
|
||||
user << "<font color='red'>The udder is dry. Wait a bit longer...</font>"
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/cow/Life()
|
||||
. = ..()
|
||||
if(stat == CONSCIOUS)
|
||||
if(udder && prob(5))
|
||||
udder.add_reagent("milk", rand(5, 10))
|
||||
|
||||
/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M as mob)
|
||||
if(!stat && M.a_intent == I_DISARM && icon_state != icon_dead)
|
||||
M.visible_message("<span class='warning'>[M] tips over [src].</span>","<span class='notice'>You tip over [src].</span>")
|
||||
Weaken(30)
|
||||
icon_state = icon_dead
|
||||
spawn(rand(20,50))
|
||||
if(!stat && M)
|
||||
icon_state = icon_living
|
||||
var/list/responses = list( "[src] looks at you imploringly.",
|
||||
"[src] looks at you pleadingly",
|
||||
"[src] looks at you with a resigned expression.",
|
||||
"[src] seems resigned to its fate.")
|
||||
M << pick(responses)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/chick
|
||||
name = "\improper chick"
|
||||
desc = "Adorable! They make such a racket though."
|
||||
tt_desc = "E Gallus gallus"
|
||||
icon_state = "chick"
|
||||
icon_living = "chick"
|
||||
icon_dead = "chick_dead"
|
||||
icon_gib = "chick_gib"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
health = 1
|
||||
turns_per_move = 2
|
||||
|
||||
pass_flags = PASSTABLE | PASSGRILLE
|
||||
mob_size = MOB_MINISCULE
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
attacktext = list("kicked")
|
||||
|
||||
has_langs = list("Bird")
|
||||
speak_chance = 2
|
||||
speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
|
||||
speak_emote = list("cheeps")
|
||||
emote_hear = list("cheeps")
|
||||
emote_see = list("pecks at the ground","flaps its tiny wings")
|
||||
|
||||
meat_amount = 1
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
var/amount_grown = 0
|
||||
|
||||
/mob/living/simple_animal/chick/New()
|
||||
..()
|
||||
pixel_x = rand(-6, 6)
|
||||
pixel_y = rand(0, 10)
|
||||
|
||||
/mob/living/simple_animal/chick/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
return
|
||||
if(!stat)
|
||||
amount_grown += rand(1,2)
|
||||
if(amount_grown >= 100)
|
||||
new /mob/living/simple_animal/chicken(src.loc)
|
||||
qdel(src)
|
||||
|
||||
var/const/MAX_CHICKENS = 50
|
||||
var/global/chicken_count = 0
|
||||
|
||||
/mob/living/simple_animal/chicken
|
||||
name = "\improper chicken"
|
||||
desc = "Hopefully the eggs are good this season."
|
||||
tt_desc = "E Gallus gallus"
|
||||
icon_state = "chicken"
|
||||
icon_living = "chicken"
|
||||
icon_dead = "chicken_dead"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
health = 10
|
||||
turns_per_move = 3
|
||||
pass_flags = PASSTABLE
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
attacktext = list("kicked")
|
||||
|
||||
has_langs = list("Bird")
|
||||
speak_chance = 2
|
||||
speak = list("Cluck!","BWAAAAARK BWAK BWAK BWAK!","Bwaak bwak.")
|
||||
speak_emote = list("clucks","croons")
|
||||
emote_hear = list("clucks")
|
||||
emote_see = list("pecks at the ground","flaps its wings viciously")
|
||||
|
||||
meat_amount = 2
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
var/eggsleft = 0
|
||||
var/body_color
|
||||
|
||||
/mob/living/simple_animal/chicken/New()
|
||||
..()
|
||||
if(!body_color)
|
||||
body_color = pick( list("brown","black","white") )
|
||||
icon_state = "chicken_[body_color]"
|
||||
icon_living = "chicken_[body_color]"
|
||||
icon_dead = "chicken_[body_color]_dead"
|
||||
pixel_x = rand(-6, 6)
|
||||
pixel_y = rand(0, 10)
|
||||
chicken_count += 1
|
||||
|
||||
/mob/living/simple_animal/chicken/death()
|
||||
..()
|
||||
chicken_count -= 1
|
||||
|
||||
/mob/living/simple_animal/chicken/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown)) //feedin' dem chickens
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O
|
||||
if(G.seed && G.seed.kitchen_tag == "wheat")
|
||||
if(!stat && eggsleft < 8)
|
||||
user.visible_message("<font color='blue'>[user] feeds [O] to [name]! It clucks happily.</font>","<font color='blue'>You feed [O] to [name]! It clucks happily.</font>")
|
||||
user.drop_item()
|
||||
qdel(O)
|
||||
eggsleft += rand(1, 4)
|
||||
else
|
||||
user << "<font color='blue'>[name] doesn't seem hungry!</font>"
|
||||
else
|
||||
user << "[name] doesn't seem interested in that."
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/chicken/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
return
|
||||
if(!stat && prob(3) && eggsleft > 0)
|
||||
visible_message("[src] [pick("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")]")
|
||||
eggsleft--
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/egg/E = new(get_turf(src))
|
||||
E.pixel_x = rand(-6,6)
|
||||
E.pixel_y = rand(-6,6)
|
||||
if(chicken_count < MAX_CHICKENS && prob(10))
|
||||
START_PROCESSING(SSobj, E)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/process()
|
||||
if(isturf(loc))
|
||||
amount_grown += rand(1,2)
|
||||
if(amount_grown >= 100)
|
||||
visible_message("[src] hatches with a quiet cracking sound.")
|
||||
new /mob/living/simple_animal/chick(get_turf(src))
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
qdel(src)
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
@@ -1,80 +0,0 @@
|
||||
// Different types of fish! They are all subtypes of this tho
|
||||
/mob/living/simple_animal/fish
|
||||
name = "fish"
|
||||
desc = "Its a fishy. No touchy fishy."
|
||||
icon = 'icons/mob/fish.dmi'
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
// By defautl they can be in any water turf. Subtypes might restrict to deep/shallow etc
|
||||
var/global/list/suitable_turf_types = list(
|
||||
/turf/simulated/floor/beach/water,
|
||||
/turf/simulated/floor/beach/coastline,
|
||||
/turf/simulated/floor/holofloor/beach/water,
|
||||
/turf/simulated/floor/holofloor/beach/coastline,
|
||||
/turf/simulated/floor/water
|
||||
)
|
||||
|
||||
// Don't swim out of the water
|
||||
/mob/living/simple_animal/fish/handle_wander_movement()
|
||||
if(isturf(src.loc) && !resting && !buckled && canmove) //Physically capable of moving?
|
||||
lifes_since_move++ //Increment turns since move (turns are life() cycles)
|
||||
if(lifes_since_move >= turns_per_move)
|
||||
if(!(stop_when_pulled && pulledby)) //Some animals don't move when pulled
|
||||
var/moving_to = 0 // otherwise it always picks 4, fuck if I know. Did I mention fuck BYOND
|
||||
moving_to = pick(cardinal)
|
||||
dir = moving_to //How about we turn them the direction they are moving, yay.
|
||||
var/turf/T = get_step(src,moving_to)
|
||||
if(T && is_type_in_list(T, suitable_turf_types))
|
||||
Move(T)
|
||||
lifes_since_move = 0
|
||||
|
||||
// Take damage if we are not in water
|
||||
/mob/living/simple_animal/fish/handle_breathing()
|
||||
var/turf/T = get_turf(src)
|
||||
if(T && !is_type_in_list(T, suitable_turf_types))
|
||||
if(prob(50))
|
||||
say(pick("Blub", "Glub", "Burble"))
|
||||
adjustBruteLoss(unsuitable_atoms_damage)
|
||||
|
||||
/mob/living/simple_animal/fish/bass
|
||||
name = "bass"
|
||||
tt_desc = "E Micropterus notius"
|
||||
icon_state = "bass-swim"
|
||||
icon_living = "bass-swim"
|
||||
icon_dead = "bass-dead"
|
||||
|
||||
/mob/living/simple_animal/fish/trout
|
||||
name = "trout"
|
||||
tt_desc = "E Salmo trutta"
|
||||
icon_state = "trout-swim"
|
||||
icon_living = "trout-swim"
|
||||
icon_dead = "trout-dead"
|
||||
|
||||
/mob/living/simple_animal/fish/salmon
|
||||
name = "salmon"
|
||||
tt_desc = "E Oncorhynchus nerka"
|
||||
icon_state = "salmon-swim"
|
||||
icon_living = "salmon-swim"
|
||||
icon_dead = "salmon-dead"
|
||||
|
||||
/mob/living/simple_animal/fish/perch
|
||||
name = "perch"
|
||||
tt_desc = "E Perca flavescens"
|
||||
icon_state = "perch-swim"
|
||||
icon_living = "perch-swim"
|
||||
icon_dead = "perch-dead"
|
||||
|
||||
/mob/living/simple_animal/fish/pike
|
||||
name = "pike"
|
||||
tt_desc = "E Esox aquitanicus"
|
||||
icon_state = "pike-swim"
|
||||
icon_living = "pike-swim"
|
||||
icon_dead = "pike-dead"
|
||||
|
||||
/mob/living/simple_animal/fish/koi
|
||||
name = "koi"
|
||||
tt_desc = "E Cyprinus rubrofuscus"
|
||||
icon_state = "koi-swim"
|
||||
icon_living = "koi-swim"
|
||||
icon_dead = "koi-dead"
|
||||
@@ -1,580 +0,0 @@
|
||||
|
||||
#define SPINNING_WEB 1
|
||||
#define LAYING_EGGS 2
|
||||
#define MOVING_TO_TARGET 3
|
||||
#define SPINNING_COCOON 4
|
||||
|
||||
//basic spider mob, these generally guard nests
|
||||
/mob/living/simple_animal/hostile/giant_spider
|
||||
name = "giant spider"
|
||||
desc = "Furry and brown, it makes you shudder to look at it. This one has deep red eyes."
|
||||
tt_desc = "X Brachypelma phorus"
|
||||
icon_state = "guard"
|
||||
icon_living = "guard"
|
||||
icon_dead = "guard_dead"
|
||||
|
||||
faction = "spiders"
|
||||
intelligence_level = SA_ANIMAL
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
pass_flags = PASSTABLE
|
||||
move_to_delay = 6
|
||||
speed = 3
|
||||
|
||||
stop_when_pulled = 0
|
||||
turns_per_move = 5
|
||||
see_in_dark = 10
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "punches"
|
||||
|
||||
melee_damage_lower = 18
|
||||
melee_damage_upper = 30
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
heat_damage_per_tick = 20
|
||||
cold_damage_per_tick = 20
|
||||
|
||||
speak_chance = 5
|
||||
speak_emote = list("chitters")
|
||||
emote_hear = list("chitters")
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/xenomeat/spidermeat
|
||||
|
||||
var/busy = 0
|
||||
var/poison_per_bite = 5
|
||||
var/poison_chance = 10
|
||||
var/poison_type = "spidertoxin"
|
||||
var/image/eye_layer = null
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/proc/add_eyes()
|
||||
if(!eye_layer)
|
||||
eye_layer = image(icon, "[icon_state]-eyes")
|
||||
eye_layer.plane = PLANE_LIGHTING_ABOVE
|
||||
|
||||
overlays += eye_layer
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/proc/remove_eyes()
|
||||
overlays -= eye_layer
|
||||
|
||||
/*
|
||||
Nurse Family
|
||||
*/
|
||||
|
||||
//nursemaids - these create webs and eggs
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse
|
||||
desc = "Furry and beige, it makes you shudder to look at it. This one has brilliant green eyes."
|
||||
tt_desc = "X Brachypelma phorus laetus"
|
||||
icon_state = "nurse"
|
||||
icon_living = "nurse"
|
||||
icon_dead = "nurse_dead"
|
||||
|
||||
maxHealth = 40
|
||||
health = 40
|
||||
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 15
|
||||
poison_per_bite = 7
|
||||
poison_type = "stoxin"
|
||||
|
||||
var/fed = 0
|
||||
var/atom/cocoon_target
|
||||
var/egg_inject_chance = 5
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse/hat
|
||||
desc = "Furry and beige, it makes you shudder to look at it. This one has brilliant green eyes and a tiny nurse hat"
|
||||
icon_state = "nursemed"
|
||||
icon_living = "nursemed"
|
||||
icon_dead = "nursemed_dead"
|
||||
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse/queen
|
||||
desc = "Absolutely gigantic, this creature is horror itself."
|
||||
tt_desc = "X Brachypelma phorus tyrannus"
|
||||
icon = 'icons/mob/64x64.dmi'
|
||||
icon_state = "spider_queen"
|
||||
icon_living = "spider_queen"
|
||||
icon_dead = "spider_queen_dead"
|
||||
|
||||
maxHealth = 320
|
||||
health = 320
|
||||
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 30
|
||||
attack_armor_pen = 25
|
||||
|
||||
poison_per_bite = 10
|
||||
egg_inject_chance = 10
|
||||
|
||||
pixel_x = -16
|
||||
pixel_y = -16
|
||||
old_x = -16
|
||||
old_y = -16
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/webslinger
|
||||
desc = "Furry and green, it makes you shudder to look at it. This one has brilliant green eyes, and a cloak of web."
|
||||
tt_desc = "X Brachypelma phorus balisticus"
|
||||
icon_state = "webslinger"
|
||||
icon_living = "webslinger"
|
||||
icon_dead = "webslinger_dead"
|
||||
|
||||
maxHealth = 90
|
||||
health = 90
|
||||
|
||||
projectilesound = 'sound/weapons/thudswoosh.ogg'
|
||||
projectiletype = /obj/item/projectile/bola
|
||||
ranged = 1
|
||||
firing_lines = 1
|
||||
cooperative = 1
|
||||
shoot_range = 5
|
||||
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 15
|
||||
poison_per_bite = 2
|
||||
poison_type = "psilocybin"
|
||||
|
||||
spattack_prob = 15
|
||||
spattack_min_range = 0
|
||||
spattack_max_range = 5
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/webslinger/AttackTarget() //One day.
|
||||
var/mob/living/carbon/human/victim = null //Webslinger needs to know if its target is human later.
|
||||
if(ishuman(target_mob))
|
||||
victim = target_mob
|
||||
if(!victim.legcuffed)
|
||||
projectiletype = /obj/item/projectile/bola
|
||||
shoot_range = 7
|
||||
else
|
||||
projectiletype = /obj/item/projectile/webball
|
||||
shoot_range = 5
|
||||
else
|
||||
projectiletype = /obj/item/projectile/webball
|
||||
shoot_range = 5
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/carrier
|
||||
desc = "Furry, beige, and red, it makes you shudder to look at it. This one has luminous green eyes."
|
||||
tt_desc = "X Brachypelma phorus gerulus"
|
||||
icon_state = "carrier"
|
||||
icon_living = "carrier"
|
||||
icon_dead = "carrier_dead"
|
||||
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 25
|
||||
|
||||
poison_per_bite = 3
|
||||
poison_type = "chloralhydrate"
|
||||
|
||||
var/spiderling_count = 0
|
||||
var/spiderling_type = /obj/effect/spider/spiderling
|
||||
var/swarmling_type = /mob/living/simple_animal/hostile/giant_spider/hunter
|
||||
var/swarmling_faction = "spiders"
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/carrier/New()
|
||||
spiderling_count = rand(5,10)
|
||||
adjust_scale(1.2)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/carrier/death()
|
||||
visible_message("<span class='notice'>\The [src]'s abdomen splits as it rolls over, spiderlings crawling from the wound.</span>")
|
||||
spawn(1)
|
||||
for(var/I = 1 to spiderling_count)
|
||||
if(prob(10) && src)
|
||||
var/mob/living/simple_animal/hostile/giant_spider/swarmling = new swarmling_type(src.loc)
|
||||
var/swarm_health = FLOOR(swarmling.maxHealth * 0.4, 1)
|
||||
var/swarm_dam_lower = FLOOR(melee_damage_lower * 0.4, 1)
|
||||
var/swarm_dam_upper = FLOOR(melee_damage_upper * 0.4, 1)
|
||||
swarmling.name = "spiderling"
|
||||
swarmling.maxHealth = swarm_health
|
||||
swarmling.health = swarm_health
|
||||
swarmling.melee_damage_lower = swarm_dam_lower
|
||||
swarmling.melee_damage_upper = swarm_dam_upper
|
||||
swarmling.faction = swarmling_faction
|
||||
swarmling.adjust_scale(0.75)
|
||||
else if(src)
|
||||
var/obj/effect/spider/spiderling/child = new spiderling_type(src.loc)
|
||||
child.skitter()
|
||||
else
|
||||
break
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/carrier/recursive
|
||||
desc = "Furry, beige, and red, it makes you shudder to look at it. This one has luminous green eyes. You have a distinctly <font face='comic sans ms'>bad</font> feeling about this."
|
||||
|
||||
swarmling_type = /mob/living/simple_animal/hostile/giant_spider/carrier/recursive
|
||||
|
||||
/*
|
||||
Hunter Family
|
||||
*/
|
||||
|
||||
//hunters have the most poison and move the fastest, so they can find prey
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/hunter
|
||||
desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes."
|
||||
tt_desc = "X Brachypelma phorus venandi"
|
||||
icon_state = "hunter"
|
||||
icon_living = "hunter"
|
||||
icon_dead = "hunter_dead"
|
||||
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
move_to_delay = 4
|
||||
|
||||
poison_per_bite = 5
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/lurker
|
||||
desc = "Translucent and white, it makes you shudder to look at it. This one has incandescent red eyes."
|
||||
tt_desc = "X Brachypelma phorus insidator"
|
||||
icon_state = "lurker"
|
||||
icon_living = "lurker"
|
||||
icon_dead = "lurker_dead"
|
||||
alpha = 45
|
||||
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
move_to_delay = 4
|
||||
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 20
|
||||
|
||||
|
||||
poison_chance = 20
|
||||
poison_type = "cryptobiolin"
|
||||
poison_per_bite = 2
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/lurker/death()
|
||||
alpha = 255
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/tunneler
|
||||
desc = "Sandy and brown, it makes you shudder to look at it. This one has glittering yellow eyes."
|
||||
tt_desc = "X Brachypelma phorus cannalis"
|
||||
icon_state = "tunneler"
|
||||
icon_living = "tunneler"
|
||||
icon_dead = "tunneler_dead"
|
||||
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
move_to_delay = 4
|
||||
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
|
||||
poison_chance = 15
|
||||
poison_per_bite = 3
|
||||
poison_type = "serotrotium_v"
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/tunneler/death()
|
||||
spawn(1)
|
||||
for(var/I = 1 to rand(3,6))
|
||||
if(src)
|
||||
new/obj/item/weapon/ore/glass(src.loc)
|
||||
else
|
||||
break
|
||||
return ..()
|
||||
|
||||
/*
|
||||
Guard Family
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/pepper
|
||||
desc = "Red and brown, it makes you shudder to look at it. This one has glinting red eyes."
|
||||
tt_desc = "X Brachypelma phorus ignis"
|
||||
icon_state = "pepper"
|
||||
icon_living = "pepper"
|
||||
icon_dead = "pepper_dead"
|
||||
|
||||
maxHealth = 210
|
||||
health = 210
|
||||
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 15
|
||||
|
||||
poison_chance = 20
|
||||
poison_per_bite = 5
|
||||
poison_type = "condensedcapsaicin_v"
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/pepper/New()
|
||||
adjust_scale(1.1)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/thermic
|
||||
desc = "Mirage-cloaked and orange, it makes you shudder to look at it. This one has simmering orange eyes."
|
||||
tt_desc = "X Brachypelma phorus incaendium"
|
||||
icon_state = "pit"
|
||||
icon_living = "pit"
|
||||
icon_dead = "pit_dead"
|
||||
|
||||
maxHealth = 175
|
||||
health = 175
|
||||
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 25
|
||||
|
||||
poison_chance = 30
|
||||
poison_per_bite = 1
|
||||
poison_type = "thermite_v"
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/electric
|
||||
desc = "Spined and yellow, it makes you shudder to look at it. This one has flickering gold eyes."
|
||||
tt_desc = "X Brachypelma phorus aromatitis"
|
||||
icon_state = "spark"
|
||||
icon_living = "spark"
|
||||
icon_dead = "spark_dead"
|
||||
|
||||
maxHealth = 210
|
||||
health = 210
|
||||
taser_kill = 0 //It -is- the taser.
|
||||
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 25
|
||||
|
||||
ranged = 1
|
||||
projectilesound = 'sound/weapons/taser2.ogg'
|
||||
projectiletype = /obj/item/projectile/beam/stun/weak
|
||||
firing_lines = 1
|
||||
cooperative = 1
|
||||
|
||||
poison_chance = 15
|
||||
poison_per_bite = 3
|
||||
poison_type = "stimm"
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/phorogenic
|
||||
desc = "Crystalline and purple, it makes you shudder to look at it. This one has haunting purple eyes."
|
||||
tt_desc = "X Brachypelma phorus phorus"
|
||||
icon_state = "phoron"
|
||||
icon_living = "phoron"
|
||||
icon_dead = "phoron_dead"
|
||||
|
||||
maxHealth = 225
|
||||
health = 225
|
||||
taser_kill = 0 //You will need more than a peashooter to kill the juggernaut.
|
||||
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 40
|
||||
attack_armor_pen = 15
|
||||
|
||||
poison_chance = 30
|
||||
poison_per_bite = 0.5
|
||||
poison_type = "phoron"
|
||||
|
||||
var/exploded = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/phorogenic/New()
|
||||
adjust_scale(1.25)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/phorogenic/death()
|
||||
visible_message("<span class='danger'>\The [src]'s body begins to rupture!</span>")
|
||||
spawn(rand(1,5))
|
||||
if(src && !exploded)
|
||||
visible_message("<span class='critical'>\The [src]'s body detonates!</span>")
|
||||
exploded = 1
|
||||
explosion(src.loc, 1, 2, 4, 6)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/frost
|
||||
desc = "Icy and blue, it makes you shudder to look at it. This one has brilliant blue eyes."
|
||||
tt_desc = "X Brachypelma phorus pruinae"
|
||||
icon_state = "frost"
|
||||
icon_living = "frost"
|
||||
icon_dead = "frost_dead"
|
||||
|
||||
maxHealth = 175
|
||||
health = 175
|
||||
|
||||
poison_per_bite = 5
|
||||
poison_type = "cryotoxin"
|
||||
|
||||
/*
|
||||
Spider Procs
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/New(var/location, var/atom/parent)
|
||||
get_light_and_color(parent)
|
||||
add_eyes()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/death()
|
||||
remove_eyes()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/DoPunch(var/atom/A)
|
||||
. = ..()
|
||||
if(.) // If we succeeded in hitting.
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(L.reagents)
|
||||
var/target_zone = pick(BP_TORSO,BP_TORSO,BP_TORSO,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_HEAD)
|
||||
if(L.can_inject(src, null, target_zone))
|
||||
L.reagents.add_reagent(poison_type, poison_per_bite)
|
||||
if(prob(poison_chance))
|
||||
to_chat(L, "<span class='warning'>You feel a tiny prick.</span>")
|
||||
L.reagents.add_reagent(poison_type, poison_per_bite)
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse/DoPunch(var/atom/A)
|
||||
. = ..()
|
||||
if(.) // If we succeeded in hitting.
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(prob(egg_inject_chance))
|
||||
var/target_zone = pick(BP_TORSO,BP_TORSO,BP_TORSO,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_HEAD)
|
||||
if(H.can_inject(src, null, target_zone))
|
||||
var/obj/item/organ/external/O = H.get_organ(target_zone)
|
||||
var/eggcount
|
||||
for(var/obj/I in O.implants)
|
||||
if(istype(I, /obj/effect/spider/eggcluster))
|
||||
eggcount ++
|
||||
if(!eggcount)
|
||||
var/eggs = new /obj/effect/spider/eggcluster/small(O, src)
|
||||
O.implants += eggs
|
||||
to_chat(H, "<font size='3'><span class='warning'>\The [src] injects something into your [O.name]!</span></font>")
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/webslinger/DoPunch(var/atom/A)
|
||||
. = ..()
|
||||
if(.) // If we succeeded in hitting.
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
var/obj/effect/spider/stickyweb/W = locate() in get_turf(L)
|
||||
if(!W && prob(75))
|
||||
visible_message("<span class='danger'>\The [src] throws a layer of web at \the [L]!</span>")
|
||||
new /obj/effect/spider/stickyweb(L.loc)
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/handle_stance()
|
||||
. = ..()
|
||||
if(ai_inactive) return
|
||||
|
||||
switch(stance)
|
||||
if(STANCE_IDLE)
|
||||
//1% chance to skitter madly away
|
||||
if(!busy && prob(1))
|
||||
/*var/list/move_targets = list()
|
||||
for(var/turf/T in orange(20, src))
|
||||
move_targets.Add(T)*/
|
||||
stop_automated_movement = 1
|
||||
walk_to(src, pick(orange(20, src)), 1, move_to_delay)
|
||||
spawn(5 SECONDS)
|
||||
stop_automated_movement = 0
|
||||
walk(src,0)
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse/proc/GiveUp(var/C)
|
||||
spawn(10 SECONDS)
|
||||
if(busy == MOVING_TO_TARGET)
|
||||
if(cocoon_target == C && get_dist(src,cocoon_target) > 1)
|
||||
cocoon_target = null
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse/Life()
|
||||
. = ..()
|
||||
if(!. || ai_inactive) return
|
||||
|
||||
if(stance == STANCE_IDLE)
|
||||
var/list/can_see = view(src, 10)
|
||||
//30% chance to stop wandering and do something
|
||||
if(!busy && prob(30))
|
||||
//first, check for potential food nearby to cocoon
|
||||
for(var/mob/living/C in can_see)
|
||||
if(C.stat)
|
||||
cocoon_target = C
|
||||
busy = MOVING_TO_TARGET
|
||||
walk_to(src, C, 1, move_to_delay)
|
||||
//give up if we can't reach them after 10 seconds
|
||||
GiveUp(C)
|
||||
return
|
||||
|
||||
//second, spin a sticky spiderweb on this tile
|
||||
var/obj/effect/spider/stickyweb/W = locate() in get_turf(src)
|
||||
if(!W)
|
||||
busy = SPINNING_WEB
|
||||
src.visible_message("<span class='notice'>\The [src] begins to secrete a sticky substance.</span>")
|
||||
stop_automated_movement = 1
|
||||
spawn(40)
|
||||
if(busy == SPINNING_WEB)
|
||||
new /obj/effect/spider/stickyweb(src.loc)
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
else
|
||||
//third, lay an egg cluster there
|
||||
var/obj/effect/spider/eggcluster/E = locate() in get_turf(src)
|
||||
if(!E && fed > 0)
|
||||
busy = LAYING_EGGS
|
||||
src.visible_message("<span class='notice'>\The [src] begins to lay a cluster of eggs.</span>")
|
||||
stop_automated_movement = 1
|
||||
spawn(50)
|
||||
if(busy == LAYING_EGGS)
|
||||
E = locate() in get_turf(src)
|
||||
if(!E)
|
||||
new /obj/effect/spider/eggcluster(loc, src)
|
||||
fed--
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
else
|
||||
//fourthly, cocoon any nearby items so those pesky pinkskins can't use them
|
||||
for(var/obj/O in can_see)
|
||||
|
||||
if(O.anchored)
|
||||
continue
|
||||
|
||||
if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery))
|
||||
cocoon_target = O
|
||||
busy = MOVING_TO_TARGET
|
||||
stop_automated_movement = 1
|
||||
walk_to(src, O, 1, move_to_delay)
|
||||
//give up if we can't reach them after 10 seconds
|
||||
GiveUp(O)
|
||||
|
||||
else if(busy == MOVING_TO_TARGET && cocoon_target)
|
||||
if(get_dist(src, cocoon_target) <= 1)
|
||||
busy = SPINNING_COCOON
|
||||
src.visible_message("<span class='notice'>\The [src] begins to secrete a sticky substance around \the [cocoon_target].</span>")
|
||||
stop_automated_movement = 1
|
||||
walk(src,0)
|
||||
spawn(50)
|
||||
if(busy == SPINNING_COCOON)
|
||||
if(cocoon_target && istype(cocoon_target.loc, /turf) && get_dist(src,cocoon_target) <= 1)
|
||||
var/obj/effect/spider/cocoon/C = new(cocoon_target.loc)
|
||||
var/large_cocoon = 0
|
||||
C.pixel_x = cocoon_target.pixel_x
|
||||
C.pixel_y = cocoon_target.pixel_y
|
||||
for(var/mob/living/M in C.loc)
|
||||
if(istype(M, /mob/living/simple_animal/hostile/giant_spider))
|
||||
continue
|
||||
large_cocoon = 1
|
||||
fed++
|
||||
src.visible_message("<span class='warning'>\The [src] sticks a proboscis into \the [cocoon_target] and sucks a viscous substance out.</span>")
|
||||
M.forceMove(C)
|
||||
C.pixel_x = M.pixel_x
|
||||
C.pixel_y = M.pixel_y
|
||||
break
|
||||
for(var/obj/item/I in C.loc)
|
||||
I.forceMove(C)
|
||||
for(var/obj/structure/S in C.loc)
|
||||
if(!S.anchored)
|
||||
S.forceMove(C)
|
||||
large_cocoon = 1
|
||||
for(var/obj/machinery/M in C.loc)
|
||||
if(!M.anchored)
|
||||
M.forceMove(C)
|
||||
large_cocoon = 1
|
||||
if(large_cocoon)
|
||||
C.icon_state = pick("cocoon_large1","cocoon_large2","cocoon_large3")
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
|
||||
else
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
|
||||
|
||||
#undef SPINNING_WEB
|
||||
#undef LAYING_EGGS
|
||||
#undef MOVING_TO_TARGET
|
||||
#undef SPINNING_COCOON
|
||||
@@ -1,59 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/goose //hey are these even in the game
|
||||
name = "goose"
|
||||
desc = "It looks pretty angry!"
|
||||
tt_desc = "E Branta canadensis" //that iconstate is just a regular goose
|
||||
icon_state = "goose"
|
||||
icon_living = "goose"
|
||||
icon_dead = "goose_dead"
|
||||
|
||||
faction = "geese"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
maxHealth = 15
|
||||
health = 15
|
||||
speed = 4
|
||||
|
||||
turns_per_move = 5
|
||||
|
||||
response_help = "pets the"
|
||||
response_disarm = "gently pushes aside the"
|
||||
response_harm = "hits the"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 5 //they're meant to be annoying, not threatening.
|
||||
melee_damage_upper = 5 //unless there's like a dozen of them, then you're screwed.
|
||||
attacktext = list("pecked")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
//SPACE geese aren't affected by atmos.
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
has_langs = list("Bird")
|
||||
speak_chance = 10
|
||||
speak = list("HONK!")
|
||||
emote_hear = list("honks loudly!")
|
||||
emote_see = list()
|
||||
say_understood = list()
|
||||
say_cannot = list()
|
||||
say_maybe_target = list("Honk?")
|
||||
say_got_target = list("HONK!!!")
|
||||
reactions = list()
|
||||
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
/mob/living/simple_animal/hostile/goose/set_target()
|
||||
. = ..()
|
||||
if(.)
|
||||
custom_emote(1,"flaps and honks at [.]!")
|
||||
|
||||
/mob/living/simple_animal/hostile/goose/Process_Spacemove(var/check_drift = 0)
|
||||
return
|
||||
@@ -1,24 +0,0 @@
|
||||
/mob/living/simple_animal/lizard
|
||||
name = "Lizard"
|
||||
desc = "A cute tiny lizard."
|
||||
tt_desc = "E Anolis cuvieri"
|
||||
icon = 'icons/mob/critter.dmi'
|
||||
icon_state = "lizard"
|
||||
icon_living = "lizard"
|
||||
icon_dead = "lizard-dead"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
health = 5
|
||||
maxHealth = 5
|
||||
mob_size = MOB_MINISCULE
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "shoos"
|
||||
response_harm = "stomps on"
|
||||
|
||||
attacktext = list("bitten")
|
||||
melee_damage_lower = 1
|
||||
melee_damage_upper = 2
|
||||
|
||||
speak_chance = 1
|
||||
speak_emote = list("hisses")
|
||||
@@ -1,21 +0,0 @@
|
||||
/mob/living/simple_animal/yithian
|
||||
name = "yithian"
|
||||
desc = "A friendly creature vaguely resembling an oversized snail without a shell."
|
||||
tt_desc = "J Escargot escargot" // a product of Jade, which is a planet that totally exists
|
||||
icon_state = "yithian"
|
||||
icon_living = "yithian"
|
||||
icon_dead = "yithian_dead"
|
||||
icon = 'icons/jungle.dmi'
|
||||
|
||||
faction = "yithian"
|
||||
|
||||
/mob/living/simple_animal/tindalos
|
||||
name = "tindalos"
|
||||
desc = "It looks like a large, flightless grasshopper."
|
||||
tt_desc = "J Locusta bruchus"
|
||||
icon_state = "tindalos"
|
||||
icon_living = "tindalos"
|
||||
icon_dead = "tindalos_dead"
|
||||
icon = 'icons/jungle.dmi'
|
||||
|
||||
faction = "tindalos"
|
||||
@@ -1,137 +0,0 @@
|
||||
/mob/living/simple_animal/mouse
|
||||
name = "mouse"
|
||||
real_name = "mouse"
|
||||
desc = "It's a small rodent."
|
||||
tt_desc = "E Mus musculus"
|
||||
icon_state = "mouse_gray"
|
||||
item_state = "mouse_gray"
|
||||
icon_living = "mouse_gray"
|
||||
icon_dead = "mouse_gray_dead"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
maxHealth = 5
|
||||
health = 5
|
||||
|
||||
turns_per_move = 5
|
||||
see_in_dark = 6
|
||||
universal_understand = 1
|
||||
|
||||
mob_size = MOB_SMALL
|
||||
pass_flags = PASSTABLE
|
||||
// can_pull_size = ITEMSIZE_TINY
|
||||
// can_pull_mobs = MOB_PULL_NONE
|
||||
layer = MOB_LAYER
|
||||
density = 0
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "stamps on"
|
||||
|
||||
min_oxy = 16 //Require atleast 16kPA oxygen
|
||||
minbodytemp = 223 //Below -50 Degrees Celcius
|
||||
maxbodytemp = 323 //Above 50 Degrees Celcius
|
||||
|
||||
has_langs = list("Mouse")
|
||||
speak_chance = 1
|
||||
speak = list("Squeek!","SQUEEK!","Squeek?")
|
||||
speak_emote = list("squeeks","squeeks","squiks")
|
||||
emote_hear = list("squeeks","squeaks","squiks")
|
||||
emote_see = list("runs in a circle", "shakes", "scritches at something")
|
||||
|
||||
holder_type = /obj/item/weapon/holder/mouse
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
var/body_color //brown, gray and white, leave blank for random
|
||||
|
||||
/mob/living/simple_animal/mouse/Life()
|
||||
. = ..()
|
||||
if(!. || ai_inactive) return
|
||||
|
||||
if(prob(speak_chance))
|
||||
for(var/mob/M in view())
|
||||
M << 'sound/effects/mouse_squeak.ogg'
|
||||
|
||||
if(!resting && prob(0.5))
|
||||
lay_down()
|
||||
speak_chance = 0
|
||||
//snuffles
|
||||
|
||||
else if(resting)
|
||||
if(prob(1))
|
||||
lay_down()
|
||||
speak_chance = initial(speak_chance)
|
||||
else if(prob(1))
|
||||
audible_emote("snuffles.")
|
||||
|
||||
/mob/living/simple_animal/mouse/New()
|
||||
..()
|
||||
|
||||
verbs += /mob/living/proc/ventcrawl
|
||||
verbs += /mob/living/proc/hide
|
||||
|
||||
if(name == initial(name))
|
||||
name = "[name] ([rand(1, 1000)])"
|
||||
real_name = name
|
||||
|
||||
if(!body_color)
|
||||
body_color = pick( list("brown","gray","white") )
|
||||
icon_state = "mouse_[body_color]"
|
||||
item_state = "mouse_[body_color]"
|
||||
icon_living = "mouse_[body_color]"
|
||||
icon_dead = "mouse_[body_color]_dead"
|
||||
icon_rest = "mouse_[body_color]_sleep"
|
||||
desc = "A small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself."
|
||||
|
||||
/mob/living/simple_animal/mouse/proc/splat()
|
||||
src.health = 0
|
||||
src.stat = DEAD
|
||||
src.icon_dead = "mouse_[body_color]_splat"
|
||||
src.icon_state = "mouse_[body_color]_splat"
|
||||
layer = MOB_LAYER
|
||||
if(client)
|
||||
client.time_died_as_mouse = world.time
|
||||
|
||||
|
||||
/mob/living/simple_animal/mouse/Crossed(AM as mob|obj)
|
||||
if( ishuman(AM) )
|
||||
if(!stat)
|
||||
var/mob/M = AM
|
||||
M.visible_message("<font color='blue'>\icon[src] Squeek!</font>")
|
||||
M << 'sound/effects/mouse_squeak.ogg'
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/mouse/death()
|
||||
layer = MOB_LAYER
|
||||
playsound(src, 'sound/effects/mouse_squeak_loud.ogg', 35, 1)
|
||||
if(client)
|
||||
client.time_died_as_mouse = world.time
|
||||
..()
|
||||
|
||||
/*
|
||||
* Mouse types
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/mouse/white
|
||||
body_color = "white"
|
||||
icon_state = "mouse_white"
|
||||
|
||||
/mob/living/simple_animal/mouse/gray
|
||||
body_color = "gray"
|
||||
icon_state = "mouse_gray"
|
||||
|
||||
/mob/living/simple_animal/mouse/brown
|
||||
body_color = "brown"
|
||||
icon_state = "mouse_brown"
|
||||
|
||||
//TOM IS ALIVE! SQUEEEEEEEE~K :)
|
||||
/mob/living/simple_animal/mouse/brown/Tom
|
||||
name = "Tom"
|
||||
desc = "Jerry the cat is not amused."
|
||||
|
||||
/mob/living/simple_animal/mouse/brown/Tom/New()
|
||||
..()
|
||||
// Change my name back, don't want to be named Tom (666)
|
||||
name = initial(name)
|
||||
|
||||
/mob/living/simple_animal/mouse/cannot_use_vents()
|
||||
return
|
||||
@@ -1,768 +0,0 @@
|
||||
/* Parrots!
|
||||
* Contains
|
||||
* Defines
|
||||
* Inventory (headset stuff)
|
||||
* Attack responces
|
||||
* AI
|
||||
* Procs / Verbs (usable by players)
|
||||
* Sub-types
|
||||
*/
|
||||
|
||||
/*
|
||||
* Defines
|
||||
*/
|
||||
|
||||
//Parrot is too snowflake for me to rewrite right now, someone should make it use the new
|
||||
//simple_animal movement stuff. -Aro
|
||||
|
||||
//Only a maximum of one action and one intent should be active at any given time.
|
||||
//Actions
|
||||
#define PARROT_PERCH 1 //Sitting/sleeping, not moving
|
||||
#define PARROT_SWOOP 2 //Moving towards or away from a target
|
||||
#define PARROT_WANDER 4 //Moving without a specific target in mind
|
||||
|
||||
//Intents
|
||||
#define PARROT_STEAL 8 //Flying towards a target to steal it/from it
|
||||
#define PARROT_ATTACK 16 //Flying towards a target to attack it
|
||||
#define PARROT_RETURN 32 //Flying towards its perch
|
||||
#define PARROT_FLEE 64 //Flying away from its attacker
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot
|
||||
name = "parrot"
|
||||
desc = "The parrot squawks, \"It's a parrot! BAWWK!\""
|
||||
tt_desc = "E Ara macao"
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
icon_state = "parrot_fly"
|
||||
icon_living = "parrot_fly"
|
||||
icon_dead = "parrot_dead"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
turns_per_move = 5
|
||||
pass_flags = PASSTABLE
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently moves aside"
|
||||
response_harm = "swats"
|
||||
stop_automated_movement = 1
|
||||
universal_speak = 1
|
||||
|
||||
has_langs = list("Bird", "Galactic Common")
|
||||
speak_chance = 2
|
||||
speak = list("Hi","Hello!","Cracker?","Bawk!")
|
||||
speak_emote = list("squawks","says","yells")
|
||||
emote_hear = list("squawks","bawks")
|
||||
emote_see = list("flutters its wings")
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/cracker
|
||||
|
||||
hovering = TRUE
|
||||
softfall = TRUE
|
||||
parachuting = TRUE
|
||||
|
||||
var/parrot_state = PARROT_WANDER //Hunt for a perch when created
|
||||
var/parrot_sleep_max = 25 //The time the parrot sits while perched before looking around. Mosly a way to avoid the parrot's AI in life() being run every single tick.
|
||||
var/parrot_sleep_dur = 25 //Same as above, this is the var that physically counts down
|
||||
var/parrot_dam_zone = list(BP_TORSO, BP_HEAD, BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG) //For humans, select a bodypart to attack
|
||||
|
||||
var/parrot_speed = 5 //"Delay in world ticks between movement." according to byond. Yeah, that's BS but it does directly affect movement. Higher number = slower.
|
||||
var/parrot_been_shot = 0 //Parrots get a speed bonus after being shot. This will deincrement every Life() and at 0 the parrot will return to regular speed.
|
||||
|
||||
var/list/speech_buffer = list()
|
||||
var/list/available_channels = list()
|
||||
|
||||
//Headset for Poly to yell at engineers :)
|
||||
var/obj/item/device/radio/headset/ears = null
|
||||
|
||||
//The thing the parrot is currently interested in. This gets used for items the parrot wants to pick up, mobs it wants to steal from,
|
||||
//mobs it wants to attack or mobs that have attacked it
|
||||
var/atom/movable/parrot_interest = null
|
||||
|
||||
//Parrots will generally sit on their pertch unless something catches their eye.
|
||||
//These vars store their preffered perch and if they dont have one, what they can use as a perch
|
||||
var/obj/parrot_perch = null
|
||||
var/obj/desired_perches = list(/obj/structure/frame, /obj/structure/displaycase, \
|
||||
/obj/structure/filingcabinet, /obj/machinery/teleport, \
|
||||
/obj/machinery/computer, /obj/machinery/clonepod, \
|
||||
/obj/machinery/dna_scannernew, /obj/machinery/telecomms, \
|
||||
/obj/machinery/nuclearbomb, /obj/machinery/particle_accelerator, \
|
||||
/obj/machinery/recharge_station, /obj/machinery/smartfridge, \
|
||||
/obj/machinery/suit_storage_unit)
|
||||
|
||||
//Parrots are kleptomaniacs. This variable ... stores the item a parrot is holding.
|
||||
var/obj/item/held_item = null
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/New()
|
||||
..()
|
||||
if(!ears)
|
||||
var/headset = pick(/obj/item/device/radio/headset/headset_sec, \
|
||||
/obj/item/device/radio/headset/headset_eng, \
|
||||
/obj/item/device/radio/headset/headset_med, \
|
||||
/obj/item/device/radio/headset/headset_sci, \
|
||||
/obj/item/device/radio/headset/headset_cargo)
|
||||
ears = new headset(src)
|
||||
|
||||
parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var
|
||||
|
||||
verbs.Add(/mob/living/simple_animal/parrot/proc/steal_from_ground, \
|
||||
/mob/living/simple_animal/parrot/proc/steal_from_mob, \
|
||||
/mob/living/simple_animal/parrot/verb/drop_held_item_player, \
|
||||
/mob/living/simple_animal/parrot/proc/perch_player)
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/death()
|
||||
if(held_item)
|
||||
held_item.forceMove(src.loc)
|
||||
held_item = null
|
||||
walk(src,0)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/parrot/Stat()
|
||||
..()
|
||||
stat("Held Item", held_item)
|
||||
|
||||
/*
|
||||
* Inventory
|
||||
*/
|
||||
/mob/living/simple_animal/parrot/show_inv(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
if(user.stat) return
|
||||
|
||||
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
if(ears)
|
||||
dat += "<br><b>Headset:</b> [ears] (<a href='?src=\ref[src];remove_inv=ears'>Remove</a>)"
|
||||
else
|
||||
dat += "<br><b>Headset:</b> <a href='?src=\ref[src];add_inv=ears'>Nothing</a>"
|
||||
|
||||
user << browse(dat, text("window=mob[];size=325x500", name))
|
||||
onclose(user, "mob[real_name]")
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/parrot/Topic(href, href_list)
|
||||
|
||||
//Can the usr physically do this?
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
return
|
||||
|
||||
//Is the usr's mob type able to do this?
|
||||
if(ishuman(usr) || issmall(usr) || isrobot(usr))
|
||||
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
var/remove_from = href_list["remove_inv"]
|
||||
switch(remove_from)
|
||||
if("ears")
|
||||
if(ears)
|
||||
if(available_channels.len)
|
||||
src.say("[pick(available_channels)] BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
else
|
||||
src.say("BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
ears.forceMove(src.loc)
|
||||
ears = null
|
||||
for(var/possible_phrase in speak)
|
||||
if(copytext(possible_phrase,1,3) in department_radio_keys)
|
||||
possible_phrase = copytext(possible_phrase,3,length(possible_phrase))
|
||||
else
|
||||
to_chat(usr, "<font color='red'>There is nothing to remove from its [remove_from].</font>")
|
||||
return
|
||||
|
||||
//Adding things to inventory
|
||||
else if(href_list["add_inv"])
|
||||
var/add_to = href_list["add_inv"]
|
||||
if(!usr.get_active_hand())
|
||||
to_chat(usr, "<font color='red'>You have nothing in your hand to put on its [add_to].</font>")
|
||||
return
|
||||
switch(add_to)
|
||||
if("ears")
|
||||
if(ears)
|
||||
to_chat(usr, "<font color='red'>It's already wearing something.</font>")
|
||||
return
|
||||
else
|
||||
var/obj/item/item_to_add = usr.get_active_hand()
|
||||
if(!item_to_add)
|
||||
return
|
||||
|
||||
if( !istype(item_to_add, /obj/item/device/radio/headset) )
|
||||
to_chat(usr, "<font color='red'>This object won't fit.</font>")
|
||||
return
|
||||
|
||||
var/obj/item/device/radio/headset/headset_to_add = item_to_add
|
||||
|
||||
usr.drop_item()
|
||||
headset_to_add.forceMove(src)
|
||||
src.ears = headset_to_add
|
||||
to_chat(usr, "You fit the headset onto [src].")
|
||||
|
||||
clearlist(available_channels)
|
||||
for(var/ch in headset_to_add.channels)
|
||||
switch(ch)
|
||||
if("Engineering")
|
||||
available_channels.Add(":e")
|
||||
if("Command")
|
||||
available_channels.Add(":c")
|
||||
if("Security")
|
||||
available_channels.Add(":s")
|
||||
if("Science")
|
||||
available_channels.Add(":n")
|
||||
if("Medical")
|
||||
available_channels.Add(":m")
|
||||
if("Mining")
|
||||
available_channels.Add(":d")
|
||||
if("Cargo")
|
||||
available_channels.Add(":q")
|
||||
|
||||
if(headset_to_add.translate_binary)
|
||||
available_channels.Add("#b")
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/*
|
||||
* Attack responces
|
||||
*/
|
||||
//Humans, monkeys, aliens
|
||||
/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M as mob)
|
||||
..()
|
||||
if(client) return
|
||||
if(!stat && M.a_intent == I_HURT)
|
||||
|
||||
icon_state = "parrot_fly" //It is going to be flying regardless of whether it flees or attacks
|
||||
|
||||
if(parrot_state == PARROT_PERCH)
|
||||
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
|
||||
|
||||
parrot_interest = M
|
||||
parrot_state = PARROT_SWOOP //The parrot just got hit, it WILL move, now to pick a direction..
|
||||
|
||||
if(M.health < 50) //Weakened mob? Fight back!
|
||||
parrot_state |= PARROT_ATTACK
|
||||
else
|
||||
parrot_state |= PARROT_FLEE //Otherwise, fly like a bat out of hell!
|
||||
drop_held_item(0)
|
||||
return
|
||||
|
||||
//Mobs with objects
|
||||
/mob/living/simple_animal/parrot/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
..()
|
||||
if(!stat && !client && !istype(O, /obj/item/stack/medical))
|
||||
if(O.force)
|
||||
if(parrot_state == PARROT_PERCH)
|
||||
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
|
||||
|
||||
parrot_interest = user
|
||||
parrot_state = PARROT_SWOOP | PARROT_FLEE
|
||||
icon_state = "parrot_fly"
|
||||
drop_held_item(0)
|
||||
return
|
||||
|
||||
//Bullets
|
||||
/mob/living/simple_animal/parrot/bullet_act(var/obj/item/projectile/Proj)
|
||||
..()
|
||||
if(!stat && !client)
|
||||
if(parrot_state == PARROT_PERCH)
|
||||
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
|
||||
|
||||
parrot_interest = null
|
||||
parrot_state = PARROT_WANDER //OWFUCK, Been shot! RUN LIKE HELL!
|
||||
parrot_been_shot += 5
|
||||
icon_state = "parrot_fly"
|
||||
drop_held_item(0)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* AI - Not really intelligent, but I'm calling it AI anyway.
|
||||
*/
|
||||
/mob/living/simple_animal/parrot/Life()
|
||||
..()
|
||||
|
||||
//Sprite and AI update for when a parrot gets pulled
|
||||
if(pulledby && stat == CONSCIOUS)
|
||||
icon_state = "parrot_fly"
|
||||
if(!client)
|
||||
parrot_state = PARROT_WANDER
|
||||
return
|
||||
|
||||
if(client || stat)
|
||||
return //Lets not force players or dead/incap parrots to move
|
||||
|
||||
if(!isturf(src.loc) || !canmove || buckled)
|
||||
return //If it can't move, dont let it move. (The buckled check probably isn't necessary thanks to canmove)
|
||||
|
||||
|
||||
//-----SPEECH
|
||||
/* Parrot speech mimickry!
|
||||
Phrases that the parrot hears in mob/living/say() get added to speach_buffer.
|
||||
Every once in a while, the parrot picks one of the lines from the buffer and replaces an element of the 'speech' list.
|
||||
Then it clears the buffer to make sure they dont magically remember something from hours ago. */
|
||||
if(speech_buffer.len && prob(10))
|
||||
if(speak.len)
|
||||
speak.Remove(pick(speak))
|
||||
|
||||
speak.Add(pick(speech_buffer))
|
||||
clearlist(speech_buffer)
|
||||
|
||||
|
||||
//-----SLEEPING
|
||||
if(parrot_state == PARROT_PERCH)
|
||||
if(parrot_perch && parrot_perch.loc != src.loc) //Make sure someone hasnt moved our perch on us
|
||||
if(parrot_perch in view(src))
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
icon_state = "parrot_fly"
|
||||
return
|
||||
else
|
||||
parrot_state = PARROT_WANDER
|
||||
icon_state = "parrot_fly"
|
||||
return
|
||||
|
||||
if(--parrot_sleep_dur) //Zzz
|
||||
return
|
||||
|
||||
else
|
||||
//This way we only call the stuff below once every [sleep_max] ticks.
|
||||
parrot_sleep_dur = parrot_sleep_max
|
||||
|
||||
//Cycle through message modes for the headset
|
||||
if(speak.len)
|
||||
var/list/newspeak = list()
|
||||
|
||||
if(available_channels.len && src.ears)
|
||||
for(var/possible_phrase in speak)
|
||||
|
||||
//50/50 chance to not use the radio at all
|
||||
var/useradio = 0
|
||||
if(prob(50))
|
||||
useradio = 1
|
||||
|
||||
if(copytext(possible_phrase,1,3) in department_radio_keys)
|
||||
possible_phrase = "[useradio?pick(available_channels):""] [copytext(possible_phrase,3,length(possible_phrase)+1)]" //crop out the channel prefix
|
||||
else
|
||||
possible_phrase = "[useradio?pick(available_channels):""] [possible_phrase]"
|
||||
|
||||
newspeak.Add(possible_phrase)
|
||||
|
||||
else //If we have no headset or channels to use, dont try to use any!
|
||||
for(var/possible_phrase in speak)
|
||||
if(copytext(possible_phrase,1,3) in department_radio_keys)
|
||||
possible_phrase = "[copytext(possible_phrase,3,length(possible_phrase)+1)]" //crop out the channel prefix
|
||||
newspeak.Add(possible_phrase)
|
||||
speak = newspeak
|
||||
|
||||
//Search for item to steal
|
||||
parrot_interest = search_for_item()
|
||||
if(parrot_interest)
|
||||
visible_emote("looks in [parrot_interest]'s direction and takes flight")
|
||||
parrot_state = PARROT_SWOOP | PARROT_STEAL
|
||||
icon_state = "parrot_fly"
|
||||
return
|
||||
|
||||
//-----WANDERING - This is basically a 'I dont know what to do yet' state
|
||||
else if(parrot_state == PARROT_WANDER)
|
||||
//Stop movement, we'll set it later
|
||||
walk(src, 0)
|
||||
parrot_interest = null
|
||||
|
||||
//Wander around aimlessly. This will help keep the loops from searches down
|
||||
//and possibly move the mob into a new are in view of something they can use
|
||||
if(prob(90))
|
||||
step(src, pick(cardinal))
|
||||
return
|
||||
|
||||
if(!held_item && !parrot_perch) //If we've got nothing to do.. look for something to do.
|
||||
var/atom/movable/AM = search_for_perch_and_item() //This handles checking through lists so we know it's either a perch or stealable item
|
||||
if(AM)
|
||||
if(istype(AM, /obj/item) || isliving(AM)) //If stealable item
|
||||
parrot_interest = AM
|
||||
visible_emote("turns and flies towards [parrot_interest]")
|
||||
parrot_state = PARROT_SWOOP | PARROT_STEAL
|
||||
return
|
||||
else //Else it's a perch
|
||||
parrot_perch = AM
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
return
|
||||
return
|
||||
|
||||
if(parrot_interest && parrot_interest in view(src))
|
||||
parrot_state = PARROT_SWOOP | PARROT_STEAL
|
||||
return
|
||||
|
||||
if(parrot_perch && parrot_perch in view(src))
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
return
|
||||
|
||||
else //Have an item but no perch? Find one!
|
||||
parrot_perch = search_for_perch()
|
||||
if(parrot_perch)
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
return
|
||||
//-----STEALING
|
||||
else if(parrot_state == (PARROT_SWOOP | PARROT_STEAL))
|
||||
walk(src,0)
|
||||
if(!parrot_interest || held_item)
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
return
|
||||
|
||||
if(!(parrot_interest in view(src)))
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
return
|
||||
|
||||
if(in_range(src, parrot_interest))
|
||||
|
||||
if(isliving(parrot_interest))
|
||||
steal_from_mob()
|
||||
|
||||
else //This should ensure that we only grab the item we want, and make sure it's not already collected on our perch
|
||||
if(!parrot_perch || parrot_interest.loc != parrot_perch.loc)
|
||||
held_item = parrot_interest
|
||||
parrot_interest.forceMove(src)
|
||||
visible_message("[src] grabs the [held_item]!", "<font color='blue'>You grab the [held_item]!</font>", "You hear the sounds of wings flapping furiously.")
|
||||
|
||||
parrot_interest = null
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
return
|
||||
|
||||
walk_to(src, parrot_interest, 1, parrot_speed)
|
||||
return
|
||||
|
||||
//-----RETURNING TO PERCH
|
||||
else if(parrot_state == (PARROT_SWOOP | PARROT_RETURN))
|
||||
walk(src, 0)
|
||||
if(!parrot_perch || !isturf(parrot_perch.loc)) //Make sure the perch exists and somehow isnt inside of something else.
|
||||
parrot_perch = null
|
||||
parrot_state = PARROT_WANDER
|
||||
return
|
||||
|
||||
if(in_range(src, parrot_perch))
|
||||
src.forceMove(parrot_perch.loc)
|
||||
drop_held_item()
|
||||
parrot_state = PARROT_PERCH
|
||||
icon_state = "parrot_sit"
|
||||
return
|
||||
|
||||
walk_to(src, parrot_perch, 1, parrot_speed)
|
||||
return
|
||||
|
||||
//-----FLEEING
|
||||
else if(parrot_state == (PARROT_SWOOP | PARROT_FLEE))
|
||||
walk(src,0)
|
||||
if(!parrot_interest || !isliving(parrot_interest)) //Sanity
|
||||
parrot_state = PARROT_WANDER
|
||||
|
||||
walk_away(src, parrot_interest, 1, parrot_speed-parrot_been_shot)
|
||||
parrot_been_shot--
|
||||
return
|
||||
|
||||
//-----ATTACKING
|
||||
else if(parrot_state == (PARROT_SWOOP | PARROT_ATTACK))
|
||||
|
||||
//If we're attacking a nothing, an object, a turf or a ghost for some stupid reason, switch to wander
|
||||
if(!parrot_interest || !isliving(parrot_interest))
|
||||
parrot_interest = null
|
||||
parrot_state = PARROT_WANDER
|
||||
return
|
||||
|
||||
var/mob/living/L = parrot_interest
|
||||
|
||||
//If the mob is close enough to interact with
|
||||
if(in_range(src, parrot_interest))
|
||||
|
||||
//If the mob we've been chasing/attacking dies or falls into crit, check for loot!
|
||||
if(L.stat)
|
||||
parrot_interest = null
|
||||
if(!held_item)
|
||||
held_item = steal_from_ground()
|
||||
if(!held_item)
|
||||
held_item = steal_from_mob() //Apparently it's possible for dead mobs to hang onto items in certain circumstances.
|
||||
if(parrot_perch in view(src)) //If we have a home nearby, go to it, otherwise find a new home
|
||||
parrot_state = PARROT_SWOOP | PARROT_RETURN
|
||||
else
|
||||
parrot_state = PARROT_WANDER
|
||||
return
|
||||
|
||||
//Time for the hurt to begin!
|
||||
var/damage = rand(5,10)
|
||||
|
||||
if(ishuman(parrot_interest))
|
||||
var/mob/living/carbon/human/H = parrot_interest
|
||||
var/obj/item/organ/external/affecting = H.get_organ(ran_zone(pick(parrot_dam_zone)))
|
||||
|
||||
H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee"), H.get_armor_soak(affecting, "melee"), sharp=1)
|
||||
visible_emote(pick("pecks [H]'s [affecting].", "cuts [H]'s [affecting] with its talons."))
|
||||
|
||||
else
|
||||
L.adjustBruteLoss(damage)
|
||||
visible_emote(pick("pecks at [L].", "claws [L]."))
|
||||
return
|
||||
|
||||
//Otherwise, fly towards the mob!
|
||||
else
|
||||
walk_to(src, parrot_interest, 1, parrot_speed)
|
||||
return
|
||||
//-----STATE MISHAP
|
||||
else //This should not happen. If it does lets reset everything and try again
|
||||
walk(src,0)
|
||||
parrot_interest = null
|
||||
parrot_perch = null
|
||||
drop_held_item()
|
||||
parrot_state = PARROT_WANDER
|
||||
return
|
||||
|
||||
/*
|
||||
* Procs
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/parrot/movement_delay()
|
||||
if(client && stat == CONSCIOUS && parrot_state != "parrot_fly")
|
||||
icon_state = "parrot_fly"
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/parrot/proc/search_for_item()
|
||||
for(var/atom/movable/AM in view(src))
|
||||
//Skip items we already stole or are wearing or are too big
|
||||
if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src)
|
||||
continue
|
||||
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(I.w_class < ITEMSIZE_SMALL)
|
||||
return I
|
||||
|
||||
if(iscarbon(AM))
|
||||
var/mob/living/carbon/C = AM
|
||||
if((C.l_hand && C.l_hand.w_class <= ITEMSIZE_SMALL) || (C.r_hand && C.r_hand.w_class <= ITEMSIZE_SMALL))
|
||||
return C
|
||||
return null
|
||||
|
||||
/mob/living/simple_animal/parrot/proc/search_for_perch()
|
||||
for(var/obj/O in view(src))
|
||||
for(var/path in desired_perches)
|
||||
if(istype(O, path))
|
||||
return O
|
||||
return null
|
||||
|
||||
//This proc was made to save on doing two 'in view' loops seperatly
|
||||
/mob/living/simple_animal/parrot/proc/search_for_perch_and_item()
|
||||
for(var/atom/movable/AM in view(src))
|
||||
for(var/perch_path in desired_perches)
|
||||
if(istype(AM, perch_path))
|
||||
return AM
|
||||
|
||||
//Skip items we already stole or are wearing or are too big
|
||||
if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src)
|
||||
continue
|
||||
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(I.w_class <= ITEMSIZE_SMALL)
|
||||
return I
|
||||
|
||||
if(iscarbon(AM))
|
||||
var/mob/living/carbon/C = AM
|
||||
if(C.l_hand && C.l_hand.w_class <= ITEMSIZE_SMALL || C.r_hand && C.r_hand.w_class <= ITEMSIZE_SMALL)
|
||||
return C
|
||||
return null
|
||||
|
||||
|
||||
/*
|
||||
* Verbs - These are actually procs, but can be used as verbs by player-controlled parrots.
|
||||
*/
|
||||
/mob/living/simple_animal/parrot/proc/steal_from_ground()
|
||||
set name = "Steal from ground"
|
||||
set category = "Parrot"
|
||||
set desc = "Grabs a nearby item."
|
||||
|
||||
if(stat)
|
||||
return -1
|
||||
|
||||
if(held_item)
|
||||
to_chat(src, "<font color='red'>You are already holding the [held_item]</font>")
|
||||
return 1
|
||||
|
||||
for(var/obj/item/I in view(1,src))
|
||||
//Make sure we're not already holding it and it's small enough
|
||||
if(I.loc != src && I.w_class <= ITEMSIZE_SMALL)
|
||||
|
||||
//If we have a perch and the item is sitting on it, continue
|
||||
if(!client && parrot_perch && I.loc == parrot_perch.loc)
|
||||
continue
|
||||
|
||||
held_item = I
|
||||
I.forceMove(src)
|
||||
visible_message("[src] grabs the [held_item]!", "<font color='blue'>You grab the [held_item]!</font>", "You hear the sounds of wings flapping furiously.")
|
||||
return held_item
|
||||
|
||||
to_chat(src, "<font color='red'>There is nothing of interest to take.</font>")
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/parrot/proc/steal_from_mob()
|
||||
set name = "Steal from mob"
|
||||
set category = "Parrot"
|
||||
set desc = "Steals an item right out of a person's hand!"
|
||||
|
||||
if(stat)
|
||||
return -1
|
||||
|
||||
if(held_item)
|
||||
to_chat(src, "<font color='red'>You are already holding the [held_item]</font>")
|
||||
return 1
|
||||
|
||||
var/obj/item/stolen_item = null
|
||||
|
||||
for(var/mob/living/carbon/C in view(1,src))
|
||||
if(C.l_hand && C.l_hand.w_class <= ITEMSIZE_SMALL)
|
||||
stolen_item = C.l_hand
|
||||
|
||||
if(C.r_hand && C.r_hand.w_class <= ITEMSIZE_SMALL)
|
||||
stolen_item = C.r_hand
|
||||
|
||||
if(stolen_item)
|
||||
C.remove_from_mob(stolen_item)
|
||||
held_item = stolen_item
|
||||
stolen_item.forceMove(src)
|
||||
visible_message("[src] grabs the [held_item] out of [C]'s hand!", "<font color='blue'>You snag the [held_item] out of [C]'s hand!</font>", "You hear the sounds of wings flapping furiously.")
|
||||
return held_item
|
||||
|
||||
to_chat(src, "<font color='red'>There is nothing of interest to take.</font>")
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/parrot/verb/drop_held_item_player()
|
||||
set name = "Drop held item"
|
||||
set category = "Parrot"
|
||||
set desc = "Drop the item you're holding."
|
||||
|
||||
if(stat)
|
||||
return
|
||||
|
||||
src.drop_held_item()
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/parrot/proc/drop_held_item(var/drop_gently = 1)
|
||||
set name = "Drop held item"
|
||||
set category = "Parrot"
|
||||
set desc = "Drop the item you're holding."
|
||||
|
||||
if(stat)
|
||||
return -1
|
||||
|
||||
if(!held_item)
|
||||
to_chat(usr, "<font color='red'>You have nothing to drop!</font>")
|
||||
return 0
|
||||
|
||||
if(!drop_gently)
|
||||
if(istype(held_item, /obj/item/weapon/grenade))
|
||||
var/obj/item/weapon/grenade/G = held_item
|
||||
G.forceMove(src.loc)
|
||||
G.detonate()
|
||||
to_chat(src, "You let go of the [held_item]!")
|
||||
held_item = null
|
||||
return 1
|
||||
|
||||
to_chat(src, "You drop the [held_item].")
|
||||
|
||||
held_item.forceMove(src.loc)
|
||||
held_item = null
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/parrot/proc/perch_player()
|
||||
set name = "Sit"
|
||||
set category = "Parrot"
|
||||
set desc = "Sit on a nice comfy perch."
|
||||
|
||||
if(stat || !client)
|
||||
return
|
||||
|
||||
if(icon_state == "parrot_fly")
|
||||
for(var/atom/movable/AM in view(src,1))
|
||||
for(var/perch_path in desired_perches)
|
||||
if(istype(AM, perch_path))
|
||||
src.forceMove(AM.loc)
|
||||
icon_state = "parrot_sit"
|
||||
return
|
||||
to_chat(src, "<font color='red'>There is no perch nearby to sit on.</font>")
|
||||
return
|
||||
|
||||
/*
|
||||
* Sub-types
|
||||
*/
|
||||
/mob/living/simple_animal/parrot/Poly
|
||||
name = "Poly"
|
||||
desc = "Poly the Parrot. An expert on quantum cracker theory."
|
||||
speak = list("Poly wanna cracker!", ":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS FREE CALL THE SHUTTLE")
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/New()
|
||||
ears = new /obj/item/device/radio/headset/headset_eng(src)
|
||||
available_channels = list(":e")
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/parrot/say(var/message)
|
||||
|
||||
if(stat)
|
||||
return
|
||||
|
||||
var/verb = "says"
|
||||
if(speak_emote.len)
|
||||
verb = pick(speak_emote)
|
||||
|
||||
|
||||
var/message_mode=""
|
||||
if(copytext(message,1,2) == ";")
|
||||
message_mode = "headset"
|
||||
message = copytext(message,2)
|
||||
|
||||
if(length(message) >= 2)
|
||||
var/channel_prefix = copytext(message, 1 ,3)
|
||||
message_mode = department_radio_keys[channel_prefix]
|
||||
|
||||
if(copytext(message,1,2) == ":")
|
||||
var/positioncut = 3
|
||||
message = trim(copytext(message,positioncut))
|
||||
|
||||
message = capitalize(trim_left(message))
|
||||
|
||||
if(message_mode)
|
||||
if(message_mode in radiochannels)
|
||||
if(ears && istype(ears,/obj/item/device/radio))
|
||||
ears.talk_into(src,sanitize(message), message_mode, verb, null)
|
||||
|
||||
|
||||
..(message)
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null)
|
||||
if(prob(50))
|
||||
parrot_hear(message)
|
||||
..(message,verb,language,alt_name,italics,speaker)
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0)
|
||||
if(prob(50))
|
||||
parrot_hear("[pick(available_channels)] [message]")
|
||||
..(message,verb,language,part_a,part_b,speaker,hard_to_hear)
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/proc/parrot_hear(var/message="")
|
||||
if(!message || stat)
|
||||
return
|
||||
speech_buffer.Add(message)
|
||||
|
||||
/mob/living/simple_animal/parrot/attack_generic(var/mob/user, var/damage, var/attack_message)
|
||||
|
||||
var/success = ..()
|
||||
|
||||
if(client)
|
||||
return success
|
||||
|
||||
if(parrot_state == PARROT_PERCH)
|
||||
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
|
||||
|
||||
if(!success)
|
||||
return 0
|
||||
|
||||
parrot_interest = user
|
||||
parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless
|
||||
icon_state = "parrot_fly"
|
||||
return success
|
||||
@@ -1,27 +0,0 @@
|
||||
/mob/living/simple_animal/penguin
|
||||
name = "space penguin"
|
||||
desc = "An ungainly, waddling, cute, and VERY well-dressed bird."
|
||||
tt_desc = "E Aptenodytes forsteri"
|
||||
icon_state = "penguin"
|
||||
icon_living = "penguin"
|
||||
icon_dead = "penguin_dead"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
|
||||
turns_per_move = 5
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "pushes aside"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
attacktext = list("pecked")
|
||||
|
||||
has_langs = list("Bird")
|
||||
speak_chance = 0
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
@@ -1,29 +0,0 @@
|
||||
/mob/living/simple_animal/retaliate/diyaab
|
||||
name = "diyaab"
|
||||
desc = "A small pack animal. Although omnivorous, it will hunt meat on occasion."
|
||||
tt_desc = "S Choeros hirtus" //diyaab and shantak are technically reletives!
|
||||
faction = "diyaab"
|
||||
icon_state = "diyaab"
|
||||
icon_living = "diyaab"
|
||||
icon_dead = "diyaab_dead"
|
||||
icon = 'icons/jungle.dmi'
|
||||
|
||||
faction = "diyaab"
|
||||
cooperative = 1
|
||||
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
speed = 1
|
||||
move_to_delay = 1
|
||||
|
||||
melee_damage_lower = 4
|
||||
melee_damage_upper = 12
|
||||
attack_sharp = 1 //Bleeds, but it shouldn't rip off a limb?
|
||||
|
||||
attacktext = list("gouged")
|
||||
cold_damage_per_tick = 0
|
||||
|
||||
speak_chance = 5
|
||||
speak = list("Awrr?","Aowrl!","Worrl")
|
||||
emote_see = list("sniffs the air cautiously","looks around")
|
||||
emote_hear = list("snuffles")
|
||||
@@ -1,36 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/savik
|
||||
name = "savik"
|
||||
desc = "A fast, armoured predator accustomed to hiding and ambushing in cold terrain."
|
||||
tt_desc = "S Pistris tellus" //landshark
|
||||
faction = "savik"
|
||||
icon_state = "savik"
|
||||
icon_living = "savik"
|
||||
icon_dead = "savik_dead"
|
||||
icon = 'icons/jungle.dmi'
|
||||
|
||||
faction = "savik"
|
||||
|
||||
maxHealth = 125
|
||||
health = 125
|
||||
speed = 2
|
||||
move_to_delay = 2
|
||||
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 35
|
||||
attack_armor_pen = 15
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
attacktext = list("mauled")
|
||||
cold_damage_per_tick = 0
|
||||
|
||||
speak_chance = 5
|
||||
speak = list("Hruuugh!","Hrunnph")
|
||||
emote_see = list("paws the ground","shakes its mane","stomps")
|
||||
emote_hear = list("snuffles")
|
||||
|
||||
/mob/living/simple_animal/hostile/savik/handle_stance(var/new_stance)
|
||||
..(new_stance)
|
||||
if(stance == STANCE_ATTACK || stance == STANCE_ATTACKING)
|
||||
if((health / maxHealth) <= 0.5) // At half health, and fighting someone currently.
|
||||
add_modifier(/datum/modifier/berserk, 30 SECONDS)
|
||||
@@ -1,29 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/shantak
|
||||
name = "shantak"
|
||||
desc = "A piglike creature with a bright iridiscent mane that sparkles as though lit by an inner light. Don't be fooled by its beauty though."
|
||||
tt_desc = "S Choeros shantak"
|
||||
faction = "shantak"
|
||||
icon_state = "shantak"
|
||||
icon_living = "shantak"
|
||||
icon_dead = "shantak_dead"
|
||||
icon = 'icons/jungle.dmi'
|
||||
|
||||
faction = "shantak"
|
||||
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
speed = 1
|
||||
move_to_delay = 1
|
||||
|
||||
melee_damage_lower = 12
|
||||
melee_damage_upper = 28
|
||||
attack_armor_pen = 5
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
attacktext = list("gouged")
|
||||
cold_damage_per_tick = 0
|
||||
|
||||
speak_chance = 5
|
||||
speak = list("Shuhn","Shrunnph?","Shunpf")
|
||||
emote_see = list("scratches the ground","shakes out its mane","clinks gently as it moves")
|
||||
@@ -1,70 +0,0 @@
|
||||
/mob/living/simple_animal/slime
|
||||
name = "pet slime"
|
||||
desc = "A lovable, domesticated slime."
|
||||
tt_desc = "Amorphidae proteus"
|
||||
icon = 'icons/mob/slimes.dmi'
|
||||
icon_state = "grey baby slime"
|
||||
icon_living = "grey baby slime"
|
||||
icon_dead = "grey baby slime dead"
|
||||
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "shoos"
|
||||
response_harm = "stomps on"
|
||||
|
||||
speak_chance = 1
|
||||
speak_emote = list("chirps")
|
||||
emote_see = list("jiggles", "bounces in place")
|
||||
|
||||
var/colour = "grey"
|
||||
|
||||
/mob/living/simple_animal/slime/science
|
||||
name = "Kendrick"
|
||||
colour = "rainbow"
|
||||
icon_state = "rainbow baby slime"
|
||||
icon_living = "rainbow baby slime"
|
||||
icon_dead = "rainbow baby slime dead"
|
||||
|
||||
/mob/living/simple_animal/slime/science/Initialize()
|
||||
. = ..()
|
||||
overlays.Cut()
|
||||
overlays += "aslime-:33"
|
||||
|
||||
/mob/living/simple_animal/adultslime
|
||||
name = "pet slime"
|
||||
desc = "A lovable, domesticated slime."
|
||||
icon = 'icons/mob/slimes.dmi'
|
||||
icon_state = "grey adult slime"
|
||||
icon_living = "grey adult slime"
|
||||
icon_dead = "grey baby slime dead"
|
||||
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "shoos"
|
||||
response_harm = "stomps on"
|
||||
|
||||
speak_chance = 1
|
||||
emote_see = list("jiggles", "bounces in place")
|
||||
|
||||
var/colour = "grey"
|
||||
|
||||
/mob/living/simple_animal/adultslime/New()
|
||||
..()
|
||||
overlays += "aslime-:33"
|
||||
|
||||
/mob/living/simple_animal/adultslime/death()
|
||||
var/mob/living/simple_animal/slime/S1 = new /mob/living/simple_animal/slime (src.loc)
|
||||
S1.icon_state = "[src.colour] baby slime"
|
||||
S1.icon_living = "[src.colour] baby slime"
|
||||
S1.icon_dead = "[src.colour] baby slime dead"
|
||||
S1.colour = "[src.colour]"
|
||||
var/mob/living/simple_animal/slime/S2 = new /mob/living/simple_animal/slime (src.loc)
|
||||
S2.icon_state = "[src.colour] baby slime"
|
||||
S2.icon_living = "[src.colour] baby slime"
|
||||
S2.icon_dead = "[src.colour] baby slime dead"
|
||||
S2.colour = "[src.colour]"
|
||||
qdel(src)
|
||||
@@ -1,302 +0,0 @@
|
||||
/mob/living/simple_animal/spiderbot
|
||||
name = "spider-bot"
|
||||
desc = "A skittering robotic friend!"
|
||||
tt_desc = "Maintenance Robot"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "spiderbot-chassis"
|
||||
icon_living = "spiderbot-chassis"
|
||||
icon_dead = "spiderbot-smashed"
|
||||
intelligence_level = SA_HUMANOID // Because its piloted by players.
|
||||
|
||||
health = 10
|
||||
maxHealth = 10
|
||||
|
||||
wander = 0
|
||||
speed = -1 //Spiderbots gotta go fast.
|
||||
pass_flags = PASSTABLE
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "shoos"
|
||||
response_harm = "stomps on"
|
||||
|
||||
melee_damage_lower = 1
|
||||
melee_damage_upper = 3
|
||||
attacktext = list("shocked")
|
||||
|
||||
min_oxy = 0
|
||||
max_tox = 0
|
||||
max_co2 = 0
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 500
|
||||
|
||||
speak_chance = 1
|
||||
speak_emote = list("beeps","clicks","chirps")
|
||||
|
||||
var/obj/item/device/radio/borg/radio = null
|
||||
var/mob/living/silicon/ai/connected_ai = null
|
||||
var/obj/item/weapon/cell/cell = null
|
||||
var/obj/machinery/camera/camera = null
|
||||
var/obj/item/device/mmi/mmi = null
|
||||
var/list/req_access = list(access_robotics) //Access needed to pop out the brain.
|
||||
var/positronic
|
||||
|
||||
can_enter_vent_with = list(
|
||||
/obj/item/weapon/implant,
|
||||
/obj/item/device/radio/borg,
|
||||
/obj/item/weapon/holder,
|
||||
/obj/machinery/camera,
|
||||
/mob/living/simple_mob/animal/borer,
|
||||
/obj/item/device/mmi,
|
||||
)
|
||||
|
||||
var/emagged = 0
|
||||
var/obj/item/held_item = null //Storage for single item they can hold.
|
||||
|
||||
/mob/living/simple_animal/spiderbot/New()
|
||||
..()
|
||||
add_language(LANGUAGE_GALCOM)
|
||||
default_language = all_languages[LANGUAGE_GALCOM]
|
||||
verbs |= /mob/living/proc/ventcrawl
|
||||
verbs |= /mob/living/proc/hide
|
||||
|
||||
/mob/living/simple_animal/spiderbot/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
|
||||
if(istype(O, /obj/item/device/mmi))
|
||||
var/obj/item/device/mmi/B = O
|
||||
if(src.mmi)
|
||||
user << "<span class='warning'>There's already a brain in [src]!</span>"
|
||||
return
|
||||
if(!B.brainmob)
|
||||
user << "<span class='warning'>Sticking an empty MMI into the frame would sort of defeat the purpose.</span>"
|
||||
return
|
||||
if(!B.brainmob.key)
|
||||
var/ghost_can_reenter = 0
|
||||
if(B.brainmob.mind)
|
||||
for(var/mob/observer/dead/G in player_list)
|
||||
if(G.can_reenter_corpse && G.mind == B.brainmob.mind)
|
||||
ghost_can_reenter = 1
|
||||
break
|
||||
if(!ghost_can_reenter)
|
||||
user << "<span class='notice'>[O] is completely unresponsive; there's no point.</span>"
|
||||
return
|
||||
|
||||
if(B.brainmob.stat == DEAD)
|
||||
user << "<span class='warning'>[O] is dead. Sticking it into the frame would sort of defeat the purpose.</span>"
|
||||
return
|
||||
|
||||
if(jobban_isbanned(B.brainmob, "Cyborg"))
|
||||
user << "<span class='warning'>\The [O] does not seem to fit.</span>"
|
||||
return
|
||||
|
||||
user << "<span class='notice'>You install \the [O] in \the [src]!</span>"
|
||||
|
||||
if(istype(O, /obj/item/device/mmi/digital))
|
||||
positronic = 1
|
||||
add_language("Robot Talk")
|
||||
|
||||
user.drop_item()
|
||||
src.mmi = O
|
||||
src.transfer_personality(O)
|
||||
|
||||
O.forceMove(src)
|
||||
src.update_icon()
|
||||
return 1
|
||||
|
||||
if (istype(O, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = O
|
||||
if (WT.remove_fuel(0))
|
||||
if(health < getMaxHealth())
|
||||
health += pick(1,1,1,2,2,3)
|
||||
if(health > getMaxHealth())
|
||||
health = getMaxHealth()
|
||||
add_fingerprint(user)
|
||||
src.visible_message("<span class='notice'>\The [user] has spot-welded some of the damage to \the [src]!</span>")
|
||||
else
|
||||
user << "<span class='warning'>\The [src] is undamaged!</span>"
|
||||
else
|
||||
user << "<span class='danger'>You need more welding fuel for this task!</span>"
|
||||
return
|
||||
else if(istype(O, /obj/item/weapon/card/id)||istype(O, /obj/item/device/pda))
|
||||
if (!mmi)
|
||||
user << "<span class='danger'>There's no reason to swipe your ID - \the [src] has no brain to remove.</span>"
|
||||
return 0
|
||||
|
||||
var/obj/item/weapon/card/id/id_card
|
||||
|
||||
if(istype(O, /obj/item/weapon/card/id))
|
||||
id_card = O
|
||||
else
|
||||
var/obj/item/device/pda/pda = O
|
||||
id_card = pda.id
|
||||
|
||||
if(access_robotics in id_card.access)
|
||||
user << "<span class='notice'>You swipe your access card and pop the brain out of \the [src].</span>"
|
||||
eject_brain()
|
||||
if(held_item)
|
||||
held_item.forceMove(src.loc)
|
||||
held_item = null
|
||||
return 1
|
||||
else
|
||||
user << "<span class='danger'>You swipe your card with no effect.</span>"
|
||||
return 0
|
||||
|
||||
else
|
||||
O.attack(src, user, user.zone_sel.selecting)
|
||||
|
||||
/mob/living/simple_animal/spiderbot/emag_act(var/remaining_charges, var/mob/user)
|
||||
if (emagged)
|
||||
user << "<span class='warning'>[src] is already overloaded - better run.</span>"
|
||||
return 0
|
||||
else
|
||||
user << "<span class='notice'>You short out the security protocols and overload [src]'s cell, priming it to explode in a short time.</span>"
|
||||
spawn(100)
|
||||
to_chat(src, "<span class='danger'>Your cell seems to be outputting a lot of power...</span>")
|
||||
spawn(200)
|
||||
to_chat(src, "<span class='danger'>Internal heat sensors are spiking! Something is badly wrong with your cell!</span>")
|
||||
spawn(300) src.explode()
|
||||
|
||||
/mob/living/simple_animal/spiderbot/proc/transfer_personality(var/obj/item/device/mmi/M as obj)
|
||||
|
||||
src.mind = M.brainmob.mind
|
||||
src.mind.key = M.brainmob.key
|
||||
src.ckey = M.brainmob.ckey
|
||||
src.name = "spider-bot ([M.brainmob.name])"
|
||||
src.languages = M.brainmob.languages
|
||||
|
||||
/mob/living/simple_animal/spiderbot/proc/explode() //When emagged.
|
||||
src.visible_message("<span class='danger'>\The [src] makes an odd warbling noise, fizzles, and explodes!</span>")
|
||||
explosion(get_turf(loc), -1, -1, 3, 5)
|
||||
eject_brain()
|
||||
death()
|
||||
|
||||
/mob/living/simple_animal/spiderbot/update_icon()
|
||||
if(mmi)
|
||||
if(positronic)
|
||||
icon_state = "spiderbot-chassis-posi"
|
||||
icon_living = "spiderbot-chassis-posi"
|
||||
else
|
||||
icon_state = "spiderbot-chassis-mmi"
|
||||
icon_living = "spiderbot-chassis-mmi"
|
||||
else
|
||||
icon_state = "spiderbot-chassis"
|
||||
icon_living = "spiderbot-chassis"
|
||||
|
||||
/mob/living/simple_animal/spiderbot/proc/eject_brain()
|
||||
if(mmi)
|
||||
var/turf/T = get_turf(loc)
|
||||
if(T)
|
||||
mmi.forceMove(T)
|
||||
if(mind) mind.transfer_to(mmi.brainmob)
|
||||
mmi = null
|
||||
real_name = initial(real_name)
|
||||
name = real_name
|
||||
update_icon()
|
||||
remove_language("Robot Talk")
|
||||
positronic = null
|
||||
|
||||
/mob/living/simple_animal/spiderbot/Destroy()
|
||||
eject_brain()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/spiderbot/New()
|
||||
|
||||
radio = new /obj/item/device/radio/borg(src)
|
||||
camera = new /obj/machinery/camera(src)
|
||||
camera.c_tag = "spiderbot-[real_name]"
|
||||
camera.replace_networks(list("SS13"))
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/spiderbot/death()
|
||||
|
||||
living_mob_list -= src
|
||||
dead_mob_list += src
|
||||
|
||||
if(camera)
|
||||
camera.status = 0
|
||||
|
||||
held_item.forceMove(src.loc)
|
||||
held_item = null
|
||||
|
||||
gibs(loc, null, null, /obj/effect/gibspawner/robot) //TODO: use gib() or refactor spiderbots into synthetics.
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
//Cannibalized from the parrot mob. ~Zuhayr
|
||||
/mob/living/simple_animal/spiderbot/verb/drop_held_item()
|
||||
set name = "Drop held item"
|
||||
set category = "Spiderbot"
|
||||
set desc = "Drop the item you're holding."
|
||||
|
||||
if(stat)
|
||||
return
|
||||
|
||||
if(!held_item)
|
||||
usr << "<font color='red'>You have nothing to drop!</font>"
|
||||
return 0
|
||||
|
||||
if(istype(held_item, /obj/item/weapon/grenade))
|
||||
visible_message("<span class='danger'>\The [src] launches \the [held_item]!</span>", \
|
||||
"<span class='danger'>You launch \the [held_item]!</span>", \
|
||||
"You hear a skittering noise and a thump!")
|
||||
var/obj/item/weapon/grenade/G = held_item
|
||||
G.forceMove(src.loc)
|
||||
G.detonate()
|
||||
held_item = null
|
||||
return 1
|
||||
|
||||
visible_message("<span class='notice'>\The [src] drops \the [held_item].</span>", \
|
||||
"<span class='notice'>You drop \the [held_item].</span>", \
|
||||
"You hear a skittering noise and a soft thump.")
|
||||
|
||||
held_item.forceMove(src.loc)
|
||||
held_item = null
|
||||
return 1
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/spiderbot/verb/get_item()
|
||||
set name = "Pick up item"
|
||||
set category = "Spiderbot"
|
||||
set desc = "Allows you to take a nearby small item."
|
||||
|
||||
if(stat)
|
||||
return -1
|
||||
|
||||
if(held_item)
|
||||
to_chat(src, "<span class='warning'>You are already holding \the [held_item]</span>")
|
||||
return 1
|
||||
|
||||
var/list/items = list()
|
||||
for(var/obj/item/I in view(1,src))
|
||||
if(I.loc != src && I.w_class <= ITEMSIZE_SMALL && I.Adjacent(src) )
|
||||
items.Add(I)
|
||||
|
||||
var/obj/selection = input("Select an item.", "Pickup") in items
|
||||
|
||||
if(selection)
|
||||
for(var/obj/item/I in view(1, src))
|
||||
if(selection == I)
|
||||
held_item = selection
|
||||
selection.forceMove(src)
|
||||
visible_message("<span class='notice'>\The [src] scoops up \the [held_item].</span>", \
|
||||
"<span class='notice'>You grab \the [held_item].</span>", \
|
||||
"You hear a skittering noise and a clink.")
|
||||
return held_item
|
||||
to_chat(src, "<span class='warning'>\The [selection] is too far away.</span>")
|
||||
return 0
|
||||
|
||||
to_chat(src, "<span class='warning'>There is nothing of interest to take.</span>")
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/spiderbot/examine(mob/user)
|
||||
..(user)
|
||||
if(src.held_item)
|
||||
user << "It is carrying \icon[src.held_item] \a [src.held_item]."
|
||||
|
||||
/mob/living/simple_animal/spiderbot/cannot_use_vents()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/spiderbot/binarycheck()
|
||||
return positronic
|
||||
@@ -1,24 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/tomato
|
||||
name = "tomato"
|
||||
desc = "It's a horrifyingly enormous beef tomato, and it's packing extra beef!"
|
||||
tt_desc = "X Solanum abominable"
|
||||
icon_state = "tomato"
|
||||
icon_living = "tomato"
|
||||
icon_dead = "tomato_dead"
|
||||
intelligence_level = SA_PLANT
|
||||
|
||||
faction = "plants"
|
||||
maxHealth = 15
|
||||
health = 15
|
||||
turns_per_move = 5
|
||||
|
||||
response_help = "prods"
|
||||
response_disarm = "pushes aside"
|
||||
response_harm = "smacks"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_upper = 15
|
||||
melee_damage_lower = 10
|
||||
attacktext = list("mauled")
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/tomatomeat
|
||||
@@ -1,60 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/tree
|
||||
name = "pine tree"
|
||||
desc = "A pissed off tree-like alien. It seems annoyed with the festivities..."
|
||||
tt_desc = "X Festivus tyrannus"
|
||||
icon = 'icons/obj/flora/pinetrees.dmi'
|
||||
icon_state = "pine_1"
|
||||
icon_living = "pine_1"
|
||||
icon_dead = "pine_1"
|
||||
icon_gib = "pine_1"
|
||||
intelligence_level = SA_PLANT
|
||||
|
||||
faction = "carp" //Trees can be carp friends?
|
||||
maxHealth = 250
|
||||
health = 250
|
||||
speed = -1
|
||||
|
||||
turns_per_move = 5
|
||||
|
||||
response_help = "brushes"
|
||||
response_disarm = "pushes"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 12
|
||||
attacktext = list("bitten")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat
|
||||
|
||||
pixel_x = -16
|
||||
|
||||
/mob/living/simple_animal/hostile/tree/FindTarget()
|
||||
. = ..()
|
||||
if(.)
|
||||
audible_emote("growls at [.]")
|
||||
|
||||
/mob/living/simple_animal/hostile/tree/PunchTarget()
|
||||
. =..()
|
||||
var/mob/living/L = .
|
||||
if(istype(L))
|
||||
if(prob(15))
|
||||
L.Weaken(3)
|
||||
L.visible_message("<span class='danger'>\the [src] knocks down \the [L]!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/tree/death()
|
||||
..(null,"is hacked into pieces!")
|
||||
playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1)
|
||||
new /obj/item/stack/material/wood(loc)
|
||||
qdel(src)
|
||||
@@ -1,199 +0,0 @@
|
||||
/mob/living/simple_animal/space_worm
|
||||
name = "space worm segment"
|
||||
desc = "A part of a space worm."
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
icon_state = "spaceworm"
|
||||
icon_living = "spaceworm"
|
||||
icon_dead = "spacewormdead"
|
||||
intelligence_level = SA_ANIMAL
|
||||
|
||||
|
||||
maxHealth = 30
|
||||
health = 30
|
||||
speed = -1
|
||||
|
||||
status_flags = 0
|
||||
universal_speak = 1
|
||||
stop_automated_movement = 1
|
||||
wander = 0
|
||||
animate_movement = SYNC_STEPS
|
||||
|
||||
response_help = "touches"
|
||||
response_disarm = "flails at"
|
||||
response_harm = "punches the"
|
||||
|
||||
harm_intent_damage = 2
|
||||
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 350
|
||||
min_oxy = 0
|
||||
max_co2 = 0
|
||||
max_tox = 0
|
||||
|
||||
environment_smash = 2
|
||||
|
||||
speak_emote = list("transmits") //not supposed to be used under AI control
|
||||
emote_hear = list("transmits") //I'm just adding it so it doesn't runtime if controlled by player who speaks
|
||||
|
||||
var/mob/living/simple_animal/space_worm/previous //next/previous segments, correspondingly
|
||||
var/mob/living/simple_animal/space_worm/next //head is the nextest segment
|
||||
|
||||
var/stomachProcessProbability = 50
|
||||
var/digestionProbability = 20
|
||||
var/flatPlasmaValue = 5 //flat plasma amount given for non-items
|
||||
|
||||
var/atom/currentlyEating //what the worm is currently eating
|
||||
var/eatingDuration = 0 //how long he's been eating it for
|
||||
|
||||
head
|
||||
name = "space worm head"
|
||||
icon_state = "spacewormhead"
|
||||
icon_living = "spacewormhead"
|
||||
icon_dead = "spacewormdead"
|
||||
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
attacktext = list("bitten")
|
||||
|
||||
animate_movement = SLIDE_STEPS
|
||||
|
||||
New(var/location, var/segments = 6)
|
||||
..()
|
||||
|
||||
var/mob/living/simple_animal/space_worm/current = src
|
||||
|
||||
for(var/i = 1 to segments)
|
||||
var/mob/living/simple_animal/space_worm/newSegment = new /mob/living/simple_animal/space_worm(loc)
|
||||
current.Attach(newSegment)
|
||||
current = newSegment
|
||||
|
||||
update_icon()
|
||||
if(stat == CONSCIOUS || stat == UNCONSCIOUS)
|
||||
icon_state = "spacewormhead[previous?1:0]"
|
||||
if(previous)
|
||||
set_dir(get_dir(previous,src))
|
||||
else
|
||||
icon_state = "spacewormheaddead"
|
||||
|
||||
Life()
|
||||
..()
|
||||
|
||||
if(next && !(next in view(src,1)))
|
||||
Detach()
|
||||
|
||||
if(stat == DEAD) //dead chunks fall off and die immediately
|
||||
if(previous)
|
||||
previous.Detach()
|
||||
if(next)
|
||||
Detach(1)
|
||||
|
||||
if(prob(stomachProcessProbability))
|
||||
ProcessStomach()
|
||||
|
||||
update_icon()
|
||||
|
||||
return
|
||||
|
||||
Destroy() //if a chunk a destroyed, make a new worm out of the split halves
|
||||
if(previous)
|
||||
previous.Detach()
|
||||
..()
|
||||
|
||||
Move()
|
||||
var/attachementNextPosition = loc
|
||||
if(..())
|
||||
if(previous)
|
||||
previous.Move(attachementNextPosition)
|
||||
update_icon()
|
||||
|
||||
Bump(atom/obstacle)
|
||||
if(currentlyEating != obstacle)
|
||||
currentlyEating = obstacle
|
||||
eatingDuration = 0
|
||||
|
||||
if(!AttemptToEat(obstacle))
|
||||
eatingDuration++
|
||||
else
|
||||
currentlyEating = null
|
||||
eatingDuration = 0
|
||||
|
||||
return
|
||||
|
||||
update_icon() //only for the sake of consistency with the other update icon procs
|
||||
if(stat == CONSCIOUS || stat == UNCONSCIOUS)
|
||||
if(previous) //midsection
|
||||
icon_state = "spaceworm[get_dir(src,previous) | get_dir(src,next)]" //see 3 lines below
|
||||
else //tail
|
||||
icon_state = "spacewormtail"
|
||||
set_dir(get_dir(src,next)) //next will always be present since it's not a head and if it's dead, it goes in the other if branch
|
||||
else
|
||||
icon_state = "spacewormdead"
|
||||
|
||||
return
|
||||
|
||||
proc/AttemptToEat(var/atom/target)
|
||||
if(istype(target,/turf/simulated/wall))
|
||||
var/turf/simulated/wall/W = target
|
||||
if((!W.reinf_material && eatingDuration >= 100) || eatingDuration >= 200) //need 20 ticks to eat an rwall, 10 for a regular one
|
||||
W.dismantle_wall()
|
||||
return 1
|
||||
else if(istype(target,/atom/movable))
|
||||
if(istype(target,/mob) || eatingDuration >= 50) //5 ticks to eat stuff like airlocks
|
||||
var/atom/movable/objectOrMob = target
|
||||
contents += objectOrMob
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
proc/Attach(var/mob/living/simple_animal/space_worm/attachement)
|
||||
if(!attachement)
|
||||
return
|
||||
|
||||
previous = attachement
|
||||
attachement.next = src
|
||||
|
||||
return
|
||||
|
||||
proc/Detach(die = 0)
|
||||
var/mob/living/simple_animal/space_worm/newHead = new /mob/living/simple_animal/space_worm/head(loc,0)
|
||||
var/mob/living/simple_animal/space_worm/newHeadPrevious = previous
|
||||
|
||||
previous = null //so that no extra heads are spawned
|
||||
|
||||
newHead.Attach(newHeadPrevious)
|
||||
|
||||
if(die)
|
||||
newHead.death()
|
||||
|
||||
qdel(src)
|
||||
|
||||
proc/ProcessStomach()
|
||||
for(var/atom/movable/stomachContent in contents)
|
||||
if(prob(digestionProbability))
|
||||
if(istype(stomachContent,/obj/item/stack)) //converts to plasma, keeping the stack value
|
||||
if(!istype(stomachContent,/obj/item/stack/material/phoron))
|
||||
var/obj/item/stack/oldStack = stomachContent
|
||||
new /obj/item/stack/material/phoron(src, oldStack.get_amount())
|
||||
qdel(oldStack)
|
||||
continue
|
||||
else if(istype(stomachContent,/obj/item)) //converts to plasma, keeping the w_class
|
||||
var/obj/item/oldItem = stomachContent
|
||||
new /obj/item/stack/material/phoron(src, oldItem.w_class)
|
||||
qdel(oldItem)
|
||||
continue
|
||||
else
|
||||
new /obj/item/stack/material/phoron(src, flatPlasmaValue) //just flat amount
|
||||
qdel(stomachContent)
|
||||
continue
|
||||
|
||||
if(previous)
|
||||
for(var/atom/movable/stomachContent in contents) //transfer it along the digestive tract
|
||||
previous.contents += stomachContent
|
||||
else
|
||||
for(var/atom/movable/stomachContent in contents) //or poop it out
|
||||
loc.contents += stomachContent
|
||||
|
||||
return
|
||||
@@ -1,213 +0,0 @@
|
||||
/mob/living/simple_mob/animal/borer
|
||||
name = "cortical borer"
|
||||
real_name = "cortical borer"
|
||||
desc = "A small, quivering sluglike creature."
|
||||
speak_emote = list("chirrups")
|
||||
emote_hear = list("chirrups")
|
||||
intelligence_level = SA_HUMANOID // Player controlled.
|
||||
response_help = "pokes"
|
||||
response_disarm = "prods"
|
||||
response_harm = "stomps on"
|
||||
icon_state = "brainslug"
|
||||
item_state = "brainslug"
|
||||
icon_living = "brainslug"
|
||||
icon_dead = "brainslug_dead"
|
||||
speed = 5
|
||||
a_intent = I_HURT
|
||||
stop_automated_movement = 1
|
||||
status_flags = CANPUSH
|
||||
attacktext = list("nipped")
|
||||
friendly = "prods"
|
||||
wander = 0
|
||||
pass_flags = PASSTABLE
|
||||
universal_understand = 1
|
||||
holder_type = /obj/item/weapon/holder/borer
|
||||
|
||||
var/used_dominate
|
||||
var/chemicals = 10 // Chemicals used for reproduction and spitting neurotoxin.
|
||||
var/mob/living/carbon/human/host // Human host for the brain worm.
|
||||
var/truename // Name used for brainworm-speak.
|
||||
var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth.
|
||||
var/controlling // Used in human death check.
|
||||
var/docile = 0 // Sugar can stop borers from acting.
|
||||
var/has_reproduced
|
||||
var/roundstart
|
||||
|
||||
can_be_antagged = TRUE
|
||||
|
||||
/mob/living/simple_mob/animal/borer/roundstart
|
||||
roundstart = 1
|
||||
|
||||
/mob/living/simple_mob/animal/borer/Login()
|
||||
..()
|
||||
if(mind)
|
||||
borers.add_antagonist(mind)
|
||||
|
||||
/mob/living/simple_mob/animal/borer/New()
|
||||
..()
|
||||
|
||||
add_language("Cortical Link")
|
||||
verbs += /mob/living/proc/ventcrawl
|
||||
verbs += /mob/living/proc/hide
|
||||
|
||||
truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
|
||||
if(!roundstart) request_player()
|
||||
|
||||
/mob/living/simple_mob/animal/borer/Life()
|
||||
|
||||
..()
|
||||
|
||||
if(host)
|
||||
|
||||
if(!stat && !host.stat)
|
||||
|
||||
if(host.reagents.has_reagent("sugar"))
|
||||
if(!docile)
|
||||
if(controlling)
|
||||
host << "<font color='blue'>You feel the soporific flow of sugar in your host's blood, lulling you into docility.</font>"
|
||||
else
|
||||
to_chat(src, "<font color='blue'>You feel the soporific flow of sugar in your host's blood, lulling you into docility.</font>")
|
||||
docile = 1
|
||||
else
|
||||
if(docile)
|
||||
if(controlling)
|
||||
host << "<font color='blue'>You shake off your lethargy as the sugar leaves your host's blood.</font>"
|
||||
else
|
||||
to_chat(src, "<font color='blue'>You shake off your lethargy as the sugar leaves your host's blood.</font>")
|
||||
docile = 0
|
||||
|
||||
if(chemicals < 250)
|
||||
chemicals++
|
||||
if(controlling)
|
||||
|
||||
if(docile)
|
||||
host << "<font color='blue'>You are feeling far too docile to continue controlling your host...</font>"
|
||||
host.release_control()
|
||||
return
|
||||
|
||||
if(prob(5))
|
||||
host.adjustBrainLoss(0.1)
|
||||
|
||||
if(prob(host.brainloss/20))
|
||||
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_v","gasp"))]")
|
||||
|
||||
/mob/living/simple_mob/animal/borer/Stat()
|
||||
..()
|
||||
statpanel("Status")
|
||||
|
||||
if(emergency_shuttle)
|
||||
var/eta_status = emergency_shuttle.get_status_panel_eta()
|
||||
if(eta_status)
|
||||
stat(null, eta_status)
|
||||
|
||||
if (client.statpanel == "Status")
|
||||
stat("Chemicals", chemicals)
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/detatch()
|
||||
|
||||
if(!host || !controlling) return
|
||||
|
||||
if(istype(host,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = host
|
||||
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
|
||||
head.implants -= src
|
||||
|
||||
controlling = 0
|
||||
|
||||
host.remove_language("Cortical Link")
|
||||
host.verbs -= /mob/living/carbon/proc/release_control
|
||||
host.verbs -= /mob/living/carbon/proc/punish_host
|
||||
host.verbs -= /mob/living/carbon/proc/spawn_larvae
|
||||
|
||||
if(host_brain)
|
||||
|
||||
// these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed.
|
||||
// computer_id and IP are not updated magically on their own in offline mobs -walter0o
|
||||
|
||||
// host -> self
|
||||
var/h2s_id = host.computer_id
|
||||
var/h2s_ip= host.lastKnownIP
|
||||
host.computer_id = null
|
||||
host.lastKnownIP = null
|
||||
|
||||
src.ckey = host.ckey
|
||||
|
||||
if(!src.computer_id)
|
||||
src.computer_id = h2s_id
|
||||
|
||||
if(!host_brain.lastKnownIP)
|
||||
src.lastKnownIP = h2s_ip
|
||||
|
||||
// brain -> host
|
||||
var/b2h_id = host_brain.computer_id
|
||||
var/b2h_ip= host_brain.lastKnownIP
|
||||
host_brain.computer_id = null
|
||||
host_brain.lastKnownIP = null
|
||||
|
||||
host.ckey = host_brain.ckey
|
||||
|
||||
if(!host.computer_id)
|
||||
host.computer_id = b2h_id
|
||||
|
||||
if(!host.lastKnownIP)
|
||||
host.lastKnownIP = b2h_ip
|
||||
|
||||
qdel(host_brain)
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/leave_host()
|
||||
|
||||
if(!host) return
|
||||
|
||||
if(host.mind)
|
||||
borers.remove_antagonist(host.mind)
|
||||
|
||||
src.forceMove(get_turf(host))
|
||||
|
||||
reset_view(null)
|
||||
machine = null
|
||||
|
||||
host.reset_view(null)
|
||||
host.machine = null
|
||||
host = null
|
||||
return
|
||||
|
||||
//Procs for grabbing players.
|
||||
/mob/living/simple_mob/animal/borer/proc/request_player()
|
||||
for(var/mob/observer/dead/O in player_list)
|
||||
if(jobban_isbanned(O, "Borer"))
|
||||
continue
|
||||
if(O.client)
|
||||
if(O.client.prefs.be_special & BE_ALIEN)
|
||||
question(O.client)
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/question(var/client/C)
|
||||
spawn(0)
|
||||
if(!C) return
|
||||
var/response = alert(C, "A cortical borer needs a player. Are you interested?", "Cortical borer request", "Yes", "No", "Never for this round")
|
||||
if(!C || ckey)
|
||||
return
|
||||
if(response == "Yes")
|
||||
transfer_personality(C)
|
||||
else if (response == "Never for this round")
|
||||
C.prefs.be_special ^= BE_ALIEN
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/transfer_personality(var/client/candidate)
|
||||
|
||||
if(!candidate || !candidate.mob || !candidate.mob.mind)
|
||||
return
|
||||
|
||||
src.mind = candidate.mob.mind
|
||||
candidate.mob.mind.current = src
|
||||
src.ckey = candidate.ckey
|
||||
|
||||
if(src.mind)
|
||||
src.mind.assigned_role = "Cortical Borer"
|
||||
src.mind.special_role = "Cortical Borer"
|
||||
|
||||
to_chat(src, "<span class='notice'>You are a cortical borer!</span> You are a brain slug that worms its way \
|
||||
into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, \
|
||||
your host and your eventual spawn safe and warm.")
|
||||
to_chat(src, "You can speak to your victim with <b>say</b>, to other borers with <b>say :x</b>, and use your Abilities tab to access powers.")
|
||||
|
||||
/mob/living/simple_mob/animal/borer/cannot_use_vents()
|
||||
return
|
||||
@@ -1,57 +0,0 @@
|
||||
/mob/living/captive_brain
|
||||
name = "host brain"
|
||||
real_name = "host brain"
|
||||
universal_understand = 1
|
||||
|
||||
/mob/living/captive_brain/say(var/message)
|
||||
|
||||
if (src.client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "<font color='red'>You cannot speak in IC (muted).</font>")
|
||||
return
|
||||
|
||||
if(istype(src.loc,/mob/living/simple_mob/animal/borer))
|
||||
|
||||
message = sanitize(message)
|
||||
if (!message)
|
||||
return
|
||||
log_say(message,src)
|
||||
if (stat == 2)
|
||||
return say_dead(message)
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = src.loc
|
||||
to_chat(src, "You whisper silently, \"[message]\"")
|
||||
B.host << "The captive mind of [src] whispers, \"[message]\""
|
||||
|
||||
for (var/mob/M in player_list)
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
M << "The captive mind of [src] whispers, \"[message]\""
|
||||
|
||||
/mob/living/captive_brain/emote(var/message)
|
||||
return
|
||||
|
||||
/mob/living/captive_brain/process_resist()
|
||||
//Resisting control by an alien mind.
|
||||
if(istype(src.loc,/mob/living/simple_mob/animal/borer))
|
||||
var/mob/living/simple_mob/animal/borer/B = src.loc
|
||||
var/mob/living/captive_brain/H = src
|
||||
|
||||
H << "<span class='danger'>You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).</span>"
|
||||
B.host << "<span class='danger'>You feel the captive mind of [src] begin to resist your control.</span>"
|
||||
|
||||
spawn(rand(200,250)+B.host.brainloss)
|
||||
if(!B || !B.controlling) return
|
||||
|
||||
B.host.adjustBrainLoss(rand(0.1,0.5))
|
||||
H << "<span class='danger'>With an immense exertion of will, you regain control of your body!</span>"
|
||||
B.host << "<span class='danger'>You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.</span>"
|
||||
B.detatch()
|
||||
verbs -= /mob/living/carbon/proc/release_control
|
||||
verbs -= /mob/living/carbon/proc/punish_host
|
||||
verbs -= /mob/living/carbon/proc/spawn_larvae
|
||||
|
||||
return
|
||||
|
||||
..()
|
||||
@@ -1,337 +0,0 @@
|
||||
/mob/living/simple_mob/animal/borer/verb/release_host()
|
||||
set category = "Abilities"
|
||||
set name = "Release Host"
|
||||
set desc = "Slither out of your host."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, "You are not inside a host body.")
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, "You cannot leave your host in your current state.")
|
||||
|
||||
if(docile)
|
||||
to_chat(src, "<font color='blue'>You are feeling far too docile to do that.</font>")
|
||||
return
|
||||
|
||||
if(!host || !src) return
|
||||
|
||||
to_chat(src, "You begin disconnecting from [host]'s synapses and prodding at their internal ear canal.")
|
||||
|
||||
if(!host.stat)
|
||||
host << "An odd, uncomfortable pressure begins to build inside your skull, behind your ear..."
|
||||
|
||||
spawn(100)
|
||||
|
||||
if(!host || !src) return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, "You cannot release your host in your current state.")
|
||||
return
|
||||
|
||||
to_chat(src, "You wiggle out of [host]'s ear and plop to the ground.")
|
||||
if(host.mind)
|
||||
if(!host.stat)
|
||||
host << "<span class='danger'>Something slimy wiggles out of your ear and plops to the ground!</span>"
|
||||
host << "<span class='danger'>As though waking from a dream, you shake off the insidious mind control of the brain worm. Your thoughts are your own again.</span>"
|
||||
|
||||
detatch()
|
||||
leave_host()
|
||||
|
||||
/mob/living/simple_mob/animal/borer/verb/infest()
|
||||
set category = "Abilities"
|
||||
set name = "Infest"
|
||||
set desc = "Infest a suitable humanoid host."
|
||||
|
||||
if(host)
|
||||
to_chat(src, "You are already within a host.")
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, "You cannot infest a target in your current state.")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/C in view(1,src))
|
||||
if(src.Adjacent(C))
|
||||
choices += C
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src, "There are no viable hosts within range...")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/M = input(src,"Who do you wish to infest?") in null|choices
|
||||
|
||||
if(!M || !src) return
|
||||
|
||||
if(!(src.Adjacent(M))) return
|
||||
|
||||
if(M.has_brain_worms())
|
||||
to_chat(src, "You cannot infest someone who is already infested!")
|
||||
return
|
||||
|
||||
if(istype(M,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
var/obj/item/organ/external/E = H.organs_by_name[BP_HEAD]
|
||||
if(!E || E.is_stump())
|
||||
to_chat(src, "\The [H] does not have a head!")
|
||||
|
||||
if(!H.should_have_organ("brain"))
|
||||
to_chat(src, "\The [H] does not seem to have an ear canal to breach.")
|
||||
return
|
||||
|
||||
if(H.check_head_coverage())
|
||||
to_chat(src, "You cannot get through that host's protective gear.")
|
||||
return
|
||||
|
||||
M << "Something slimy begins probing at the opening of your ear canal..."
|
||||
to_chat(src, "You slither up [M] and begin probing at their ear canal...")
|
||||
|
||||
if(!do_after(src,30))
|
||||
to_chat(src, "As [M] moves away, you are dislodged and fall to the ground.")
|
||||
return
|
||||
|
||||
if(!M || !src) return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, "You cannot infest a target in your current state.")
|
||||
return
|
||||
|
||||
if(M in view(1, src))
|
||||
to_chat(src, "You wiggle into [M]'s ear.")
|
||||
if(!M.stat)
|
||||
M << "Something disgusting and slimy wiggles into your ear!"
|
||||
|
||||
src.host = M
|
||||
src.forceMove(M)
|
||||
|
||||
//Update their traitor status.
|
||||
if(host.mind)
|
||||
borers.add_antagonist_mind(host.mind, 1, borers.faction_role_text, borers.faction_welcome)
|
||||
|
||||
if(istype(M,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/I = H.internal_organs_by_name["brain"]
|
||||
if(!I) // No brain organ, so the borer moves in and replaces it permanently.
|
||||
replace_brain()
|
||||
else
|
||||
// If they're in normally, implant removal can get them out.
|
||||
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
|
||||
head.implants += src
|
||||
|
||||
return
|
||||
else
|
||||
to_chat(src, "They are no longer in range!")
|
||||
return
|
||||
|
||||
/*
|
||||
/mob/living/simple_mob/animal/borer/verb/devour_brain()
|
||||
set category = "Abilities"
|
||||
set name = "Devour Brain"
|
||||
set desc = "Take permanent control of a dead host."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, "You are not inside a host body.")
|
||||
return
|
||||
|
||||
if(host.stat != 2)
|
||||
to_chat(src, "Your host is still alive.")
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, "You cannot do that in your current state.")
|
||||
|
||||
if(docile)
|
||||
to_chat(src, "<font color='blue'>You are feeling far too docile to do that.</font>")
|
||||
return
|
||||
|
||||
|
||||
to_chat(src, "<span class = 'danger'>It only takes a few moments to render the dead host brain down into a nutrient-rich slurry...</span>")
|
||||
replace_brain()
|
||||
*/
|
||||
|
||||
// BRAIN WORM ZOMBIES AAAAH.
|
||||
/mob/living/simple_mob/animal/borer/proc/replace_brain()
|
||||
|
||||
var/mob/living/carbon/human/H = host
|
||||
|
||||
if(!istype(host))
|
||||
to_chat(src, "This host does not have a suitable brain.")
|
||||
return
|
||||
|
||||
to_chat(src, "<span class = 'danger'>You settle into the empty brainpan and begin to expand, fusing inextricably with the dead flesh of [H].</span>")
|
||||
|
||||
H.add_language("Cortical Link")
|
||||
|
||||
if(host.stat == 2)
|
||||
H.verbs |= /mob/living/carbon/human/proc/jumpstart
|
||||
|
||||
H.verbs |= /mob/living/carbon/human/proc/psychic_whisper
|
||||
H.verbs |= /mob/living/carbon/human/proc/tackle
|
||||
H.verbs |= /mob/living/carbon/proc/spawn_larvae
|
||||
|
||||
if(H.client)
|
||||
H.ghostize(0)
|
||||
|
||||
if(src.mind)
|
||||
src.mind.special_role = "Borer Husk"
|
||||
src.mind.transfer_to(host)
|
||||
|
||||
H.ChangeToHusk()
|
||||
|
||||
var/obj/item/organ/internal/borer/B = new(H)
|
||||
H.internal_organs_by_name["brain"] = B
|
||||
H.internal_organs |= B
|
||||
|
||||
var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD)
|
||||
affecting.implants -= src
|
||||
|
||||
var/s2h_id = src.computer_id
|
||||
var/s2h_ip= src.lastKnownIP
|
||||
src.computer_id = null
|
||||
src.lastKnownIP = null
|
||||
|
||||
if(!H.computer_id)
|
||||
H.computer_id = s2h_id
|
||||
|
||||
if(!H.lastKnownIP)
|
||||
H.lastKnownIP = s2h_ip
|
||||
|
||||
/mob/living/simple_mob/animal/borer/verb/secrete_chemicals()
|
||||
set category = "Abilities"
|
||||
set name = "Secrete Chemicals"
|
||||
set desc = "Push some chemicals into your host's bloodstream."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, "You are not inside a host body.")
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, "You cannot secrete chemicals in your current state.")
|
||||
|
||||
if(docile)
|
||||
to_chat(src, "<font color='blue'>You are feeling far too docile to do that.</font>")
|
||||
return
|
||||
|
||||
if(chemicals < 50)
|
||||
to_chat(src, "You don't have enough chemicals!")
|
||||
|
||||
var/chem = input("Select a chemical to secrete.", "Chemicals") as null|anything in list("alkysine","bicaridine","hyperzine","tramadol")
|
||||
|
||||
if(!chem || chemicals < 50 || !host || controlling || !src || stat) //Sanity check.
|
||||
return
|
||||
|
||||
to_chat(src, "<font color='red'><B>You squirt a measure of [chem] from your reservoirs into [host]'s bloodstream.</B></font>")
|
||||
host.reagents.add_reagent(chem, 10)
|
||||
chemicals -= 50
|
||||
|
||||
/mob/living/simple_mob/animal/borer/verb/dominate_victim()
|
||||
set category = "Abilities"
|
||||
set name = "Paralyze Victim"
|
||||
set desc = "Freeze the limbs of a potential host with supernatural fear."
|
||||
|
||||
if(world.time - used_dominate < 150)
|
||||
to_chat(src, "You cannot use that ability again so soon.")
|
||||
return
|
||||
|
||||
if(host)
|
||||
to_chat(src, "You cannot do that from within a host body.")
|
||||
return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, "You cannot do that in your current state.")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/C in view(3,src))
|
||||
if(C.stat != 2)
|
||||
choices += C
|
||||
|
||||
if(world.time - used_dominate < 150)
|
||||
to_chat(src, "You cannot use that ability again so soon.")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/M = input(src,"Who do you wish to dominate?") in null|choices
|
||||
|
||||
if(!M || !src) return
|
||||
|
||||
if(M.has_brain_worms())
|
||||
to_chat(src, "You cannot infest someone who is already infested!")
|
||||
return
|
||||
|
||||
to_chat(src, "<font color='red'>You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread.</font>")
|
||||
M << "<font color='red'>You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.</font>"
|
||||
M.Weaken(10)
|
||||
|
||||
used_dominate = world.time
|
||||
|
||||
/mob/living/simple_mob/animal/borer/verb/bond_brain()
|
||||
set category = "Abilities"
|
||||
set name = "Assume Control"
|
||||
set desc = "Fully connect to the brain of your host."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, "You are not inside a host body.")
|
||||
return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, "You cannot do that in your current state.")
|
||||
return
|
||||
|
||||
if(docile)
|
||||
to_chat(src, "<font color='blue'>You are feeling far too docile to do that.</font>")
|
||||
return
|
||||
|
||||
to_chat(src, "You begin delicately adjusting your connection to the host brain...")
|
||||
|
||||
spawn(100+(host.brainloss*5))
|
||||
|
||||
if(!host || !src || controlling)
|
||||
return
|
||||
else
|
||||
|
||||
to_chat(src, "<font color='red'><B>You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.</B></font>")
|
||||
host << "<font color='red'><B>You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.</B></font>"
|
||||
host.add_language("Cortical Link")
|
||||
|
||||
// host -> brain
|
||||
var/h2b_id = host.computer_id
|
||||
var/h2b_ip= host.lastKnownIP
|
||||
host.computer_id = null
|
||||
host.lastKnownIP = null
|
||||
|
||||
qdel(host_brain)
|
||||
host_brain = new(src)
|
||||
|
||||
host_brain.ckey = host.ckey
|
||||
|
||||
host_brain.name = host.name
|
||||
|
||||
if(!host_brain.computer_id)
|
||||
host_brain.computer_id = h2b_id
|
||||
|
||||
if(!host_brain.lastKnownIP)
|
||||
host_brain.lastKnownIP = h2b_ip
|
||||
|
||||
// self -> host
|
||||
var/s2h_id = src.computer_id
|
||||
var/s2h_ip= src.lastKnownIP
|
||||
src.computer_id = null
|
||||
src.lastKnownIP = null
|
||||
|
||||
host.ckey = src.ckey
|
||||
|
||||
if(!host.computer_id)
|
||||
host.computer_id = s2h_id
|
||||
|
||||
if(!host.lastKnownIP)
|
||||
host.lastKnownIP = s2h_ip
|
||||
|
||||
controlling = 1
|
||||
|
||||
host.verbs += /mob/living/carbon/proc/release_control
|
||||
host.verbs += /mob/living/carbon/proc/punish_host
|
||||
host.verbs += /mob/living/carbon/proc/spawn_larvae
|
||||
|
||||
return
|
||||
@@ -1,40 +0,0 @@
|
||||
/mob/living/simple_mob/animal/borer/say(var/message)
|
||||
|
||||
message = sanitize(message)
|
||||
message = capitalize(message)
|
||||
|
||||
if(!message)
|
||||
return
|
||||
|
||||
if (stat == 2)
|
||||
return say_dead(message)
|
||||
|
||||
if (stat)
|
||||
return
|
||||
|
||||
if (src.client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "<font color='red'>You cannot speak in IC (muted).</font>")
|
||||
return
|
||||
|
||||
if (copytext(message, 1, 2) == "*")
|
||||
return emote(copytext(message, 2))
|
||||
|
||||
var/datum/language/L = parse_language(message)
|
||||
if(L && L.flags & HIVEMIND)
|
||||
L.broadcast(src,trim(copytext(message,3)),src.truename)
|
||||
return
|
||||
|
||||
if(!host)
|
||||
//TODO: have this pick a random mob within 3 tiles to speak for the borer.
|
||||
to_chat(src, "You have no host to speak to.")
|
||||
return //No host, no audible speech.
|
||||
|
||||
to_chat(src, "You drop words into [host]'s mind: \"[message]\"")
|
||||
host << "Your own thoughts speak: \"[message]\""
|
||||
|
||||
for (var/mob/M in player_list)
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
M << "[src.truename] whispers to [host], \"[message]\""
|
||||
@@ -1,49 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/clown
|
||||
name = "clown"
|
||||
desc = "A denizen of clown planet"
|
||||
tt_desc = "E Homo sapiens corydon" //this is an actual clown, as opposed to someone dressed up as one
|
||||
icon_state = "clown"
|
||||
icon_living = "clown"
|
||||
icon_dead = "clown_dead"
|
||||
icon_gib = "clown_gib"
|
||||
intelligence_level = SA_HUMANOID
|
||||
|
||||
faction = "clown"
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
speed = -1
|
||||
move_to_delay = 2
|
||||
|
||||
run_at_them = 0
|
||||
cooperative = 1
|
||||
|
||||
turns_per_move = 5
|
||||
stop_when_pulled = 0
|
||||
|
||||
response_help = "pokes"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 8
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 10
|
||||
attacktext = list("attacked")
|
||||
attack_sound = 'sound/items/bikehorn.ogg'
|
||||
|
||||
min_oxy = 5
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 1
|
||||
min_co2 = 0
|
||||
max_co2 = 5
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 270
|
||||
maxbodytemp = 370
|
||||
heat_damage_per_tick = 15 //amount of damage applied if animal's body temperature is higher than maxbodytemp
|
||||
cold_damage_per_tick = 10 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp
|
||||
unsuitable_atoms_damage = 10
|
||||
|
||||
speak_chance = 1
|
||||
speak = list("HONK", "Honk!", "Welcome to clown planet!")
|
||||
emote_see = list("honks")
|
||||
@@ -1,123 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/mecha
|
||||
name = "mercenary gygax"
|
||||
desc = "Well that's forboding."
|
||||
icon = 'icons/mecha/mecha.dmi'
|
||||
icon_state = "darkgygax"
|
||||
icon_living = "darkgygax"
|
||||
icon_dead = "darkgygax-broken"
|
||||
intelligence_level = SA_HUMANOID // Piloted by a human.
|
||||
|
||||
faction = "syndicate"
|
||||
maxHealth = 300
|
||||
health = 300
|
||||
speed = 7
|
||||
move_to_delay = 8
|
||||
|
||||
run_at_them = 0
|
||||
cooperative = 1
|
||||
investigates = 1
|
||||
firing_lines = 1
|
||||
|
||||
turns_per_move = 5
|
||||
stop_when_pulled = 0
|
||||
|
||||
response_help = "taps on"
|
||||
response_disarm = "knocks on"
|
||||
response_harm = "uselessly hits"
|
||||
|
||||
harm_intent_damage = 0
|
||||
melee_damage_lower = 35
|
||||
melee_damage_upper = 35
|
||||
attacktext = list("slashed")
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
|
||||
armor = list(melee = 40, bullet = 40, laser = 50, energy = 45, bomb = 20, bio = 100, rad = 100) // As close to the actual Dark Gygax as possible
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
unsuitable_atoms_damage = 0
|
||||
|
||||
ranged = 1
|
||||
rapid = 1
|
||||
projectiletype = /obj/item/projectile/beam/midlaser
|
||||
projectilesound = 'sound/weapons/laser.ogg'
|
||||
|
||||
speak_chance = 1
|
||||
speak = list("Know what we need? More meatshields.",
|
||||
"Glad I finally got a mech.",
|
||||
"I'll stomp those NanoTrasen dogs into paste.",
|
||||
"Glad I didn't become a line chef.",
|
||||
"This anti-fog visor is nice...",
|
||||
"Did I refill the air tank?")
|
||||
emote_hear = list("humms ominously","whirrs softly","grinds a gear")
|
||||
emote_see = list("looks around the area","turns from side to side")
|
||||
say_understood = list()
|
||||
say_cannot = list()
|
||||
say_maybe_target = list("Just my sensors?","Detecting something?","Is that...?","What was that?")
|
||||
say_got_target = list("ENGAGING!!!","CONTACT!!!","TARGET SPOTTED!","FOUND ONE!")
|
||||
reactions = list()
|
||||
|
||||
var/datum/effect/effect/system/spark_spread/sparks
|
||||
var/wreckage = /obj/effect/decal/mecha_wreckage/gygax/dark
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/New()
|
||||
..()
|
||||
sparks = new (src)
|
||||
sparks.set_up(3, 1, src)
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/Destroy()
|
||||
qdel(sparks)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/Life()
|
||||
. = ..()
|
||||
if(!.) return
|
||||
if((health < getMaxHealth()*0.3) && prob(10))
|
||||
sparks.start()
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/bullet_act()
|
||||
..()
|
||||
sparks.start()
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/death()
|
||||
..(0,"explodes!")
|
||||
sparks.start()
|
||||
explosion(get_turf(src), 0, 0, 1, 3)
|
||||
qdel(src)
|
||||
new /obj/effect/decal/mecha_wreckage/gygax/dark(get_turf(src))
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/Move()
|
||||
..()
|
||||
playsound(src,'sound/mecha/mechstep.ogg',40,1)
|
||||
|
||||
// This is a PoI mob, not the normal, floaty drones that hang out around windows
|
||||
/mob/living/simple_animal/hostile/mecha/malf_drone
|
||||
name = "autonomous mechanized drone"
|
||||
desc = "It appears to be an exosuit, piloted by a drone intelligence. It looks scary."
|
||||
intelligence_level = SA_ROBOTIC
|
||||
faction = "malf_drone"
|
||||
speak_chance = 1
|
||||
speak = list(
|
||||
"Resuming task: Protect area.",
|
||||
"No threats found.",
|
||||
"Error: No targets found."
|
||||
)
|
||||
emote_hear = list("humms ominously", "whirrs softly", "grinds a gear")
|
||||
emote_see = list("looks around the area", "turns from side to side")
|
||||
say_understood = list("Affirmative.", "Positive.")
|
||||
say_cannot = list("Denied.", "Negative.")
|
||||
say_maybe_target = list("Possible threat detected. Investigating.", "Motion detected.", "Investigating.")
|
||||
say_got_target = list("Threat detected.", "New task: Remove threat.", "Threat removal engaged.", "Engaging target.")
|
||||
returns_home = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/malf_drone/isSynthetic()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/mecha/malf_drone/speech_bubble_appearance()
|
||||
return "synthetic_evil"
|
||||
@@ -1,72 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/pirate
|
||||
name = "Pirate"
|
||||
desc = "Does what he wants cause a pirate is free."
|
||||
tt_desc = "E Homo sapiens"
|
||||
icon_state = "piratemelee"
|
||||
icon_living = "piratemelee"
|
||||
icon_dead = "piratemelee_dead"
|
||||
intelligence_level = SA_HUMANOID
|
||||
|
||||
faction = "pirate"
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
speed = 4
|
||||
|
||||
run_at_them = 0
|
||||
cooperative = 1
|
||||
investigates = 1
|
||||
firing_lines = 1
|
||||
returns_home = 1
|
||||
reacts = 1
|
||||
|
||||
turns_per_move = 5
|
||||
stop_when_pulled = 0
|
||||
|
||||
response_help = "pushes"
|
||||
response_disarm = "shoves"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
attack_armor_pen = 50
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
|
||||
attacktext = list("slashed")
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
|
||||
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_atoms_damage = 15
|
||||
|
||||
loot_list = list(/obj/item/weapon/melee/energy/sword/pirate = 100)
|
||||
|
||||
var/corpse = /obj/effect/landmark/mobcorpse/pirate
|
||||
|
||||
/mob/living/simple_animal/hostile/pirate/ranged
|
||||
name = "Pirate Gunner"
|
||||
icon_state = "pirateranged"
|
||||
icon_living = "pirateranged"
|
||||
icon_dead = "piratemelee_dead"
|
||||
|
||||
ranged = 1
|
||||
projectiletype = /obj/item/projectile/beam
|
||||
projectilesound = 'sound/weapons/laser.ogg'
|
||||
|
||||
loot_list = list(/obj/item/weapon/gun/energy/laser = 100)
|
||||
|
||||
corpse = /obj/effect/landmark/mobcorpse/pirate/ranged
|
||||
|
||||
/mob/living/simple_animal/hostile/pirate/death()
|
||||
..()
|
||||
if(corpse)
|
||||
new corpse (src.loc)
|
||||
qdel(src)
|
||||
return
|
||||
@@ -1,68 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/russian
|
||||
name = "russian"
|
||||
desc = "For the Motherland!"
|
||||
tt_desc = "E Homo sapiens"
|
||||
icon_state = "russianmelee"
|
||||
icon_living = "russianmelee"
|
||||
icon_dead = "russianmelee_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
intelligence_level = SA_HUMANOID
|
||||
|
||||
faction = "russian"
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
speed = 4
|
||||
|
||||
run_at_them = 0
|
||||
cooperative = 1
|
||||
investigates = 1
|
||||
firing_lines = 1
|
||||
returns_home = 1
|
||||
reacts = 1
|
||||
|
||||
turns_per_move = 5
|
||||
stop_when_pulled = 0
|
||||
status_flags = CANPUSH
|
||||
|
||||
response_help = "pokes"
|
||||
response_disarm = "shoves"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attacktext = list("punched")
|
||||
|
||||
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_atoms_damage = 15
|
||||
|
||||
loot_list = list(/obj/item/weapon/material/knife = 100)
|
||||
|
||||
var/corpse = /obj/effect/landmark/mobcorpse/russian
|
||||
|
||||
/mob/living/simple_animal/hostile/russian/ranged
|
||||
icon_state = "russianranged"
|
||||
icon_living = "russianranged"
|
||||
|
||||
ranged = 1
|
||||
projectiletype = /obj/item/projectile/bullet
|
||||
casingtype = /obj/item/ammo_casing/spent
|
||||
projectilesound = 'sound/weapons/Gunshot.ogg'
|
||||
|
||||
loot_list = list(/obj/item/weapon/gun/projectile/revolver/mateba = 100)
|
||||
|
||||
corpse = /obj/effect/landmark/mobcorpse/russian/ranged
|
||||
|
||||
/mob/living/simple_animal/hostile/russian/death()
|
||||
..()
|
||||
if(corpse)
|
||||
new corpse (src.loc)
|
||||
qdel(src)
|
||||
return
|
||||
@@ -1,265 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/syndicate
|
||||
name = "mercenary"
|
||||
desc = "Death to the Company."
|
||||
tt_desc = "E Homo sapiens"
|
||||
icon_state = "syndicate"
|
||||
icon_living = "syndicate"
|
||||
icon_dead = "syndicate_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
intelligence_level = SA_HUMANOID
|
||||
|
||||
faction = "syndicate"
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
speed = 4
|
||||
|
||||
run_at_them = 0
|
||||
cooperative = 1
|
||||
investigates = 1
|
||||
firing_lines = 1
|
||||
returns_home = 1
|
||||
reacts = 1
|
||||
|
||||
turns_per_move = 5
|
||||
stop_when_pulled = 0
|
||||
status_flags = CANPUSH
|
||||
|
||||
response_help = "pokes"
|
||||
response_disarm = "shoves"
|
||||
response_harm = "hits"
|
||||
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 15 //Tac Knife damage
|
||||
melee_damage_upper = 15
|
||||
environment_smash = 1
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
attacktext = list("slashed", "stabbed")
|
||||
|
||||
armor = list(melee = 40, bullet = 30, laser = 30, energy = 10, bomb = 10, bio = 100, rad = 100) // Same armor values as the vest they drop, plus simple mob immunities
|
||||
|
||||
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_atoms_damage = 15
|
||||
|
||||
speak_chance = 1
|
||||
speak = list("Fuckin' NT, man.",
|
||||
"When are we gonna get out of this chicken-shit outfit?",
|
||||
"Wish I had better equipment...",
|
||||
"I knew I should have been a line chef...",
|
||||
"Fuckin' helmet keeps fogging up.",
|
||||
"Anyone else smell that?")
|
||||
emote_hear = list("sniffs","coughs","taps his foot")
|
||||
emote_see = list("looks around","checks his equipment")
|
||||
say_understood = list()
|
||||
say_cannot = list()
|
||||
say_maybe_target = list("What's that?","Is someone there?","Is that...?","Hmm?")
|
||||
say_got_target = list("ENGAGING!!!","CONTACT!!!","TARGET SPOTTED!","FOUND ONE!")
|
||||
reactions = list("Hey guys, you ready?" = "Fuck yeah!")
|
||||
|
||||
var/corpse = /obj/effect/landmark/mobcorpse/syndicatesoldier
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/death()
|
||||
if(corpse)
|
||||
..()
|
||||
new corpse (src.loc)
|
||||
else
|
||||
..(0,"explodes!")
|
||||
new /obj/effect/gibspawner/human(src.loc)
|
||||
explosion(get_turf(src), -1, 0, 1, 3)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
///////////////Sword and shield////////////
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/melee
|
||||
icon_state = "syndicatemelee"
|
||||
icon_living = "syndicatemelee"
|
||||
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
attack_armor_pen = 50
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
attacktext = list("slashed")
|
||||
|
||||
status_flags = 0
|
||||
|
||||
loot_list = list(/obj/item/weapon/melee/energy/sword/red = 100, /obj/item/weapon/shield/energy = 100)
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/melee/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(O.force)
|
||||
if(prob(20))
|
||||
visible_message("<span class='danger'>\The [src] blocks \the [O] with its shield!</span>")
|
||||
if(user)
|
||||
react_to_attack(user)
|
||||
return
|
||||
else
|
||||
..()
|
||||
else
|
||||
usr << "<span class='warning'>This weapon is ineffective, it does no damage.</span>"
|
||||
visible_message("<span class='warning'>\The [user] gently taps [src] with \the [O].</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/melee/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(!Proj) return
|
||||
if(prob(35))
|
||||
visible_message("<font color='red'><B>[src] blocks [Proj] with its shield!</B></font>")
|
||||
if(Proj.firer)
|
||||
react_to_attack(Proj.firer)
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/melee/space
|
||||
name = "syndicate commando"
|
||||
icon_state = "syndicatemeleespace"
|
||||
icon_living = "syndicatemeleespace"
|
||||
|
||||
speed = 0
|
||||
|
||||
armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 100) // Same armor as their voidsuit
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
corpse = /obj/effect/landmark/mobcorpse/syndicatecommando
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(var/check_drift = 0)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged
|
||||
icon_state = "syndicateranged"
|
||||
icon_living = "syndicateranged"
|
||||
|
||||
ranged = 1
|
||||
rapid = 1
|
||||
projectiletype = /obj/item/projectile/bullet/pistol/medium
|
||||
// casingtype = /obj/item/ammo_casing/spent //Makes infinite stacks of bullets when put in PoIs.
|
||||
projectilesound = 'sound/weapons/Gunshot_light.ogg'
|
||||
|
||||
loot_list = list(/obj/item/weapon/gun/projectile/automatic/c20r = 100)
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/laser
|
||||
icon_state = "syndicateranged_laser"
|
||||
icon_living = "syndicateranged_laser"
|
||||
rapid = 0
|
||||
projectiletype = /obj/item/projectile/beam/midlaser
|
||||
projectilesound = 'sound/weapons/Laser.ogg'
|
||||
|
||||
loot_list = list(/obj/item/weapon/gun/energy/laser = 100)
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/ionrifle
|
||||
icon_state = "syndicateranged_ionrifle"
|
||||
icon_living = "syndicateranged_ionrifle"
|
||||
rapid = 0
|
||||
projectiletype = /obj/item/projectile/ion
|
||||
projectilesound = 'sound/weapons/Laser.ogg'
|
||||
|
||||
loot_list = list(/obj/item/weapon/gun/energy/ionrifle = 100)
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/space
|
||||
name = "syndicate sommando"
|
||||
icon_state = "syndicaterangedpsace"
|
||||
icon_living = "syndicaterangedpsace"
|
||||
|
||||
speed = 0
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
corpse = /obj/effect/landmark/mobcorpse/syndicatecommando
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(var/check_drift = 0)
|
||||
return
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// POI Mobs
|
||||
// Don't leave corpses, to help balance loot.
|
||||
///////////////////////////////////////////////
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/poi
|
||||
loot_list = list()
|
||||
corpse = null
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/melee/poi
|
||||
loot_list = list()
|
||||
corpse = null
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/melee/space/poi
|
||||
loot_list = list()
|
||||
corpse = null
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/poi
|
||||
loot_list = list()
|
||||
corpse = null
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/laser/poi
|
||||
loot_list = list()
|
||||
corpse = null
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/ionrifle/poi
|
||||
loot_list = list()
|
||||
corpse = null
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/space/poi
|
||||
loot_list = list()
|
||||
corpse = null
|
||||
|
||||
|
||||
//Viscerators
|
||||
|
||||
/mob/living/simple_animal/hostile/viscerator
|
||||
name = "viscerator"
|
||||
desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations."
|
||||
icon = 'icons/mob/critter.dmi'
|
||||
icon_state = "viscerator_attack"
|
||||
icon_living = "viscerator_attack"
|
||||
intelligence_level = SA_ROBOTIC
|
||||
hovering = TRUE
|
||||
|
||||
faction = "syndicate"
|
||||
maxHealth = 15
|
||||
health = 15
|
||||
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attack_sharp = 1
|
||||
attack_edge = 1
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
attacktext = list("cut")
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/viscerator/death()
|
||||
..(null,"is smashed into pieces!")
|
||||
qdel(src)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,311 +0,0 @@
|
||||
/mob/living/simple_animal/instantiate_hud(var/datum/hud/hud)
|
||||
if(!client)
|
||||
return //Why bother.
|
||||
|
||||
var/ui_style = 'icons/mob/screen1_animal.dmi'
|
||||
if(ui_icons)
|
||||
ui_style = ui_icons
|
||||
|
||||
var/ui_color = "#ffffff"
|
||||
var/ui_alpha = 255
|
||||
|
||||
var/list/adding = list()
|
||||
var/list/other = list()
|
||||
var/list/hotkeybuttons = list()
|
||||
var/list/slot_info = list()
|
||||
|
||||
hud.adding = adding
|
||||
hud.other = other
|
||||
hud.hotkeybuttons = hotkeybuttons
|
||||
|
||||
var/list/hud_elements = list()
|
||||
var/obj/screen/using
|
||||
var/obj/screen/inventory/inv_box
|
||||
|
||||
var/has_hidden_gear
|
||||
if(LAZYLEN(hud_gears))
|
||||
for(var/gear_slot in hud_gears)
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.icon = ui_style
|
||||
inv_box.color = ui_color
|
||||
inv_box.alpha = ui_alpha
|
||||
|
||||
var/list/slot_data = hud_gears[gear_slot]
|
||||
inv_box.name = gear_slot
|
||||
inv_box.screen_loc = slot_data["loc"]
|
||||
inv_box.slot_id = slot_data["slot"]
|
||||
inv_box.icon_state = slot_data["state"]
|
||||
slot_info["[inv_box.slot_id]"] = inv_box.screen_loc
|
||||
|
||||
if(slot_data["dir"])
|
||||
inv_box.set_dir(slot_data["dir"])
|
||||
|
||||
if(slot_data["toggle"])
|
||||
other += inv_box
|
||||
has_hidden_gear = 1
|
||||
else
|
||||
adding += inv_box
|
||||
|
||||
if(has_hidden_gear)
|
||||
using = new /obj/screen()
|
||||
using.name = "toggle"
|
||||
using.icon = ui_style
|
||||
using.icon_state = "other"
|
||||
using.screen_loc = ui_inventory
|
||||
using.hud_layerise()
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
adding += using
|
||||
|
||||
//Intent Backdrop
|
||||
using = new /obj/screen()
|
||||
using.name = "act_intent"
|
||||
using.icon = ui_style
|
||||
using.icon_state = "intent_"+a_intent
|
||||
using.screen_loc = ui_acti
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
hud.action_intent = using
|
||||
|
||||
hud_elements |= using
|
||||
|
||||
//Small intent quarters
|
||||
var/icon/ico
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height())
|
||||
using = new /obj/screen()
|
||||
using.name = I_HELP
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM //These sit on the intent box
|
||||
hud.adding += using
|
||||
hud.help_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height())
|
||||
using = new /obj/screen()
|
||||
using.name = I_DISARM
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM
|
||||
hud.adding += using
|
||||
hud.disarm_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2)
|
||||
using = new /obj/screen()
|
||||
using.name = I_GRAB
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM
|
||||
hud.adding += using
|
||||
hud.grab_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2)
|
||||
using = new /obj/screen()
|
||||
using.name = I_HURT
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM
|
||||
hud.adding += using
|
||||
hud.hurt_intent = using
|
||||
|
||||
//Move intent (walk/run)
|
||||
using = new /obj/screen()
|
||||
using.name = "mov_intent"
|
||||
using.icon = ui_style
|
||||
using.icon_state = (m_intent == "run" ? "running" : "walking")
|
||||
using.screen_loc = ui_movi
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
hud.move_intent = using
|
||||
|
||||
//Resist button
|
||||
using = new /obj/screen()
|
||||
using.name = "resist"
|
||||
using.icon = ui_style
|
||||
using.icon_state = "act_resist"
|
||||
using.screen_loc = ui_pull_resist
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.hotkeybuttons += using
|
||||
|
||||
//Pull button
|
||||
pullin = new /obj/screen()
|
||||
pullin.icon = ui_style
|
||||
pullin.icon_state = "pull0"
|
||||
pullin.name = "pull"
|
||||
pullin.screen_loc = ui_pull_resist
|
||||
hud.hotkeybuttons += pullin
|
||||
hud_elements |= pullin
|
||||
|
||||
//Health status
|
||||
healths = new /obj/screen()
|
||||
healths.icon = ui_style
|
||||
healths.icon_state = "health0"
|
||||
healths.name = "health"
|
||||
healths.screen_loc = ui_health
|
||||
hud_elements |= healths
|
||||
|
||||
//Oxygen dep icon
|
||||
oxygen = new /obj/screen()
|
||||
oxygen.icon = ui_style
|
||||
oxygen.icon_state = "oxy0"
|
||||
oxygen.name = "oxygen"
|
||||
oxygen.screen_loc = ui_oxygen
|
||||
hud_elements |= oxygen
|
||||
|
||||
//Toxins present icon
|
||||
toxin = new /obj/screen()
|
||||
toxin.icon = ui_style
|
||||
toxin.icon_state = "tox0"
|
||||
toxin.name = "toxin"
|
||||
toxin.screen_loc = ui_toxin
|
||||
hud_elements |= toxin
|
||||
|
||||
//Fire warning
|
||||
fire = new /obj/screen()
|
||||
fire.icon = ui_style
|
||||
fire.icon_state = "fire0"
|
||||
fire.name = "fire"
|
||||
fire.screen_loc = ui_fire
|
||||
hud_elements |= fire
|
||||
|
||||
//Pressure warning
|
||||
pressure = new /obj/screen()
|
||||
pressure.icon = ui_style
|
||||
pressure.icon_state = "pressure0"
|
||||
pressure.name = "pressure"
|
||||
pressure.screen_loc = ui_pressure
|
||||
hud_elements |= pressure
|
||||
|
||||
//Body temp warning
|
||||
bodytemp = new /obj/screen()
|
||||
bodytemp.icon = ui_style
|
||||
bodytemp.icon_state = "temp0"
|
||||
bodytemp.name = "body temperature"
|
||||
bodytemp.screen_loc = ui_temp
|
||||
hud_elements |= bodytemp
|
||||
|
||||
//Nutrition status
|
||||
nutrition_icon = new /obj/screen()
|
||||
nutrition_icon.icon = ui_style
|
||||
nutrition_icon.icon_state = "nutrition0"
|
||||
nutrition_icon.name = "nutrition"
|
||||
nutrition_icon.screen_loc = ui_nutrition
|
||||
hud_elements |= nutrition_icon
|
||||
|
||||
pain = new /obj/screen( null )
|
||||
|
||||
zone_sel = new /obj/screen/zone_sel( null )
|
||||
zone_sel.icon = ui_style
|
||||
zone_sel.color = ui_color
|
||||
zone_sel.alpha = ui_alpha
|
||||
zone_sel.overlays.Cut()
|
||||
zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[zone_sel.selecting]")
|
||||
hud_elements |= zone_sel
|
||||
|
||||
//Hand things
|
||||
if(has_hands)
|
||||
//Drop button
|
||||
using = new /obj/screen()
|
||||
using.name = "drop"
|
||||
using.icon = ui_style
|
||||
using.icon_state = "act_drop"
|
||||
using.screen_loc = ui_drop_throw
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.hotkeybuttons += using
|
||||
|
||||
//Equip detail
|
||||
using = new /obj/screen()
|
||||
using.name = "equip"
|
||||
using.icon = ui_style
|
||||
using.icon_state = "act_equip"
|
||||
using.screen_loc = ui_equip
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
|
||||
//Hand slots themselves
|
||||
inv_box = new /obj/screen/inventory/hand()
|
||||
inv_box.hud = src
|
||||
inv_box.name = "r_hand"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "r_hand_inactive"
|
||||
if(!hand) //This being 0 or null means the right hand is in use
|
||||
inv_box.icon_state = "r_hand_active"
|
||||
inv_box.screen_loc = ui_rhand
|
||||
inv_box.slot_id = slot_r_hand
|
||||
inv_box.color = ui_color
|
||||
inv_box.alpha = ui_alpha
|
||||
hud.r_hand_hud_object = inv_box
|
||||
hud.adding += inv_box
|
||||
slot_info["[slot_r_hand]"] = inv_box.screen_loc
|
||||
|
||||
inv_box = new /obj/screen/inventory/hand()
|
||||
inv_box.hud = src
|
||||
inv_box.name = "l_hand"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "l_hand_inactive"
|
||||
if(hand) //This being 1 means the left hand is in use
|
||||
inv_box.icon_state = "l_hand_active"
|
||||
inv_box.screen_loc = ui_lhand
|
||||
inv_box.slot_id = slot_l_hand
|
||||
inv_box.color = ui_color
|
||||
inv_box.alpha = ui_alpha
|
||||
hud.l_hand_hud_object = inv_box
|
||||
hud.adding += inv_box
|
||||
slot_info["[slot_l_hand]"] = inv_box.screen_loc
|
||||
|
||||
//Swaphand titlebar
|
||||
using = new /obj/screen/inventory()
|
||||
using.name = "hand"
|
||||
using.icon = ui_style
|
||||
using.icon_state = "hand1"
|
||||
using.screen_loc = ui_swaphand1
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
|
||||
using = new /obj/screen/inventory()
|
||||
using.name = "hand"
|
||||
using.icon = ui_style
|
||||
using.icon_state = "hand2"
|
||||
using.screen_loc = ui_swaphand2
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
|
||||
//Throw button
|
||||
throw_icon = new /obj/screen()
|
||||
throw_icon.icon = ui_style
|
||||
throw_icon.icon_state = "act_throw_off"
|
||||
throw_icon.name = "throw"
|
||||
throw_icon.screen_loc = ui_drop_throw
|
||||
throw_icon.color = ui_color
|
||||
throw_icon.alpha = ui_alpha
|
||||
hud.hotkeybuttons += throw_icon
|
||||
hud_elements |= throw_icon
|
||||
|
||||
extra_huds(hud,ui_style,hud_elements)
|
||||
|
||||
client.screen = list()
|
||||
|
||||
client.screen += hud_elements
|
||||
client.screen += adding + hotkeybuttons
|
||||
client.screen += client.void
|
||||
|
||||
return
|
||||
@@ -1,91 +0,0 @@
|
||||
/mob/living/simple_animal/slime/FindTarget()
|
||||
if(victim) // Don't worry about finding another target if we're eatting someone.
|
||||
return
|
||||
if(follow_mob && can_command(follow_mob)) // If following someone, don't attack until the leader says so, something hits you, or the leader is no longer worthy.
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/Found(mob/living/L)
|
||||
if(isliving(L))
|
||||
if(SA_attackable(L))
|
||||
if(L.faction == faction && !attack_same)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too.
|
||||
return H // Monkeys are always food.
|
||||
else
|
||||
return
|
||||
|
||||
if(L in friends)
|
||||
return
|
||||
|
||||
if(istype(L, /mob/living/simple_animal/slime))
|
||||
var/mob/living/simple_animal/slime/buddy = L
|
||||
if(buddy.slime_color == src.slime_color || discipline || unity || buddy.unity)
|
||||
return // Don't hurt same colored slimes.
|
||||
else
|
||||
return buddy //do hurt others
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too.
|
||||
return H // Monkeys are always food.
|
||||
|
||||
if(issilicon(L) || isbot(L))
|
||||
if(discipline && !rabid)
|
||||
return // We're a good slime. For now at least.
|
||||
return
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/special_target_check(mob/living/L)
|
||||
if(L.faction == faction && !attack_same && !istype(L, /mob/living/simple_animal/slime))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too.
|
||||
return TRUE // Monkeys are always food.
|
||||
else
|
||||
return FALSE
|
||||
if(L in friends)
|
||||
return FALSE
|
||||
|
||||
if(istype(L, /mob/living/simple_animal/slime))
|
||||
var/mob/living/simple_animal/slime/buddy = L
|
||||
if(buddy.slime_color == src.slime_color || discipline || unity || buddy.unity)
|
||||
return FALSE // Don't hurt same colored slimes.
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.species && H.species.name == "Promethean")
|
||||
return FALSE // Prometheans are always our friends.
|
||||
else if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too.
|
||||
return TRUE // Monkeys are always food.
|
||||
if(discipline && !rabid)
|
||||
return FALSE // We're a good slime. For now at least
|
||||
|
||||
if(issilicon(L) || isbot(L) )
|
||||
if(discipline && !rabid)
|
||||
return FALSE // We're a good slime. For now at least.
|
||||
return ..() // Other colors and nonslimes are jerks however.
|
||||
|
||||
/mob/living/simple_animal/slime/ClosestDistance()
|
||||
if(target_mob.stat == DEAD)
|
||||
return 1 // Melee (eat) the target if dead, don't shoot it.
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/slime/HelpRequested(var/mob/living/simple_animal/slime/buddy)
|
||||
if(istype(buddy))
|
||||
if(buddy.slime_color != src.slime_color && (!unity || !buddy.unity)) // We only help slimes of the same color, if it's another slime calling for help.
|
||||
ai_log("HelpRequested() by [buddy] but they are a [buddy.slime_color] while we are a [src.slime_color].",2)
|
||||
return
|
||||
if(buddy.target_mob)
|
||||
if(!special_target_check(buddy.target_mob))
|
||||
ai_log("HelpRequested() by [buddy] but special_target_check() failed when passed [buddy.target_mob].",2)
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/handle_resist()
|
||||
if(buckled && victim && isliving(buckled) && victim == buckled) // If it's buckled to a living thing it's probably eating it.
|
||||
return
|
||||
else
|
||||
..()
|
||||
@@ -1,277 +0,0 @@
|
||||
|
||||
|
||||
/*
|
||||
// Check target_mob if worthy of attack
|
||||
/mob/living/simple_animal/slime/SA_attackable(target_mob)
|
||||
ai_log("SA_attackable([target_mob])",3)
|
||||
if(isliving(target_mob))
|
||||
var/mob/living/L = target_mob
|
||||
if(L.stat == DEAD)
|
||||
if(can_consume(L)) // If we can eat them, then it doesn't matter if they're dead.
|
||||
return TRUE
|
||||
..()
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/slime/PunchTarget()
|
||||
if(victim)
|
||||
return // Already eatting someone.
|
||||
if(!client) // AI controlled.
|
||||
if( (!target_mob.lying && prob(60 + (power_charge * 4) ) || (!target_mob.lying && optimal_combat) )) // "Smart" slimes always stun first.
|
||||
a_intent = I_DISARM // Stun them first.
|
||||
else if(can_consume(target_mob) && target_mob.lying)
|
||||
a_intent = I_GRAB // Then eat them.
|
||||
else
|
||||
a_intent = I_HURT // Otherwise robust them.
|
||||
ai_log("PunchTarget() will [a_intent] [target_mob]",2)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/proc/can_consume(var/mob/living/L)
|
||||
if(!L || !istype(L))
|
||||
to_chat(src, "This subject is incomparable...")
|
||||
return FALSE
|
||||
if(L.isSynthetic())
|
||||
to_chat(src, "This subject is not biological...")
|
||||
return FALSE
|
||||
if(L.getarmor(null, "bio") >= 75)
|
||||
to_chat(src, "I cannot reach this subject's biological matter...")
|
||||
return FALSE
|
||||
if(istype(L, /mob/living/simple_animal/slime))
|
||||
to_chat(src, "I cannot feed on other slimes...")
|
||||
return FALSE
|
||||
if(!Adjacent(L))
|
||||
to_chat(src, "This subject is too far away...")
|
||||
return FALSE
|
||||
if(istype(L, /mob/living/carbon) && L.getCloneLoss() >= L.getMaxHealth() * 1.5 || istype(L, /mob/living/simple_animal) && L.stat == DEAD)
|
||||
to_chat(src, "This subject does not have an edible life energy...")
|
||||
return FALSE
|
||||
if(L.has_buckled_mobs())
|
||||
for(var/A in L.buckled_mobs)
|
||||
if(istype(A, /mob/living/simple_animal/slime))
|
||||
if(A != src)
|
||||
to_chat(src, "\The [A] is already feeding on this subject...")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/slime/proc/start_consuming(var/mob/living/L)
|
||||
if(!can_consume(L))
|
||||
return
|
||||
if(!Adjacent(L))
|
||||
return
|
||||
step_towards(src, L) // Get on top of them to feed.
|
||||
if(loc != L.loc)
|
||||
return
|
||||
if(L.buckle_mob(src, forced = TRUE))
|
||||
victim = L
|
||||
update_icon()
|
||||
victim.visible_message("<span class='danger'>\The [src] latches onto [victim]!</span>",
|
||||
"<span class='danger'>\The [src] latches onto you!</span>")
|
||||
|
||||
/mob/living/simple_animal/slime/proc/stop_consumption()
|
||||
if(!victim)
|
||||
return
|
||||
victim.unbuckle_mob()
|
||||
victim.visible_message("<span class='notice'>\The [src] slides off of [victim]!</span>",
|
||||
"<span class='notice'>\The [src] slides off of you!</span>")
|
||||
victim = null
|
||||
update_icon()
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/proc/handle_consumption()
|
||||
if(victim && can_consume(victim) && !stat)
|
||||
|
||||
var/armor_modifier = abs((victim.getarmor(null, "bio") / 100) - 1)
|
||||
if(istype(victim, /mob/living/carbon))
|
||||
victim.adjustCloneLoss(rand(5,6) * armor_modifier)
|
||||
victim.adjustToxLoss(rand(1,2) * armor_modifier)
|
||||
if(victim.health <= 0)
|
||||
victim.adjustToxLoss(rand(2,4) * armor_modifier)
|
||||
|
||||
else if(istype(victim, /mob/living/simple_animal))
|
||||
victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12))
|
||||
|
||||
else
|
||||
to_chat(src, "<span class='warning'>[pick("This subject is incompatable", \
|
||||
"This subject does not have a life energy", "This subject is empty", "I am not satisified", \
|
||||
"I can not feed from this subject", "I do not feel nourished", "This subject is not food")]...</span>")
|
||||
stop_consumption()
|
||||
|
||||
adjust_nutrition(50 * armor_modifier)
|
||||
|
||||
adjustOxyLoss(-10 * armor_modifier) //Heal yourself
|
||||
adjustBruteLoss(-10 * armor_modifier)
|
||||
adjustFireLoss(-10 * armor_modifier)
|
||||
adjustCloneLoss(-10 * armor_modifier)
|
||||
updatehealth()
|
||||
if(victim)
|
||||
victim.updatehealth()
|
||||
else
|
||||
stop_consumption()
|
||||
|
||||
/mob/living/simple_animal/slime/DoPunch(var/mob/living/L)
|
||||
if(!Adjacent(L)) // Might've moved away in the meantime.
|
||||
return
|
||||
|
||||
if(istype(L))
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
// Slime attacks can be blocked with shields.
|
||||
if(H.check_shields(damage = 0, damage_source = null, attacker = src, def_zone = null, attack_text = "the attack"))
|
||||
return
|
||||
|
||||
switch(a_intent)
|
||||
if(I_HELP)
|
||||
ai_log("DoPunch() against [L], helping.",2)
|
||||
L.visible_message("<span class='notice'>[src] gently pokes [L]!</span>",
|
||||
"<span class='notice'>[src] gently pokes you!</span>")
|
||||
do_attack_animation(L)
|
||||
post_attack(L, a_intent)
|
||||
|
||||
if(I_DISARM)
|
||||
ai_log("DoPunch() against [L], disarming.",2)
|
||||
var/stun_power = between(0, power_charge + rand(0, 3), 10)
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
stun_power *= max(H.species.siemens_coefficient,0)
|
||||
|
||||
|
||||
if(prob(stun_power * 10))
|
||||
power_charge = max(0, power_charge - 3)
|
||||
L.visible_message("<span class='danger'>[src] has shocked [L]!</span>", "<span class='danger'>[src] has shocked you!</span>")
|
||||
playsound(src, 'sound/weapons/Egloves.ogg', 75, 1)
|
||||
L.Weaken(4)
|
||||
L.Stun(4)
|
||||
do_attack_animation(L)
|
||||
if(L.buckled)
|
||||
L.buckled.unbuckle_mob() // To prevent an exploit where being buckled prevents slimes from jumping on you.
|
||||
L.stuttering = max(L.stuttering, stun_power)
|
||||
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(5, 1, L)
|
||||
s.start()
|
||||
|
||||
if(prob(stun_power * 10) && stun_power >= 8)
|
||||
L.adjustFireLoss(power_charge * rand(1, 2))
|
||||
post_attack(L, a_intent)
|
||||
|
||||
else if(prob(40))
|
||||
L.visible_message("<span class='danger'>[src] has pounced at [L]!</span>", "<span class='danger'>[src] has pounced at you!</span>")
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 75, 1)
|
||||
L.Weaken(2)
|
||||
do_attack_animation(L)
|
||||
if(L.buckled)
|
||||
L.buckled.unbuckle_mob() // To prevent an exploit where being buckled prevents slimes from jumping on you.
|
||||
post_attack(L, a_intent)
|
||||
else
|
||||
L.visible_message("<span class='danger'>[src] has tried to pounce at [L]!</span>", "<span class='danger'>[src] has tried to pounce at you!</span>")
|
||||
playsound(src, 'sound/weapons/punchmiss.ogg', 75, 1)
|
||||
do_attack_animation(L)
|
||||
L.updatehealth()
|
||||
return L
|
||||
|
||||
if(I_GRAB)
|
||||
ai_log("DoPunch() against [L], grabbing.",2)
|
||||
start_consuming(L)
|
||||
post_attack(L, a_intent)
|
||||
|
||||
if(I_HURT)
|
||||
ai_log("DoPunch() against [L], hurting.",2)
|
||||
var/damage_to_do = rand(melee_damage_lower, melee_damage_upper)
|
||||
var/armor_modifier = abs((L.getarmor(null, "bio") / 100) - 1)
|
||||
|
||||
L.attack_generic(src, damage_to_do, pick(attacktext))
|
||||
playsound(src, 'sound/weapons/bite.ogg', 75, 1)
|
||||
|
||||
// Give the slime some nutrition, if applicable.
|
||||
if(!L.isSynthetic())
|
||||
if(ishuman(L))
|
||||
if(L.getCloneLoss() < L.getMaxHealth() * 1.5)
|
||||
adjust_nutrition(damage_to_do * armor_modifier)
|
||||
|
||||
else if(istype(L, /mob/living/simple_animal))
|
||||
if(!isslime(L))
|
||||
var/mob/living/simple_animal/SA = L
|
||||
if(!SA.stat)
|
||||
adjust_nutrition(damage_to_do)
|
||||
|
||||
post_attack(L, a_intent)
|
||||
|
||||
if(istype(L,/obj/mecha))
|
||||
var/obj/mecha/M = L
|
||||
M.attack_generic(src, rand(melee_damage_lower, melee_damage_upper), pick(attacktext))
|
||||
|
||||
/mob/living/simple_animal/slime/proc/post_attack(var/mob/living/L, var/intent = I_HURT)
|
||||
if(intent != I_HELP)
|
||||
if(L.reagents && L.can_inject() && reagent_injected)
|
||||
L.reagents.add_reagent(reagent_injected, injection_amount)
|
||||
|
||||
/mob/living/simple_animal/slime/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/clothing/head)) // Handle hat simulator.
|
||||
give_hat(W, user)
|
||||
return
|
||||
|
||||
// Otherwise they're probably fighting the slime.
|
||||
if(prob(25))
|
||||
visible_message("<span class='danger'>\The [user]'s [W] passes right through [src]!</span>")
|
||||
user.setClickCooldown(user.get_attack_speed(W))
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
|
||||
..()
|
||||
if(!stat)
|
||||
if(O.force > 0 && discipline && !rabid) // wow, buddy, why am I getting attacked??
|
||||
adjust_discipline(1)
|
||||
return
|
||||
if(O.force >= 3)
|
||||
if(victim || target_mob) // We've been a bad slime.
|
||||
if(is_adult)
|
||||
if(prob(5 + round(O.force / 2)) )
|
||||
if(prob(80) && !client)
|
||||
adjust_discipline(2)
|
||||
if(user)
|
||||
step_away(src, user)
|
||||
else
|
||||
if(prob(10 + O.force * 2))
|
||||
if(prob(80) && !client)
|
||||
adjust_discipline(2)
|
||||
if(user)
|
||||
step_away(src, user)
|
||||
else
|
||||
if(user in friends) // Friend attacking us for no reason.
|
||||
if(prob(25))
|
||||
friends -= user
|
||||
say("[user]... not friend...")
|
||||
|
||||
/mob/living/simple_animal/slime/attack_hand(mob/living/carbon/human/M as mob)
|
||||
if(victim) // Are we eating someone?
|
||||
var/fail_odds = 30
|
||||
if(victim == M) // Harder to get the slime off if its eating you right now.
|
||||
fail_odds = 60
|
||||
|
||||
if(prob(fail_odds))
|
||||
visible_message("<span class='warning'>[M] attempts to wrestle \the [name] off!</span>")
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
|
||||
else
|
||||
visible_message("<span class='warning'> [M] manages to wrestle \the [name] off!</span>")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if(prob(40) && !client)
|
||||
adjust_discipline(1)
|
||||
stop_consumption()
|
||||
step_away(src,M)
|
||||
else
|
||||
if(M.a_intent == I_HELP)
|
||||
if(hat)
|
||||
remove_hat(M)
|
||||
else
|
||||
..()
|
||||
else
|
||||
..()
|
||||
|
||||
// Shocked grilles don't hurt slimes, and in fact give them charge.
|
||||
/mob/living/simple_animal/slime/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
|
||||
power_charge = between(0, power_charge + round(shock_damage / 10), 10)
|
||||
to_chat(src, "<span class='notice'>\The [source] shocks you, and it charges you.</span>")
|
||||
@@ -1,27 +0,0 @@
|
||||
/mob/living/simple_animal/slime/death(gibbed)
|
||||
|
||||
if(stat == DEAD)
|
||||
return
|
||||
|
||||
if(!gibbed && is_adult)
|
||||
var/death_type = type_on_death
|
||||
if(!death_type)
|
||||
death_type = src.type
|
||||
var/mob/living/simple_animal/slime/S = make_new_slime(death_type)
|
||||
S.rabid = TRUE
|
||||
step_away(S, src)
|
||||
is_adult = FALSE
|
||||
maxHealth = initial(maxHealth)
|
||||
revive()
|
||||
if(!client)
|
||||
rabid = TRUE
|
||||
number = rand(1, 1000)
|
||||
update_name()
|
||||
return
|
||||
|
||||
stop_consumption()
|
||||
. = ..(gibbed, "stops moving and partially dissolves...")
|
||||
|
||||
update_icon()
|
||||
|
||||
return
|
||||
@@ -1,183 +0,0 @@
|
||||
/mob/living/simple_animal/slime/proc/adjust_nutrition(input)
|
||||
nutrition = between(0, nutrition + input, get_max_nutrition())
|
||||
|
||||
if(input > 0)
|
||||
if(prob(input * 2)) // Gain around one level per 50 nutrition
|
||||
power_charge = min(power_charge++, 10)
|
||||
if(power_charge == 10)
|
||||
adjustToxLoss(-10)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/proc/get_max_nutrition() // Can't go above it
|
||||
if(is_adult)
|
||||
return 1200
|
||||
return 1000
|
||||
|
||||
/mob/living/simple_animal/slime/proc/get_grow_nutrition() // Above it we grow, below it we can eat
|
||||
if(is_adult)
|
||||
return 1000
|
||||
return 800
|
||||
|
||||
/mob/living/simple_animal/slime/proc/get_hunger_nutrition() // Below it we will always eat
|
||||
if(is_adult)
|
||||
return 600
|
||||
return 500
|
||||
|
||||
/mob/living/simple_animal/slime/proc/get_starve_nutrition() // Below it we will eat before everything else
|
||||
if(is_adult)
|
||||
return 300
|
||||
return 200
|
||||
|
||||
/mob/living/simple_animal/slime/proc/handle_nutrition()
|
||||
if(docile)
|
||||
return
|
||||
if(prob(15))
|
||||
adjust_nutrition(-1 - is_adult)
|
||||
|
||||
if(nutrition <= get_starve_nutrition())
|
||||
handle_starvation()
|
||||
|
||||
else if(nutrition >= get_grow_nutrition() && amount_grown < 10)
|
||||
adjust_nutrition(-20)
|
||||
amount_grown = between(0, amount_grown + 1, 10)
|
||||
|
||||
/mob/living/simple_animal/slime/proc/handle_starvation()
|
||||
if(nutrition < get_starve_nutrition() && !client) // if a slime is starving, it starts losing its friends
|
||||
if(friends.len && prob(1))
|
||||
var/mob/nofriend = pick(friends)
|
||||
if(nofriend)
|
||||
friends -= nofriend
|
||||
say("[nofriend]... food now...")
|
||||
|
||||
if(nutrition <= 0)
|
||||
adjustToxLoss(rand(1,3))
|
||||
if(client && prob(5))
|
||||
to_chat(src, "<span class='danger'>You are starving!</span>")
|
||||
|
||||
/mob/living/simple_animal/slime/proc/handle_discipline()
|
||||
if(discipline > 0)
|
||||
update_mood()
|
||||
// if(discipline >= 5 && rabid)
|
||||
// if(prob(60))
|
||||
// rabid = 0
|
||||
// adjust_discipline(1) // So it stops trying to murder everyone.
|
||||
|
||||
// Handle discipline decay.
|
||||
if(!prob(75 + (obedience * 5)))
|
||||
adjust_discipline(-1)
|
||||
if(!discipline)
|
||||
update_mood()
|
||||
|
||||
/mob/living/simple_animal/slime/handle_regular_status_updates()
|
||||
if(stat != DEAD)
|
||||
handle_nutrition()
|
||||
|
||||
handle_discipline()
|
||||
|
||||
if(prob(30))
|
||||
adjustOxyLoss(-1)
|
||||
adjustToxLoss(-1)
|
||||
adjustFireLoss(-1)
|
||||
adjustCloneLoss(-1)
|
||||
adjustBruteLoss(-1)
|
||||
|
||||
if(victim)
|
||||
handle_consumption()
|
||||
|
||||
if(amount_grown >= 10 && !target_mob && !client)
|
||||
if(is_adult)
|
||||
reproduce()
|
||||
else
|
||||
evolve()
|
||||
|
||||
handle_stuttering()
|
||||
|
||||
..()
|
||||
|
||||
|
||||
// This is to make slime responses feel a bit more natural and not instant.
|
||||
/mob/living/simple_animal/slime/proc/delayed_say(var/message, var/mob/target)
|
||||
spawn(rand(1 SECOND, 2 SECONDS))
|
||||
if(target)
|
||||
face_atom(target)
|
||||
say(message)
|
||||
|
||||
//Commands, reactions, etc
|
||||
/mob/living/simple_animal/slime/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
|
||||
..()
|
||||
if((findtext(message, num2text(number)) || findtext(message, name) || findtext(message, "slimes"))) // Talking to us
|
||||
|
||||
// First make sure it's not just another slime repeating things.
|
||||
if(istype(speaker, /mob/living/simple_animal/slime))
|
||||
if(!speaker.client)
|
||||
return
|
||||
|
||||
//Are all slimes being referred to?
|
||||
var/mass_order = 0
|
||||
if(findtext(message, "slimes"))
|
||||
mass_order = 1
|
||||
|
||||
// Say hello back.
|
||||
if(findtext(message, "hello") || findtext(message, "hi") || findtext(message, "greetings"))
|
||||
delayed_say(pick("Hello...", "Hi..."), speaker)
|
||||
|
||||
// Follow request.
|
||||
if(findtext(message, "follow") || findtext(message, "come with me"))
|
||||
if(!can_command(speaker))
|
||||
delayed_say(pick("No...", "I won't follow..."), speaker)
|
||||
return
|
||||
|
||||
delayed_say("Yes... I follow \the [speaker]...", speaker)
|
||||
set_follow(speaker)
|
||||
FollowTarget()
|
||||
|
||||
// Stop request.
|
||||
if(findtext(message, "stop") || findtext(message, "halt") || findtext(message, "cease"))
|
||||
if(victim) // We're being asked to stop eatting someone.
|
||||
if(!can_command(speaker))
|
||||
delayed_say("No...", speaker)
|
||||
return
|
||||
else
|
||||
delayed_say("Fine...", speaker)
|
||||
stop_consumption()
|
||||
adjust_discipline(1, TRUE)
|
||||
|
||||
if(target_mob) // We're being asked to stop chasing someone.
|
||||
if(!can_command(speaker))
|
||||
delayed_say("No...", speaker)
|
||||
return
|
||||
else
|
||||
delayed_say("Fine...", speaker)
|
||||
LoseTarget()
|
||||
adjust_discipline(1, TRUE)
|
||||
|
||||
if(follow_mob) // We're being asked to stop following someone.
|
||||
if(can_command(speaker) == SLIME_COMMAND_FRIEND || follow_mob == speaker)
|
||||
delayed_say("Yes... I'll stop...", speaker)
|
||||
LoseFollow()
|
||||
else
|
||||
delayed_say("No... I'll keep following \the [follow_mob]...", speaker)
|
||||
|
||||
// Murder request
|
||||
if(findtext(message, "harm") || findtext(message, "kill") || findtext(message, "murder") || findtext(message, "eat") || findtext(message, "consume"))
|
||||
if(can_command(speaker) < SLIME_COMMAND_FACTION)
|
||||
delayed_say("No...", speaker)
|
||||
return
|
||||
|
||||
for(var/mob/living/L in view(7, src) - list(src, speaker))
|
||||
if(L == src)
|
||||
continue // Don't target ourselves.
|
||||
var/list/valid_names = splittext(L.name, " ") // Should output list("John", "Doe") as an example.
|
||||
for(var/line in valid_names) // Check each part of someone's name.
|
||||
if(findtext(message, lowertext(line))) // If part of someone's name is in the command, the slime targets them if allowed to.
|
||||
if(!(mass_order && line == "slime")) //don't think random other slimes are target
|
||||
if(special_target_check(L))
|
||||
delayed_say("Okay... I attack \the [L]...", speaker)
|
||||
LoseFollow()
|
||||
set_target(L, 1)
|
||||
return
|
||||
else
|
||||
delayed_say("No... I won't attack \the [L].", speaker)
|
||||
return
|
||||
// If we're here, it couldn't find anyone with that name.
|
||||
delayed_say("No... I don't know who to attack...", speaker)
|
||||
@@ -1,470 +0,0 @@
|
||||
/mob/living/simple_animal/slime
|
||||
name = "slime"
|
||||
desc = "The most basic of slimes. The grey slime has no remarkable qualities, however it remains one of the most useful colors for scientists."
|
||||
tt_desc = "A Macrolimbus vulgaris"
|
||||
icon = 'icons/mob/slime2.dmi'
|
||||
icon_state = "grey baby slime"
|
||||
intelligence_level = SA_ANIMAL
|
||||
pass_flags = PASSTABLE
|
||||
var/shiny = FALSE // If true, will add a 'shiny' overlay.
|
||||
var/glows = FALSE // If true, will glow in the same color as the color var.
|
||||
var/icon_state_override = null // Used for special slime appearances like the rainbow slime.
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
makes_dirt = FALSE // Goop
|
||||
|
||||
speak_emote = list("chirps")
|
||||
|
||||
maxHealth = 150
|
||||
var/maxHealth_adult = 200
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
melee_miss_chance = 0
|
||||
gender = NEUTER
|
||||
|
||||
// Atmos stuff.
|
||||
minbodytemp = T0C-30
|
||||
heat_damage_per_tick = 0
|
||||
cold_damage_per_tick = 40
|
||||
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
unsuitable_atoms_damage = 0
|
||||
|
||||
response_help = "pets"
|
||||
|
||||
speak = list(
|
||||
"Blorp...",
|
||||
"Blop..."
|
||||
|
||||
)
|
||||
emote_hear = list(
|
||||
|
||||
)
|
||||
emote_see = list(
|
||||
"bounces",
|
||||
"jiggles",
|
||||
"sways"
|
||||
)
|
||||
|
||||
hostile = 1
|
||||
retaliate = 1
|
||||
attack_same = 1
|
||||
cooperative = 1
|
||||
faction = "slime" // Slimes will help other slimes, provided they share the same color.
|
||||
|
||||
color = "#CACACA"
|
||||
var/is_adult = FALSE
|
||||
var/cores = 1 // How many cores you get when placed in a Processor.
|
||||
var/power_charge = 0 // 0-10 controls how much electricity they are generating. High numbers encourage the slime to stun someone with electricity.
|
||||
var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows or reproduces
|
||||
var/number = 0 // This is used to make the slime semi-unique for indentification.
|
||||
|
||||
var/mob/living/victim = null // the person the slime is currently feeding on
|
||||
var/rabid = FALSE // If true, will attack anyone and everyone.
|
||||
var/docile = FALSE // Basically the opposite of above. If true, will never harm anything and won't get hungry.
|
||||
var/discipline = 0 // Beating slimes makes them less likely to lash out. In theory.
|
||||
var/resentment = 0 // 'Unjustified' beatings make this go up, and makes it more likely for abused slimes to go berserk.
|
||||
var/obedience = 0 // Conversely, 'justified' beatings make this go up, and makes discipline decay slowly, potentially making it not decay at all.
|
||||
var/unity = FALSE // If true, slimes will consider other colors as their own. Other slimes will see this slime as the same color as well. A rainbow slime is required to get this.
|
||||
var/optimal_combat = FALSE // Used to dumb down the combat AI somewhat. If true, the slime tends to be really dangerous to fight alone due to stunlocking.
|
||||
var/mood = ":3" // Icon to use to display 'mood'.
|
||||
var/obj/item/clothing/head/hat = null // The hat the slime may be wearing.
|
||||
|
||||
var/slime_color = "grey"
|
||||
var/mutation_chance = 25 // Odds of spawning as a new color when reproducing. Can be modified by certain xenobio products. Carried across generations of slimes.
|
||||
var/coretype = /obj/item/slime_extract/grey
|
||||
// List of potential slime color mutations. This must have exactly four types.
|
||||
var/list/slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/orange,
|
||||
/mob/living/simple_animal/slime/metal,
|
||||
/mob/living/simple_animal/slime/blue,
|
||||
/mob/living/simple_animal/slime/purple
|
||||
)
|
||||
var/type_on_death = null // Set this if you want dying slimes to split into a specific type and not their type.
|
||||
var/rainbow_core_candidate = TRUE // If false, rainbow cores cannot make this type randomly.
|
||||
|
||||
var/reagent_injected = null // Some slimes inject reagents on attack. This tells the game what reagent to use.
|
||||
var/injection_amount = 5 // This determines how much.
|
||||
|
||||
|
||||
can_enter_vent_with = list(
|
||||
/obj/item/clothing/head,
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/New(var/location, var/start_as_adult = FALSE)
|
||||
verbs += /mob/living/proc/ventcrawl
|
||||
if(start_as_adult)
|
||||
make_adult()
|
||||
health = maxHealth
|
||||
// slime_mutation = mutation_table(slime_color)
|
||||
update_icon()
|
||||
number = rand(1, 1000)
|
||||
update_name()
|
||||
..(location)
|
||||
|
||||
/mob/living/simple_animal/slime/Destroy()
|
||||
if(hat)
|
||||
drop_hat()
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/slime/proc/make_adult()
|
||||
if(is_adult)
|
||||
return
|
||||
|
||||
is_adult = TRUE
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 40
|
||||
maxHealth = maxHealth_adult
|
||||
amount_grown = 0
|
||||
update_icon()
|
||||
update_name()
|
||||
|
||||
/mob/living/simple_animal/slime/proc/update_name()
|
||||
if(docile) // Docile slimes are generally named, so we shouldn't mess with it.
|
||||
return
|
||||
name = "[slime_color] [is_adult ? "adult" : "baby"] [initial(name)] ([number])"
|
||||
real_name = name
|
||||
|
||||
/mob/living/simple_animal/slime/update_icon()
|
||||
if(stat == DEAD)
|
||||
icon_state = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"] dead"
|
||||
set_light(0)
|
||||
else
|
||||
if(incapacitated(INCAPACITATION_DISABLED))
|
||||
icon_state = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"] dead"
|
||||
else
|
||||
icon_state = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"][victim ? " eating":""]"
|
||||
|
||||
overlays.Cut()
|
||||
if(stat != DEAD)
|
||||
var/image/I = image(icon, src, "slime light")
|
||||
I.appearance_flags = RESET_COLOR
|
||||
overlays += I
|
||||
|
||||
if(shiny)
|
||||
I = image(icon, src, "slime shiny")
|
||||
I.appearance_flags = RESET_COLOR
|
||||
overlays += I
|
||||
|
||||
I = image(icon, src, "aslime-[mood]")
|
||||
I.appearance_flags = RESET_COLOR
|
||||
overlays += I
|
||||
|
||||
if(glows)
|
||||
set_light(3, 2, color)
|
||||
|
||||
if(hat)
|
||||
var/hat_state = hat.item_state ? hat.item_state : hat.icon_state
|
||||
var/image/I = image('icons/mob/head.dmi', src, hat_state)
|
||||
I.pixel_y = -7 // Slimes are small.
|
||||
I.appearance_flags = RESET_COLOR
|
||||
overlays += I
|
||||
|
||||
if(modifier_overlay) // Restore our modifier overlay.
|
||||
overlays += modifier_overlay
|
||||
|
||||
/mob/living/simple_animal/slime/proc/update_mood()
|
||||
var/old_mood = mood
|
||||
if(incapacitated(INCAPACITATION_DISABLED))
|
||||
mood = "sad"
|
||||
else if(rabid)
|
||||
mood = "angry"
|
||||
else if(target_mob)
|
||||
mood = "mischevous"
|
||||
else if(discipline)
|
||||
mood = "pout"
|
||||
else if(docile)
|
||||
mood = ":33"
|
||||
else
|
||||
mood = ":3"
|
||||
if(old_mood != mood)
|
||||
update_icon()
|
||||
|
||||
// Makes the slime very angry and dangerous.
|
||||
/mob/living/simple_animal/slime/proc/enrage()
|
||||
if(docile)
|
||||
return
|
||||
rabid = TRUE
|
||||
update_mood()
|
||||
visible_message("<span class='danger'>\The [src] enrages!</span>")
|
||||
|
||||
// Makes the slime safe and harmless.
|
||||
/mob/living/simple_animal/slime/proc/pacify()
|
||||
rabid = FALSE
|
||||
docile = TRUE
|
||||
hostile = FALSE
|
||||
retaliate = FALSE
|
||||
cooperative = FALSE
|
||||
|
||||
// If for whatever reason the mob AI decides to try to attack something anyways.
|
||||
melee_damage_upper = 0
|
||||
melee_damage_lower = 0
|
||||
|
||||
update_mood()
|
||||
|
||||
/mob/living/simple_animal/slime/proc/unify()
|
||||
unity = TRUE
|
||||
attack_same = FALSE
|
||||
|
||||
/mob/living/simple_animal/slime/examine(mob/user)
|
||||
..()
|
||||
if(hat)
|
||||
to_chat(user, "It is wearing \a [hat].")
|
||||
|
||||
if(stat == DEAD)
|
||||
to_chat(user, "It appears to be dead.")
|
||||
else if(incapacitated(INCAPACITATION_DISABLED))
|
||||
to_chat(user, "It appears to be incapacitated.")
|
||||
else if(rabid)
|
||||
to_chat(user, "It seems very, very angry and upset.")
|
||||
else if(obedience >= 5)
|
||||
to_chat(user, "It looks rather obedient.")
|
||||
else if(discipline)
|
||||
to_chat(user, "It has been subjugated by force, at least for now.")
|
||||
else if(docile)
|
||||
to_chat(user, "It appears to have been pacified.")
|
||||
|
||||
/mob/living/simple_animal/slime/water_act(amount) // This is called if a slime enters a water tile.
|
||||
adjustBruteLoss(40 * amount)
|
||||
|
||||
/mob/living/simple_animal/slime/proc/adjust_discipline(amount, silent)
|
||||
if(amount > 0)
|
||||
if(!rabid)
|
||||
var/justified = is_justified_to_discipline()
|
||||
spawn(0)
|
||||
stop_consumption()
|
||||
LoseTarget()
|
||||
if(!silent)
|
||||
if(justified)
|
||||
say(pick("Fine...", "Okay...", "Sorry...", "I yield...", "Mercy..."))
|
||||
else
|
||||
say(pick("Why...?", "I don't understand...?", "Cruel...", "Stop...", "Nooo..."))
|
||||
if(justified)
|
||||
obedience++
|
||||
else
|
||||
if(prob(resentment * 20))
|
||||
enrage() // Pushed the slime too far.
|
||||
say(pick("Evil...", "Kill...", "Tyrant..."))
|
||||
resentment++ // Done after check so first time will never enrage.
|
||||
|
||||
discipline = between(0, discipline + amount, 10)
|
||||
|
||||
/mob/living/simple_animal/slime/movement_delay()
|
||||
if(bodytemperature >= 330.23) // 135 F or 57.08 C
|
||||
return -1 // slimes become supercharged at high temperatures
|
||||
|
||||
. = ..()
|
||||
|
||||
var/health_deficiency = (maxHealth - health)
|
||||
if(health_deficiency >= 45)
|
||||
. += (health_deficiency / 25)
|
||||
|
||||
if(bodytemperature < 183.222)
|
||||
. += (283.222 - bodytemperature) / 10 * 1.75
|
||||
|
||||
. += config.slime_delay
|
||||
|
||||
/mob/living/simple_animal/slime/Process_Spacemove()
|
||||
return 2
|
||||
|
||||
/mob/living/simple_animal/slime/verb/evolve()
|
||||
set category = "Slime"
|
||||
set desc = "This will let you evolve from baby to adult slime."
|
||||
|
||||
if(stat)
|
||||
to_chat(src, "<span class='notice'>I must be conscious to do this...</span>")
|
||||
return
|
||||
|
||||
if(docile)
|
||||
to_chat(src, "<span class='notice'>I have been pacified. I cannot evolve...</span>")
|
||||
return
|
||||
|
||||
if(!is_adult)
|
||||
if(amount_grown >= 10)
|
||||
make_adult()
|
||||
else
|
||||
to_chat(src, "<span class='notice'>I am not ready to evolve yet...</span>")
|
||||
else
|
||||
to_chat(src, "<span class='notice'>I have already evolved...</span>")
|
||||
|
||||
/mob/living/simple_animal/slime/verb/reproduce()
|
||||
set category = "Slime"
|
||||
set desc = "This will make you split into four Slimes."
|
||||
|
||||
if(stat)
|
||||
to_chat(src, "<span class='notice'>I must be conscious to do this...</span>")
|
||||
return
|
||||
|
||||
if(docile)
|
||||
to_chat(src, "<span class='notice'>I have been pacified. I cannot reproduce...</span>")
|
||||
return
|
||||
|
||||
if(is_adult)
|
||||
if(amount_grown >= 10)
|
||||
// Check if there's enough 'room' to split.
|
||||
var/list/nearby_things = orange(1, src)
|
||||
var/free_tiles = 0
|
||||
for(var/turf/T in nearby_things)
|
||||
var/free = TRUE
|
||||
if(T.density) // No walls.
|
||||
continue
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.density)
|
||||
free = FALSE
|
||||
break
|
||||
|
||||
if(free)
|
||||
free_tiles++
|
||||
|
||||
if(free_tiles < 3) // Three free tiles are needed, as four slimes are made and the 4th tile is from the center tile that the current slime occupies.
|
||||
to_chat(src, "<span class='warning'>It is too cramped here to reproduce...</span>")
|
||||
return
|
||||
|
||||
var/list/babies = list()
|
||||
for(var/i = 1 to 4)
|
||||
babies.Add(make_new_slime())
|
||||
|
||||
var/mob/living/simple_animal/slime/new_slime = pick(babies)
|
||||
new_slime.universal_speak = universal_speak
|
||||
if(src.mind)
|
||||
src.mind.transfer_to(new_slime)
|
||||
else
|
||||
new_slime.key = src.key
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(src, "<span class='notice'>I am not ready to reproduce yet...</span>")
|
||||
else
|
||||
to_chat(src, "<span class='notice'>I am not old enough to reproduce yet...</span>")
|
||||
|
||||
// Used for reproducing and dying.
|
||||
/mob/living/simple_animal/slime/proc/make_new_slime(var/desired_type)
|
||||
var/t = src.type
|
||||
if(desired_type)
|
||||
t = desired_type
|
||||
if(prob(mutation_chance / 10))
|
||||
t = /mob/living/simple_animal/slime/rainbow
|
||||
|
||||
else if(prob(mutation_chance) && slime_mutation.len)
|
||||
t = slime_mutation[rand(1, slime_mutation.len)]
|
||||
var/mob/living/simple_animal/slime/baby = new t(loc)
|
||||
|
||||
// Handle 'inheriting' from parent slime.
|
||||
baby.mutation_chance = mutation_chance
|
||||
baby.power_charge = round(power_charge / 4)
|
||||
baby.resentment = max(resentment - 1, 0)
|
||||
if(!istype(baby, /mob/living/simple_animal/slime/light_pink))
|
||||
baby.discipline = max(discipline - 1, 0)
|
||||
baby.obedience = max(obedience - 1, 0)
|
||||
if(!istype(baby, /mob/living/simple_animal/slime/rainbow))
|
||||
baby.unity = unity
|
||||
baby.faction = faction
|
||||
baby.attack_same = attack_same
|
||||
baby.friends = friends.Copy()
|
||||
if(rabid)
|
||||
baby.enrage()
|
||||
|
||||
step_away(baby, src)
|
||||
return baby
|
||||
|
||||
/mob/living/simple_animal/slime/speech_bubble_appearance()
|
||||
return "slime"
|
||||
|
||||
// Called after they finish eatting someone.
|
||||
/mob/living/simple_animal/slime/proc/befriend(var/mob/living/friend)
|
||||
if(!(friend in friends))
|
||||
friends |= friend
|
||||
say("[friend]... friend...")
|
||||
|
||||
/mob/living/simple_animal/slime/proc/can_command(var/mob/living/commander)
|
||||
if(rabid)
|
||||
return FALSE
|
||||
if(docile)
|
||||
return SLIME_COMMAND_OBEY
|
||||
if(commander in friends)
|
||||
return SLIME_COMMAND_FRIEND
|
||||
if(faction == commander.faction)
|
||||
return SLIME_COMMAND_FACTION
|
||||
if(discipline > resentment && obedience >= 5)
|
||||
return SLIME_COMMAND_OBEY
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/slime/proc/give_hat(var/obj/item/clothing/head/new_hat, var/mob/living/user)
|
||||
if(!istype(new_hat))
|
||||
to_chat(user, "<span class='warning'>\The [new_hat] isn't a hat.</span>")
|
||||
return
|
||||
if(hat)
|
||||
to_chat(user, "<span class='warning'>\The [src] is already wearing \a [hat].</span>")
|
||||
return
|
||||
else
|
||||
user.drop_item(new_hat)
|
||||
hat = new_hat
|
||||
new_hat.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You place \a [new_hat] on \the [src]. How adorable!</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/proc/remove_hat(var/mob/living/user)
|
||||
if(!hat)
|
||||
to_chat(user, "<span class='warning'>\The [src] doesn't have a hat to remove.</span>")
|
||||
else
|
||||
hat.forceMove(get_turf(src))
|
||||
user.put_in_hands(hat)
|
||||
to_chat(user, "<span class='warning'>You take away \the [src]'s [hat.name]. How mean.</span>")
|
||||
hat = null
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/slime/proc/drop_hat()
|
||||
if(!hat)
|
||||
return
|
||||
hat.forceMove(get_turf(src))
|
||||
hat = null
|
||||
update_icon()
|
||||
|
||||
// Checks if disciplining the slime would be 'justified' right now.
|
||||
/mob/living/simple_animal/slime/proc/is_justified_to_discipline()
|
||||
if(rabid)
|
||||
return TRUE
|
||||
if(target_mob)
|
||||
if(ishuman(target_mob))
|
||||
var/mob/living/carbon/human/H = target_mob
|
||||
if(istype(H.species, /datum/species/monkey))
|
||||
return FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/get_description_interaction()
|
||||
var/list/results = list()
|
||||
|
||||
if(!stat)
|
||||
results += "[desc_panel_image("slimebaton")]to stun the slime, if it's being bad."
|
||||
|
||||
results += ..()
|
||||
|
||||
return results
|
||||
|
||||
/mob/living/simple_animal/slime/get_description_info()
|
||||
var/list/lines = list()
|
||||
var/intro_line = "Slimes are generally the test subjects of Xenobiology, with different colors having different properties. \
|
||||
They can be extremely dangerous if not handled properly."
|
||||
lines.Add(intro_line)
|
||||
lines.Add(null) // To pad the line breaks.
|
||||
|
||||
var/list/rewards = list()
|
||||
for(var/potential_color in slime_mutation)
|
||||
var/mob/living/simple_animal/slime/S = potential_color
|
||||
rewards.Add(initial(S.slime_color))
|
||||
var/reward_line = "This color of slime can mutate into [english_list(rewards)] colors, when it reproduces. It will do so when it has eatten enough."
|
||||
lines.Add(reward_line)
|
||||
lines.Add(null)
|
||||
|
||||
lines.Add(description_info)
|
||||
return lines.Join("\n")
|
||||
|
||||
@@ -1,748 +0,0 @@
|
||||
// Tier 1
|
||||
|
||||
/mob/living/simple_animal/slime/purple
|
||||
desc = "This slime is rather toxic to handle, as it is poisonous."
|
||||
color = "#CC23FF"
|
||||
slime_color = "purple"
|
||||
coretype = /obj/item/slime_extract/purple
|
||||
reagent_injected = "toxin"
|
||||
|
||||
description_info = "This slime spreads a toxin when it attacks. A biosuit or other thick armor can protect from the toxic attack."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/dark_purple,
|
||||
/mob/living/simple_animal/slime/dark_blue,
|
||||
/mob/living/simple_animal/slime/green,
|
||||
/mob/living/simple_animal/slime
|
||||
)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/orange
|
||||
desc = "This slime is known to be flammable and can ignite enemies."
|
||||
color = "#FFA723"
|
||||
slime_color = "orange"
|
||||
coretype = /obj/item/slime_extract/orange
|
||||
|
||||
description_info = "Attacks from this slime can ignite you. A firesuit can protect from the burning attacks of this slime."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/dark_purple,
|
||||
/mob/living/simple_animal/slime/yellow,
|
||||
/mob/living/simple_animal/slime/red,
|
||||
/mob/living/simple_animal/slime
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/orange/post_attack(mob/living/L, intent)
|
||||
if(intent != I_HELP)
|
||||
L.adjust_fire_stacks(1)
|
||||
if(prob(25))
|
||||
L.IgniteMob()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/blue
|
||||
desc = "This slime produces 'cryotoxin' and uses it against their foes. Very deadly to other slimes."
|
||||
color = "#19FFFF"
|
||||
slime_color = "blue"
|
||||
coretype = /obj/item/slime_extract/blue
|
||||
reagent_injected = "cryotoxin"
|
||||
|
||||
description_info = "Attacks from this slime can chill you. A biosuit or other thick armor can protect from the chilling attack."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/dark_blue,
|
||||
/mob/living/simple_animal/slime/silver,
|
||||
/mob/living/simple_animal/slime/pink,
|
||||
/mob/living/simple_animal/slime
|
||||
)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/metal
|
||||
desc = "This slime is a lot more resilient than the others, due to having a metamorphic metallic and sloped surface."
|
||||
color = "#5F5F5F"
|
||||
slime_color = "metal"
|
||||
shiny = 1
|
||||
coretype = /obj/item/slime_extract/metal
|
||||
|
||||
description_info = "This slime is a lot more durable and tough to damage than the others."
|
||||
|
||||
resistance = 10 // Sloped armor is strong.
|
||||
maxHealth = 250
|
||||
maxHealth_adult = 350
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/silver,
|
||||
/mob/living/simple_animal/slime/yellow,
|
||||
/mob/living/simple_animal/slime/gold,
|
||||
/mob/living/simple_animal/slime
|
||||
)
|
||||
|
||||
// Tier 2
|
||||
|
||||
/mob/living/simple_animal/slime/yellow
|
||||
desc = "This slime is very conductive, and is known to use electricity as a means of defense moreso than usual for slimes."
|
||||
color = "#FFF423"
|
||||
slime_color = "yellow"
|
||||
coretype = /obj/item/slime_extract/yellow
|
||||
|
||||
ranged = 1
|
||||
shoot_range = 3
|
||||
firing_lines = 1
|
||||
projectiletype = /obj/item/projectile/beam/lightning/slime
|
||||
projectilesound = 'sound/weapons/gauss_shoot.ogg' // Closest thing to a 'thunderstrike' sound we have.
|
||||
glows = TRUE
|
||||
|
||||
description_info = "This slime will fire lightning attacks at enemies if they are at range, and generate electricity \
|
||||
for their stun attack faster than usual. Insulative or reflective armor can protect from the lightning."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/bluespace,
|
||||
/mob/living/simple_animal/slime/bluespace,
|
||||
/mob/living/simple_animal/slime/metal,
|
||||
/mob/living/simple_animal/slime/orange
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/yellow/handle_regular_status_updates()
|
||||
if(stat == CONSCIOUS)
|
||||
if(prob(25))
|
||||
power_charge = between(0, power_charge + 1, 10)
|
||||
..()
|
||||
|
||||
/obj/item/projectile/beam/lightning/slime
|
||||
power = 15
|
||||
|
||||
/mob/living/simple_animal/slime/yellow/ClosestDistance() // Needed or else they won't eat monkeys outside of melee range.
|
||||
if(target_mob && ishuman(target_mob))
|
||||
var/mob/living/carbon/human/H = target_mob
|
||||
if(istype(H.species, /datum/species/monkey))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/dark_purple
|
||||
desc = "This slime produces ever-coveted phoron. Risky to handle but very much worth it."
|
||||
color = "#660088"
|
||||
slime_color = "dark purple"
|
||||
coretype = /obj/item/slime_extract/dark_purple
|
||||
reagent_injected = "phoron"
|
||||
|
||||
description_info = "This slime applies phoron to enemies it attacks. A biosuit or other thick armor can protect from the toxic attack. \
|
||||
If hit with a burning attack, it will erupt in flames."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/purple,
|
||||
/mob/living/simple_animal/slime/orange,
|
||||
/mob/living/simple_animal/slime/ruby,
|
||||
/mob/living/simple_animal/slime/ruby
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/dark_purple/proc/ignite()
|
||||
visible_message("<span class='danger'>\The [src] erupts in an inferno!</span>")
|
||||
for(var/turf/simulated/target_turf in view(2, src))
|
||||
target_turf.assume_gas("phoron", 30, 1500+T0C)
|
||||
spawn(0)
|
||||
target_turf.hotspot_expose(1500+T0C, 400)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/slime/dark_purple/ex_act(severity)
|
||||
log_and_message_admins("[src] ignited due to a chain reaction with an explosion.")
|
||||
ignite()
|
||||
|
||||
/mob/living/simple_animal/slime/dark_purple/fire_act(datum/gas_mixture/air, temperature, volume)
|
||||
log_and_message_admins("[src] ignited due to exposure to fire.")
|
||||
ignite()
|
||||
|
||||
/mob/living/simple_animal/slime/dark_purple/bullet_act(var/obj/item/projectile/P, var/def_zone)
|
||||
if(P.damage_type && P.damage_type == BURN && P.damage) // Most bullets won't trigger the explosion, as a mercy towards Security.
|
||||
log_and_message_admins("[src] ignited due to bring hit by a burning projectile[P.firer ? " by [key_name(P.firer)]" : ""].")
|
||||
ignite()
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/dark_purple/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
if(istype(W) && W.force && W.damtype == BURN)
|
||||
log_and_message_admins("[src] ignited due to being hit with a burning weapon ([W]) by [key_name(user)].")
|
||||
ignite()
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/dark_blue
|
||||
desc = "This slime makes other entities near it feel much colder, and is more resilient to the cold. It tends to kill other slimes rather quickly."
|
||||
color = "#2398FF"
|
||||
glows = TRUE
|
||||
slime_color = "dark blue"
|
||||
coretype = /obj/item/slime_extract/dark_blue
|
||||
|
||||
description_info = "This slime is immune to the cold, however water will still kill it. A winter coat or other cold-resistant clothing can protect from the chilling aura."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/purple,
|
||||
/mob/living/simple_animal/slime/blue,
|
||||
/mob/living/simple_animal/slime/cerulean,
|
||||
/mob/living/simple_animal/slime/cerulean
|
||||
)
|
||||
|
||||
minbodytemp = 0
|
||||
cold_damage_per_tick = 0
|
||||
|
||||
/mob/living/simple_animal/slime/dark_blue/Life()
|
||||
if(stat != DEAD)
|
||||
cold_aura()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/dark_blue/proc/cold_aura()
|
||||
for(var/mob/living/L in view(2, src))
|
||||
var/protection = L.get_cold_protection()
|
||||
|
||||
if(protection < 1)
|
||||
var/cold_factor = abs(protection - 1)
|
||||
var/delta = -20
|
||||
delta *= cold_factor
|
||||
L.bodytemperature = max(50, L.bodytemperature + delta)
|
||||
var/turf/T = get_turf(src)
|
||||
var/datum/gas_mixture/env = T.return_air()
|
||||
if(env)
|
||||
env.add_thermal_energy(-10 * 1000)
|
||||
|
||||
/mob/living/simple_animal/slime/dark_blue/get_cold_protection()
|
||||
return 1 // This slime is immune to cold.
|
||||
|
||||
// Surface variant
|
||||
/mob/living/simple_animal/slime/dark_blue/feral
|
||||
name = "feral slime"
|
||||
desc = "The result of slimes escaping containment from some xenobiology lab. The slime makes other entities near it feel much colder, \
|
||||
and it is more resilient to the cold. These qualities have made this color of slime able to thrive on a harsh, cold world and is able to rival \
|
||||
the ferocity of other apex predators in this region of Sif. As such, it is a very invasive species."
|
||||
description_info = "This slime makes other entities near it feel much colder, and is more resilient to the cold. It also has learned advanced combat tactics from \
|
||||
having to endure the harsh world outside its lab. Note that processing this large slime will give six cores."
|
||||
icon_scale_x = 2
|
||||
icon_scale_y = 2
|
||||
optimal_combat = TRUE // Gotta be sharp to survive out there.
|
||||
rabid = TRUE
|
||||
rainbow_core_candidate = FALSE
|
||||
cores = 6
|
||||
maxHealth = 150
|
||||
maxHealth_adult = 250
|
||||
type_on_death = /mob/living/simple_animal/slime/dark_blue // Otherwise infinite slimes might occur.
|
||||
pixel_y = -10 // Since the base sprite isn't centered properly, the pixel auto-adjustment needs some help.
|
||||
|
||||
/mob/living/simple_animal/slime/dark_blue/feral/New()
|
||||
..()
|
||||
make_adult()
|
||||
|
||||
/mob/living/simple_animal/slime/silver
|
||||
desc = "This slime is shiny, and can deflect lasers or other energy weapons directed at it."
|
||||
color = "#AAAAAA"
|
||||
slime_color = "silver"
|
||||
coretype = /obj/item/slime_extract/silver
|
||||
shiny = TRUE
|
||||
|
||||
description_info = "Tasers, including the slime version, are ineffective against this slime. The slimebation still works."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/metal,
|
||||
/mob/living/simple_animal/slime/blue,
|
||||
/mob/living/simple_animal/slime/amber,
|
||||
/mob/living/simple_animal/slime/amber
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/silver/bullet_act(var/obj/item/projectile/P, var/def_zone)
|
||||
if(istype(P,/obj/item/projectile/beam) || istype(P, /obj/item/projectile/energy))
|
||||
visible_message("<span class='danger'>\The [src] reflects \the [P]!</span>")
|
||||
|
||||
// Find a turf near or on the original location to bounce to
|
||||
var/new_x = P.starting.x + pick(0, 0, 0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, 0, 0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(src)
|
||||
|
||||
// redirect the projectile
|
||||
P.redirect(new_x, new_y, curloc, src)
|
||||
return PROJECTILE_CONTINUE // complete projectile permutation
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
// Tier 3
|
||||
|
||||
/mob/living/simple_animal/slime/bluespace
|
||||
desc = "Trapping this slime in a cell is generally futile, as it can teleport at will."
|
||||
color = null
|
||||
slime_color = "bluespace"
|
||||
icon_state_override = "bluespace"
|
||||
coretype = /obj/item/slime_extract/bluespace
|
||||
|
||||
description_info = "This slime will teleport to attack something if it is within a range of seven tiles. The teleport has a cooldown of five seconds."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/bluespace,
|
||||
/mob/living/simple_animal/slime/bluespace,
|
||||
/mob/living/simple_animal/slime/yellow,
|
||||
/mob/living/simple_animal/slime/yellow
|
||||
)
|
||||
|
||||
spattack_prob = 100
|
||||
spattack_min_range = 3
|
||||
spattack_max_range = 7
|
||||
var/last_tele = null // Uses world.time
|
||||
var/tele_cooldown = 5 SECONDS
|
||||
|
||||
/mob/living/simple_animal/slime/bluespace/ClosestDistance() // Needed or the SA AI won't ever try to teleport.
|
||||
if(world.time > last_tele + tele_cooldown)
|
||||
return spattack_max_range - 1
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/slime/bluespace/SpecialAtkTarget()
|
||||
// Teleport attack.
|
||||
if(!target_mob)
|
||||
to_chat(src, "<span class='warning'>There's nothing to teleport to.</span>")
|
||||
return FALSE
|
||||
|
||||
if(world.time < last_tele + tele_cooldown)
|
||||
to_chat(src, "<span class='warning'>You can't teleport right now, wait a few seconds.</span>")
|
||||
return FALSE
|
||||
|
||||
var/list/nearby_things = range(1, target_mob)
|
||||
var/list/valid_turfs = list()
|
||||
|
||||
// All this work to just go to a non-dense tile.
|
||||
for(var/turf/potential_turf in nearby_things)
|
||||
var/valid_turf = TRUE
|
||||
if(potential_turf.density)
|
||||
continue
|
||||
for(var/atom/movable/AM in potential_turf)
|
||||
if(AM.density)
|
||||
valid_turf = FALSE
|
||||
if(valid_turf)
|
||||
valid_turfs.Add(potential_turf)
|
||||
|
||||
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/target_turf = pick(valid_turfs)
|
||||
|
||||
if(!target_turf)
|
||||
to_chat(src, "<span class='warning'>There wasn't an unoccupied spot to teleport to.</span>")
|
||||
return FALSE
|
||||
|
||||
var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread
|
||||
s1.set_up(5, 1, T)
|
||||
var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread
|
||||
s2.set_up(5, 1, target_turf)
|
||||
|
||||
|
||||
T.visible_message("<span class='notice'>\The [src] vanishes!</span>")
|
||||
s1.start()
|
||||
|
||||
forceMove(target_turf)
|
||||
playsound(target_turf, 'sound/effects/phasein.ogg', 50, 1)
|
||||
to_chat(src, "<span class='notice'>You teleport to \the [target_turf].</span>")
|
||||
|
||||
target_turf.visible_message("<span class='warning'>\The [src] appears!</span>")
|
||||
s2.start()
|
||||
|
||||
last_tele = world.time
|
||||
|
||||
if(Adjacent(target_mob))
|
||||
PunchTarget()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/slime/ruby
|
||||
desc = "This slime has great physical strength."
|
||||
color = "#FF3333"
|
||||
slime_color = "ruby"
|
||||
shiny = TRUE
|
||||
glows = TRUE
|
||||
coretype = /obj/item/slime_extract/ruby
|
||||
|
||||
description_info = "This slime is unnaturally stronger, allowing it to hit much harder, take less damage, and be stunned for less time. \
|
||||
Their glomp attacks also send the victim flying."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/dark_purple,
|
||||
/mob/living/simple_animal/slime/dark_purple,
|
||||
/mob/living/simple_animal/slime/ruby,
|
||||
/mob/living/simple_animal/slime/ruby
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/ruby/New()
|
||||
..()
|
||||
add_modifier(/datum/modifier/slime_strength, null, src) // Slime is always swole.
|
||||
|
||||
/mob/living/simple_animal/slime/ruby/DoPunch(var/mob/living/L)
|
||||
..() // Do regular attacks.
|
||||
|
||||
if(istype(L))
|
||||
if(a_intent == I_HURT)
|
||||
visible_message("<span class='danger'>\The [src] sends \the [L] flying with the impact!</span>")
|
||||
playsound(src, "punch", 50, 1)
|
||||
L.Weaken(1)
|
||||
var/throwdir = get_dir(src, L)
|
||||
L.throw_at(get_edge_target_turf(L, throwdir), 3, 1, src)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/amber
|
||||
desc = "This slime seems to be an expert in the culinary arts, as they create their own food to share with others. \
|
||||
They would probably be very important to other slimes, if the other colors didn't try to kill them."
|
||||
color = "#FFBB00"
|
||||
slime_color = "amber"
|
||||
shiny = TRUE
|
||||
glows = TRUE
|
||||
coretype = /obj/item/slime_extract/amber
|
||||
|
||||
description_info = "This slime feeds nearby entities passively while it is alive. This can cause uncontrollable \
|
||||
slime growth and reproduction if not kept in check. The amber slime cannot feed itself, but can be fed by other amber slimes."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/silver,
|
||||
/mob/living/simple_animal/slime/silver,
|
||||
/mob/living/simple_animal/slime/amber,
|
||||
/mob/living/simple_animal/slime/amber
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/amber/Life()
|
||||
if(stat != DEAD)
|
||||
feed_aura()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/amber/proc/feed_aura()
|
||||
for(var/mob/living/L in view(2, src))
|
||||
if(L == src) // Don't feed themselves, or it is impossible to stop infinite slimes without killing all of the ambers.
|
||||
continue
|
||||
if(isslime(L))
|
||||
var/mob/living/simple_animal/slime/S = L
|
||||
S.adjust_nutrition(rand(15, 25))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.isSynthetic())
|
||||
continue
|
||||
H.nutrition = between(0, H.nutrition + rand(15, 25), 600)
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/cerulean
|
||||
desc = "This slime is generally superior in a wide range of attributes, compared to the common slime. The jack of all trades, but master of none."
|
||||
color = "#4F7EAA"
|
||||
slime_color = "cerulean"
|
||||
coretype = /obj/item/slime_extract/cerulean
|
||||
|
||||
// Less than the specialized slimes, but higher than the rest.
|
||||
maxHealth = 200
|
||||
maxHealth_adult = 250
|
||||
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 30
|
||||
|
||||
move_to_delay = 3
|
||||
|
||||
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/dark_blue,
|
||||
/mob/living/simple_animal/slime/dark_blue,
|
||||
/mob/living/simple_animal/slime/cerulean,
|
||||
/mob/living/simple_animal/slime/cerulean
|
||||
)
|
||||
|
||||
// Tier 4
|
||||
|
||||
/mob/living/simple_animal/slime/red
|
||||
desc = "This slime is full of energy, and very aggressive. 'The red ones go faster.' seems to apply here."
|
||||
color = "#FF3333"
|
||||
slime_color = "red"
|
||||
coretype = /obj/item/slime_extract/red
|
||||
move_to_delay = 3 // The red ones go faster.
|
||||
|
||||
description_info = "This slime is faster than the others. Attempting to discipline this slime will always cause it to go berserk."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/red,
|
||||
/mob/living/simple_animal/slime/oil,
|
||||
/mob/living/simple_animal/slime/oil,
|
||||
/mob/living/simple_animal/slime/orange
|
||||
)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/red/adjust_discipline(amount)
|
||||
if(amount > 0)
|
||||
if(!rabid)
|
||||
enrage() // How dare you try to control the red slime.
|
||||
say("Grrr...!")
|
||||
|
||||
/mob/living/simple_animal/slime/red/enrage()
|
||||
..()
|
||||
add_modifier(/datum/modifier/berserk, 30 SECONDS)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/green
|
||||
desc = "This slime is radioactive."
|
||||
color = "#14FF20"
|
||||
slime_color = "green"
|
||||
coretype = /obj/item/slime_extract/green
|
||||
glows = TRUE
|
||||
reagent_injected = "radium"
|
||||
var/rads = 25
|
||||
|
||||
description_info = "This slime will irradiate anything nearby passively, and will inject radium on attack. \
|
||||
A radsuit or other thick and radiation-hardened armor can protect from this. It will only radiate while alive."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/purple,
|
||||
/mob/living/simple_animal/slime/green,
|
||||
/mob/living/simple_animal/slime/emerald,
|
||||
/mob/living/simple_animal/slime/emerald
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/green/Life()
|
||||
if(stat != DEAD)
|
||||
irradiate()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/green/proc/irradiate()
|
||||
SSradiation.radiate(src, rads)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/pink
|
||||
desc = "This slime has regenerative properties."
|
||||
color = "#FF0080"
|
||||
slime_color = "pink"
|
||||
coretype = /obj/item/slime_extract/pink
|
||||
glows = TRUE
|
||||
|
||||
description_info = "This slime will passively heal nearby entities within two tiles, including itself. It will only do this while alive."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/blue,
|
||||
/mob/living/simple_animal/slime/light_pink,
|
||||
/mob/living/simple_animal/slime/light_pink,
|
||||
/mob/living/simple_animal/slime/pink
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/pink/Life()
|
||||
if(stat != DEAD)
|
||||
heal_aura()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/pink/proc/heal_aura()
|
||||
for(var/mob/living/L in view(src, 2))
|
||||
if(L.stat == DEAD || L == target_mob)
|
||||
continue
|
||||
L.add_modifier(/datum/modifier/slime_heal, 5 SECONDS, src)
|
||||
|
||||
/datum/modifier/slime_heal
|
||||
name = "slime mending"
|
||||
desc = "You feel somewhat gooy."
|
||||
mob_overlay_state = "pink_sparkles"
|
||||
|
||||
on_created_text = "<span class='warning'>Twinkling spores of goo surround you. It makes you feel healthier.</span>"
|
||||
on_expired_text = "<span class='notice'>The spores of goo have faded, although you feel much healthier than before.</span>"
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
/datum/modifier/slime_heal/tick()
|
||||
if(holder.stat == DEAD) // Required or else simple animals become immortal.
|
||||
expire()
|
||||
|
||||
if(ishuman(holder)) // Robolimbs need this code sadly.
|
||||
var/mob/living/carbon/human/H = holder
|
||||
for(var/obj/item/organ/external/E in H.organs)
|
||||
var/obj/item/organ/external/O = E
|
||||
O.heal_damage(2, 2, 0, 1)
|
||||
else
|
||||
holder.adjustBruteLoss(-2)
|
||||
holder.adjustFireLoss(-2)
|
||||
|
||||
holder.adjustToxLoss(-2)
|
||||
holder.adjustOxyLoss(-2)
|
||||
holder.adjustCloneLoss(-1)
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/gold
|
||||
desc = "This slime absorbs energy, and cannot be stunned by normal means."
|
||||
color = "#EEAA00"
|
||||
shiny = TRUE
|
||||
slime_color = "gold"
|
||||
coretype = /obj/item/slime_extract/gold
|
||||
description_info = "This slime is immune to the slimebaton and taser, and will actually charge the slime, however it will still discipline the slime."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/metal,
|
||||
/mob/living/simple_animal/slime/gold,
|
||||
/mob/living/simple_animal/slime/sapphire,
|
||||
/mob/living/simple_animal/slime/sapphire
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/gold/Weaken(amount)
|
||||
power_charge = between(0, power_charge + amount, 10)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/gold/Stun(amount)
|
||||
power_charge = between(0, power_charge + amount, 10)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/gold/get_description_interaction() // So it doesn't say to use a baton on them.
|
||||
return list()
|
||||
|
||||
|
||||
// Tier 5
|
||||
|
||||
/mob/living/simple_animal/slime/oil
|
||||
desc = "This slime is explosive and volatile. Smoking near it is probably a bad idea."
|
||||
color = "#333333"
|
||||
slime_color = "oil"
|
||||
shiny = TRUE
|
||||
coretype = /obj/item/slime_extract/oil
|
||||
|
||||
description_info = "If this slime suffers damage from a fire or heat based source, or if it is caught inside \
|
||||
an explosion, it will explode. Rabid oil slimes will charge at enemies, then suicide-bomb themselves. \
|
||||
Bomb suits can protect from the explosion."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/oil,
|
||||
/mob/living/simple_animal/slime/oil,
|
||||
/mob/living/simple_animal/slime/red,
|
||||
/mob/living/simple_animal/slime/red
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/oil/proc/explode()
|
||||
if(stat != DEAD)
|
||||
// explosion(src.loc, 1, 2, 4)
|
||||
explosion(src.loc, 0, 2, 4) // A bit weaker since the suicide charger tended to gib the poor sod being targeted.
|
||||
if(src) // Delete ourselves if the explosion didn't do it.
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/slime/oil/post_attack(var/mob/living/L, var/intent = I_HURT)
|
||||
if(!rabid)
|
||||
return ..()
|
||||
if(intent == I_HURT || intent == I_GRAB)
|
||||
say(pick("Sacrifice...!", "Sssss...", "Boom...!"))
|
||||
sleep(2 SECOND)
|
||||
log_and_message_admins("[src] has suicide-bombed themselves while trying to kill \the [L].")
|
||||
explode()
|
||||
|
||||
/mob/living/simple_animal/slime/oil/ex_act(severity)
|
||||
log_and_message_admins("[src] exploded due to a chain reaction with another explosion.")
|
||||
explode()
|
||||
|
||||
/mob/living/simple_animal/slime/oil/fire_act(datum/gas_mixture/air, temperature, volume)
|
||||
log_and_message_admins("[src] exploded due to exposure to fire.")
|
||||
explode()
|
||||
|
||||
/mob/living/simple_animal/slime/oil/bullet_act(var/obj/item/projectile/P, var/def_zone)
|
||||
if(P.damage_type && P.damage_type == BURN && P.damage) // Most bullets won't trigger the explosion, as a mercy towards Security.
|
||||
log_and_message_admins("[src] exploded due to bring hit by a burning projectile[P.firer ? " by [key_name(P.firer)]" : ""].")
|
||||
explode()
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/oil/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
if(istype(W) && W.force && W.damtype == BURN)
|
||||
log_and_message_admins("[src] exploded due to being hit with a burning weapon ([W]) by [key_name(user)].")
|
||||
explode()
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/sapphire
|
||||
desc = "This slime seems a bit brighter than the rest, both figuratively and literally."
|
||||
color = "#2398FF"
|
||||
slime_color = "sapphire"
|
||||
shiny = TRUE
|
||||
glows = TRUE
|
||||
coretype = /obj/item/slime_extract/sapphire
|
||||
|
||||
optimal_combat = TRUE // Lift combat AI restrictions to look smarter.
|
||||
run_at_them = FALSE // Use fancy A* pathing.
|
||||
astar_adjacent_proc = /turf/proc/TurfsWithAccess // Normal slimes don't care about cardinals (because BYOND) so smart slimes shouldn't as well.
|
||||
move_to_delay = 3 // A* chasing is slightly slower in terms of movement speed than regular pathing so reducing this hopefully makes up for that.
|
||||
|
||||
description_info = "This slime uses more robust tactics when fighting and won't hold back, so it is dangerous to be alone \
|
||||
with one if hostile, and especially dangerous if they outnumber you."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/sapphire,
|
||||
/mob/living/simple_animal/slime/sapphire,
|
||||
/mob/living/simple_animal/slime/gold,
|
||||
/mob/living/simple_animal/slime/gold
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/emerald
|
||||
desc = "This slime is faster than usual, even more so than the red slimes."
|
||||
color = "#22FF22"
|
||||
shiny = TRUE
|
||||
glows = TRUE
|
||||
slime_color = "emerald"
|
||||
coretype = /obj/item/slime_extract/emerald
|
||||
|
||||
description_info = "This slime will make everything around it, and itself, faster for a few seconds, if close by."
|
||||
move_to_delay = 2
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/green,
|
||||
/mob/living/simple_animal/slime/green,
|
||||
/mob/living/simple_animal/slime/emerald,
|
||||
/mob/living/simple_animal/slime/emerald
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/emerald/Life()
|
||||
if(stat != DEAD)
|
||||
zoom_aura()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/slime/emerald/proc/zoom_aura()
|
||||
for(var/mob/living/L in view(src, 2))
|
||||
if(L.stat == DEAD || L == target_mob)
|
||||
continue
|
||||
L.add_modifier(/datum/modifier/technomancer/haste, 5 SECONDS, src)
|
||||
|
||||
/mob/living/simple_animal/slime/light_pink
|
||||
desc = "This slime seems a lot more peaceful than the others."
|
||||
color = "#FF8888"
|
||||
slime_color = "light pink"
|
||||
coretype = /obj/item/slime_extract/light_pink
|
||||
|
||||
description_info = "This slime is effectively always disciplined initially."
|
||||
obedience = 5
|
||||
discipline = 5
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/pink,
|
||||
/mob/living/simple_animal/slime/pink,
|
||||
/mob/living/simple_animal/slime/light_pink,
|
||||
/mob/living/simple_animal/slime/light_pink
|
||||
)
|
||||
|
||||
// Special
|
||||
/mob/living/simple_animal/slime/rainbow
|
||||
desc = "This slime changes colors constantly."
|
||||
color = null // Only slime subtype that uses a different icon_state.
|
||||
slime_color = "rainbow"
|
||||
coretype = /obj/item/slime_extract/rainbow
|
||||
icon_state_override = "rainbow"
|
||||
unity = TRUE
|
||||
|
||||
description_info = "This slime is considered to be the same color as all other slime colors at the same time for the purposes of \
|
||||
other slimes being friendly to them, and therefore will never be harmed by another slime. \
|
||||
Attacking this slime will provoke the wrath of all slimes within range."
|
||||
|
||||
slime_mutation = list(
|
||||
/mob/living/simple_animal/slime/rainbow,
|
||||
/mob/living/simple_animal/slime/rainbow,
|
||||
/mob/living/simple_animal/slime/rainbow,
|
||||
/mob/living/simple_animal/slime/rainbow
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/slime/rainbow/New()
|
||||
unify()
|
||||
..()
|
||||
|
||||
// The RD's pet slime.
|
||||
/mob/living/simple_animal/slime/rainbow/kendrick
|
||||
name = "Kendrick"
|
||||
desc = "The Research Director's pet slime. It shifts colors constantly."
|
||||
rainbow_core_candidate = FALSE
|
||||
|
||||
/mob/living/simple_animal/slime/rainbow/kendrick/New()
|
||||
pacify()
|
||||
..()
|
||||
Reference in New Issue
Block a user