Merge pull request #11719 from Terilia/headcrabs

Headcrabs
This commit is contained in:
variableundefined
2019-08-23 15:16:30 -04:00
committed by GitHub
12 changed files with 344 additions and 90 deletions
+146
View File
@@ -0,0 +1,146 @@
#define LOC_ATMOS_CONTROL 0
#define LOC_FPMAINT 1
#define LOC_FPMAINT2 2
#define LOC_FSMAINT 3
#define LOC_FSMAINT2 4
#define LOC_ASMAINT 5
#define LOC_ASMAINT2 6
#define LOC_APMAINT 7
#define LOC_MAINTCENTRAL 8
#define LOC_FORE 9
#define LOC_STARBOARD 10
#define LOC_PORT 11
#define LOC_AFT 12
#define LOC_STORAGE 13
#define LOC_DISPOSAL 14
#define LOC_GENETICS 15
#define LOC_ELECTRICAL 16
#define LOC_ABANDONEDBAR 17
#define LOC_ELECTRICAL_SHOP 18
#define LOC_GAMBLING_DEN 19
#define HEADCRAB_NORMAL 0
/*#define HEADCRAB_SPECIAL 1
#define HEADCRAB_CLOWN 2 */ //Planned for the future
/datum/event/headcrabs
announceWhen = 10
endWhen = 11
var/location
var/locstring
var/headcrab
/datum/event/headcrabs/start()
location = rand(0,19)
var/list/turf/simulated/floor/turfs = list()
var/spawn_area_type
switch(location)
if(LOC_ATMOS_CONTROL)
spawn_area_type = /area/maintenance/atmos_control
locstring = "Atmospherics Maintenance"
if(LOC_FPMAINT)
spawn_area_type = /area/maintenance/fpmaint
locstring = "EVA Maintenance"
if(LOC_FPMAINT2)
spawn_area_type = /area/maintenance/fpmaint2
locstring = "Arrivals North Maintenance"
if(LOC_FSMAINT)
spawn_area_type = /area/maintenance/fsmaint
locstring = "Dormitory Maintenance"
if(LOC_FSMAINT2)
spawn_area_type = /area/maintenance/fsmaint2
locstring = "Bar Maintenance"
if(LOC_ASMAINT)
spawn_area_type = /area/maintenance/asmaint
locstring = "Medbay Maintenance"
if(LOC_ASMAINT2)
spawn_area_type = /area/maintenance/asmaint2
locstring = "Science Maintenance"
if(LOC_APMAINT)
spawn_area_type = /area/maintenance/apmaint
locstring = "Cargo Maintenance"
if(LOC_MAINTCENTRAL)
spawn_area_type = /area/maintenance/maintcentral
locstring = "Bridge Maintenance"
if(LOC_FORE)
spawn_area_type = /area/maintenance/fore
locstring = "Fore Maintenance"
if(LOC_STARBOARD)
spawn_area_type = /area/maintenance/starboard
locstring = "Starboard Maintenance"
if(LOC_PORT)
spawn_area_type = /area/maintenance/port
locstring = "Locker Room Maintenance"
if(LOC_AFT)
spawn_area_type = /area/maintenance/aft
locstring = "Engineering Maintenance"
if(LOC_STORAGE)
spawn_area_type = /area/maintenance/storage
locstring = "Atmospherics Maintenance"
if(LOC_DISPOSAL)
spawn_area_type = /area/maintenance/disposal
locstring = "Waste Disposal"
if(LOC_GENETICS)
spawn_area_type = /area/maintenance/genetics
locstring = "Genetics Maintenance"
if(LOC_ELECTRICAL)
spawn_area_type = /area/maintenance/electrical
locstring = "Electrical Maintenance"
if(LOC_ABANDONEDBAR)
spawn_area_type = /area/maintenance/abandonedbar
locstring = "Maintenance Bar"
if(LOC_ELECTRICAL_SHOP)
spawn_area_type = /area/maintenance/electrical_shop
locstring ="Electronics Den"
if(LOC_GAMBLING_DEN)
spawn_area_type = /area/maintenance/gambling_den
locstring = "Gambling Den"
for(var/areapath in typesof(spawn_area_type))
var/area/A = locate(areapath)
for(var/turf/simulated/floor/F in A.contents)
if(turf_clear(F))
turfs += F
var/list/spawn_types = list()
var/max_number
headcrab = 0 //rand(0,x) for the future
switch(headcrab) //Switch is for the future
if(HEADCRAB_NORMAL)
spawn_types = list(/mob/living/simple_animal/hostile/headcrab)
max_number = 6
var/num = rand(2,max_number)
while(turfs.len > 0 && num > 0)
var/turf/simulated/floor/T = pick(turfs)
turfs.Remove(T)
num--
var/spawn_type = pick(spawn_types)
new spawn_type(T)
/datum/event/headcrabs/announce()
event_announcement.Announce("Bioscans indicate that creatures have been breeding in [locstring]. Clear them out, before this starts to affect productivity", "Lifesign Alert")
#undef LOC_ATMOS_CONTROL
#undef LOC_FPMAINT
#undef LOC_FPMAINT2
#undef LOC_FSMAINT
#undef LOC_FSMAINT2
#undef LOC_ASMAINT
#undef LOC_ASMAINT2
#undef LOC_APMAINT
#undef LOC_MAINTCENTRAL
#undef LOC_FORE
#undef LOC_STARBOARD
#undef LOC_PORT
#undef LOC_AFT
#undef LOC_STORAGE
#undef LOC_DISPOSAL
#undef LOC_GENETICS
#undef LOC_ELECTRICAL
#undef LOC_ABANDONEDBAR
#undef LOC_ELECTRICAL_SHOP
#undef LOC_GAMBLING_DEN
#undef HEADCRAB_NORMAL
@@ -1,100 +1,106 @@
#define EGG_INCUBATION_TIME 120
/mob/living/simple_animal/hostile/headcrab
name = "headslug"
desc = "Absolutely not de-beaked or harmless. Keep away from corpses."
name = "headcrab"
desc = "A small parasitic creature that would like to connect with your brain stem."
icon = 'icons/mob/headcrab.dmi'
icon_state = "headcrab"
icon_living = "headcrab"
icon_dead = "headcrab_dead"
icon = 'icons/mob/mob.dmi'
health = 50
maxHealth = 50
health = 40
maxHealth = 40
melee_damage_lower = 5
melee_damage_upper = 5
attacktext = "chomps"
attack_sound = 'sound/weapons/bite.ogg'
faction = list("creature")
robust_searching = 1
stat_attack = 2
obj_damage = 0
environment_smash = 0
speak_emote = list("squeaks")
ventcrawler = 2
var/datum/mind/origin
var/egg_lain = 0
melee_damage_upper = 10
ranged = 1
ranged_message = "leaps"
ranged_cooldown_time = 40
var/jumpdistance = 4
var/jumpspeed = 1
attacktext = "bites"
attack_sound = 'sound/creatures/headcrab_attack.ogg'
speak_emote = list("hisses")
var/is_zombie = 0
stat_attack = 1 //so they continue to attack when they are on the ground.
var/host_species = ""
var/list/human_overlays = list()
/mob/living/simple_animal/hostile/headcrab/examine(mob/user)
/mob/living/simple_animal/hostile/headcrab/Life(seconds, times_fired)
if(!is_zombie && isturf(src.loc) && stat != DEAD)
for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
Zombify(H)
break
..()
if(stat == DEAD)
to_chat(desc = "It appears to be dead.")
/mob/living/simple_animal/hostile/headcrab/proc/Infect(mob/living/carbon/victim)
var/obj/item/organ/internal/body_egg/changeling_egg/egg = new(victim)
egg.insert(victim)
if(origin)
egg.origin = origin
else if(mind) // Let's make this a feature
egg.origin = mind
for(var/obj/item/organ/internal/I in src)
I.loc = egg
visible_message("<span class='warning'>[src] plants something in [victim]'s flesh!</span>", \
"<span class='danger'>We inject our egg into [victim]'s body!</span>")
egg_lain = 1
/mob/living/simple_animal/hostile/headcrab/OpenFire(atom/A)
if(check_friendly_fire)
for(var/turf/T in getline(src,A)) // Not 100% reliable but this is faster than simulating actual trajectory
for(var/mob/living/L in T)
if(L == src || L == A)
continue
if(faction_check(L) && !attack_same)
return
visible_message("<span class='danger'><b>[src]</b> [ranged_message] at [A]!</span>")
throw_at(A, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE)
ranged_cooldown = world.time + ranged_cooldown_time
/mob/living/simple_animal/hostile/headcrab/AttackingTarget()
if(egg_lain)
target.attack_animal(src)
return
if(iscarbon(target) && !issmall(target))
// Changeling egg can survive in aliens!
var/mob/living/carbon/C = target
if(C.stat == DEAD)
if(C.status_flags & XENO_HOST)
to_chat(src, "<span class='userdanger'>A foreign presence repels us from this body. Perhaps we should try to infest another?</span>")
return
Infect(target)
to_chat(src, "<span class='userdanger'>With our egg laid, our death approaches rapidly...</span>")
spawn(100)
death()
return
target.attack_animal(src)
/mob/living/simple_animal/hostile/headcrab/proc/Zombify(mob/living/carbon/human/H)
if(!H.check_death_method())
H.death()
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
if(A.armor && A.armor["melee"])
maxHealth += A.armor["melee"] //That zombie's got armor, I want armor!
maxHealth += 50
health = maxHealth
name = "zombie"
desc = "A corpse animated by the alien being on its head."
melee_damage_lower = 10
melee_damage_upper = 15
ranged = 0
icon = H.icon
speak = list('sound/creatures/zombie_idle1.ogg','sound/creatures/zombie_idle2.ogg','sound/creatures/zombie_idle3.ogg')
speak_chance = 50
speak_emote = list("groans")
attacktext = "bites"
attack_sound = 'sound/creatures/zombie_attack.ogg'
icon_state = "zombie2_s"
if(head_organ)
head_organ.h_style = null
H.update_hair()
host_species = H.dna.species.name
human_overlays = H.overlays
update_icons()
H.forceMove(src)
visible_message("<span class='warning'>The corpse of [H.name] suddenly rises!</span>")
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
desc = "Twitching and disgusting."
origin_tech = "biotech=7" // You need to be really lucky to obtain it.
var/datum/mind/origin
var/time
/obj/item/organ/internal/body_egg/changeling_egg/egg_process()
// Changeling eggs grow in dead people
time++
if(time >= EGG_INCUBATION_TIME)
Pop()
remove(owner)
/mob/living/simple_animal/hostile/headcrab/death()
..()
if(is_zombie)
qdel(src)
/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop()
var/mob/living/carbon/human/monkey/M = new(owner)
owner.stomach_contents += M
for(var/obj/item/organ/internal/I in src)
I.insert(M, 1)
/mob/living/simple_animal/hostile/headcrab/handle_automated_speech() // This way they have different screams when attacking, sometimes. Might be seen as sphagetthi code though.
if(speak_chance)
if(rand(0,200) < speak_chance)
if(speak && speak.len)
playsound(get_turf(src), pick(speak), 200, 1)
if(origin && origin.current && (origin.current.stat == DEAD))
origin.transfer_to(M)
if(!origin.changeling)
M.make_changeling()
if(origin.changeling.can_absorb_dna(M, owner))
origin.changeling.absorb_dna(owner, M)
/mob/living/simple_animal/hostile/headcrab/Destroy()
if(contents)
for(var/mob/M in contents)
M.loc = get_turf(src)
return ..()
var/datum/action/changeling/humanform/HF = new
HF.Grant(M)
for(var/power in origin.changeling.purchasedpowers)
var/datum/action/changeling/S = power
if(istype(S) && S.needs_button)
S.Grant(M)
M.key = origin.key
owner.gib()
#undef EGG_INCUBATION_TIME
/mob/living/simple_animal/hostile/headcrab/update_icons()
..()
if(is_zombie)
overlays.Cut()
overlays = human_overlays
var/image/I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod")
if(host_species == "Vox")
I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod_vox")
else if(host_species == "Gray")
I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod_gray")
overlays += I
@@ -0,0 +1,100 @@
#define EGG_INCUBATION_TIME 120
/mob/living/simple_animal/hostile/headslug
name = "headslug"
desc = "Absolutely not de-beaked or harmless. Keep away from corpses."
icon_state = "headslug"
icon_living = "headslug"
icon_dead = "headslug_dead"
icon = 'icons/mob/mob.dmi'
health = 50
maxHealth = 50
melee_damage_lower = 5
melee_damage_upper = 5
attacktext = "chomps"
attack_sound = 'sound/weapons/bite.ogg'
faction = list("creature")
robust_searching = 1
stat_attack = 2
obj_damage = 0
environment_smash = 0
speak_emote = list("squeaks")
ventcrawler = 2
var/datum/mind/origin
var/egg_lain = 0
/mob/living/simple_animal/hostile/headslug/examine(mob/user)
..()
if(stat == DEAD)
to_chat(desc = "It appears to be dead.")
/mob/living/simple_animal/hostile/headslug/proc/Infect(mob/living/carbon/victim)
var/obj/item/organ/internal/body_egg/changeling_egg/egg = new(victim)
egg.insert(victim)
if(origin)
egg.origin = origin
else if(mind) // Let's make this a feature
egg.origin = mind
for(var/obj/item/organ/internal/I in src)
I.loc = egg
visible_message("<span class='warning'>[src] plants something in [victim]'s flesh!</span>", \
"<span class='danger'>We inject our egg into [victim]'s body!</span>")
egg_lain = 1
/mob/living/simple_animal/hostile/headslug/AttackingTarget()
if(egg_lain)
target.attack_animal(src)
return
if(iscarbon(target) && !issmall(target))
// Changeling egg can survive in aliens!
var/mob/living/carbon/C = target
if(C.stat == DEAD)
if(C.status_flags & XENO_HOST)
to_chat(src, "<span class='userdanger'>A foreign presence repels us from this body. Perhaps we should try to infest another?</span>")
return
Infect(target)
to_chat(src, "<span class='userdanger'>With our egg laid, our death approaches rapidly...</span>")
spawn(100)
death()
return
target.attack_animal(src)
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
desc = "Twitching and disgusting."
origin_tech = "biotech=7" // You need to be really lucky to obtain it.
var/datum/mind/origin
var/time
/obj/item/organ/internal/body_egg/changeling_egg/egg_process()
// Changeling eggs grow in dead people
time++
if(time >= EGG_INCUBATION_TIME)
Pop()
remove(owner)
qdel(src)
/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop()
var/mob/living/carbon/human/monkey/M = new(owner)
owner.stomach_contents += M
for(var/obj/item/organ/internal/I in src)
I.insert(M, 1)
if(origin && origin.current && (origin.current.stat == DEAD))
origin.transfer_to(M)
if(!origin.changeling)
M.make_changeling()
if(origin.changeling.can_absorb_dna(M, owner))
origin.changeling.absorb_dna(owner, M)
var/datum/action/changeling/humanform/HF = new
HF.Grant(M)
for(var/power in origin.changeling.purchasedpowers)
var/datum/action/changeling/S = power
if(istype(S) && S.needs_button)
S.Grant(M)
M.key = origin.key
owner.gib()
#undef EGG_INCUBATION_TIME