mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-16 01:23:41 +01:00
Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into BookClub
This commit is contained in:
@@ -428,6 +428,19 @@
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
follow = 1
|
||||
|
||||
|
||||
/datum/language/terrorspider
|
||||
name = "Spider Hivemind"
|
||||
desc = "Terror spiders have a limited ability to commune over a psychic hivemind, similar to xenomorphs."
|
||||
speech_verb = "chitters"
|
||||
ask_verb = "chitters"
|
||||
exclaim_verb = "chitters"
|
||||
colour = "terrorspider"
|
||||
key = "ts"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
follow = 1
|
||||
|
||||
|
||||
/datum/language/ling
|
||||
name = "Changeling"
|
||||
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
|
||||
@@ -559,7 +572,7 @@
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
drone_only = 1
|
||||
follow = 1
|
||||
|
||||
|
||||
/datum/language/drone
|
||||
name = "Drone"
|
||||
desc = "An encrypted stream of data converted to speech patterns."
|
||||
|
||||
@@ -454,8 +454,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
|
||||
totalMembers |= pipeline.other_atmosmch
|
||||
for(var/obj/machinery/atmospherics/A in totalMembers)
|
||||
if(!A.pipe_image)
|
||||
A.pipe_image = image(A, A.loc, layer = 20, dir = A.dir) //the 20 puts it above Byond's darkness (not its opacity view)
|
||||
A.pipe_image.plane = HUD_PLANE
|
||||
A.update_pipe_image()
|
||||
pipes_shown += A.pipe_image
|
||||
client.images += A.pipe_image
|
||||
|
||||
|
||||
@@ -47,10 +47,12 @@
|
||||
to_chat(src, "Alert cancelled. Power has been restored without our assistance.")
|
||||
aiRestorePowerRoutine = 0
|
||||
clear_fullscreen("blind")
|
||||
update_sight()
|
||||
else if(aiRestorePowerRoutine == 3)
|
||||
to_chat(src, "Alert cancelled. Power has been restored.")
|
||||
aiRestorePowerRoutine = 0
|
||||
clear_fullscreen("blind")
|
||||
update_sight()
|
||||
|
||||
|
||||
else
|
||||
|
||||
@@ -114,8 +114,6 @@
|
||||
C.toff = 1
|
||||
..()
|
||||
|
||||
/mob/living/silicon/pai/Login()
|
||||
..()
|
||||
|
||||
// this function shows the information about being silenced as a pAI in the Status panel
|
||||
/mob/living/silicon/pai/proc/show_silenced()
|
||||
|
||||
@@ -41,7 +41,12 @@ var/global/list/default_pai_software = list()
|
||||
if(ui_key != "main")
|
||||
var/datum/pai_software/S = software[ui_key]
|
||||
if(S && !S.toggle)
|
||||
S.on_ui_interact(src, ui, force_open)
|
||||
ui = nanomanager.try_update_ui(user, src, S.id, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, S.id, S.template_file, S.ui_title, S.ui_width, S.ui_height, state = state)
|
||||
ui.open()
|
||||
if(S.autoupdate)
|
||||
ui.set_auto_update(1)
|
||||
else
|
||||
if(ui)
|
||||
ui.set_status(STATUS_CLOSE, 0)
|
||||
@@ -53,9 +58,15 @@ var/global/list/default_pai_software = list()
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/mob/living/silicon/pai/ui_data(mob/user, datum/topic_state/state = self_state)
|
||||
/mob/living/silicon/pai/ui_data(mob/user, ui_key = "main", datum/topic_state/state = self_state)
|
||||
var/data[0]
|
||||
|
||||
if(ui_key != "main")
|
||||
var/datum/pai_software/S = software[ui_key]
|
||||
if(S && !S.toggle)
|
||||
return S.on_ui_data(user, state)
|
||||
log_runtime(EXCEPTION("Unrecognized/invalid pAI UI state '[ui_key]'"), src)
|
||||
return
|
||||
// Software we have bought
|
||||
var/bought_software[0]
|
||||
// Software we have not bought
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -285,6 +285,7 @@
|
||||
|
||||
if(player.mob && player.mob.mind)
|
||||
player.mob.mind.transfer_to(src)
|
||||
player.mob.mind.assigned_role = "Drone"
|
||||
|
||||
lawupdate = 0
|
||||
to_chat(src, "<b>Systems rebooted</b>. Loading base pattern maintenance protocol... <b>loaded</b>.")
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
#define SPINNING_WEB 1
|
||||
#define LAYING_EGGS 2
|
||||
#define MOVING_TO_TARGET 3
|
||||
#define SPINNING_COCOON 4
|
||||
|
||||
#define TS_TIER_1 1
|
||||
#define TS_TIER_2 2
|
||||
#define TS_TIER_3 3
|
||||
#define TS_TIER_4 4
|
||||
#define TS_TIER_5 5
|
||||
@@ -0,0 +1,127 @@
|
||||
|
||||
|
||||
/datum/action/innate/terrorspider/web
|
||||
name = "Web"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "stickyweb1"
|
||||
|
||||
/datum/action/innate/terrorspider/web/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/user = owner
|
||||
user.Web()
|
||||
|
||||
/datum/action/innate/terrorspider/wrap
|
||||
name = "Wrap"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "cocoon_large1"
|
||||
|
||||
/datum/action/innate/terrorspider/wrap/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/user = owner
|
||||
user.FindWrapTarget()
|
||||
user.DoWrap()
|
||||
|
||||
|
||||
// ---------- WEB
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/Web()
|
||||
visible_message("<span class='notice'>[src] begins to secrete a sticky substance.</span>")
|
||||
if(do_after(src, 40, target = loc))
|
||||
var/obj/effect/spider/terrorweb/T = locate() in get_turf(src)
|
||||
if(T)
|
||||
to_chat(src, "<span class='danger'>There is already a web here.</span>")
|
||||
else
|
||||
new /obj/effect/spider/terrorweb(loc)
|
||||
|
||||
/obj/effect/spider/terrorweb
|
||||
name = "terror web"
|
||||
desc = "it's stringy and sticky"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
anchored = 1 // prevents people dragging it
|
||||
density = 0 // prevents it blocking all movement
|
||||
health = 20 // two welders, or one laser shot (15 for the normal spider webs)
|
||||
icon_state = "stickyweb1"
|
||||
|
||||
|
||||
/obj/effect/spider/terrorweb/New()
|
||||
..()
|
||||
if(prob(50))
|
||||
icon_state = "stickyweb2"
|
||||
|
||||
|
||||
/obj/effect/spider/terrorweb/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
return 1
|
||||
if(isliving(mover))
|
||||
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.
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
if(istype(mover, /obj/item/projectile))
|
||||
return prob(20)
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------- WRAP
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/FindWrapTarget()
|
||||
if(!cocoon_target)
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/L in oview(1,src))
|
||||
if(Adjacent(L))
|
||||
if(L.stat == DEAD)
|
||||
choices += L
|
||||
for(var/obj/O in oview(1,src))
|
||||
if(Adjacent(O) && !O.anchored)
|
||||
if(!istype(O, /obj/effect/spider/terrorweb) && !istype(O, /obj/effect/spider/cocoon))
|
||||
choices += O
|
||||
if(choices.len)
|
||||
cocoon_target = input(src,"What do you wish to cocoon?") in null|choices
|
||||
else
|
||||
to_chat(src, "<span class='danger'>There is nothing nearby you can wrap.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/DoWrap()
|
||||
if(cocoon_target && busy != SPINNING_COCOON)
|
||||
busy = SPINNING_COCOON
|
||||
visible_message("<span class='notice'>[src] begins to secrete a sticky substance around [cocoon_target].</span>")
|
||||
stop_automated_movement = 1
|
||||
walk(src,0)
|
||||
if(do_after(src, 40, target = cocoon_target.loc))
|
||||
if(busy == SPINNING_COCOON)
|
||||
if(cocoon_target && isturf(cocoon_target.loc) && get_dist(src,cocoon_target) <= 1)
|
||||
var/obj/effect/spider/cocoon/C = new(cocoon_target.loc)
|
||||
var/large_cocoon = 0
|
||||
C.pixel_x = cocoon_target.pixel_x
|
||||
C.pixel_y = cocoon_target.pixel_y
|
||||
for(var/obj/O in C.loc)
|
||||
if(istype(O, /obj/item))
|
||||
O.loc = C
|
||||
else if(istype(O, /obj/machinery) || istype(O, /obj/structure))
|
||||
O.loc = C
|
||||
large_cocoon = 1
|
||||
for(var/mob/living/L in C.loc)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
continue
|
||||
if(L.stat != DEAD)
|
||||
continue
|
||||
if(iscarbon(L))
|
||||
regen_points += regen_points_per_kill
|
||||
fed++
|
||||
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")
|
||||
cocoon_target = null
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T2 BLACK TERROR ------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: assassin, poisoner, DoT expert
|
||||
// -------------: AI: attacks to inject its venom, then retreats. Will inject its enemies multiple times then hang back to ensure they die.
|
||||
// -------------: SPECIAL: venom that does more damage the more of it is in you
|
||||
// -------------: TO FIGHT IT: if bitten once, retreat, get charcoal/etc treatment, and come back with a gun.
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/black
|
||||
name = "Black Terror spider"
|
||||
desc = "An ominous-looking spider, black as the darkest night, and with merciless eyes and a blood-red hourglass pattern on its back."
|
||||
spider_role_summary = "Hit-and-run attacker with extremely venomous bite."
|
||||
|
||||
icon_state = "terror_widow"
|
||||
icon_living = "terror_widow"
|
||||
icon_dead = "terror_widow_dead"
|
||||
maxHealth = 120 // same health as hunter spider, aka, pretty weak.. but its bite will kill you!
|
||||
health = 120
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 10
|
||||
move_to_delay = 5
|
||||
stat_attack = 1 // ensures they will target people in crit, too!
|
||||
spider_tier = TS_TIER_2
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/black/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(!poisonable)
|
||||
return ..()
|
||||
if(L.reagents.has_reagent("terror_black_toxin", 50))
|
||||
return ..()
|
||||
var/inject_target = pick("chest", "head")
|
||||
if(L.stunned || L.can_inject(null, 0, inject_target, 0))
|
||||
L.reagents.add_reagent("terror_black_toxin", 15) // inject our special poison
|
||||
visible_message("<span class='danger'>[src] buries its long 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)
|
||||
@@ -0,0 +1,33 @@
|
||||
// Terror Spider, Black, Deadly Venom
|
||||
|
||||
/datum/reagent/terror_black_toxin
|
||||
name = "Black Widow venom"
|
||||
id = "terror_black_toxin"
|
||||
description = "An incredibly toxic venom injected by the Black Widow spider."
|
||||
color = "#CF3600"
|
||||
metabolization_rate = 0.1
|
||||
|
||||
/datum/reagent/terror_black_toxin/on_mob_life(mob/living/M)
|
||||
if(volume < 15)
|
||||
// bitten once, die slowly. Easy to survive a single bite - just go to medbay.
|
||||
// total damage: 2/tick, human health 150 until crit, = 75 ticks, = 150 seconds = 2.5 minutes to get to medbay.
|
||||
M.adjustToxLoss(2) // same damage/tick as tabun cycle 0 to 60
|
||||
else if(volume < 30)
|
||||
// bitten twice, die more quickly, muscle cramps make movement difficult. Call medics immediately.
|
||||
// total damage: 4, human health 150 until crit, = 37.5 ticks, = 75s = 1m15s until death
|
||||
M.adjustToxLoss(4)
|
||||
M.Confused(3)
|
||||
M.EyeBlurry(3)
|
||||
else if(volume < 45)
|
||||
// bitten thrice, die very quickly, severe muscle cramps make movement very difficult. Even calling for help probably won't save you.
|
||||
// total damage: 8, human health 150 until crit, = 18.75 ticks, = 37s until death
|
||||
M.adjustToxLoss(8) // a bit worse than coiine
|
||||
M.Confused(6)
|
||||
M.EyeBlurry(6)
|
||||
else
|
||||
// bitten 4 or more times, whole body goes into shock/death
|
||||
// total damage: 12, human health 150 until crit, = 12.5 ticks, = 25s until death
|
||||
M.adjustToxLoss(12)
|
||||
M.EyeBlurry(6)
|
||||
M.Paralyse(5)
|
||||
..()
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Topic(href, href_list)
|
||||
if(href_list["activate"])
|
||||
var/mob/dead/observer/ghost = usr
|
||||
if(istype(ghost))
|
||||
humanize_spider(ghost)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/attack_ghost(mob/user)
|
||||
humanize_spider(user)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/humanize_spider(mob/user)
|
||||
if(key)//Someone is in it
|
||||
return
|
||||
var/error_on_humanize = ""
|
||||
var/humanize_prompt = "Take direct control of [src]?"
|
||||
humanize_prompt += "Role: [spider_role_summary]"
|
||||
if(user.ckey in ts_ckey_blacklist)
|
||||
error_on_humanize = "You are not able to control any terror spider this round."
|
||||
else if(!ai_playercontrol_allowingeneral)
|
||||
error_on_humanize = "Terror spiders cannot currently be player-controlled."
|
||||
else if(spider_awaymission)
|
||||
error_on_humanize = "Terror spiders that are part of an away mission cannot be controlled by ghosts."
|
||||
else if(!ai_playercontrol_allowtype)
|
||||
error_on_humanize = "This specific type of terror spider is not player-controllable."
|
||||
else if(stat == DEAD)
|
||||
error_on_humanize = "Dead spiders are not player-controllable."
|
||||
if(jobban_isbanned(user, "Syndicate") || jobban_isbanned(user, "alien"))
|
||||
to_chat(user,"You are jobbanned from role of syndicate and/or alien lifeform.")
|
||||
return
|
||||
if(error_on_humanize == "")
|
||||
var/spider_ask = alert(humanize_prompt, "Join as Terror Spider?", "Yes", "No")
|
||||
if(spider_ask == "No" || !src || qdeleted(src))
|
||||
return
|
||||
else
|
||||
to_chat(user, "Cannot inhabit spider: [error_on_humanize]")
|
||||
return
|
||||
if(key)
|
||||
to_chat(user, "<span class='notice'>Someone else already took this spider.</span>")
|
||||
return
|
||||
key = user.key
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
G.show_message("<i>A ghost has taken control of <b>[src]</b>. ([ghost_follow_link(src, ghost=G)]).</i>")
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T1 GRAY TERROR -------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: fast, weak terror spider
|
||||
// -------------: SPECIAL: silences targets
|
||||
// -------------: TO FIGHT IT: shoot it!
|
||||
// -------------: 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."
|
||||
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
|
||||
health = 120
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
ventcrawler = 1
|
||||
move_to_delay = 5 // normal speed
|
||||
stat_attack = 1 // ensures they will target people in crit, too!
|
||||
environment_smash = 1
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(!poisonable)
|
||||
..()
|
||||
return
|
||||
if(L.silent >= 10)
|
||||
L.attack_animal(src)
|
||||
else
|
||||
var/inject_target = pick("chest","head")
|
||||
if(L.stunned || L.can_inject(null,0,inject_target,0))
|
||||
L.Silence(20) // instead of having a venom that only lasts seconds, we just add the silence directly.
|
||||
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)
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T3 PRINCE OF TERROR --------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: boss
|
||||
// -------------: AI: no special ai
|
||||
// -------------: SPECIAL: massive health
|
||||
// -------------: TO FIGHT IT: a squad of at least 4 people with laser rifles.
|
||||
// -------------: SPRITES FROM: Travelling Merchant, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=2766
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince
|
||||
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 = "Boss-level terror spider. Lightning bruiser. Capable of taking on a squad by itself."
|
||||
icon_state = "terror_allblack"
|
||||
icon_living = "terror_allblack"
|
||||
icon_dead = "terror_allblack_dead"
|
||||
maxHealth = 400 // 20 laser shots.
|
||||
health = 400
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 25
|
||||
move_to_delay = 5
|
||||
ventcrawler = 1
|
||||
loot = list(/obj/item/clothing/accessory/medal)
|
||||
spider_tier = TS_TIER_3
|
||||
spider_opens_doors = 2
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/spider_specialattack(mob/living/carbon/human/L)
|
||||
if(prob(15))
|
||||
visible_message("<span class='danger'>[src] rams into [L], knocking them to the floor!</span>")
|
||||
L.Weaken(5)
|
||||
L.Stun(5)
|
||||
else
|
||||
..()
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T1 RED TERROR --------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: generic attack spider
|
||||
// -------------: AI: uses very powerful fangs to wreck people in melee
|
||||
// -------------: SPECIAL: the more you hurt it, the harder it bites you
|
||||
// -------------: TO FIGHT IT: shoot it from range. Kite it.
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/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"
|
||||
|
||||
icon_state = "terror_red"
|
||||
icon_living = "terror_red"
|
||||
icon_dead = "terror_red_dead"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
move_to_delay = 20
|
||||
spider_opens_doors = 2
|
||||
var/enrage = 0
|
||||
var/melee_damage_lower_rage0 = 15
|
||||
var/melee_damage_upper_rage0 = 20
|
||||
var/melee_damage_lower_rage1 = 15
|
||||
var/melee_damage_upper_rage1 = 35
|
||||
var/melee_damage_lower_rage2 = 35
|
||||
var/melee_damage_upper_rage2 = 40
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/red/AttackingTarget()
|
||||
if(enrage == 0)
|
||||
if(health < maxHealth)
|
||||
enrage = 1
|
||||
visible_message("<span class='danger'>[src] growls, flexing its fangs!</span>")
|
||||
melee_damage_lower = melee_damage_lower_rage1
|
||||
melee_damage_upper = melee_damage_upper_rage1
|
||||
else if(enrage == 1)
|
||||
if(health == maxHealth)
|
||||
enrage = 0
|
||||
visible_message("<span class='notice'>[src] retracts its fangs a little.</span>")
|
||||
melee_damage_lower = melee_damage_lower_rage0
|
||||
melee_damage_upper = melee_damage_upper_rage0
|
||||
else if(health < (maxHealth/2))
|
||||
enrage = 2
|
||||
visible_message("<span class='danger'>[src] growls, spreading its fangs wide!</span>")
|
||||
melee_damage_lower = melee_damage_lower_rage2
|
||||
melee_damage_upper = melee_damage_upper_rage2
|
||||
else if(enrage == 2)
|
||||
if(health > (maxHealth/2))
|
||||
enrage = 1
|
||||
visible_message("<span class='notice'>[src] retracts its fangs a little.</span>")
|
||||
melee_damage_lower = melee_damage_lower_rage0
|
||||
melee_damage_upper = melee_damage_upper_rage0
|
||||
..()
|
||||
@@ -0,0 +1,329 @@
|
||||
|
||||
var/global/list/ts_ckey_blacklist = list()
|
||||
var/global/ts_count_dead = 0
|
||||
var/global/ts_count_alive_awaymission = 0
|
||||
var/global/ts_count_alive_station = 0
|
||||
var/global/ts_death_last = 0
|
||||
var/global/ts_death_window = 9000 // 15 minutes
|
||||
var/global/list/ts_spiderlist = list()
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: DEFAULTS ---------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// Because: http://tvtropes.org/pmwiki/pmwiki.php/Main/SpidersAreScary
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider
|
||||
// Name / Description
|
||||
name = "terror spider"
|
||||
desc = "The generic parent of all other terror spider types. If you see this in-game, it is a bug."
|
||||
|
||||
// Icons
|
||||
icon = 'icons/mob/terrorspider.dmi'
|
||||
icon_state = "terror_red"
|
||||
icon_living = "terror_red"
|
||||
icon_dead = "terror_red_dead"
|
||||
|
||||
// Health
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
|
||||
// Melee attacks
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
poison_type = "" // we do not use that silly system.
|
||||
|
||||
// Movement
|
||||
move_to_delay = 6
|
||||
turns_per_move = 5
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
// Ventcrawling
|
||||
ventcrawler = 1 // allows player ventcrawling
|
||||
|
||||
// Speech
|
||||
speak_chance = 0 // quiet but deadly
|
||||
speak_emote = list("hisses")
|
||||
emote_hear = list("hisses")
|
||||
|
||||
// Languages are handled in terror_spider/New()
|
||||
|
||||
// Interaction keywords
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
|
||||
// regeneration settings - overridable by child classes
|
||||
var/regen_points = 0 // number of regen points they have by default
|
||||
var/regen_points_max = 100 // max number of points they can accumulate
|
||||
var/regen_points_per_tick = 1 // gain one regen point per tick
|
||||
var/regen_points_per_kill = 90 // gain extra regen points if you kill something
|
||||
var/regen_points_per_hp = 3 // every X regen points = 1 health point you can regen
|
||||
// desired: 20hp/minute unmolested, 40hp/min on food boost, assuming one tick every 2 seconds
|
||||
// 90/kill means bonus 30hp/kill regenerated over the next 1-2 minutes
|
||||
|
||||
// Vision
|
||||
idle_vision_range = 10
|
||||
aggro_vision_range = 10
|
||||
see_in_dark = 10
|
||||
nightvision = 1
|
||||
vision_type = new /datum/vision_override/nightvision/thermals/ling_augmented_eyesight
|
||||
see_invisible = 5
|
||||
|
||||
// player control by ghosts
|
||||
var/ai_playercontrol_allowingeneral = 1 // if 0, no spiders are player controllable. Default set in code, can be changed by queens.
|
||||
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/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_role_summary = "UNDEFINED"
|
||||
var/spider_placed = 0
|
||||
|
||||
// AI variables designed for use in procs
|
||||
var/atom/cocoon_target // for queen and nurse
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/entry_vent // nearby vent they are going to try to get to, and enter
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/exit_vent // remote vent they intend to come out of
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/nest_vent // home vent, usually used by queens
|
||||
var/fed = 0
|
||||
var/travelling_in_vent = 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, 5 for empress.
|
||||
var/hasdied = 0
|
||||
var/attackstep = 0
|
||||
var/attackcycles = 0
|
||||
var/mylocation = null
|
||||
var/chasecycles = 0
|
||||
var/last_cocoon_object = 0 // leave this, changed by procs.
|
||||
var/killcount = 0
|
||||
|
||||
// Breathing, Pressure & Fire
|
||||
// - No breathing / cannot be suffocated (spiders can hold their breath, look it up)
|
||||
// - No pressure damage either - they have effectively exoskeletons
|
||||
// - HOWEVER they can be burned to death!
|
||||
// - Normal SPACE spiders should probably be immune to SPACE too, but meh, we try to leave the base spiders alone.
|
||||
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)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
heat_damage_per_tick = 5 //amount of damage applied if animal's body temperature is higher than maxbodytemp
|
||||
|
||||
// DEBUG OPTIONS & COMMANDS
|
||||
var/spider_debug = 0
|
||||
|
||||
var/datum/action/innate/terrorspider/web/web_action
|
||||
var/datum/action/innate/terrorspider/wrap/wrap_action
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: SHARED ATTACK CODE -----------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/AttackingTarget()
|
||||
if(istype(target, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
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>")
|
||||
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>")
|
||||
else
|
||||
visible_message("<span class='notice'>[src] harmlessly nuzzles [target].</span>")
|
||||
T.CheckFaction()
|
||||
CheckFaction()
|
||||
else if(istype(target, /obj/effect/spider/cocoon))
|
||||
to_chat(src, "Destroying our own cocoons would not help us.")
|
||||
else if(istype(target, /obj/machinery/door/firedoor))
|
||||
var/obj/machinery/door/firedoor/F = target
|
||||
if(F.density)
|
||||
if(F.blocked)
|
||||
to_chat(src, "The fire door is welded shut.")
|
||||
else
|
||||
visible_message("<span class='danger'>\The [src] pries open the firedoor!</span>")
|
||||
F.open()
|
||||
else
|
||||
to_chat(src, "Closing fire doors does not help.")
|
||||
else if(istype(target, /obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/A = target
|
||||
if(A.density)
|
||||
try_open_airlock(A)
|
||||
else if(isliving(target))
|
||||
var/mob/living/G = target
|
||||
if(issilicon(G))
|
||||
G.attack_animal(src)
|
||||
return
|
||||
else if(G.reagents && (iscarbon(G)))
|
||||
var/can_poison = 1
|
||||
if(ishuman(G))
|
||||
var/mob/living/carbon/human/H = G
|
||||
if(!(H.species.reagent_tag & PROCESS_ORG) || (H.species.flags & NO_POISON))
|
||||
can_poison = 0
|
||||
spider_specialattack(G,can_poison)
|
||||
else
|
||||
G.attack_animal(src)
|
||||
else
|
||||
target.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/spider_specialattack(mob/living/carbon/human/L, var/poisonable)
|
||||
L.attack_animal(src)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: PROC OVERRIDES ---------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/examine(mob/user)
|
||||
..()
|
||||
var/list/msgs = list()
|
||||
if(stat == DEAD)
|
||||
msgs += "<span class='notice'>It appears to be dead.</span>\n"
|
||||
else
|
||||
if(key)
|
||||
msgs += "<span class='warning'>Its eyes regard you with a curious intelligence.</span>"
|
||||
if(health > (maxHealth*0.95))
|
||||
msgs += "<span class='notice'>It is in excellent health.</span>"
|
||||
else if(health > (maxHealth*0.75))
|
||||
msgs += "<span class='notice'>It has a few injuries.</span>"
|
||||
else if(health > (maxHealth*0.55))
|
||||
msgs += "<span class='warning'>It has many injuries.</span>"
|
||||
else if(health > (maxHealth*0.25))
|
||||
msgs += "<span class='warning'>It is barely clinging on to life!</span>"
|
||||
else if(health < maxHealth && regen_points > regen_points_per_kill)
|
||||
msgs += "<span class='notice'>It appears to be regenerating quickly.</span>"
|
||||
if(killcount >= 1)
|
||||
msgs += "<span class='warning'>It has blood dribbling from its mouth.</span>"
|
||||
to_chat(usr,msgs.Join("<BR>"))
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/New()
|
||||
..()
|
||||
ts_spiderlist += src
|
||||
add_language("Spider Hivemind")
|
||||
add_language("Galactic Common")
|
||||
default_language = all_languages["Spider Hivemind"]
|
||||
|
||||
web_action = new()
|
||||
web_action.Grant(src)
|
||||
wrap_action = new()
|
||||
wrap_action.Grant(src)
|
||||
|
||||
name += " ([rand(1, 1000)])"
|
||||
msg_terrorspiders("[src] has grown in [get_area(src)].")
|
||||
if(is_away_level(z))
|
||||
spider_awaymission = 1
|
||||
ts_count_alive_awaymission++
|
||||
else
|
||||
ts_count_alive_station++
|
||||
// after 30 seconds, assuming nobody took control of it yet, offer it to ghosts.
|
||||
addtimer(src, "CheckFaction", 150)
|
||||
addtimer(src, "announcetoghosts", 300)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/announcetoghosts()
|
||||
if(spider_awaymission)
|
||||
return
|
||||
if(stat == DEAD)
|
||||
return
|
||||
if(ckey)
|
||||
var/image/alert_overlay = image('icons/mob/terrorspider.dmi', icon_state)
|
||||
notify_ghosts("[src] has appeared in [get_area(src)]. (already player-controlled)", source = src, alert_overlay = alert_overlay)
|
||||
else if(ai_playercontrol_allowingeneral && ai_playercontrol_allowtype)
|
||||
var/image/alert_overlay = image('icons/mob/terrorspider.dmi', icon_state)
|
||||
notify_ghosts("[src] has appeared in [get_area(src)].", enter_link = "<a href=?src=[UID()];activate=1>(Click to control)</a>", source = src, alert_overlay = alert_overlay, attack_not_jump = 1)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Destroy()
|
||||
ts_spiderlist -= src
|
||||
handle_dying()
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Life()
|
||||
..()
|
||||
if(stat == DEAD)
|
||||
if(prob(2))
|
||||
// 2% chance every cycle to decompose
|
||||
visible_message("<span class='notice'>\The dead body of the [src] decomposes!</span>")
|
||||
gib()
|
||||
else
|
||||
if(regen_points < regen_points_max)
|
||||
regen_points += regen_points_per_tick
|
||||
if((bruteloss > 0) || (fireloss > 0))
|
||||
if(regen_points > regen_points_per_hp)
|
||||
if(bruteloss > 0)
|
||||
adjustBruteLoss(-1)
|
||||
regen_points -= regen_points_per_hp
|
||||
else if(fireloss > 0)
|
||||
adjustFireLoss(-1)
|
||||
regen_points -= regen_points_per_hp
|
||||
if(prob(5))
|
||||
CheckFaction()
|
||||
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/handle_dying()
|
||||
if(!hasdied)
|
||||
hasdied = 1
|
||||
ts_count_dead++
|
||||
ts_death_last = world.time
|
||||
if(spider_awaymission)
|
||||
ts_count_alive_awaymission--
|
||||
else
|
||||
ts_count_alive_station--
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/death(gibbed)
|
||||
if(!gibbed)
|
||||
msg_terrorspiders("[src] has died in [get_area(src)].")
|
||||
handle_dying()
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/spider_special_action()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Bump(atom/A)
|
||||
if(istype(A, /obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/L = A
|
||||
if(L.density)
|
||||
try_open_airlock(L)
|
||||
if(istype(A, /obj/machinery/door/firedoor))
|
||||
var/obj/machinery/door/firedoor/F = A
|
||||
if(F.density && !F.blocked)
|
||||
F.open()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/msg_terrorspiders(msgtext)
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist)
|
||||
if(T.stat != DEAD)
|
||||
to_chat(T, "<span class='terrorspider'>TerrorSense: [msgtext]</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CheckFaction()
|
||||
if(faction.len != 1 || (!("terrorspiders" in faction)) || master_commander != null)
|
||||
visible_message("<span class='danger'>[src] writhes in pain!</span>")
|
||||
log_runtime(EXCEPTION("Terror spider created with incorrect faction list at: [atom_loc_line(src)]"))
|
||||
death()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/try_open_airlock(obj/machinery/door/airlock/D)
|
||||
if(D.operating)
|
||||
return
|
||||
if(!D.density)
|
||||
to_chat(src, "<span class='warning'>Closing doors does not help us.</span>")
|
||||
else if(D.welded)
|
||||
to_chat(src, "<span class='warning'>The door is welded shut.</span>")
|
||||
else if(D.locked)
|
||||
to_chat(src, "<span class='warning'>The door is bolted shut.</span>")
|
||||
else if(D.allowed(src))
|
||||
D.open(1)
|
||||
else if(D.arePowerSystemsOn() && (spider_opens_doors != 2))
|
||||
to_chat(src, "<span class='warning'>The door's motors resist your efforts to force it.</span>")
|
||||
else if(!spider_opens_doors)
|
||||
to_chat(src, "<span class='warning'>Your type of spider is not strong enough to force open doors.</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] pries open the door!</span>")
|
||||
playsound(src.loc, "sparks", 100, 1)
|
||||
D.open(1)
|
||||
@@ -244,8 +244,10 @@
|
||||
if(!job.is_position_available()) return 0
|
||||
if(jobban_isbanned(src,rank)) return 0
|
||||
if(!is_job_whitelisted(src, rank)) return 0
|
||||
if(!job.player_old_enough(src.client)) return 0
|
||||
if(!job.player_old_enough(client)) return 0
|
||||
if(job.admin_only && !(check_rights(R_EVENT, 0))) return 0
|
||||
if(job.available_in_playtime(client))
|
||||
return 0
|
||||
|
||||
if(config.assistantlimit)
|
||||
if(job.title == "Civilian")
|
||||
|
||||
Reference in New Issue
Block a user