mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-15 17:13:46 +01:00
Merge branch 'master' into adminin
This commit is contained in:
@@ -169,7 +169,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
else
|
||||
var/response
|
||||
var/alertmsg = "Are you -sure- you want to ghost?\n([warningmsg]. If you ghost now, you probably won't be able to rejoin the round! You can't change your mind, so choose wisely!)"
|
||||
response = alert(src, alertmsg,"Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
response = alert(src, alertmsg,"Are you sure you want to ghost?","Stay in body","Ghost")
|
||||
if(response != "Ghost")
|
||||
return //didn't want to ghost after-all
|
||||
resting = 1
|
||||
|
||||
@@ -82,6 +82,17 @@ I'm using this for Stat to give it a more nifty interface to work with
|
||||
/mob/living/carbon/brain/proc/has_synthetic_assistance()
|
||||
return (container && istype(container, /obj/item/device/mmi)) || in_contents_of(/obj/mecha)
|
||||
|
||||
/mob/living/carbon/brain/proc/get_race()
|
||||
if(container)
|
||||
var/obj/item/device/mmi/M = container
|
||||
if(istype(M) && M.held_brain)
|
||||
return M.held_brain.dna.get_species_name()
|
||||
else
|
||||
return "Artificial Life"
|
||||
if(istype(loc, /obj/item/organ/internal/brain))
|
||||
var/obj/item/organ/internal/brain/B = loc
|
||||
return B.dna.get_species_name()
|
||||
|
||||
/mob/living/carbon/brain/Stat()
|
||||
..()
|
||||
if(has_synthetic_assistance())
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
return 0
|
||||
if(reagents.has_reagent("teslium"))
|
||||
shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging!
|
||||
take_overall_damage(0,shock_damage)
|
||||
take_overall_damage(0,shock_damage, used_weapon = "Electrocution")
|
||||
//src.burn_skin(shock_damage)
|
||||
//src.adjustFireLoss(shock_damage) //burn_skin will do this for us
|
||||
//src.updatehealth()
|
||||
|
||||
@@ -494,7 +494,8 @@
|
||||
msg += "<span class = 'deptradio'>Medical records:</span> <a href='?src=[UID()];medrecord=`'>\[View\]</a> <a href='?src=[UID()];medrecordadd=`'>\[Add comment\]</a>\n"
|
||||
|
||||
|
||||
if(print_flavor_text()) msg += "[print_flavor_text()]\n"
|
||||
if(print_flavor_text() && !skipface)
|
||||
msg += "[print_flavor_text()]\n"
|
||||
|
||||
msg += "*---------*</span>"
|
||||
if(pose)
|
||||
|
||||
@@ -923,12 +923,11 @@
|
||||
if(R.fields["id"] == E.fields["id"])
|
||||
if(hasHUD(usr,"security"))
|
||||
read = 1
|
||||
var/counter = 1
|
||||
while(R.fields[text("com_[]", counter)])
|
||||
to_chat(usr, text("[]", R.fields[text("com_[]", counter)]))
|
||||
counter++
|
||||
if(counter == 1)
|
||||
to_chat(usr, "No comment found")
|
||||
if(length(R.fields["comments"]))
|
||||
for(var/c in R.fields["comments"])
|
||||
to_chat(usr, c)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>No comment found</span>")
|
||||
to_chat(usr, "<a href='?src=[UID()];secrecordadd=`'>\[Add comment\]</a>")
|
||||
|
||||
if(!read)
|
||||
@@ -950,21 +949,18 @@
|
||||
for(var/datum/data/record/R in data_core.security)
|
||||
if(R.fields["id"] == E.fields["id"])
|
||||
if(hasHUD(usr,"security"))
|
||||
var/t1 = sanitize(copytext(input("Add Comment:", "Sec. records", null, null) as message,1,MAX_MESSAGE_LEN))
|
||||
if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) )
|
||||
var/t1 = copytext(trim(sanitize(input("Add Comment:", "Sec. records", null, null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || usr.stat || usr.restrained() || !hasHUD(usr, "security"))
|
||||
return
|
||||
var/counter = 1
|
||||
while(R.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
if(istype(usr,/mob/living/carbon/human))
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/U = usr
|
||||
R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
|
||||
if(istype(usr,/mob/living/silicon/robot))
|
||||
R.fields["comments"] += "Made by [U.get_authentification_name()] ([U.get_assignment()]) on [current_date_string] [worldtime2text()]<BR>[t1]"
|
||||
if(isrobot(usr))
|
||||
var/mob/living/silicon/robot/U = usr
|
||||
R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
|
||||
if(istype(usr,/mob/living/silicon/ai))
|
||||
R.fields["comments"] += "Made by [U.name] ([U.modtype] [U.braintype]) on [current_date_string] [worldtime2text()]<BR>[t1]"
|
||||
if(isAI(usr))
|
||||
var/mob/living/silicon/ai/U = usr
|
||||
R.fields[text("com_[counter]")] = text("Made by [U.name] (artificial intelligence) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
|
||||
R.fields["comments"] += "Made by [U.name] (artificial intelligence) on [current_date_string] [worldtime2text()]<BR>[t1]"
|
||||
|
||||
if(href_list["medical"])
|
||||
if(hasHUD(usr,"medical"))
|
||||
@@ -1049,12 +1045,11 @@
|
||||
if(R.fields["id"] == E.fields["id"])
|
||||
if(hasHUD(usr,"medical"))
|
||||
read = 1
|
||||
var/counter = 1
|
||||
while(R.fields[text("com_[]", counter)])
|
||||
to_chat(usr, text("[]", R.fields[text("com_[]", counter)]))
|
||||
counter++
|
||||
if(counter == 1)
|
||||
to_chat(usr, "No comment found")
|
||||
if(length(R.fields["comments"]))
|
||||
for(var/c in R.fields["comments"])
|
||||
to_chat(usr, c)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>No comment found</span>")
|
||||
to_chat(usr, "<a href='?src=[UID()];medrecordadd=`'>\[Add comment\]</a>")
|
||||
|
||||
if(!read)
|
||||
@@ -1076,18 +1071,15 @@
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
if(R.fields["id"] == E.fields["id"])
|
||||
if(hasHUD(usr,"medical"))
|
||||
var/t1 = sanitize(copytext(input("Add Comment:", "Med. records", null, null) as message,1,MAX_MESSAGE_LEN))
|
||||
if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"medical")) )
|
||||
var/t1 = copytext(trim(sanitize(input("Add Comment:", "Med. records", null, null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || usr.stat || usr.restrained() || !hasHUD(usr, "medical"))
|
||||
return
|
||||
var/counter = 1
|
||||
while(R.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
if(istype(usr,/mob/living/carbon/human))
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/U = usr
|
||||
R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
|
||||
if(istype(usr,/mob/living/silicon/robot))
|
||||
R.fields["comments"] += "Made by [U.get_authentification_name()] ([U.get_assignment()]) on [current_date_string] [worldtime2text()]<BR>[t1]"
|
||||
if(isrobot(usr))
|
||||
var/mob/living/silicon/robot/U = usr
|
||||
R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
|
||||
R.fields["comments"] += "Made by [U.name] ([U.modtype] [U.braintype]) on [current_date_string] [worldtime2text()]<BR>[t1]"
|
||||
|
||||
if(href_list["lookitem"])
|
||||
var/obj/item/I = locate(href_list["lookitem"])
|
||||
|
||||
@@ -88,19 +88,19 @@
|
||||
return amount
|
||||
|
||||
|
||||
/mob/living/carbon/human/adjustBruteLoss(amount)
|
||||
/mob/living/carbon/human/adjustBruteLoss(amount, damage_source)
|
||||
if(species)
|
||||
amount = amount * species.brute_mod
|
||||
if(amount > 0)
|
||||
take_overall_damage(amount, 0)
|
||||
take_overall_damage(amount, 0, used_weapon = damage_source)
|
||||
else
|
||||
heal_overall_damage(-amount, 0)
|
||||
|
||||
/mob/living/carbon/human/adjustFireLoss(amount)
|
||||
/mob/living/carbon/human/adjustFireLoss(amount, damage_source)
|
||||
if(species)
|
||||
amount = amount * species.burn_mod
|
||||
if(amount > 0)
|
||||
take_overall_damage(0, amount)
|
||||
take_overall_damage(0, amount, used_weapon = damage_source)
|
||||
else
|
||||
heal_overall_damage(0, -amount)
|
||||
|
||||
@@ -394,4 +394,4 @@ This function restores all organs.
|
||||
|
||||
// Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life().
|
||||
updatehealth()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -132,7 +132,6 @@
|
||||
job = myjob.title
|
||||
mind.assigned_role = job
|
||||
myjob.equip(src)
|
||||
myjob.apply_fingerprints(T)
|
||||
|
||||
/mob/living/carbon/human/interactive/proc/reset()
|
||||
walk(src, 0)
|
||||
@@ -193,7 +192,6 @@
|
||||
for(var/obj/item/W in T)
|
||||
qdel(W)
|
||||
T.myjob.equip(T)
|
||||
T.myjob.apply_fingerprints(T)
|
||||
T.doSetup(alt_title)
|
||||
|
||||
var/shouldDoppel = input("Do you want the SNPC to disguise themself as a crewmember?") as anything in list("Yes", "No")
|
||||
|
||||
@@ -615,3 +615,17 @@
|
||||
return 1
|
||||
|
||||
return 0 //Unsupported slot
|
||||
|
||||
/mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE)
|
||||
var/datum/outfit/O = null
|
||||
|
||||
if(ispath(outfit))
|
||||
O = new outfit
|
||||
else
|
||||
O = outfit
|
||||
if(!istype(O))
|
||||
return 0
|
||||
if(!O)
|
||||
return 0
|
||||
|
||||
return O.equip(src, visualsOnly)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
butt_sprite = "plasma"
|
||||
|
||||
breath_type = "plasma"
|
||||
poison_type = null //Certainly isn't plasma.
|
||||
|
||||
heat_level_1 = 350 // Heat damage level 1 above this point.
|
||||
heat_level_2 = 400 // Heat damage level 2 above this point.
|
||||
@@ -33,20 +34,21 @@
|
||||
message = replacetext(message, "s", stutter("ss"))
|
||||
return message
|
||||
|
||||
/datum/species/plasmaman/equip(var/mob/living/carbon/human/H)
|
||||
/datum/species/plasmaman/after_equip_job(datum/job/J, mob/living/carbon/human/H)
|
||||
var/assigned_role = H.mind && H.mind.assigned_role ? H.mind.assigned_role : "Civilian"
|
||||
// Unequip existing suits and hats.
|
||||
H.unEquip(H.wear_suit)
|
||||
H.unEquip(H.head)
|
||||
if(H.mind.assigned_role != "Clown")
|
||||
if(assigned_role != "Clown")
|
||||
H.unEquip(H.wear_mask)
|
||||
|
||||
H.equip_or_collect(new /obj/item/clothing/mask/breath(H), slot_wear_mask)
|
||||
var/suit=/obj/item/clothing/suit/space/eva/plasmaman
|
||||
var/helm=/obj/item/clothing/head/helmet/space/eva/plasmaman
|
||||
var/suit=/obj/item/clothing/suit/space/eva/plasmaman/assistant
|
||||
var/helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/assistant
|
||||
var/tank_slot = slot_s_store
|
||||
var/tank_slot_name = "suit storage"
|
||||
|
||||
switch(H.mind.assigned_role)
|
||||
switch(assigned_role)
|
||||
if("Scientist","Geneticist","Roboticist")
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/science
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/science
|
||||
@@ -54,8 +56,8 @@
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/science/rd
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/science/rd
|
||||
if("Station Engineer", "Mechanic")
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/engineer/
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/engineer/
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/engineer
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/engineer
|
||||
if("Chief Engineer")
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/engineer/ce
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/engineer/ce
|
||||
@@ -63,11 +65,11 @@
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/atmostech
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/atmostech
|
||||
if("Detective")
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/security/
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/security/
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/security
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/security
|
||||
if("Warden","Security Officer","Security Pod Pilot")
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/security/
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/security/
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/security
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/security
|
||||
H.equip_or_collect(new /obj/item/weapon/gun/energy/gun/advtaser(H), slot_in_backpack)
|
||||
if("Internal Affairs Agent")
|
||||
suit=/obj/item/clothing/suit/space/eva/plasmaman/lawyer
|
||||
@@ -127,8 +129,10 @@
|
||||
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/mime
|
||||
H.equip_or_collect(new suit(H), slot_wear_suit)
|
||||
H.equip_or_collect(new helm(H), slot_head)
|
||||
H.equip_or_collect(new/obj/item/weapon/tank/plasma/plasmaman(H), tank_slot) // Bigger plasma tank from Raggy.
|
||||
to_chat(H, "<span class='notice'>You are now running on plasma internals from the [H.s_store] in your [tank_slot_name]. You must breathe plasma in order to survive, and are extremely flammable.</span>")
|
||||
H.equip_or_collect(new /obj/item/weapon/tank/plasma/plasmaman(H), tank_slot) // Bigger plasma tank from Raggy.
|
||||
H.equip_or_collect(new /obj/item/weapon/plasmensuit_cartridge(H), slot_in_backpack)
|
||||
H.equip_or_collect(new /obj/item/weapon/plasmensuit_cartridge(H), slot_in_backpack) //Two refill cartridges for their suit. Can fit in boxes.
|
||||
to_chat(H, "<span class='notice'>You are now running on plasma internals from the [H.s_store] in your [tank_slot_name]. You must breathe plasma in order to survive, and are extremely flammable.</span>")
|
||||
H.internal = H.get_item_by_slot(tank_slot)
|
||||
H.update_internals_hud_icon(1)
|
||||
|
||||
@@ -235,10 +239,29 @@
|
||||
if(heat_level_3 to INFINITY)
|
||||
H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
|
||||
H.fire_alert = max(H.fire_alert, 2)
|
||||
|
||||
if(!istype(H.wear_suit, /obj/item/clothing/suit/space/eva/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/eva/plasmaman))
|
||||
to_chat(H, "<span class='warning'>Your body reacts with the atmosphere and bursts into flame!</span>")
|
||||
H.adjust_fire_stacks(0.5)
|
||||
H.IgniteMob()
|
||||
|
||||
return 1
|
||||
|
||||
/datum/species/plasmaman/handle_life(var/mob/living/carbon/human/H)
|
||||
if(!istype(H.wear_suit, /obj/item/clothing/suit/space/eva/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/eva/plasmaman))
|
||||
var/datum/gas_mixture/environment = H.loc.return_air()
|
||||
if(environment && environment.oxygen && environment.oxygen >= OXYCONCEN_PLASMEN_IGNITION) //Plasmamen so long as there's enough oxygen (0.5 moles, same as it takes to burn gaseous plasma).
|
||||
H.adjust_fire_stacks(0.5)
|
||||
if(!H.on_fire && H.fire_stacks > 0)
|
||||
H.visible_message("<span class='danger'>[H]'s body reacts with the atmosphere and bursts into flames!</span>","<span class='userdanger'>Your body reacts with the atmosphere and bursts into flame!</span>")
|
||||
H.IgniteMob()
|
||||
else
|
||||
if(H.on_fire && H.fire_stacks > 0)
|
||||
var/obj/item/clothing/suit/space/eva/plasmaman/P = H.wear_suit
|
||||
if(istype(P))
|
||||
P.Extinguish(H)
|
||||
H.update_fire()
|
||||
|
||||
/datum/species/plasmaman/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R)
|
||||
if(R.id == "plasma")
|
||||
H.adjustBruteLoss(-0.5*REAGENTS_EFFECT_MULTIPLIER)
|
||||
H.adjustFireLoss(-0.5*REAGENTS_EFFECT_MULTIPLIER)
|
||||
H.adjustPlasma(20)
|
||||
H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM)
|
||||
return 0 //Handling reagent removal on our own. Prevents plasma from dealing toxin damage to Plasmamen.
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -439,7 +439,10 @@
|
||||
/datum/species/proc/say_filter(mob/M, message, datum/language/speaking)
|
||||
return message
|
||||
|
||||
/datum/species/proc/equip(var/mob/living/carbon/human/H)
|
||||
/datum/species/proc/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
return
|
||||
|
||||
/datum/species/proc/after_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
return
|
||||
|
||||
/datum/species/proc/can_understand(var/mob/other)
|
||||
|
||||
@@ -343,13 +343,13 @@
|
||||
newname += pick(vox_name_syllables)
|
||||
return capitalize(newname)
|
||||
|
||||
/datum/species/vox/equip(var/mob/living/carbon/human/H)
|
||||
if(H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime")
|
||||
/datum/species/vox/after_equip_job(datum/job/J, mob/living/carbon/human/H)
|
||||
if(!H.mind || !H.mind.assigned_role || H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime")
|
||||
H.unEquip(H.wear_mask)
|
||||
H.unEquip(H.l_hand)
|
||||
|
||||
H.equip_or_collect(new /obj/item/clothing/mask/breath/vox(H), slot_wear_mask)
|
||||
var/tank_pref = H.client.prefs.speciesprefs
|
||||
var/tank_pref = H.client && H.client.prefs ? H.client.prefs.speciesprefs : null
|
||||
if(tank_pref)//Diseasel, here you go
|
||||
H.equip_or_collect(new /obj/item/weapon/tank/nitrogen(H), slot_l_hand)
|
||||
else
|
||||
@@ -365,7 +365,7 @@
|
||||
..()
|
||||
|
||||
/datum/species/vox/updatespeciescolor(var/mob/living/carbon/human/H, var/owner_sensitive = 1) //Handling species-specific skin-tones for the Vox race.
|
||||
if(H.species.name == "Vox") //Making sure we don't break Armalis.
|
||||
if(H.species.bodyflags & HAS_ICON_SKIN_TONE) //Making sure we don't break Armalis.
|
||||
var/new_icobase = 'icons/mob/human_races/vox/r_vox.dmi' //Default Green Vox.
|
||||
var/new_deform = 'icons/mob/human_races/vox/r_def_vox.dmi' //Default Green Vox.
|
||||
switch(H.s_tone)
|
||||
@@ -395,6 +395,14 @@
|
||||
H.change_icobase(new_icobase, new_deform, owner_sensitive) //Update the icobase/deform of all our organs, but make sure we don't mess with frankenstein limbs in doing so.
|
||||
H.update_dna()
|
||||
|
||||
/datum/species/vox/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R)
|
||||
if(R.id == "oxygen") //Armalis are above such petty things.
|
||||
H.adjustToxLoss(1*REAGENTS_EFFECT_MULTIPLIER) //Same as plasma.
|
||||
H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM)
|
||||
return 0 //Handling reagent removal on our own.
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
H.verbs += /mob/living/carbon/human/proc/leap
|
||||
H.verbs += /mob/living/carbon/human/proc/gut
|
||||
@@ -427,7 +435,8 @@
|
||||
breath_type = "nitrogen"
|
||||
poison_type = "oxygen"
|
||||
|
||||
flags = NO_SCAN | NO_BLOOD | HAS_TAIL | NO_PAIN | IS_WHITELISTED
|
||||
flags = NO_SCAN | NO_BLOOD | NO_PAIN | IS_WHITELISTED
|
||||
bodyflags = HAS_TAIL
|
||||
dietflags = DIET_OMNI //should inherit this from vox, this is here just in case
|
||||
|
||||
blood_color = "#2299FC"
|
||||
@@ -455,6 +464,9 @@
|
||||
"is holding their breath!",
|
||||
"is huffing oxygen!")
|
||||
|
||||
/datum/species/vox/armalis/handle_reagents() //Skip the Vox oxygen reagent toxicity. Armalis are above such things.
|
||||
return 1
|
||||
|
||||
/datum/species/kidan
|
||||
name = "Kidan"
|
||||
name_plural = "Kidan"
|
||||
@@ -728,7 +740,7 @@
|
||||
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
|
||||
..()
|
||||
|
||||
/datum/species/grey/equip(var/mob/living/carbon/human/H)
|
||||
/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H)
|
||||
var/speech_pref = H.client.prefs.speciesprefs
|
||||
if(speech_pref)
|
||||
H.mind.speech_span = "wingdings"
|
||||
|
||||
@@ -289,6 +289,7 @@ var/list/robot_verbs_default = list(
|
||||
module_sprites["Basic"] = "robot_old"
|
||||
module_sprites["Android"] = "droid"
|
||||
module_sprites["Default"] = "robot"
|
||||
module_sprites["Noble-STD"] = "Noble-STD"
|
||||
|
||||
if("Service")
|
||||
module = new /obj/item/weapon/robot_module/butler(src)
|
||||
@@ -299,6 +300,7 @@ var/list/robot_verbs_default = list(
|
||||
module_sprites["Rich"] = "maximillion"
|
||||
module_sprites["Default"] = "Service2"
|
||||
module_sprites["Standard"] = "robotServ"
|
||||
module_sprites["Noble-SRV"] = "Noble-SRV"
|
||||
|
||||
if("Miner")
|
||||
module = new /obj/item/weapon/robot_module/miner(src)
|
||||
@@ -309,6 +311,7 @@ var/list/robot_verbs_default = list(
|
||||
module_sprites["Advanced Droid"] = "droid-miner"
|
||||
module_sprites["Treadhead"] = "Miner"
|
||||
module_sprites["Standard"] = "robotMine"
|
||||
module_sprites["Noble-DIG"] = "Noble-DIG"
|
||||
|
||||
if("Medical")
|
||||
module = new /obj/item/weapon/robot_module/medical(src)
|
||||
@@ -320,6 +323,7 @@ var/list/robot_verbs_default = list(
|
||||
module_sprites["Advanced Droid"] = "droid-medical"
|
||||
module_sprites["Needles"] = "medicalrobot"
|
||||
module_sprites["Standard"] = "robotMedi"
|
||||
module_sprites["Noble-MED"] = "Noble-MED"
|
||||
status_flags &= ~CANPUSH
|
||||
|
||||
if("Security")
|
||||
@@ -330,6 +334,7 @@ var/list/robot_verbs_default = list(
|
||||
module_sprites["Black Knight"] = "securityrobot"
|
||||
module_sprites["Bloodhound"] = "bloodhound"
|
||||
module_sprites["Standard"] = "robotSecy"
|
||||
module_sprites["Noble-SEC"] = "Noble-SEC"
|
||||
status_flags &= ~CANPUSH
|
||||
|
||||
if("Engineering")
|
||||
@@ -341,6 +346,7 @@ var/list/robot_verbs_default = list(
|
||||
module_sprites["Antique"] = "engineerrobot"
|
||||
module_sprites["Landmate"] = "landmate"
|
||||
module_sprites["Standard"] = "robotEngi"
|
||||
module_sprites["Noble-ENG"] = "Noble-ENG"
|
||||
magpulse = 1
|
||||
|
||||
if("Janitor")
|
||||
@@ -350,6 +356,7 @@ var/list/robot_verbs_default = list(
|
||||
module_sprites["Mopbot"] = "janitorrobot"
|
||||
module_sprites["Mop Gear Rex"] = "mopgearrex"
|
||||
module_sprites["Standard"] = "robotJani"
|
||||
module_sprites["Noble-CLN"] = "Noble-CLN"
|
||||
|
||||
if("Combat")
|
||||
module = new /obj/item/weapon/robot_module/combat(src)
|
||||
|
||||
@@ -161,8 +161,8 @@
|
||||
/mob/living/simple_animal/hostile/poison/bees/worker/Found(atom/A)
|
||||
if(istype(A, /obj/machinery/hydroponics))
|
||||
var/obj/machinery/hydroponics/Hydro = A
|
||||
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit)
|
||||
wanted_objects |= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted
|
||||
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit && !Hydro.lid_state)
|
||||
wanted_objects |= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted and uncovered
|
||||
return 1
|
||||
..()
|
||||
|
||||
@@ -188,12 +188,12 @@
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/bees/worker/proc/pollinate(obj/machinery/hydroponics/Hydro)
|
||||
if(!istype(Hydro) || !Hydro.myseed || Hydro.dead || Hydro.recent_bee_visit)
|
||||
if(!istype(Hydro) || !Hydro.myseed || Hydro.dead || Hydro.recent_bee_visit || Hydro.lid_state)
|
||||
target = null
|
||||
return
|
||||
|
||||
target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity
|
||||
wanted_objects -= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted
|
||||
wanted_objects -= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted and uncovered
|
||||
Hydro.recent_bee_visit = TRUE
|
||||
spawn(BEE_TRAY_RECENT_VISIT)
|
||||
if(Hydro)
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
#define MOVING_TO_TARGET 3
|
||||
#define SPINNING_COCOON 4
|
||||
|
||||
#define TS_AI_AGGRESSIVE 0
|
||||
#define TS_AI_DEFENSIVE 1
|
||||
|
||||
#define TS_DAMAGE_SIMPLE 0
|
||||
#define TS_DAMAGE_POISON 1
|
||||
#define TS_DAMAGE_BRUTE 2
|
||||
|
||||
#define TS_DESC_RED "Red - Assault"
|
||||
#define TS_DESC_GRAY "Gray - Ambush"
|
||||
#define TS_DESC_GREEN "Green - Nurse"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/datum/action/innate/terrorspider/web/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/user = owner
|
||||
user.Web()
|
||||
user.Web(0)
|
||||
|
||||
/datum/action/innate/terrorspider/wrap
|
||||
name = "Wrap"
|
||||
@@ -32,14 +32,25 @@
|
||||
|
||||
// ---------- PRINCE ACTIONS
|
||||
|
||||
/datum/action/innate/terrorspider/princesmash
|
||||
/datum/action/innate/terrorspider/thickweb
|
||||
name = "Thick Web"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "stickyweb2"
|
||||
|
||||
/datum/action/innate/terrorspider/thickweb/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/user = owner
|
||||
user.Web(1)
|
||||
|
||||
// ---------- BOSS ACTIONS
|
||||
|
||||
/datum/action/innate/terrorspider/ventsmash
|
||||
name = "Smash Welded Vent"
|
||||
icon_icon = 'icons/atmos/vent_pump.dmi'
|
||||
button_icon_state = "map_vent"
|
||||
|
||||
/datum/action/innate/terrorspider/princesmash/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/prince/user = owner
|
||||
user.DoPrinceSmash()
|
||||
/datum/action/innate/terrorspider/ventsmash/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/user = owner
|
||||
user.DoVentSmash()
|
||||
|
||||
// ---------- QUEEN ACTIONS
|
||||
|
||||
@@ -50,7 +61,7 @@
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queennest/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/user = owner
|
||||
user.NestMode()
|
||||
user.NestPrompt()
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queensense
|
||||
name = "Hive Sense"
|
||||
@@ -81,10 +92,10 @@
|
||||
|
||||
// ---------- WEB
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/Web()
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/Web(var/thick = 0)
|
||||
var/turf/mylocation = loc
|
||||
visible_message("<span class='notice'>[src] begins to secrete a sticky substance.</span>")
|
||||
if(do_after(src, 40, target = loc))
|
||||
if(do_after(src, delay_web, target = loc))
|
||||
if(loc != mylocation)
|
||||
return
|
||||
else if(istype(loc, /turf/space))
|
||||
@@ -96,6 +107,8 @@
|
||||
else
|
||||
var/obj/effect/spider/terrorweb/W = new /obj/effect/spider/terrorweb(loc)
|
||||
W.creator_ckey = ckey
|
||||
if(thick)
|
||||
W.opacity = 1
|
||||
|
||||
/obj/effect/spider/terrorweb
|
||||
name = "terror web"
|
||||
@@ -112,20 +125,30 @@
|
||||
if(prob(50))
|
||||
icon_state = "stickyweb2"
|
||||
|
||||
/obj/effect/spider/terrorweb/proc/DeCloakNearby()
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/gray/G in view(6,src))
|
||||
if(!G.ckey && G.stat != DEAD)
|
||||
G.GrayDeCloak()
|
||||
G.Aggro()
|
||||
|
||||
/obj/effect/spider/terrorweb/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
return 1
|
||||
if(istype(mover, /obj/item/projectile/terrorqueenspit))
|
||||
return 1
|
||||
if(isliving(mover))
|
||||
var/mob/living/M = mover
|
||||
if(M.lying)
|
||||
return 1
|
||||
if(prob(80))
|
||||
to_chat(mover, "<span class='danger'>You get stuck in [src] for a moment.</span>")
|
||||
var/mob/living/M = mover
|
||||
M.Stun(4) // 8 seconds.
|
||||
M.Weaken(4) // 8 seconds.
|
||||
DeCloakNearby()
|
||||
if(iscarbon(mover))
|
||||
spawn(70)
|
||||
qdel(src)
|
||||
if(mover.loc == loc)
|
||||
qdel(src)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
@@ -188,12 +211,15 @@
|
||||
if(iscarbon(L))
|
||||
regen_points += regen_points_per_kill
|
||||
fed++
|
||||
visible_message("<span class='danger'>[src] sticks a proboscis into [L] and sucks a viscous substance out.</span>")
|
||||
to_chat(src, "<span class='notice'>You feel invigorated!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] wraps [L] in a web.</span>")
|
||||
large_cocoon = 1
|
||||
last_cocoon_object = 0
|
||||
L.loc = C
|
||||
C.pixel_x = L.pixel_x
|
||||
C.pixel_y = L.pixel_y
|
||||
visible_message("<span class='danger'>[src] sticks a proboscis into [L] and sucks a viscous substance out.</span>")
|
||||
break
|
||||
if(large_cocoon)
|
||||
C.icon_state = pick("cocoon_large1","cocoon_large2","cocoon_large3")
|
||||
@@ -201,7 +227,7 @@
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/proc/DoPrinceSmash()
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/DoVentSmash()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/P in view(1,src))
|
||||
if(P.welded)
|
||||
P.welded = 0
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
name = "Black Terror spider"
|
||||
desc = "An ominous-looking spider, black as the darkest night. It has merciless eyes, and a blood-red hourglass pattern on its back."
|
||||
spider_role_summary = "Hit-and-run attacker with extremely venomous bite."
|
||||
ai_target_method = TS_DAMAGE_POISON
|
||||
|
||||
icon_state = "terror_widow"
|
||||
icon_living = "terror_widow"
|
||||
@@ -37,3 +38,10 @@
|
||||
else
|
||||
visible_message("<span class='danger'>[src] bites [target], but cannot inject venom into their [inject_target]!</span>")
|
||||
L.attack_animal(src)
|
||||
if(!ckey && (!(target in enemies) || L.reagents.has_reagent("terror_black_toxin", 60)))
|
||||
step_away(src,L)
|
||||
step_away(src,L)
|
||||
LoseTarget()
|
||||
for(var/i in 0 to 3)
|
||||
step_away(src, L)
|
||||
visible_message("<span class='notice'>[src] warily eyes [L] from a distance.</span>")
|
||||
@@ -0,0 +1,92 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T5 EMPRESS OF TERROR -------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: ruling over planets of uncountable spiders, like Xenomorph Empresses.
|
||||
// -------------: AI: none - this is strictly adminspawn-only and intended for RP events, coder testing, and teaching people 'how to queen'
|
||||
// -------------: SPECIAL: Lay Eggs ability that allows laying queen-level eggs.
|
||||
// -------------: TO FIGHT IT: run away screaming?
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress
|
||||
name = "Empress of Terror"
|
||||
desc = "The unholy offspring of spiders, nightmares, and lovecraft fiction."
|
||||
spider_role_summary = "Adminbus spider"
|
||||
ai_target_method = TS_DAMAGE_SIMPLE
|
||||
maxHealth = 1000
|
||||
health = 1000
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 60
|
||||
move_to_delay = 5
|
||||
ventcrawler = 1
|
||||
idle_ventcrawl_chance = 0
|
||||
ai_playercontrol_allowtype = 0
|
||||
ai_type = TS_AI_AGGRESSIVE
|
||||
rapid = 1
|
||||
canlay = 1000
|
||||
spider_tier = TS_TIER_5
|
||||
var/datum/action/innate/terrorspider/queen/empress/empresslings/empresslings_action
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/handle_automated_action()
|
||||
return
|
||||
|
||||
/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_RED, TS_DESC_GRAY, TS_DESC_GREEN, TS_DESC_BLACK, TS_DESC_PURPLE, TS_DESC_WHITE)
|
||||
var/numlings = input("How many in the batch?") as null|anything in list(1, 2, 3, 4, 5, 10, 15, 20, 30, 40, 50)
|
||||
if(eggtype == null || numlings == null)
|
||||
to_chat(src, "<span class='danger'>Cancelled.</span>")
|
||||
return
|
||||
switch(eggtype)
|
||||
if(TS_DESC_RED)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red,numlings,1)
|
||||
if(TS_DESC_GRAY)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/gray,numlings,1)
|
||||
if(TS_DESC_GREEN)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green,numlings,1)
|
||||
if(TS_DESC_BLACK)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/black,numlings,1)
|
||||
if(TS_DESC_PURPLE)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple,numlings,0)
|
||||
if(TS_DESC_WHITE)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/white,numlings,0)
|
||||
if(TS_DESC_PRINCE)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/prince,numlings,1)
|
||||
if(TS_DESC_MOTHER)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/mother,numlings,1)
|
||||
if(TS_DESC_QUEEN)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/queen,numlings,1)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>Unrecognized egg type.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/QueenFakeLings()
|
||||
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++)
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S = new /obj/effect/spider/spiderling/terror_spiderling(get_turf(src))
|
||||
S.grow_as = pick(/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/white, \
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/black)
|
||||
S.spider_myqueen = spider_myqueen
|
||||
if(prob(sbpc))
|
||||
S.stillborn = 1
|
||||
if(spider_growinstantly)
|
||||
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 ts_spiderlist)
|
||||
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>")
|
||||
for(var/obj/effect/spider/eggcluster/terror_eggcluster/T in ts_egg_list)
|
||||
qdel(T)
|
||||
for(var/obj/effect/spider/spiderling/terror_spiderling/T in ts_spiderling_list)
|
||||
T.stillborn = 1
|
||||
to_chat(src, "<span class='userdanger'>Brood will die off shortly.</span>")
|
||||
|
||||
@@ -2,24 +2,30 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T1 GRAY TERROR -------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: fast, weak terror spider
|
||||
// -------------: SPECIAL: silences targets
|
||||
// -------------: TO FIGHT IT: shoot it!
|
||||
// -------------: ROLE: ambusher
|
||||
// -------------: AI: hides in vents, emerges when prey is near to kill it, then hides again. Intended to scare normal crew.
|
||||
// -------------: SPECIAL: invisible when on top of a vent, emerges when prey approaches or gets trapped in webs. Bite silences targets.
|
||||
// -------------: TO FIGHT IT: shoot it through a window, or make it regret ambushing you
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray
|
||||
name = "Gray Terror spider"
|
||||
desc = "An ominous-looking gray spider, it seems jittery."
|
||||
spider_role_summary = "Fast-moving but weak spider."
|
||||
desc = "An ominous-looking gray spider. It twitches occasionally, always seeming ready to pounce."
|
||||
spider_role_summary = "Stealth spider that ambushes weak humans from vents."
|
||||
ai_target_method = TS_DAMAGE_BRUTE
|
||||
icon_state = "terror_gray"
|
||||
icon_living = "terror_gray"
|
||||
icon_dead = "terror_gray_dead"
|
||||
maxHealth = 120 // same health as hunter spider, aka, pretty weak.. but silences its targets
|
||||
maxHealth = 120 // same health as hunter spider, aka, pretty weak.. but its almost invisible.
|
||||
health = 120
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
move_to_delay = 5 // normal speed
|
||||
regen_points_per_hp = 2 // 50% higher regen speed
|
||||
move_to_delay = 5 // slightly faster than normal
|
||||
stat_attack = 1 // ensures they will target people in crit, too!
|
||||
wander = 0 // wandering defeats the purpose of stealth
|
||||
idle_vision_range = 3 // very low idle vision range
|
||||
delay_web = 20 // double speed
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
@@ -35,4 +41,102 @@
|
||||
visible_message("<span class='danger'>[src] buries grey fangs deep into the [inject_target] of [target]!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] bites [target], but cannot inject venom into their [inject_target]!</span>")
|
||||
L.attack_animal(src)
|
||||
L.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/adjustBruteLoss(damage)
|
||||
..(damage)
|
||||
if(invisibility > 0)
|
||||
GrayDeCloak()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/adjustFireLoss(damage)
|
||||
..(damage)
|
||||
if(invisibility > 0)
|
||||
GrayDeCloak()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/Aggro()
|
||||
GrayDeCloak()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/AttackingTarget()
|
||||
if(invisibility > 0)
|
||||
GrayDeCloak()
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/GrayCloak()
|
||||
visible_message("<span class='notice'>[src] hides in the vent.</span>")
|
||||
invisibility = SEE_INVISIBLE_LEVEL_ONE
|
||||
icon_state = "terror_gray_cloaked"
|
||||
icon_living = "terror_gray_cloaked"
|
||||
if(!ckey)
|
||||
vision_range = 3
|
||||
idle_vision_range = 3
|
||||
// Bugged, does not work yet. Also spams webs. Also doesn't look great. But... planned.
|
||||
move_to_delay = 15 // while invisible, slow.
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/GrayDeCloak()
|
||||
invisibility = 0
|
||||
icon_state = "terror_gray"
|
||||
icon_living = "terror_gray"
|
||||
vision_range = 9
|
||||
idle_vision_range = 9
|
||||
move_to_delay = 5
|
||||
prob_ai_hides_in_vents = 10
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/spider_special_action()
|
||||
if(prob(prob_ai_hides_in_vents))
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/e = locate() in get_turf(src)
|
||||
if(e)
|
||||
if(!e.welded || spider_awaymission)
|
||||
if(invisibility != SEE_INVISIBLE_LEVEL_ONE) // aka: 35. ghosts have 15 with no darkness, 60 with darkness. Weird...
|
||||
var/list/g_turfs_webbed = ListWebbedTurfs()
|
||||
var/webcount = g_turfs_webbed.len
|
||||
if(webcount >= 4)
|
||||
// if there are already at least 4 webs around us, then we have a good web setup already. Cloak.
|
||||
GrayCloak()
|
||||
// I wonder if we should settle down here forever?
|
||||
var/foundqueen = 0
|
||||
for(var/mob/living/H in view(src, 10))
|
||||
if(istype(H, /mob/living/simple_animal/hostile/poison/terror_spider/queen))
|
||||
foundqueen = 1
|
||||
break
|
||||
if(!foundqueen)
|
||||
var/list/g_turfs_visible = ListVisibleTurfs()
|
||||
if(g_turfs_visible.len >= 12)
|
||||
// So long as the room isn't tiny, and it has no queen in it, sure, settle there
|
||||
// since we are settled now, disable most AI behaviors so we don't waste CPU.
|
||||
ai_ventcrawls = 0
|
||||
ai_spins_webs = 0
|
||||
ai_break_lights = 0
|
||||
prob_ai_hides_in_vents = 3
|
||||
visible_message("<span class='notice'>[src] finishes setting up its trap in [get_area(src)].</span>")
|
||||
else
|
||||
var/list/g_turfs_valid = ListValidTurfs()
|
||||
var/turfcount = g_turfs_valid.len
|
||||
if(turfcount == 0)
|
||||
// if there is literally nowhere else we could put a web, cloak.
|
||||
GrayCloak()
|
||||
else
|
||||
// otherwise, pick one of the valid turfs with no web to create a web there.
|
||||
new /obj/effect/spider/terrorweb(pick(g_turfs_valid))
|
||||
visible_message("<span class='notice'>[src] spins a web.</span>")
|
||||
else
|
||||
if(invisibility == SEE_INVISIBLE_LEVEL_ONE)
|
||||
// if our vent is welded, decloak
|
||||
GrayDeCloak()
|
||||
else
|
||||
if(invisibility == SEE_INVISIBLE_LEVEL_ONE)
|
||||
// if there is no vent under us, and we are cloaked, decloak
|
||||
GrayDeCloak()
|
||||
var/vdistance = 99
|
||||
var/temp_vent = null
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
|
||||
if(!v.welded)
|
||||
if(get_dist(src,v) < vdistance)
|
||||
temp_vent = v
|
||||
vdistance = get_dist(src,v)
|
||||
if(temp_vent)
|
||||
if(get_dist(src,temp_vent) > 0 && get_dist(src,temp_vent) < 5)
|
||||
step_to(src,temp_vent)
|
||||
// if you're bumped off your vent, try to get back to it
|
||||
@@ -3,6 +3,7 @@
|
||||
// ----------------- TERROR SPIDERS: T1 GREEN TERROR ------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: reproduction
|
||||
// -------------: AI: after it kills you, it webs you and lays new terror eggs on your body
|
||||
// -------------: SPECIAL: can also create webs, web normal objects, etc
|
||||
// -------------: TO FIGHT IT: kill it however you like - just don't die to it!
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
@@ -11,7 +12,7 @@
|
||||
name = "Green Terror spider"
|
||||
desc = "An ominous-looking green spider. It has a small egg-sac attached to it, and dried blood stains on its carapace."
|
||||
spider_role_summary = "Average melee spider that webs its victims and lays more spider eggs"
|
||||
|
||||
ai_target_method = TS_DAMAGE_BRUTE
|
||||
icon_state = "terror_green"
|
||||
icon_living = "terror_green"
|
||||
icon_dead = "terror_green_dead"
|
||||
@@ -20,7 +21,6 @@
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
var/feedings_to_lay = 2
|
||||
|
||||
var/datum/action/innate/terrorspider/greeneggs/greeneggs_action
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
if(E)
|
||||
to_chat(src, "<span class='notice'>There is already a cluster of eggs here!</span>")
|
||||
else if(fed < feedings_to_lay)
|
||||
to_chat(src, "<span class='warning'>You must wrap more prey before you can do this!</span>")
|
||||
to_chat(src, "<span class='warning'>You must wrap more humanoid prey before you can do this!</span>")
|
||||
else
|
||||
visible_message("<span class='notice'>[src] begins to lay a cluster of eggs.</span>")
|
||||
if(prob(33))
|
||||
@@ -45,6 +45,43 @@
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, 1, 1)
|
||||
fed -= feedings_to_lay
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/green/spider_special_action()
|
||||
if(cocoon_target)
|
||||
if(get_dist(src, cocoon_target) <= 1)
|
||||
spider_steps_taken = 0
|
||||
DoWrap()
|
||||
else
|
||||
if(spider_steps_taken > spider_max_steps)
|
||||
spider_steps_taken = 0
|
||||
cocoon_target = null
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
else
|
||||
spider_steps_taken++
|
||||
CreatePath(cocoon_target)
|
||||
step_to(src,cocoon_target)
|
||||
if(spider_debug)
|
||||
visible_message("<span class='notice'>[src] moves towards [cocoon_target] to cocoon it.</span>")
|
||||
else if(fed >= feedings_to_lay)
|
||||
DoLayGreenEggs()
|
||||
else if(world.time > (last_cocoon_object + freq_cocoon_object))
|
||||
last_cocoon_object = world.time
|
||||
var/list/can_see = view(src, 10)
|
||||
for(var/mob/living/C in can_see)
|
||||
if(C.stat == DEAD && !isterrorspider(C) && !C.anchored)
|
||||
spider_steps_taken = 0
|
||||
cocoon_target = C
|
||||
return
|
||||
for(var/obj/O in can_see)
|
||||
if(O.anchored)
|
||||
continue
|
||||
if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery))
|
||||
if(!istype(O, /obj/item/weapon/paper))
|
||||
cocoon_target = O
|
||||
stop_automated_movement = 1
|
||||
spider_steps_taken = 0
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/green/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(!poisonable)
|
||||
..()
|
||||
|
||||
@@ -18,6 +18,21 @@
|
||||
hsline += " AI "
|
||||
to_chat(src,hsline)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/SetHiveCommand(set_ai, set_ventcrawl)
|
||||
var/numspiders = 0
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist)
|
||||
if(spider_awaymission && !T.spider_awaymission)
|
||||
continue
|
||||
else if(!spider_awaymission && T.spider_awaymission)
|
||||
continue
|
||||
numspiders += 1
|
||||
if(spider_tier >= T.spider_tier)
|
||||
if(T.ai_type != set_ai)
|
||||
T.ai_type = set_ai
|
||||
if(T.idle_ventcrawl_chance != set_ventcrawl)
|
||||
T.idle_ventcrawl_chance = set_ventcrawl
|
||||
return numspiders
|
||||
|
||||
/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 ts_spiderlist)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// ----------------- TERROR SPIDERS: T3 MOTHER OF TERROR --------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: living schmuck bait
|
||||
// -------------: AI: no special ai
|
||||
// -------------: SPECIAL: spawns an ungodly number of spiderlings when killed
|
||||
// -------------: TO FIGHT IT: don't! Just leave it alone! It is harmless by itself... but god help you if you aggro it.
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
@@ -11,7 +12,7 @@
|
||||
name = "Mother of Terror spider"
|
||||
desc = "An enormous spider. Hundreds of tiny spiderlings are crawling all over it. Their beady little eyes all stare at you. The horror!"
|
||||
spider_role_summary = "Schmuck bait. Extremely weak in combat, but spawns many spiderlings when it dies."
|
||||
|
||||
ai_target_method = TS_DAMAGE_SIMPLE
|
||||
icon_state = "terror_gray2"
|
||||
icon_living = "terror_gray2"
|
||||
icon_dead = "terror_gray2_dead"
|
||||
@@ -20,12 +21,16 @@
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
move_to_delay = 5
|
||||
|
||||
idle_ventcrawl_chance = 5
|
||||
spider_tier = TS_TIER_3
|
||||
spider_opens_doors = 2
|
||||
|
||||
var/canspawn = 1
|
||||
var/datum/action/innate/terrorspider/ventsmash/ventsmash_action
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/mother/New()
|
||||
..()
|
||||
ventsmash_action = new()
|
||||
ventsmash_action.Grant(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/mother/death(gibbed)
|
||||
if(canspawn)
|
||||
@@ -37,6 +42,8 @@
|
||||
S.stillborn = 1
|
||||
else if(prob(10))
|
||||
S.grow_as = pick(/mob/living/simple_animal/hostile/poison/terror_spider/black, /mob/living/simple_animal/hostile/poison/terror_spider/green)
|
||||
S.amount_grown = 50 // double speed growth
|
||||
S.immediate_ventcrawl = 1
|
||||
visible_message("<span class='userdanger'>[src] breaks apart, the many spiders on its back scurrying everywhere!</span>")
|
||||
degenerate = 1
|
||||
..()
|
||||
|
||||
@@ -12,33 +12,35 @@
|
||||
name = "Prince of Terror spider"
|
||||
desc = "An enormous, terrifying spider. It looks like it is judging everything it sees. Its hide seems armored, and it bears the scars of many battles."
|
||||
spider_role_summary = "Miniboss terror spider. Lightning bruiser."
|
||||
|
||||
ai_target_method = TS_DAMAGE_BRUTE
|
||||
icon_state = "terror_allblack"
|
||||
icon_living = "terror_allblack"
|
||||
icon_dead = "terror_allblack_dead"
|
||||
|
||||
maxHealth = 600 // 30 laser shots
|
||||
health = 600
|
||||
regen_points_per_hp = 6 // double the normal - IE halved regen speed
|
||||
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 30
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 40
|
||||
move_to_delay = 4 // faster than normal
|
||||
|
||||
ventcrawler = 0
|
||||
ai_ventcrawls = 0
|
||||
environment_smash = 3
|
||||
|
||||
loot = list(/obj/item/clothing/accessory/medal)
|
||||
idle_ventcrawl_chance = 0
|
||||
spider_tier = TS_TIER_3
|
||||
spider_opens_doors = 2
|
||||
|
||||
var/datum/action/innate/terrorspider/princesmash/princesmash_action
|
||||
|
||||
var/datum/action/innate/terrorspider/thickweb/thickweb_action
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/New()
|
||||
..()
|
||||
princesmash_action = new()
|
||||
princesmash_action.Grant(src)
|
||||
thickweb_action = new()
|
||||
thickweb_action.Grant(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/death(gibbed)
|
||||
if(!hasdied)
|
||||
if(spider_uo71)
|
||||
UnlockBlastDoors("UO71_SciStorage")
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/spider_specialattack(mob/living/carbon/human/L)
|
||||
if(prob(15))
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// ----------------- TERROR SPIDERS: T2 PURPLE TERROR -----------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: guarding queen nests
|
||||
// -------------: AI: dies if too far from queen
|
||||
// -------------: SPECIAL: chance to stun on hit
|
||||
// -------------: TO FIGHT IT: shoot it from range, bring friends!
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
@@ -11,7 +12,7 @@
|
||||
name = "Purple Terror spider"
|
||||
desc = "An ominous-looking purple spider. It looks about warily, as if waiting for something."
|
||||
spider_role_summary = "Guards the nest of the Queen of Terror."
|
||||
|
||||
ai_target_method = TS_DAMAGE_BRUTE
|
||||
icon_state = "terror_purple"
|
||||
icon_living = "terror_purple"
|
||||
icon_dead = "terror_purple_dead"
|
||||
@@ -20,17 +21,28 @@
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 25
|
||||
move_to_delay = 6
|
||||
|
||||
spider_tier = TS_TIER_2
|
||||
spider_opens_doors = 2
|
||||
|
||||
ventcrawler = 0
|
||||
ai_ventcrawls = 0
|
||||
environment_smash = 3
|
||||
|
||||
idle_ventcrawl_chance = 0 // stick to the queen!
|
||||
var/dcheck_counter = 0
|
||||
var/queen_visible = 1
|
||||
var/cycles_noqueen = 0
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/purple/death(gibbed)
|
||||
if(spider_myqueen)
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q = spider_myqueen
|
||||
if(Q.stat != DEAD && !Q.ckey)
|
||||
if(get_dist(src,Q) > 20)
|
||||
if(!degenerate && !Q.degenerate)
|
||||
degenerate = 1
|
||||
Q.DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple,1,0)
|
||||
visible_message("<span class='notice'>[src] chitters in the direction of [Q]!</span>")
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/purple/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(cycles_noqueen < 6 && prob(10))
|
||||
visible_message("<span class='danger'>[src] rams into [L], knocking them to the floor!</span>")
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// ----------------- TERROR SPIDERS: T4 QUEEN OF TERROR ---------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: 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.
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
@@ -11,12 +12,13 @@
|
||||
name = "Queen of Terror spider"
|
||||
desc = "An enormous, terrifying spider. Its egg sac is almost as big as its body, and teeming with spider eggs!"
|
||||
spider_role_summary = "Commander of the spider forces. Lays eggs, directs the brood."
|
||||
|
||||
ai_target_method = TS_DAMAGE_SIMPLE
|
||||
icon_state = "terror_queen"
|
||||
icon_living = "terror_queen"
|
||||
icon_dead = "terror_queen_dead"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
regen_points_per_tick = 3
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
move_to_delay = 15 // yeah, this is very slow, but
|
||||
@@ -29,32 +31,31 @@
|
||||
var/neststep = 0
|
||||
var/hasnested = 0
|
||||
var/spider_max_per_nest = 20 // above this, queen stops spawning more, and declares war.
|
||||
|
||||
var/canlay = 0 // main counter for egg-laying ability! # = num uses, incremented at intervals
|
||||
var/canlay = 4 // 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
|
||||
|
||||
idle_ventcrawl_chance = 0
|
||||
force_threshold = 18 // outright immune to anything of force under 18, this means welders can't hurt it, only guns can
|
||||
|
||||
ranged = 1
|
||||
retreat_distance = 5
|
||||
minimum_distance = 5
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
projectiletype = /obj/item/projectile/terrorqueenspit
|
||||
|
||||
spider_tier = TS_TIER_4
|
||||
spider_opens_doors = 2
|
||||
loot = list(/obj/item/clothing/accessory/medal)
|
||||
|
||||
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)
|
||||
spider_myqueen = src
|
||||
if(spider_awaymission)
|
||||
spider_growinstantly = 1
|
||||
@@ -65,10 +66,15 @@
|
||||
if(.) // if mob is NOT dead
|
||||
if(ckey && canlay < 12 && hasnested) // max 12 eggs worth stored at any one time, realistically that's tons.
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
canlay++
|
||||
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 are able to lay eggs again.</span>")
|
||||
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
|
||||
@@ -76,6 +82,9 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/death(gibbed)
|
||||
if(!hasdied)
|
||||
SetHiveCommand(0, 15) // Hive becomes very aggressive.
|
||||
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 ts_spiderlist)
|
||||
if(ckey)
|
||||
@@ -84,6 +93,134 @@
|
||||
P.degenerate = 1
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/Retaliate()
|
||||
..()
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist)
|
||||
T.enemies |= enemies
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/handle_automated_action()
|
||||
..()
|
||||
if(!stat && !ckey && AIStatus != AI_OFF && !target && !path_to_vent)
|
||||
switch(neststep)
|
||||
if(0)
|
||||
// we have no nest :(
|
||||
var/ok_to_nest = 1
|
||||
var/area/new_area = get_area(loc)
|
||||
if(new_area)
|
||||
if(findtext(new_area.name, "hall"))
|
||||
ok_to_nest = 0
|
||||
// nesting in a hallway would be very stupid - crew would find and kill you almost instantly
|
||||
var/numhostiles = 0
|
||||
for(var/mob/living/H in oview(10, src))
|
||||
if(!istype(H, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
if(H.stat != DEAD)
|
||||
numhostiles += 1
|
||||
// nesting RIGHT NEXT TO SOMEONE is even worse
|
||||
if(numhostiles > 0)
|
||||
ok_to_nest = 0
|
||||
var/vdistance = 99
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(10, src))
|
||||
if(!v.welded)
|
||||
if(get_dist(src, v) < vdistance)
|
||||
entry_vent = v
|
||||
vdistance = get_dist(src, v)
|
||||
if(!entry_vent)
|
||||
ok_to_nest = 0
|
||||
// don't nest somewhere with no vent - your brood won't be able to get out!
|
||||
if(ok_to_nest && entry_vent)
|
||||
nest_vent = entry_vent
|
||||
neststep = 1
|
||||
visible_message("<span class='danger'>\The [src] settles down, starting to build a nest.</span>")
|
||||
else if(entry_vent)
|
||||
if(!path_to_vent)
|
||||
visible_message("<span class='danger'>\The [src] looks around warily - then seeks a better nesting ground.</span>")
|
||||
path_to_vent = 1
|
||||
else
|
||||
visible_message("<span class='danger'>\The [src] looks around, searching for the vent that should be there, but isn't. A bluespace portal forms on her, and she is gone.</span>")
|
||||
qdel(src)
|
||||
new /obj/effect/portal(get_turf(loc))
|
||||
if(1)
|
||||
if(world.time > (lastnestsetup + nestfrequency))
|
||||
lastnestsetup = world.time
|
||||
neststep = 2
|
||||
NestMode()
|
||||
if(2)
|
||||
if(world.time > (lastnestsetup + nestfrequency))
|
||||
lastnestsetup = world.time
|
||||
spider_lastspawn = world.time
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, 2, 0)
|
||||
neststep = 3
|
||||
if(3)
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
if(prob(20))
|
||||
var/obj/effect/spider/eggcluster/terror_eggcluster/N = locate() in get_turf(src)
|
||||
if(!N)
|
||||
spider_lastspawn = world.time
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, 2, 0)
|
||||
neststep = 4
|
||||
if(4)
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
if(prob(20))
|
||||
var/obj/effect/spider/eggcluster/terror_eggcluster/N = locate() in get_turf(src)
|
||||
if(!N)
|
||||
spider_lastspawn = world.time
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, 2, 1)
|
||||
neststep = 5
|
||||
if(5)
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
if(prob(20))
|
||||
var/obj/effect/spider/eggcluster/terror_eggcluster/N = locate() in get_turf(src)
|
||||
if(!N)
|
||||
if(!spider_awaymission)
|
||||
QueenFakeLings()
|
||||
spider_lastspawn = world.time
|
||||
if(prob(33))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/gray, 2, 1)
|
||||
else if(prob(50))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, 2, 1)
|
||||
else
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, 2, 1)
|
||||
var/spidercount = CountSpiders()
|
||||
if(spidercount >= spider_max_per_nest) // station overwhelmed!
|
||||
neststep = 6
|
||||
if(6)
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
spider_lastspawn = world.time
|
||||
// go hostile, EXTERMINATE MODE.
|
||||
SetHiveCommand(0, 15) // AI=0 (attack everyone), ventcrawl=15%/tick
|
||||
var/numspiders = CountSpiders()
|
||||
if(numspiders < spider_max_per_nest)
|
||||
if(prob(33))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/black, 2, 1)
|
||||
else if(prob(50))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, 2, 0)
|
||||
else
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, 2, 1)
|
||||
else if(spider_awaymission)
|
||||
neststep = 7
|
||||
spider_spawnfrequency = spider_spawnfrequency_stable
|
||||
// if we're an away mission queen... don't keep spawning spiders at high rates. Away team should have a chance.
|
||||
if(7)
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
spider_lastspawn = world.time
|
||||
var/numspiders = CountSpiders()
|
||||
if(numspiders < spider_max_per_nest)
|
||||
// someone is killing my children...
|
||||
if(prob(25))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/black, 2, 1)
|
||||
else if(prob(33))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, 2, 0)
|
||||
else if(prob(50))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, 2, 1)
|
||||
else
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, 2, 0)
|
||||
neststep = 6
|
||||
|
||||
/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)
|
||||
@@ -94,6 +231,7 @@
|
||||
queennest_action.Remove(src)
|
||||
hasnested = 1
|
||||
ventcrawler = 0
|
||||
ai_ventcrawls = 0
|
||||
environment_smash = 3
|
||||
DoQueenScreech(8, 100, 8, 100)
|
||||
MassFlicker()
|
||||
@@ -159,8 +297,8 @@
|
||||
if(eggtype == null || numlings == null)
|
||||
to_chat(src, "<span class='danger'>Cancelled.</span>")
|
||||
return
|
||||
//spider_lastspawn = world.time // don't think we actually need this, if queen is laying manually canlay controls her rate.
|
||||
canlay -= numlings
|
||||
eggslaid += numlings
|
||||
if(eggtype == TS_DESC_RED)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, numlings, 1)
|
||||
else if(eggtype == TS_DESC_GRAY)
|
||||
@@ -184,6 +322,9 @@
|
||||
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>")
|
||||
return
|
||||
if(spider_can_fakelings)
|
||||
spider_can_fakelings--
|
||||
var/numlings = 15
|
||||
@@ -210,5 +351,5 @@
|
||||
if(L.reagents)
|
||||
if(L.can_inject(null, 0, "chest", 0))
|
||||
L.reagents.add_reagent("terror_queen_toxin", 15)
|
||||
if(!istype(L, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
if(!isterrorspider(L))
|
||||
L.adjustToxLoss(30)
|
||||
@@ -12,9 +12,8 @@
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/red
|
||||
name = "Red Terror spider"
|
||||
desc = "An ominous-looking red spider, it has eight beady red eyes, and nasty, big, pointy fangs! It looks like it has a vicious streak a mile wide."
|
||||
|
||||
spider_role_summary = "High health, high damage, very slow, melee juggernaut"
|
||||
|
||||
ai_target_method = TS_DAMAGE_BRUTE
|
||||
icon_state = "terror_red"
|
||||
icon_living = "terror_red"
|
||||
icon_dead = "terror_red_dead"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
faction = list("terrorspiders")
|
||||
var/spider_myqueen = null
|
||||
var/use_vents = 1
|
||||
var/list/enemies = list()
|
||||
var/immediate_ventcrawl = 0
|
||||
|
||||
/obj/effect/spider/spiderling/terror_spiderling/New()
|
||||
..()
|
||||
@@ -72,8 +74,10 @@
|
||||
var/list/nearby = oview(10, src)
|
||||
if(nearby.len)
|
||||
var/target_atom = pick(nearby)
|
||||
walk_to(src, target_atom)
|
||||
else if(prob(10) && use_vents)
|
||||
if(!istype(get_turf(target_atom),/turf/space))
|
||||
walk_to(src, target_atom)
|
||||
else if(immediate_ventcrawl || (prob(10) && use_vents))
|
||||
immediate_ventcrawl = 0
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
|
||||
if(!v.welded)
|
||||
entry_vent = v
|
||||
@@ -91,6 +95,7 @@
|
||||
S.faction = faction
|
||||
S.spider_myqueen = spider_myqueen
|
||||
S.master_commander = master_commander
|
||||
S.enemies = enemies
|
||||
qdel(src)
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
@@ -106,6 +111,7 @@
|
||||
C.faction = faction
|
||||
C.spider_myqueen = spider_myqueen
|
||||
C.master_commander = master_commander
|
||||
C.enemies = enemies
|
||||
if(spider_growinstantly)
|
||||
C.amount_grown = 250
|
||||
C.spider_growinstantly = 1
|
||||
@@ -122,6 +128,7 @@
|
||||
var/spiderling_type = null
|
||||
var/spiderling_number = 1
|
||||
var/spiderling_ventcrawl = 1
|
||||
var/list/enemies = list()
|
||||
|
||||
/obj/effect/spider/eggcluster/terror_eggcluster/New()
|
||||
..()
|
||||
@@ -162,6 +169,7 @@
|
||||
S.faction = faction
|
||||
S.spider_myqueen = spider_myqueen
|
||||
S.master_commander = master_commander
|
||||
S.enemies = enemies
|
||||
if(spider_growinstantly)
|
||||
S.amount_grown = 250
|
||||
var/rnum = 5 - spiderling_number
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: TARGETING CODE -----------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/ListTargets()
|
||||
var/list/targets1 = list()
|
||||
var/list/targets2 = list()
|
||||
var/list/targets3 = list()
|
||||
for(var/mob/living/H in view(src, vision_range))
|
||||
if(H.stat == DEAD)
|
||||
continue
|
||||
if(H.flags & GODMODE)
|
||||
continue
|
||||
if(H.stat == UNCONSCIOUS && !stat_attack)
|
||||
continue
|
||||
if(ai_type == TS_AI_DEFENSIVE && !(H in enemies))
|
||||
continue
|
||||
if(isterrorspider(H))
|
||||
if(H in enemies)
|
||||
targets3 += H
|
||||
continue
|
||||
if(iscarbon(H))
|
||||
var/mob/living/carbon/C = H
|
||||
if(IsInfected(C)) // only target the infected if they're attacking us. Even then, lowest priority.
|
||||
if(C in enemies)
|
||||
targets3 += C
|
||||
continue
|
||||
else if(C.reagents.has_reagent("terror_black_toxin",60))
|
||||
// only target those dying of black spider venom if they are close, or our enemy
|
||||
if(get_dist(src,C) <= 2 || (C in enemies))
|
||||
targets2 += C
|
||||
else
|
||||
// Target prioritization by spider type. BRUTE spiders prioritize lower armor values, POISON spiders prioritize poisonable targets
|
||||
if(ai_target_method == TS_DAMAGE_BRUTE)
|
||||
var/theirarmor = C.getarmor(type = "melee")
|
||||
// Example values: Civilian: 2, Engineer w/ Hardsuit: 10, Sec Officer with armor: 19, HoS: 48, Deathsquad: 80
|
||||
if(theirarmor < 10)
|
||||
targets1 += C
|
||||
else if(C in enemies)
|
||||
if(theirarmor < 30)
|
||||
targets2 += C
|
||||
else
|
||||
targets3 += C
|
||||
else
|
||||
targets3 += C
|
||||
else if(ai_target_method == TS_DAMAGE_POISON)
|
||||
if(C.can_inject(null,0,"chest",0))
|
||||
targets1 += C
|
||||
else if(C in enemies)
|
||||
targets2 += C
|
||||
else
|
||||
targets3 += C
|
||||
else
|
||||
// TS_DAMAGE_SIMPLE
|
||||
if(C in enemies)
|
||||
targets2 += C
|
||||
else
|
||||
targets3 += C
|
||||
else
|
||||
if(istype(H,/mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/S = H
|
||||
if(S.force_threshold > melee_damage_upper)
|
||||
continue
|
||||
if(H in enemies)
|
||||
targets2 += H
|
||||
else
|
||||
targets3 += H
|
||||
if(health < maxHealth)
|
||||
// if we're hurt, and ONLY if we're hurt, do the additional check for mechs/space pods. Save processing time.
|
||||
for(var/obj/mecha/M in view(src, vision_range))
|
||||
if(get_dist(M, src) <= 2)
|
||||
targets2 += M
|
||||
else
|
||||
targets3 += M
|
||||
for(var/obj/spacepod/S in view(src, vision_range))
|
||||
targets3 += S
|
||||
if(targets1.len)
|
||||
return targets1
|
||||
if(targets2.len)
|
||||
return targets2
|
||||
return targets3
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/LoseTarget()
|
||||
if(target && isliving(target))
|
||||
var/mob/living/T = target
|
||||
if(T.stat > 0)
|
||||
killcount++
|
||||
regen_points += regen_points_per_kill
|
||||
attackstep = 0
|
||||
attackcycles = 0
|
||||
..()
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: AI BEHAVIOR CODE -------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/handle_automated_action()
|
||||
if (stat || ckey)
|
||||
return ..()
|
||||
if(AIStatus != AI_OFF && !target)
|
||||
var/my_ventcrawl_freq = freq_ventcrawl_idle
|
||||
if(ts_count_dead > 0)
|
||||
if(world.time < (ts_death_last + ts_death_window))
|
||||
my_ventcrawl_freq = freq_ventcrawl_combat
|
||||
// First, check for general actions that any spider could take.
|
||||
if(path_to_vent)
|
||||
if(entry_vent)
|
||||
if(spider_steps_taken > spider_max_steps)
|
||||
path_to_vent = 0
|
||||
stop_automated_movement = 0
|
||||
spider_steps_taken = 0
|
||||
path_to_vent = 0
|
||||
entry_vent = null
|
||||
else if(get_dist(src, entry_vent) <= 1)
|
||||
path_to_vent = 0
|
||||
stop_automated_movement = 1
|
||||
spider_steps_taken = 0
|
||||
spawn(50)
|
||||
stop_automated_movement = 0
|
||||
TSVentCrawlRandom(entry_vent)
|
||||
else
|
||||
spider_steps_taken++
|
||||
CreatePath(entry_vent)
|
||||
step_to(src,entry_vent)
|
||||
if(spider_debug > 0)
|
||||
visible_message("<span class='notice'>[src] moves towards the vent [entry_vent].</span>")
|
||||
else
|
||||
path_to_vent = 0
|
||||
else if(ai_break_lights && world.time > (last_break_light + freq_break_light))
|
||||
last_break_light = world.time
|
||||
for(var/obj/machinery/light/L in range(1, src))
|
||||
if(!L.status)
|
||||
step_to(src,L)
|
||||
L.on = 1
|
||||
L.broken()
|
||||
L.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>[src] smashes the [L.name].</span>")
|
||||
break
|
||||
else if(ai_spins_webs && world.time > (last_spins_webs + freq_spins_webs))
|
||||
last_spins_webs = world.time
|
||||
var/obj/effect/spider/terrorweb/T = locate() in get_turf(src)
|
||||
if(!T)
|
||||
new /obj/effect/spider/terrorweb(get_turf(src))
|
||||
visible_message("<span class='notice'>[src] puts up some spider webs.</span>")
|
||||
else if(ai_ventcrawls && world.time > (last_ventcrawl_time + my_ventcrawl_freq))
|
||||
if(prob(idle_ventcrawl_chance))
|
||||
last_ventcrawl_time = world.time
|
||||
var/vdistance = 99
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(10, src))
|
||||
if(!v.welded)
|
||||
if(get_dist(src,v) < vdistance)
|
||||
entry_vent = v
|
||||
vdistance = get_dist(src,v)
|
||||
if(entry_vent)
|
||||
path_to_vent = 1
|
||||
else
|
||||
// If none of the general actions apply, check for class-specific actions.
|
||||
spider_special_action()
|
||||
else if(AIStatus != AI_OFF && target)
|
||||
CreatePath(target)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/adjustBruteLoss(damage)
|
||||
..(damage)
|
||||
Retaliate()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/adjustFireLoss(damage)
|
||||
..(damage)
|
||||
Retaliate()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/Retaliate()
|
||||
var/list/around = oview(src, 7)
|
||||
var/list/ts_nearby = list()
|
||||
for(var/atom/movable/A in around)
|
||||
if(A in enemies)
|
||||
continue
|
||||
if(isterrorspider(A))
|
||||
ts_nearby += A
|
||||
continue
|
||||
if(isliving(A))
|
||||
var/mob/living/M = A
|
||||
if(!("terrorspiders" in M.faction))
|
||||
enemies |= M
|
||||
visible_message("<span class='danger'>[src] glares at [M]!</span>")
|
||||
else if(istype(A, /obj/mecha))
|
||||
var/obj/mecha/M = A
|
||||
if(M.occupant)
|
||||
enemies |= M
|
||||
enemies |= M.occupant
|
||||
else if(istype(A, /obj/spacepod))
|
||||
var/obj/spacepod/M = A
|
||||
if(M.pilot)
|
||||
enemies |= M
|
||||
enemies |= M.pilot
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/H in ts_nearby)
|
||||
var/retaliate_faction_check = 0
|
||||
for(var/F in faction)
|
||||
if(F in H.faction)
|
||||
retaliate_faction_check = 1
|
||||
break
|
||||
if(retaliate_faction_check && !attack_same && !H.attack_same)
|
||||
H.enemies |= enemies
|
||||
return 0
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: PATHING CODE -----------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CreatePath(mygoal)
|
||||
var/m2 = get_turf(src)
|
||||
if(m2 == mylocation)
|
||||
chasecycles++
|
||||
ClearObstacle(get_turf(mygoal))
|
||||
if(chasecycles >= 2)
|
||||
chasecycles = 0
|
||||
if(spider_opens_doors)
|
||||
var/tgt_dir = get_dir(src,mygoal)
|
||||
for(var/obj/machinery/door/airlock/A in view(1, src))
|
||||
if(A.density)
|
||||
try_open_airlock(A)
|
||||
for(var/obj/machinery/door/firedoor/F in view(1, src))
|
||||
if(tgt_dir == get_dir(src,F) && F.density && !F.welded)
|
||||
visible_message("<span class='danger'>[src] pries open the firedoor!</span>")
|
||||
F.open()
|
||||
|
||||
else
|
||||
mylocation = m2
|
||||
chasecycles = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/ClearObstacle(turf/target_turf)
|
||||
var/list/valid_obstacles = list(/obj/structure/window, /obj/structure/closet, /obj/structure/table, /obj/structure/grille, /obj/structure/rack, /obj/machinery/door/window)
|
||||
for(var/dir in cardinal) // North, South, East, West
|
||||
var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
|
||||
if(is_type_in_list(obstacle, valid_obstacles))
|
||||
obstacle.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/TSVentCrawlRandom(/var/entry_vent)
|
||||
if(entry_vent)
|
||||
if(get_dist(src, entry_vent) <= 2)
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in entry_vent.parent.other_atmosmch)
|
||||
vents.Add(temp_vent)
|
||||
if(!vents.len)
|
||||
entry_vent = null
|
||||
return
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = pick(vents)
|
||||
visible_message("<B>[src] scrambles into the ventillation ducts!</B>", "<span class='notice'>You hear something squeezing through the ventilation ducts.</span>")
|
||||
spawn(rand(20,60))
|
||||
var/original_location = loc
|
||||
forceMove(exit_vent)
|
||||
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
|
||||
spawn(travel_time)
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
forceMove(original_location)
|
||||
entry_vent = null
|
||||
return
|
||||
if(prob(50))
|
||||
audible_message("<span class='notice'>You hear something squeezing through the ventilation ducts.</span>")
|
||||
spawn(travel_time)
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
forceMove(original_location)
|
||||
entry_vent = null
|
||||
return
|
||||
forceMove(exit_vent.loc)
|
||||
entry_vent = null
|
||||
var/area/new_area = get_area(loc)
|
||||
if(new_area)
|
||||
new_area.Entered(src)
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: ENVIRONMENT CODE -------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/ListValidTurfs()
|
||||
var/list/potentials = list()
|
||||
for(var/turf/simulated/T in oview(3,get_turf(src)))
|
||||
if(T.density == 0 && get_dist(get_turf(src),T) == 3)
|
||||
var/obj/effect/spider/terrorweb/W = locate() in T
|
||||
if(!W)
|
||||
var/obj/structure/grille/G = locate() in T
|
||||
if(!G)
|
||||
var/obj/structure/window/O = locate() in T
|
||||
if(!O)
|
||||
potentials += T
|
||||
return potentials
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/ListWebbedTurfs()
|
||||
var/list/webbed = list()
|
||||
for(var/turf/simulated/T in oview(3,get_turf(src)))
|
||||
if(T.density == 0 && get_dist(get_turf(src),T) == 3)
|
||||
var/obj/effect/spider/terrorweb/W = locate() in T
|
||||
if(W)
|
||||
webbed += T
|
||||
return webbed
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/ListVisibleTurfs()
|
||||
var/list/vturfs = list()
|
||||
for(var/turf/simulated/T in oview(7,get_turf(src)))
|
||||
if(T.density == 0)
|
||||
vturfs += T
|
||||
return vturfs
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: MISC AI CODE -----------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/UnlockBlastDoors(target_id_tag)
|
||||
for(var/obj/machinery/door/poddoor/P in airlocks)
|
||||
if(P.density && P.id_tag == target_id_tag && P.z == z && !P.operating)
|
||||
P.open()
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
var/global/list/ts_ckey_blacklist = list()
|
||||
var/global/ts_count_dead = 0
|
||||
var/global/ts_count_alive_awaymission = 0
|
||||
@@ -43,6 +42,15 @@ var/global/list/ts_spiderling_list = list()
|
||||
|
||||
// Ventcrawling
|
||||
ventcrawler = 1 // allows player ventcrawling
|
||||
var/ai_ventcrawls = 1
|
||||
var/idle_ventcrawl_chance = 3 // default 3% chance to ventcrawl when not in combat to a random exit vent
|
||||
var/freq_ventcrawl_combat = 1800 // 3 minutes
|
||||
var/freq_ventcrawl_idle = 9000 // 15 minutes
|
||||
var/last_ventcrawl_time = -9000 // Last time the spider crawled. Used to prevent excessive crawling. Setting to freq*-1 ensures they can crawl once on spawn.
|
||||
|
||||
// AI movement tracking
|
||||
var/spider_steps_taken = 0 // leave at 0, its a counter for ai steps taken.
|
||||
var/spider_max_steps = 15 // after we take X turns trying to do something, give up!
|
||||
|
||||
// Speech
|
||||
speak_chance = 0 // quiet but deadly
|
||||
@@ -71,15 +79,35 @@ var/global/list/ts_spiderling_list = list()
|
||||
aggro_vision_range = 10
|
||||
see_in_dark = 10
|
||||
nightvision = 1
|
||||
vision_type = new /datum/vision_override/nightvision/thermals/ling_augmented_eyesight
|
||||
see_invisible = 5
|
||||
sight = SEE_MOBS
|
||||
|
||||
// AI aggression settings
|
||||
var/ai_type = TS_AI_AGGRESSIVE // 0 = aggressive to everyone, 1 = defends self only
|
||||
var/ai_target_method = TS_DAMAGE_SIMPLE
|
||||
|
||||
// AI player control by ghosts
|
||||
var/ai_playercontrol_allowtype = 1 // if 0, this specific class of spider is not player-controllable. Default set in code for each class, cannot be changed.
|
||||
|
||||
var/ai_break_lights = 1 // AI lightbreaking behavior
|
||||
var/freq_break_light = 600
|
||||
var/last_break_light = 0 // leave this, changed by procs.
|
||||
|
||||
var/ai_spins_webs = 1 // AI web-spinning behavior
|
||||
var/freq_spins_webs = 600
|
||||
var/last_spins_webs = 0 // leave this, changed by procs.
|
||||
var/delay_web = 40 // delay between starting to spin web, and finishing
|
||||
|
||||
var/freq_cocoon_object = 1200 // two minutes between each attempt
|
||||
var/last_cocoon_object = 0 // leave this, changed by procs.
|
||||
|
||||
var/prob_ai_hides_in_vents = 15 // probabily of a gray spider hiding in a vent
|
||||
|
||||
var/spider_opens_doors = 1 // all spiders can open firedoors (they have no security). 1 = can open depowered doors. 2 = can open powered doors
|
||||
faction = list("terrorspiders")
|
||||
var/spider_awaymission = 0 // if 1, limits certain behavior in away missions
|
||||
var/spider_uo71 = 0 // if 1, spider is in the UO71 away mission
|
||||
var/spider_unlock_id_tag = "" // if defined, unlock awaymission blast doors with this tag on death
|
||||
var/spider_role_summary = "UNDEFINED"
|
||||
var/spider_placed = 0
|
||||
|
||||
@@ -90,16 +118,18 @@ var/global/list/ts_spiderling_list = list()
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/nest_vent // home vent, usually used by queens
|
||||
var/fed = 0
|
||||
var/travelling_in_vent = 0
|
||||
var/list/enemies = list()
|
||||
var/path_to_vent = 0
|
||||
var/killcount = 0
|
||||
var/busy = 0 // leave this alone!
|
||||
var/spider_tier = TS_TIER_1 // 1 for red,gray,green. 2 for purple,black,white, 3 for prince, mother. 4 for queen
|
||||
var/hasdied = 0
|
||||
var/list/spider_special_drops = list()
|
||||
var/attackstep = 0
|
||||
var/attackcycles = 0
|
||||
var/spider_myqueen = null
|
||||
var/mylocation = null
|
||||
var/chasecycles = 0
|
||||
var/last_cocoon_object = 0 // leave this, changed by procs.
|
||||
|
||||
var/datum/action/innate/terrorspider/web/web_action
|
||||
var/datum/action/innate/terrorspider/wrap/wrap_action
|
||||
@@ -124,13 +154,15 @@ var/global/list/ts_spiderling_list = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/AttackingTarget()
|
||||
if(isterrorspider(target))
|
||||
if(target in enemies)
|
||||
enemies -= target
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/T = target
|
||||
if(T.spider_tier > spider_tier)
|
||||
visible_message("<span class='notice'>[src] bows in respect for the terrifying presence of [target].</span>")
|
||||
visible_message("<span class='notice'>[src] cowers before [target].</span>")
|
||||
else if(T.spider_tier == spider_tier)
|
||||
visible_message("<span class='notice'>[src] nuzzles [target].</span>")
|
||||
else if(T.spider_tier < spider_tier && spider_tier >= 4)
|
||||
visible_message("<span class='notice'>[src] gives [target] a stern look.</span>")
|
||||
target.attack_animal(src)
|
||||
else
|
||||
visible_message("<span class='notice'>[src] harmlessly nuzzles [target].</span>")
|
||||
T.CheckFaction()
|
||||
@@ -223,6 +255,15 @@ var/global/list/ts_spiderling_list = list()
|
||||
if(is_away_level(z))
|
||||
spider_awaymission = 1
|
||||
ts_count_alive_awaymission++
|
||||
if(spider_tier >= 3)
|
||||
ai_ventcrawls = 0 // means that pre-spawned bosses on away maps won't ventcrawl. Necessary to keep prince/mother in one place.
|
||||
if(istype(get_area(src), /area/awaymission/UO71)) // if we are playing the away mission with our special spiders...
|
||||
spider_uo71 = 1
|
||||
if(world.time < 600)
|
||||
// these are static spiders, specifically for the UO71 away mission, make them stay in place
|
||||
ai_ventcrawls = 0
|
||||
spider_placed = 1
|
||||
wander = 0
|
||||
else
|
||||
ts_count_alive_station++
|
||||
// after 30 seconds, assuming nobody took control of it yet, offer it to ghosts.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T2 WHITE TERROR ------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
@@ -12,12 +11,12 @@
|
||||
name = "White Terror spider"
|
||||
desc = "An ominous-looking white spider, its ghostly eyes and vicious-looking fangs are the stuff of nightmares."
|
||||
spider_role_summary = "Rare, bite-and-run spider that infects hosts with spiderlings"
|
||||
|
||||
ai_target_method = TS_DAMAGE_POISON
|
||||
icon_state = "terror_white"
|
||||
icon_living = "terror_white"
|
||||
icon_dead = "terror_white_dead"
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 15
|
||||
move_to_delay = 4
|
||||
@@ -25,6 +24,18 @@
|
||||
loot = list(/obj/item/clothing/accessory/medal)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/white/LoseTarget()
|
||||
stop_automated_movement = 0
|
||||
attackstep = 0
|
||||
attackcycles = 0
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/white/death(gibbed)
|
||||
if(!hasdied)
|
||||
if(spider_uo71)
|
||||
UnlockBlastDoors("UO71_Bridge")
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/white/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(!poisonable)
|
||||
..()
|
||||
@@ -35,6 +46,13 @@
|
||||
if(!IsInfected(L))
|
||||
visible_message("<span class='danger'>[src] buries its long fangs deep into the [inject_target] of [L]!</span>")
|
||||
new /obj/item/organ/internal/body_egg/terror_eggs(L)
|
||||
if(!ckey)
|
||||
LoseTarget()
|
||||
walk_away(src,L,2,1)
|
||||
else if(prob(25))
|
||||
visible_message("<span class='danger'>[src] pounces on [L]!</span>")
|
||||
L.Weaken(5)
|
||||
L.Stun(5)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/IsInfected(mob/living/carbon/C) // Terror AI requires this
|
||||
if(C.get_int_organ(/obj/item/organ/internal/body_egg))
|
||||
|
||||
@@ -140,12 +140,14 @@
|
||||
/mob/living/proc/StartResting(updating = 1)
|
||||
var/val_change = !resting
|
||||
resting = TRUE
|
||||
|
||||
if(updating && val_change)
|
||||
update_canmove()
|
||||
|
||||
/mob/living/proc/StopResting(updating = 1)
|
||||
var/val_change = !!resting
|
||||
resting = FALSE
|
||||
|
||||
if(updating && val_change)
|
||||
update_canmove()
|
||||
|
||||
|
||||
+12
-16
@@ -231,22 +231,18 @@
|
||||
//Mob can equip. Equip it.
|
||||
equip_to_slot_or_del(W, slot)
|
||||
else
|
||||
//Mob can't equip it. Put it in a bag B.
|
||||
// Do I have a backpack?
|
||||
var/obj/item/weapon/storage/B
|
||||
if(istype(back,/obj/item/weapon/storage))
|
||||
//Mob is wearing backpack
|
||||
B = back
|
||||
else
|
||||
//not wearing backpack. Check if player holding plastic bag
|
||||
B=is_in_hands(/obj/item/weapon/storage/bag/plasticbag)
|
||||
if(!B) //If not holding plastic bag, give plastic bag
|
||||
B=new /obj/item/weapon/storage/bag/plasticbag(null) // Null in case of failed equip.
|
||||
if(!put_in_hands(B))
|
||||
return // Bag could not be placed in players hands. I don't know what to do here...
|
||||
//Now, B represents a container we can insert W into.
|
||||
B.handle_item_insertion(W,1)
|
||||
return B
|
||||
//Mob can't equip it. Put it their backpack or toss it on the floor
|
||||
if(istype(back, /obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/S = back
|
||||
//Now, B represents a container we can insert W into.
|
||||
S.handle_item_insertion(W,1)
|
||||
return S
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(istype(T))
|
||||
W.forceMove(T)
|
||||
return T
|
||||
|
||||
|
||||
//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
|
||||
var/list/slot_equipment_priority = list( \
|
||||
|
||||
@@ -380,9 +380,16 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
|
||||
set name = "Rest"
|
||||
set category = "IC"
|
||||
|
||||
resting = !resting
|
||||
update_canmove()
|
||||
to_chat(src, "<span class='notice'>You are now [resting ? "resting" : "getting up"].</span>")
|
||||
if(world.time < client.move_delay)
|
||||
return
|
||||
|
||||
if(!resting)
|
||||
client.move_delay = world.time + 20
|
||||
to_chat(src, "<span class='notice'>You are now resting.</span>")
|
||||
StartResting()
|
||||
else if(resting)
|
||||
to_chat(src, "<span class='notice'>You are now getting up.</span>")
|
||||
StopResting()
|
||||
|
||||
/proc/is_blind(A)
|
||||
if(iscarbon(A))
|
||||
|
||||
@@ -470,7 +470,7 @@
|
||||
if(CHEF)
|
||||
clothes_s = new /icon(uniform_dmi, "chef_s")
|
||||
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
|
||||
clothes_s.Blend(new /icon('icons/mob/head.dmi', "chefhat"), ICON_OVERLAY)
|
||||
clothes_s.Blend(new /icon('icons/mob/head.dmi', "chef"), ICON_OVERLAY)
|
||||
if(prob(1))
|
||||
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "apronchef"), ICON_OVERLAY)
|
||||
switch(backbag)
|
||||
|
||||
Reference in New Issue
Block a user