Merge branch 'master' into adminin

This commit is contained in:
Crazy Lemon
2017-03-03 21:45:41 -08:00
committed by Crazylemon64
244 changed files with 11181 additions and 6402 deletions
+1 -1
View File
@@ -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())
+1 -1
View File
@@ -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)
+24 -32
View File
@@ -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))
+2
View File
@@ -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
View File
@@ -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( \
+10 -3
View File
@@ -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)