Terror Princess Rework (#13657)

* rework queen eggs, princess caste

* add trailing newlines for travis

* refactor for code standards

* Remove old/incorrect comment from queen.dm

* refactor purple.dm, add notification for which area queen is in

* princesses no longer lose ventcrawl or gain wallsmash when nesting, deletes MassFlicker()

* add status tab info for purples about where their queen is

* Simplified princess code: removed NestMode(), NestMode2().

* makes terrors use 'bite' animation when attacking something

* status tab spider regeneration helptext

* converts queen spit from TOX to BURN, empress single-fire

* fixes terror gender, double-examine text. add terrors closing airlocks, remove queen wrap

* newline for travis

* alter terror spider event balance depending on server pop

* white infection sequence: gray, red, brown, green, green

* moves #define isterrorspider(A) to __DEFINES\mobs.dm

* remove typoed comment

* fix: prevent exploit with spam-clicking egglay action button

* fix: prevent AI trying to move spiders after a player takes control of them

* fix bug where terrors bumping an airlock repeatedly could make it both open and close

* clarify comment on event odds

* increase queen spit burn damage from 30 to 40

* add: queen webs are now airtight, instead of dealing damage/hallucination

* remove spider alert for already-controlled spiders

* queen spit naming fix

* travis newline

* encourage princesses to remain outside vents

* fixes calls to CountSpidersDetailed not using list()

* makes it easier to debug away mission AI

* code quality: more typeless loops

* add: killing a queen, also kills most of her offspring

* remove walk fix, for splitting into another PR

* remove events\spider_terror.dm changes, move to another PR

* makes it compile - will still require merge conflict resolving later.

* fix: purple webs cause purples to lose sign of queen and die

* visible-> near for purples

* fix wrong gender on spiders

* queen spit now damages structures (like mechs) and other spiders

* ghost spacing

* show queen living time on examine

* Fixes #12969 - terrors getting stuck in web

* revert all changes to purple.dm

* farie requests 1

* farie refactoring II

* var/list/spider_array

* var/list/spider_totals

* more farie

* queen examine laycount, initial eggcount

* terror heat vulnerability, refactoring 1/0 vars

Co-authored-by: Kyep <Kyep@users.noreply.github.com>
This commit is contained in:
Kyep
2020-09-17 22:29:32 +00:00
committed by GitHub
parent 5cafb0bf16
commit e135c2326b
16 changed files with 395 additions and 287 deletions
+1
View File
@@ -208,6 +208,7 @@
#define isguardian(A) (istype((A), /mob/living/simple_animal/hostile/guardian))
#define isnymph(A) (istype((A), /mob/living/simple_animal/diona))
#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile))
#define isterrorspider(A) (istype((A), /mob/living/simple_animal/hostile/poison/terror_spider))
#define issilicon(A) (istype((A), /mob/living/silicon))
#define isAI(A) (istype((A), /mob/living/silicon/ai))
+1 -1
View File
@@ -42,7 +42,7 @@
/obj/structure/spider/stickyweb/CanPass(atom/movable/mover, turf/target, height=0)
if(height == 0)
return TRUE
if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider))
if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider) || isterrorspider(mover))
return TRUE
else if(istype(mover, /mob/living))
if(prob(50))
+2 -2
View File
@@ -43,8 +43,8 @@
spawncount = 2
if(4)
// Pretty strong.
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/princess
spawncount = 2
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/queen/princess
spawncount = 3
if(5)
// Strongest, only used during highpop.
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/queen
@@ -42,27 +42,6 @@
var/mob/living/simple_animal/hostile/poison/terror_spider/user = owner
user.DoVentSmash()
// ---------- PRINCESS ACTIONS
/datum/action/innate/terrorspider/evolvequeen
name = "Evolve Queen"
icon_icon = 'icons/mob/terrorspider.dmi'
button_icon_state = "terror_queen"
/datum/action/innate/terrorspider/evolvequeen/Activate()
var/mob/living/simple_animal/hostile/poison/terror_spider/princess/user = owner
if(!istype(user))
to_chat(user, "<span class='warning'>ERROR: attempt to use evolve queen ability on a non-princess</span>")
return
var/feedings_left = user.feedings_to_evolve - user.fed
if(feedings_left > 0)
to_chat(user, "<span class='warning'>You must wrap [feedings_left] more humanoid prey before you can do this!</span>")
return
for(var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q in GLOB.ts_spiderlist)
if(Q.spider_awaymission == user.spider_awaymission)
to_chat(user, "<span class='warning'>The presence of another Queen in the area is preventing you from maturing.")
return
user.evolve_to_queen()
// ---------- QUEEN ACTIONS
@@ -93,19 +72,11 @@
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/user = owner
user.LayQueenEggs()
/datum/action/innate/terrorspider/queen/queenfakelings
name = "Fake Spiderlings"
icon_icon = 'icons/effects/effects.dmi'
button_icon_state = "spiderling"
/datum/action/innate/terrorspider/queen/queenfakelings/Activate()
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/user = owner
user.QueenFakeLings()
// ---------- EMPRESS
/datum/action/innate/terrorspider/queen/empress/empresserase
name = "Erase Brood"
name = "Empress Erase Brood"
icon_icon = 'icons/effects/blood.dmi'
button_icon_state = "mgibbl1"
@@ -113,6 +84,16 @@
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/user = owner
user.EraseBrood()
/datum/action/innate/terrorspider/queen/empress/empresslings
name = "Empresss Spiderlings"
icon_icon = 'icons/effects/effects.dmi'
button_icon_state = "spiderling"
/datum/action/innate/terrorspider/queen/empress/empresslings/Activate()
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/user = owner
user.EmpressLings()
// ---------- WEB
/mob/living/simple_animal/hostile/poison/terror_spider/proc/Web()
@@ -22,7 +22,7 @@
else if(volume < 90)
// bitten thrice, die quickly, severe muscle cramps make movement very difficult. Even calling for help probably won't save you.
// total damage: 4, human health 150 until crit, = 37.5 ticks, = 75s = 1m15s until death
update_flags |= M.adjustToxLoss(4, FALSE) // a bit worse than coiine
update_flags |= M.adjustToxLoss(4, FALSE)
update_flags |= M.EyeBlurry(6, FALSE)
M.Confused(6)
else
@@ -19,7 +19,6 @@
ventcrawler = 1
idle_ventcrawl_chance = 0
ai_playercontrol_allowtype = 0
rapid = 3
canlay = 1000
spider_tier = TS_TIER_5
projectiletype = /obj/item/projectile/terrorqueenspit/empress
@@ -35,6 +34,8 @@
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/New()
..()
empresslings_action = new()
empresslings_action.Grant(src)
empresserase_action = new()
empresserase_action.Grant(src)
@@ -44,7 +45,6 @@
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/NestMode()
..()
queeneggs_action.button.name = "Empress Eggs"
queenfakelings_action.button.name = "Empress Lings"
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/LayQueenEggs()
var/eggtype = input("What kind of eggs?") as null|anything in list(TS_DESC_QUEEN, TS_DESC_MOTHER, TS_DESC_PRINCE, TS_DESC_PRINCESS, TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN, TS_DESC_BLACK, TS_DESC_PURPLE, TS_DESC_WHITE, TS_DESC_BROWN)
@@ -70,7 +70,7 @@
if(TS_DESC_PRINCE)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/prince, numlings)
if(TS_DESC_PRINCESS)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/princess, numlings)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess, numlings)
if(TS_DESC_MOTHER)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/mother, numlings)
if(TS_DESC_QUEEN)
@@ -78,7 +78,7 @@
else
to_chat(src, "<span class='danger'>Unrecognized egg type.</span>")
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/QueenFakeLings()
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/proc/EmpressLings()
var/numlings = input("How many?") as null|anything in list(10, 20, 30, 40, 50)
var/sbpc = input("%chance to be stillborn?") as null|anything in list(0, 25, 50, 75, 100)
for(var/i=0, i<numlings, i++)
@@ -96,7 +96,8 @@
S.amount_grown = 250
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/proc/EraseBrood()
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist)
for(var/thing in GLOB.ts_spiderlist)
var/mob/living/simple_animal/hostile/poison/terror_spider/T = thing
if(T.spider_tier < spider_tier)
T.degenerate = 1
to_chat(T, "<span class='userdanger'>Through the hivemind, the raw power of [src] floods into your body, burning it from the inside out!</span>")
@@ -106,8 +107,6 @@
qdel(T)
to_chat(src, "<span class='userdanger'>All Terror Spiders, except yourself, will die off shortly.</span>")
/obj/item/projectile/terrorqueenspit/empress
damage_type = BURN
damage = 30
bonus_tox = 0
damage = 90
@@ -39,11 +39,10 @@
to_chat(src, "<span class='warning'>You must wrap more humanoid prey before you can do this!</span>")
return
var/list/eggtypes = list(TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN)
var/num_brown = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/brown)
if(num_brown < 2)
var/list/spider_array = CountSpidersDetailed(FALSE)
if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/brown] < 2)
eggtypes += TS_DESC_BROWN
var/num_black = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/black)
if(num_black < 2)
if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/black] < 2)
eggtypes += TS_DESC_BLACK
var/eggtype = pick(eggtypes)
if(client)
@@ -4,7 +4,8 @@
/mob/living/simple_animal/hostile/poison/terror_spider/proc/DoHiveSense()
var/hsline = ""
to_chat(src, "Your Brood: ")
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist)
for(var/thing in GLOB.ts_spiderlist)
var/mob/living/simple_animal/hostile/poison/terror_spider/T = thing
if(T.spider_awaymission != spider_awaymission)
continue
hsline = "* [T] in [get_area(T)], "
@@ -20,21 +21,55 @@
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CountSpiders()
var/numspiders = 0
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist)
for(var/thing in GLOB.ts_spiderlist)
var/mob/living/simple_animal/hostile/poison/terror_spider/T = thing
if(T.stat != DEAD && !T.spider_placed && spider_awaymission == T.spider_awaymission)
numspiders += 1
return numspiders
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CountSpidersType(specific_type)
var/numspiders = 0
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist)
if(T.stat != DEAD && !T.spider_placed && spider_awaymission == T.spider_awaymission)
if(T.type == specific_type)
numspiders += 1
for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in GLOB.ts_egg_list)
if(E.spiderling_type == specific_type && E.z == z)
numspiders += E.spiderling_number
for(var/obj/structure/spider/spiderling/terror_spiderling/L in GLOB.ts_spiderling_list)
if(!L.stillborn && L.grow_as == specific_type && L.z == z)
numspiders += 1
return numspiders
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CountSpidersDetailed(check_mine = FALSE, list/mytypes = list())
var/list/spider_totals = list("all" = 0)
var/check_list = length(mytypes) > 0
for(var/thistype in mytypes)
spider_totals[thistype] = 0
for(var/thing in GLOB.ts_spiderlist)
var/mob/living/simple_animal/hostile/poison/terror_spider/T = thing
if(T.stat == DEAD || T.spider_placed || spider_awaymission != T.spider_awaymission)
continue
if(check_mine && T.spider_myqueen != src)
continue
if(check_list && !(T.type in mytypes))
continue
if(T == src)
continue
if(spider_totals[T.type])
spider_totals[T.type]++
else
spider_totals[T.type] = 1
spider_totals["all"]++
for(var/thing in GLOB.ts_egg_list)
var/obj/structure/spider/eggcluster/terror_eggcluster/E = thing
if(check_mine && E.spider_myqueen != src)
continue
if(check_list && E.spiderling_type && !(E.spiderling_type in mytypes))
continue
if(spider_totals[E.spiderling_type])
spider_totals[E.spiderling_type] += E.spiderling_number
else
spider_totals[E.spiderling_type] = E.spiderling_number
spider_totals["all"] += E.spiderling_number
for(var/thing in GLOB.ts_spiderling_list)
var/obj/structure/spider/spiderling/terror_spiderling/L = thing
if(L.stillborn)
continue
if(check_mine && L.spider_myqueen != src)
continue
if(check_list && L.grow_as && !(L.grow_as in mytypes))
continue
if(spider_totals[L.grow_as])
spider_totals[L.grow_as]++
else
spider_totals[L.grow_as] = 1
spider_totals["all"]++
return spider_totals
@@ -29,6 +29,7 @@
spider_opens_doors = 2
web_type = /obj/structure/spider/terrorweb/purple
ai_spins_webs = FALSE
gender = MALE
/mob/living/simple_animal/hostile/poison/terror_spider/prince/death(gibbed)
if(can_die() && !hasdied && spider_uo71)
@@ -2,58 +2,76 @@
// --------------------------------------------------------------------------------
// ----------------- TERROR SPIDERS: T3 PRINCESS OF TERROR --------------------------
// --------------------------------------------------------------------------------
// -------------: ROLE: cutesy
// -------------: AI: as green, but will evolve to queen when it can
// -------------: SPECIAL: can evolve into a queen, if fed enough
// -------------: TO FIGHT IT: kill it before it evolves
// -------------: ROLE: mini-queen, maintains a smaller nest, but also more expendable
// -------------: AI: maintains a small group of spiders. Small fraction of a queen's nest.
// -------------: SPECIAL: lays eggs over time, like a queen
// -------------: TO FIGHT IT: hunt it before it lays eggs
// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos
/mob/living/simple_animal/hostile/poison/terror_spider/princess
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess
name = "Princess of Terror spider"
desc = "An enormous spider. It looks strangely cute and fluffy."
spider_role_summary = "Future Queen"
spider_role_summary = "Mini-Queen"
ai_target_method = TS_DAMAGE_SIMPLE
icon_state = "terror_princess1"
icon_living = "terror_princess1"
icon_dead = "terror_princess1_dead"
maxHealth = 150
health = 150
regen_points_per_hp = 1 // always regens very fast
force_threshold = 18 // outright immune to anything of force under 18, same as queen
melee_damage_lower = 10
melee_damage_upper = 20
idle_ventcrawl_chance = 5
spider_tier = TS_TIER_3
spider_opens_doors = 2
web_type = /obj/structure/spider/terrorweb/queen
var/feedings_to_evolve = 3
var/datum/action/innate/terrorspider/ventsmash/ventsmash_action
var/datum/action/innate/terrorspider/evolvequeen/evolvequeen_action
/mob/living/simple_animal/hostile/poison/terror_spider/princess/New()
..()
ventsmash_action = new()
ventsmash_action.Grant(src)
evolvequeen_action = new()
evolvequeen_action.Grant(src)
// Unlike queens, no ranged attack.
ranged = 0
retreat_distance = 0
minimum_distance = 0
projectilesound = null
projectiletype = null
/mob/living/simple_animal/hostile/poison/terror_spider/princess/proc/evolve_to_queen()
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q = new(loc)
if(mind)
mind.transfer_to(Q)
// Calling `transfer_to()` removes our new body (the Queen's) ability to see the med hud, so we have to re-add the queen here.
var/datum/atom_hud/U = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
U.add_hud_to(Q)
qdel(src)
canlay = 0
hasnested = TRUE
spider_spawnfrequency = 300 // 30 seconds
var/grant_prob = 25 // 25% chance every spider_spawnfrequency seconds to gain 1 egg
var/spider_max_children = 8
/mob/living/simple_animal/hostile/poison/terror_spider/princess/DoWrap()
. = ..()
if(fed == 0)
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess/grant_queen_subtype_abilities()
// Queens start in movement mode, where they can ventcrawl but not lay eggs. Then they move to NestMode() where they can wallsmash and egglay, but not ventcrawl.
// Princesses are simpler, and can always lay eggs, always vent crawl, but never smash walls. Unlike queens, they don't have a "nesting" transformation.
queeneggs_action = new()
queeneggs_action.Grant(src)
queensense_action = new()
queensense_action.Grant(src)
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess/ListAvailableEggTypes()
var/list/valid_types = list(TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN)
// Each princess can also have ONE black/purple/brown. If it dies, they can pick a new spider from the 3 advanced types to lay.
var/list/spider_array = CountSpidersDetailed(TRUE, list(/mob/living/simple_animal/hostile/poison/terror_spider/black, /mob/living/simple_animal/hostile/poison/terror_spider/purple, /mob/living/simple_animal/hostile/poison/terror_spider/brown))
if(spider_array["all"] < 1)
valid_types |= TS_DESC_BLACK
valid_types |= TS_DESC_PURPLE
valid_types |= TS_DESC_BROWN
return valid_types
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess/grant_eggs()
spider_lastspawn = world.time
if(!prob(grant_prob))
return
var/list/spider_array = CountSpidersDetailed(TRUE)
var/brood_count = spider_array["all"]
// Color shifts depending on how much of their brood capacity they have used.
if(brood_count == 0)
icon_state = "terror_princess1"
icon_living = "terror_princess1"
icon_dead = "terror_princess1_dead"
desc = "An enormous spider. It looks strangely cute and fluffy, with soft pink fur covering most of its body."
else if(fed == 1)
else if(brood_count < (spider_max_children /2))
icon_state = "terror_princess2"
icon_living = "terror_princess2"
icon_dead = "terror_princess2_dead"
@@ -62,13 +80,45 @@
icon_state = "terror_princess3"
icon_living = "terror_princess3"
icon_dead = "terror_princess3_dead"
desc = "An enormous spider. Its entire body has turned an ominous blood red color, with actual blood dripping from its jaws. It stares around, hungrily."
desc = "An enormous spider. Its entire body looks to be the color of dried blood."
/mob/living/simple_animal/hostile/poison/terror_spider/princess/spider_special_action()
if(cocoon_target)
handle_cocoon_target()
else if(fed >= feedings_to_evolve)
evolve_to_queen()
else if(world.time > (last_cocoon_object + freq_cocoon_object))
seek_cocoon_target()
if(!isturf(loc))
to_chat(src, "<span class='danger'>You cannot generate eggs while hiding in [loc].</span>")
return
if((brood_count + canlay) >= spider_max_children)
return
canlay++
if(canlay == 1)
to_chat(src, "<span class='notice'>You have an egg available to lay.</span>")
else
to_chat(src, "<span class='notice'>You have [canlay] eggs available to lay.</span>")
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess/NestMode()
// Princesses don't nest. However, we still need to override this in case an AI princess calls it.
return
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess/spider_special_action()
// Princess AI routine. GREATLY simplified version of queen routine.
if(!stat && !ckey)
// Utilize normal queen AI for finding a nest site (neststep=0), and activating NestMode() (neststep=1)
if(neststep != 2)
return ..()
// After that, simply lay an egg once per nestfrequency, until we have the max.
if(world.time < (lastnestsetup + nestfrequency))
return
lastnestsetup = world.time
if(ai_nest_is_full())
return
spider_lastspawn = world.time
DoLayTerrorEggs(pick(spider_types_standard), 1)
// Yes, this means NPC princesses won't create T2 spiders.
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess/ai_nest_is_full()
var/list/spider_array = CountSpidersDetailed(TRUE)
if(spider_array["all"] >= spider_max_children)
return TRUE
return FALSE
@@ -5,7 +5,7 @@
// -------------: ROLE: gamma-level threat to the whole station, like a blob
// -------------: AI: builds a nest, lays many eggs, attempts to take over the station
// -------------: SPECIAL: spins webs, breaks lights, breaks cameras, webs objects, lays eggs, commands other spiders...
// -------------: TO FIGHT IT: bring an army, and take no prisoners. Mechs and/or decloner guns are a very good idea.
// -------------: TO FIGHT IT: bring an army, and take no prisoners. Mechs are a very good idea.
// -------------: SPRITES FROM: IK3I
/mob/living/simple_animal/hostile/poison/terror_spider/queen
@@ -43,69 +43,94 @@
var/neststep = 0
var/hasnested = FALSE
var/spider_max_per_nest = 35 // above this, AI queens become stable
var/canlay = 4 // main counter for egg-laying ability! # = num uses, incremented at intervals
var/canlay = 5 // main counter for egg-laying ability! # = num uses, incremented at intervals
var/eggslaid = 0
var/spider_can_fakelings = 3 // spawns defective spiderlings that don't grow up, used to freak out crew, atmosphere
var/list/spider_types_standard = list(/mob/living/simple_animal/hostile/poison/terror_spider/red, /mob/living/simple_animal/hostile/poison/terror_spider/gray, /mob/living/simple_animal/hostile/poison/terror_spider/green, /mob/living/simple_animal/hostile/poison/terror_spider/black)
var/datum/action/innate/terrorspider/queen/queennest/queennest_action
var/datum/action/innate/terrorspider/queen/queensense/queensense_action
var/datum/action/innate/terrorspider/queen/queeneggs/queeneggs_action
var/datum/action/innate/terrorspider/queen/queenfakelings/queenfakelings_action
var/datum/action/innate/terrorspider/ventsmash/ventsmash_action
/mob/living/simple_animal/hostile/poison/terror_spider/queen/New()
..()
queennest_action = new()
queennest_action.Grant(src)
ventsmash_action = new()
ventsmash_action.Grant(src)
grant_queen_subtype_abilities()
spider_myqueen = src
if(spider_awaymission)
spider_growinstantly = 1
spider_growinstantly = TRUE
spider_spawnfrequency = 150
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/grant_queen_subtype_abilities()
queennest_action = new()
queennest_action.Grant(src)
/mob/living/simple_animal/hostile/poison/terror_spider/queen/Life(seconds, times_fired)
. = ..()
if(stat != DEAD) // Can't use if(.) for this due to the fact it can sometimes return FALSE even when mob is alive.
if(ckey && canlay < 12 && hasnested) // max 12 eggs worth stored at any one time, realistically that's tons.
if(ckey && hasnested)
if(world.time > (spider_lastspawn + spider_spawnfrequency))
if(eggslaid >= 20)
canlay += 3
else if(eggslaid >= 10)
canlay += 2
else
canlay++
spider_lastspawn = world.time
if(canlay == 1)
to_chat(src, "<span class='notice'>You have an egg available to lay.</span>")
else if(canlay == 12)
to_chat(src, "<span class='notice'>You have [canlay] eggs available to lay. You won't grow any more eggs until you lay some of your existing ones.</span>")
else
to_chat(src, "<span class='notice'>You have [canlay] eggs available to lay.</span>")
grant_eggs()
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/grant_eggs()
spider_lastspawn = world.time
canlay += getSpiderLevel()
if(canlay == 1)
to_chat(src, "<span class='notice'>You have an egg available to lay.</span>")
else if(canlay > 1)
to_chat(src, "<span class='notice'>You have [canlay] eggs available to lay.</span>")
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/getSpiderLevel()
return 1 + round(MinutesAlive() / 10)
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/MinutesAlive()
return round((world.time - spider_creation_time) / 600)
/mob/living/simple_animal/hostile/poison/terror_spider/queen/death(gibbed)
if(can_die() && !hasdied)
if(spider_uo71)
UnlockBlastDoors("UO71_Caves")
// When a queen dies, so do her player-controlled purple-type guardians. Intended as a motivator for purples to ensure they guard her.
for(var/mob/living/simple_animal/hostile/poison/terror_spider/purple/P in GLOB.ts_spiderlist)
if(ckey)
P.visible_message("<span class='danger'>\The [src] writhes in pain!</span>")
to_chat(P,"<span class='userdanger'>\The [src] has died. Without her hivemind link, purple terrors like yourself cannot survive more than a few minutes!</span>")
P.degenerate = 1
// When a queen (or subtype!) dies, so do all of her spiderlings, and half of all her fully grown offspring
// This feature is intended to provide a way for crew to still win even if the queen has overwhelming numbers - by sniping the queen.
for(var/thing in GLOB.ts_spiderlist)
var/mob/living/simple_animal/hostile/poison/terror_spider/T = thing
if(!T.spider_myqueen)
continue
if(T.spider_myqueen != src)
continue
if(prob(50) || T.spider_tier >= spider_tier)
to_chat(T, "<span class='userdanger'>\The psychic backlash from the death of [src] crashes into your mind! Somehow... you find a way to keep going!</span>")
continue
T.visible_message("<span class='danger'>[T] writhes in pain!</span>")
to_chat(T, "<span class='userdanger'>\The psychic backlash from the death of [src] overwhelms you! You feel the life start to drain out of you...</span>")
T.degenerate = TRUE
for(var/thing in GLOB.ts_spiderling_list)
var/obj/structure/spider/spiderling/terror_spiderling/T = thing
if(T.spider_myqueen && T.spider_myqueen == src)
qdel(T)
return ..()
/mob/living/simple_animal/hostile/poison/terror_spider/queen/Retaliate()
..()
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist)
for(var/thing in GLOB.ts_spiderlist)
var/mob/living/simple_animal/hostile/poison/terror_spider/T = thing
T.enemies |= enemies
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/ai_nest_is_full()
var/numspiders = CountSpiders()
if(numspiders >= spider_max_per_nest)
return TRUE
return FALSE
/mob/living/simple_animal/hostile/poison/terror_spider/queen/spider_special_action()
if(!stat && !ckey)
switch(neststep)
@@ -152,11 +177,13 @@
neststep = 2
NestMode()
if(2)
// Create initial four purple nest guards.
// Create initial T2 spiders.
if(world.time > (lastnestsetup + nestfrequency))
lastnestsetup = world.time
spider_lastspawn = world.time
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, 4)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, 2)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/white, 2)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/brown, 2)
neststep = 3
if(3)
// Create spiders (random types) until nest is full.
@@ -183,28 +210,26 @@
neststep = 4
else
spider_lastspawn = world.time
var/num_purple = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/purple)
var/num_white = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/white)
var/num_brown = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/brown)
if(num_purple < 4)
var/list/spider_array = CountSpidersDetailed(FALSE)
if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/purple] < 4)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, 2)
else if(num_white < 2)
else if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/white] < 2)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/white, 2)
else if(num_brown < 4)
else if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/brown] < 4)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/brown, 4)
else
DoLayTerrorEggs(pick(spider_types_standard), 5)
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/NestPrompt()
var/confirm = alert(src, "Are you sure you want to nest? You will be able to lay eggs, and smash walls, but not ventcrawl.","Nest?","Yes","No")
if(confirm == "Yes")
NestMode()
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/NestMode()
queeneggs_action = new()
queeneggs_action.Grant(src)
queenfakelings_action = new()
queenfakelings_action.Grant(src)
queensense_action = new()
queensense_action.Grant(src)
queennest_action.Remove(src)
@@ -213,21 +238,8 @@
ai_ventcrawls = FALSE
environment_smash = ENVIRONMENT_SMASH_RWALLS
DoQueenScreech(8, 100, 8, 100)
MassFlicker()
to_chat(src, "<span class='notice'>You have matured to your egglaying stage. You can now smash through walls, and lay eggs, but can no longer ventcrawl.</span>")
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/MassFlicker()
var/list/target_lights = list()
for(var/mob/living/carbon/human/H in GLOB.player_list)
if(H.z != z)
continue
if(H.stat == DEAD)
continue
for(var/obj/machinery/light/L in orange(7, H))
if(L.on && prob(25))
target_lights += L
for(var/obj/machinery/light/I in target_lights)
I.flicker()
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/LayQueenEggs()
if(stat == DEAD)
@@ -242,42 +254,21 @@
else
to_chat(src, "<span class='danger'>Too soon to attempt that again. Wait just a few more seconds...</span>")
return
var/list/eggtypes = list(TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN, TS_DESC_BLACK, TS_DESC_PURPLE)
if(canlay >= 4)
eggtypes |= TS_DESC_BROWN
if(canlay >= 12)
eggtypes |= TS_DESC_MOTHER
eggtypes |= TS_DESC_PRINCE
var/num_purples = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/purple)
if(num_purples >= 2)
eggtypes -= TS_DESC_PURPLE
var/num_blacks = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/black)
if(num_blacks >= 2)
eggtypes -= TS_DESC_BLACK
var/list/eggtypes = ListAvailableEggTypes()
var/list/eggtypes_uncapped = list(TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN)
var/eggtype = input("What kind of eggs?") as null|anything in eggtypes
if(canlay < 1)
// this was checked before input() but we have to check again to prevent them spam-clicking the popup.
to_chat(src, "<span class='danger'>Too soon to lay another egg.</span>")
return
if(!(eggtype in eggtypes))
to_chat(src, "<span class='danger'>Unrecognized egg type.</span>")
return 0
if(eggtype == TS_DESC_MOTHER || eggtype == TS_DESC_PRINCE)
if(canlay < 12)
to_chat(src, "<span class='danger'>Insufficient strength. It takes as much effort to lay one of those as it does to lay 12 normal eggs.</span>")
else
if(eggtype == TS_DESC_MOTHER)
canlay -= 12
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/mother, 1)
else if(eggtype == TS_DESC_PRINCE)
canlay -= 12
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/prince, 1)
return
else if(eggtype == TS_DESC_BROWN)
if(canlay < 4)
to_chat(src, "<span class='danger'>Insufficient strength. It takes as much effort to lay one of those as it does to lay 4 normal eggs.</span>")
else
canlay -= 4
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/brown, 1)
return
// Multiple of eggtypes_uncapped can be laid at once. Other types must be laid one at a time (to prevent exploits)
var/numlings = 1
if(eggtype != TS_DESC_PURPLE)
if(eggtype in eggtypes_uncapped)
if(canlay >= 5)
numlings = input("How many in the batch?") as null|anything in list(1, 2, 3, 4, 5)
else if(canlay >= 3)
@@ -287,27 +278,55 @@
if(eggtype == null || numlings == null)
to_chat(src, "<span class='danger'>Cancelled.</span>")
return
// Actually lay the eggs.
if(canlay < numlings)
// We have to check this again after the popups, to account for people spam-clicking the button, then doing all the popups at once.
to_chat(src, "<span class='warning'>Too soon to do this again!</span>")
return
canlay -= numlings
eggslaid += numlings
if(eggtype == TS_DESC_RED)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, numlings)
else if(eggtype == TS_DESC_GRAY)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/gray, numlings)
else if(eggtype == TS_DESC_GREEN)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, numlings)
else if(eggtype == TS_DESC_BLACK)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/black, numlings)
else if(eggtype == TS_DESC_PURPLE)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, numlings)
else
to_chat(src, "<span class='danger'>Unrecognized egg type.</span>")
switch(eggtype)
if(TS_DESC_RED)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, numlings)
if(TS_DESC_GRAY)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/gray, numlings)
if(TS_DESC_GREEN)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, numlings)
if(TS_DESC_BLACK)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/black, numlings)
if(TS_DESC_PURPLE)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, numlings)
if(TS_DESC_BROWN)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/brown, numlings)
if(TS_DESC_MOTHER)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/mother, numlings)
if(TS_DESC_PRINCE)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/prince, numlings)
if(TS_DESC_PRINCESS)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess, numlings)
else
to_chat(src, "<span class='danger'>Unrecognized egg type.</span>")
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/ListAvailableEggTypes()
if(MinutesAlive() >= 20)
var/list/spider_array = CountSpidersDetailed(TRUE, list(/mob/living/simple_animal/hostile/poison/terror_spider/mother, /mob/living/simple_animal/hostile/poison/terror_spider/prince, /mob/living/simple_animal/hostile/poison/terror_spider/queen/princess))
if(spider_array["all"] == 0)
return list(TS_DESC_PRINCE, TS_DESC_PRINCESS) // Mother will be added to this list.... AFTER mothers are reworked.
var/list/valid_types = list(TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN)
var/list/spider_array = CountSpidersDetailed(FALSE, list(/mob/living/simple_animal/hostile/poison/terror_spider/brown, /mob/living/simple_animal/hostile/poison/terror_spider/purple, /mob/living/simple_animal/hostile/poison/terror_spider/black))
if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/brown] < 2)
valid_types += TS_DESC_BROWN
if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/purple] < 2)
valid_types += TS_DESC_PURPLE
if(spider_array[/mob/living/simple_animal/hostile/poison/terror_spider/black] < 2)
valid_types += TS_DESC_BLACK
return valid_types
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/DoQueenScreech(light_range, light_chance, camera_range, camera_chance)
visible_message("<span class='userdanger'>\The [src] emits a bone-chilling shriek!</span>")
visible_message("<span class='userdanger'>[src] emits a bone-chilling shriek!</span>")
for(var/obj/machinery/light/L in orange(light_range, src))
if(L.on && prob(light_chance))
L.break_light_tube()
@@ -315,46 +334,33 @@
if(C.status && prob(camera_chance))
C.toggle_cam(src, 0)
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/QueenFakeLings()
if(eggslaid < 10)
to_chat(src, "<span class='danger'>You must lay at least 10 eggs before doing this.</span>")
/mob/living/simple_animal/hostile/poison/terror_spider/queen/examine(mob/user)
. = ..()
if(!key || stat == DEAD)
return
if(spider_can_fakelings)
spider_can_fakelings--
var/numlings = 25
for(var/i in 1 to numlings)
var/obj/structure/spider/spiderling/terror_spiderling/S = new /obj/structure/spider/spiderling/terror_spiderling(get_turf(src))
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/red
S.stillborn = 1
S.spider_mymother = src
if(!spider_can_fakelings)
queenfakelings_action.Remove(src)
else
to_chat(src, "<span class='danger'>You have run out of uses of this ability.</span>")
if(!isobserver(user) && !isterrorspider(user))
return
. += "<span class='notice'>[p_they(TRUE)] has laid [eggslaid] egg[eggslaid != 1 ? "s" : ""].</span>"
. += "<span class='notice'>[p_they(TRUE)] has lived for [MinutesAlive()] minutes.</span>"
/obj/item/projectile/terrorqueenspit
name = "poisonous spit"
damage = 0
name = "acid spit"
damage = 40
icon_state = "toxin"
damage_type = TOX
var/bonus_tox = 30
damage_type = BURN
/obj/item/projectile/terrorqueenspit/on_hit(mob/living/carbon/target, blocked = 0, hit_zone)
if(ismob(target) && blocked < 100)
var/mob/living/L = target
if(L.reagents)
if(L.can_inject(null, FALSE, "chest", FALSE))
L.Hallucinate(400)
if(!isterrorspider(L))
L.adjustToxLoss(bonus_tox)
/obj/structure/spider/terrorweb/queen
name = "shimmering web"
desc = "This web seems to shimmer all different colors in the light."
name = "airtight web"
desc = "This multi-layered web seems to be able to resist air pressure."
/obj/structure/spider/terrorweb/queen/New()
. = ..()
air_update_turf(TRUE)
/obj/structure/spider/terrorweb/queen/CanAtmosPass(turf/T)
return FALSE
/obj/structure/spider/terrorweb/queen/web_special_ability(mob/living/carbon/C)
if(istype(C))
var/inject_target = pick("chest","head")
if(C.can_inject(null, FALSE, inject_target, FALSE))
C.Hallucinate(400)
C.adjustToxLoss(30)
@@ -188,7 +188,7 @@
C.enemies = enemies
if(spider_growinstantly)
C.amount_grown = 250
C.spider_growinstantly = 1
C.spider_growinstantly = TRUE
spawn(10)
stop_automated_movement = 0
@@ -196,7 +196,7 @@
name = "terror egg cluster"
desc = "A cluster of tiny spider eggs. They pulse with a strong inner life, and appear to have sharp thorns on the sides."
icon_state = "eggs"
var/spider_growinstantly = 0
var/spider_growinstantly = FALSE
var/spider_myqueen = null
var/spider_mymother = null
var/spiderling_type = null
@@ -126,7 +126,7 @@
spider_steps_taken++
CreatePath(entry_vent)
step_to(src,entry_vent)
if(spider_debug > 0)
if(spider_debug)
visible_message("<span class='notice'>[src] moves towards the vent [entry_vent].</span>")
else
path_to_vent = 0
@@ -17,6 +17,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
// Name / Description
name = "terror spider"
desc = "The generic parent of all other terror spider types. If you see this in-game, it is a bug."
gender = FEMALE
// Icons
icon = 'icons/mob/terrorspider.dmi'
@@ -141,29 +142,33 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
var/mylocation = null
var/chasecycles = 0
var/web_infects = 0
var/spider_creation_time = 0
var/datum/action/innate/terrorspider/web/web_action
var/web_type = /obj/structure/spider/terrorweb
var/datum/action/innate/terrorspider/wrap/wrap_action
// Breathing - require some oxygen, and no toxins, but take little damage from this requirement not being met (they can hold their breath)
// Breathing - require some oxygen, and no toxins
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 1
// Temperature - can freeze in space and cook in plasma, but it takes extreme temperatures to do this.
minbodytemp = 100
maxbodytemp = 500
heat_damage_per_tick = 3
// Temperature
heat_damage_per_tick = 5 // Takes 250% normal damage from being in a hot environment ("kill it with fire!")
// DEBUG OPTIONS & COMMANDS
var/spider_growinstantly = 0 // DEBUG OPTION, DO NOT ENABLE THIS ON LIVE. IT IS USED TO TEST NEST GROWTH/SETUP AI.
var/spider_debug = 0
var/spider_growinstantly = FALSE // DEBUG OPTION, DO NOT ENABLE THIS ON LIVE. IT IS USED TO TEST NEST GROWTH/SETUP AI.
var/spider_debug = FALSE
// --------------------------------------------------------------------------------
// --------------------- TERROR SPIDERS: SHARED ATTACK CODE -----------------------
// --------------------------------------------------------------------------------
/mob/living/simple_animal/hostile/poison/terror_spider/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
// Forces terrors to use the 'bite' graphic when attacking something. Same as code/modules/mob/living/carbon/alien/larva/larva_defense.dm#L34
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_BITE
..()
/mob/living/simple_animal/hostile/poison/terror_spider/AttackingTarget()
if(isterrorspider(target))
if(target in enemies)
@@ -187,14 +192,13 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
if(F.welded)
to_chat(src, "The fire door is welded shut.")
else
visible_message("<span class='danger'>\The [src] pries open the firedoor!</span>")
visible_message("<span class='danger'>[src] pries open the firedoor!</span>")
F.open()
else
to_chat(src, "Closing fire doors does not help.")
else if(istype(target, /obj/machinery/door/airlock))
var/obj/machinery/door/airlock/A = target
if(A.density)
try_open_airlock(A)
try_open_airlock(A)
else if(isliving(target) && (!client || a_intent == INTENT_HARM))
var/mob/living/G = target
if(issilicon(G))
@@ -221,27 +225,23 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
/mob/living/simple_animal/hostile/poison/terror_spider/examine(mob/user)
. = ..()
var/list/msgs = list()
if(stat == DEAD)
msgs += "<span class='notice'>It appears to be dead.</span>\n"
else
if(stat != DEAD)
if(key)
msgs += "<span class='warning'>Its eyes regard you with a curious intelligence.</span>"
. += "<span class='warning'>[p_they(TRUE)] regards [p_their()] surroundings with a curious intelligence.</span>"
if(health > (maxHealth*0.95))
msgs += "<span class='notice'>It is in excellent health.</span>"
. += "<span class='notice'>[p_they(TRUE)] is in excellent health.</span>"
else if(health > (maxHealth*0.75))
msgs += "<span class='notice'>It has a few injuries.</span>"
. += "<span class='notice'>[p_they(TRUE)] has a few injuries.</span>"
else if(health > (maxHealth*0.55))
msgs += "<span class='warning'>It has many injuries.</span>"
. += "<span class='warning'>[p_they(TRUE)] has many injuries.</span>"
else if(health > (maxHealth*0.25))
msgs += "<span class='warning'>It is barely clinging on to life!</span>"
. += "<span class='warning'>[p_they(TRUE)] is barely clinging on to life!</span>"
if(degenerate)
msgs += "<span class='warning'>It appears to be dying.</span>"
. += "<span class='warning'>[p_they(TRUE)] appears to be dying.</span>"
else if(health < maxHealth && regen_points > regen_points_per_kill)
msgs += "<span class='notice'>It appears to be regenerating quickly.</span>"
. += "<span class='notice'>[p_they(TRUE)] appears to be regenerating quickly.</span>"
if(killcount >= 1)
msgs += "<span class='warning'>It has blood dribbling from its mouth.</span>"
. += msgs.Join("<BR>")
. += "<span class='warning'>[p_they(TRUE)] has blood dribbling from [p_their()] mouth.</span>"
/mob/living/simple_animal/hostile/poison/terror_spider/New()
..()
@@ -254,9 +254,10 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
if(web_type)
web_action = new()
web_action.Grant(src)
wrap_action = new()
wrap_action.Grant(src)
if(regen_points_per_tick < regen_points_per_hp)
// Only grant the Wrap action button to spiders who need to use it to regenerate their health
wrap_action = new()
wrap_action.Grant(src)
name += " ([rand(1, 1000)])"
real_name = name
msg_terrorspiders("[src] has grown in [get_area(src)].")
@@ -278,6 +279,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
addtimer(CALLBACK(src, .proc/announcetoghosts), 30)
var/datum/atom_hud/U = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
U.add_hud_to(src)
spider_creation_time = world.time
/mob/living/simple_animal/hostile/poison/terror_spider/proc/announcetoghosts()
if(spider_awaymission)
@@ -285,8 +287,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
if(stat == DEAD)
return
if(ckey)
var/image/alert_overlay = image('icons/mob/terrorspider.dmi', icon_state)
notify_ghosts("[src] has appeared in [get_area(src)]. (already player-controlled)", source = src, alert_overlay = alert_overlay)
notify_ghosts("[src] (player controlled) has appeared in [get_area(src)].")
else if(ai_playercontrol_allowtype)
var/image/alert_overlay = image('icons/mob/terrorspider.dmi', icon_state)
notify_ghosts("[src] has appeared in [get_area(src)].", enter_link = "<a href=?src=[UID()];activate=1>(Click to control)</a>", source = src, alert_overlay = alert_overlay, action = NOTIFY_ATTACK)
@@ -342,7 +343,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
/mob/living/simple_animal/hostile/poison/terror_spider/ObjBump(obj/O)
if(istype(O, /obj/machinery/door/airlock))
var/obj/machinery/door/airlock/L = O
if(L.density)
if(L.density) // must check density here, to avoid rapid bumping of an airlock that is in the process of opening, instantly forcing it closed
return try_open_airlock(L)
if(istype(O, /obj/machinery/door/firedoor))
var/obj/machinery/door/firedoor/F = O
@@ -352,7 +353,8 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
. = ..()
/mob/living/simple_animal/hostile/poison/terror_spider/proc/msg_terrorspiders(msgtext)
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist)
for(var/thing in GLOB.ts_spiderlist)
var/mob/living/simple_animal/hostile/poison/terror_spider/T = thing
if(T.stat != DEAD)
to_chat(T, "<span class='terrorspider'>TerrorSense: [msgtext]</span>")
@@ -365,21 +367,54 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
/mob/living/simple_animal/hostile/poison/terror_spider/proc/try_open_airlock(obj/machinery/door/airlock/D)
if(D.operating)
return
if(!D.density)
to_chat(src, "<span class='warning'>Closing doors does not help us.</span>")
else if(D.welded)
to_chat(src, "<span class='warning'>The door is welded shut.</span>")
if(D.welded)
to_chat(src, "<span class='warning'>The door is welded.</span>")
else if(D.locked)
to_chat(src, "<span class='warning'>The door is bolted shut.</span>")
to_chat(src, "<span class='warning'>The door is bolted.</span>")
else if(D.allowed(src))
D.open(1)
return 1
if(D.density)
D.open(TRUE)
else
D.close(TRUE)
return TRUE
else if(D.arePowerSystemsOn() && (spider_opens_doors != 2))
to_chat(src, "<span class='warning'>The door's motors resist your efforts to force it.</span>")
else if(!spider_opens_doors)
to_chat(src, "<span class='warning'>Your type of spider is not strong enough to force open doors.</span>")
else
visible_message("<span class='danger'>[src] pries open the door!</span>")
visible_message("<span class='danger'>[src] forces the door!</span>")
playsound(src.loc, "sparks", 100, 1)
D.open(1)
return 1
if(D.density)
D.open(TRUE)
else
D.close(TRUE)
return TRUE
/mob/living/simple_animal/hostile/poison/terror_spider/Stat()
..()
// Determines what shows in the "Status" tab for player-controlled spiders. Used to help players understand spider health regeneration mechanics.
// Uses <font color='#X'> because the status panel does NOT accept <span class='X'>.
if(statpanel("Status") && ckey && stat == CONSCIOUS)
if(degenerate)
stat(null, "<font color='#eb4034'>Hivemind Connection Severed! Dying...</font>") // color=red
return
if(health != maxHealth)
var/hp_points_per_second = 0
var/ltext = "FAST"
var/lcolor = "#fcba03" // orange
var/secs_per_tick = (SSmobs.wait / 10) // This uses SSmobs.wait because it must use the same frequency as mobs are processed
if(regen_points < (regen_points_per_hp * 2))
// Slow regen speed: using regen_points as we get them. Figure out regen_points/sec, then convert that to hp/sec.
var/regen_points_per_second = (regen_points_per_tick / secs_per_tick)
hp_points_per_second = (regen_points_per_second / regen_points_per_hp)
ltext = "SLOW (HUNGRY!)"
lcolor = "#eb4034" // red
else
// Fast regen speed: healing at full 1 hp / tick rate. Just divide 1hp/tick by seconds/tick to get healing/sec.
hp_points_per_second = 1 / secs_per_tick
if(hp_points_per_second > 0)
var/pc_of_max_per_second = round(((hp_points_per_second / maxHealth) * 100), 0.1)
stat(null, "Regeneration: [ltext]: <font color='[lcolor]'>[num2text(pc_of_max_per_second)]% of health per second</font>")
-1
View File
@@ -675,4 +675,3 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
return FALSE //This is the only case someone should actually be completely blocked from antag rolling as well
return TRUE
#define isterrorspider(A) (istype((A), /mob/living/simple_animal/hostile/poison/terror_spider))
+10 -8
View File
@@ -54,8 +54,6 @@
var/eggs_hatched = 0 // num of hatch events completed
var/awaymission_checked = FALSE
var/awaymission_infection = FALSE // TRUE if infection occurred inside gateway
var/list/types_basic = list(/mob/living/simple_animal/hostile/poison/terror_spider/red, /mob/living/simple_animal/hostile/poison/terror_spider/gray)
var/list/types_adv = list(/mob/living/simple_animal/hostile/poison/terror_spider/red, /mob/living/simple_animal/hostile/poison/terror_spider/gray, /mob/living/simple_animal/hostile/poison/terror_spider/green)
/obj/item/organ/internal/body_egg/terror_eggs/on_life()
@@ -104,12 +102,16 @@
var/infection_completed = FALSE
var/obj/structure/spider/spiderling/terror_spiderling/S = new(get_turf(owner))
switch(eggs_hatched)
if(0) // First spiderling
S.grow_as = pick(types_basic)
if(1) // Second
S.grow_as = pick(types_adv)
if(2) // Last
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/princess
if(0) // 1st spiderling
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/gray
if(1) // 2nd
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/red
if(2) // 3rd
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/brown
if(3) // 4th
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/green
if(4) // 5th
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/green
infection_completed = TRUE
S.immediate_ventcrawl = TRUE
eggs_hatched++