diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index c9e410d9e9b..be101742dfa 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -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." diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/__defines.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/__defines.dm new file mode 100644 index 00000000000..fafd30a4ae4 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/__defines.dm @@ -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 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm new file mode 100644 index 00000000000..963bfd472fd --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm @@ -0,0 +1,123 @@ + + +/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("[src] begins to secrete a sticky substance.") + if(do_after(src, 40, target = loc)) + 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, "You get stuck in [src] for a moment.") + 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, "There is nothing nearby you can wrap.") + +/mob/living/simple_animal/hostile/poison/terror_spider/proc/DoWrap() + if(cocoon_target && busy != SPINNING_COCOON) + busy = SPINNING_COCOON + visible_message("[src] begins to secrete a sticky substance around [cocoon_target].") + 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("[src] sticks a proboscis into [L] and sucks a viscous substance out.") + break + if(large_cocoon) + C.icon_state = pick("cocoon_large1","cocoon_large2","cocoon_large3") + cocoon_target = null + busy = 0 + stop_automated_movement = 0 + diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm new file mode 100644 index 00000000000..68d25a29492 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm @@ -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("[src] buries its long fangs deep into the [inject_target] of [target]!") + else + visible_message("[src] bites [target], but cannot inject venom into their [inject_target]!") + L.attack_animal(src) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/chem.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/chem.dm new file mode 100644 index 00000000000..8ad926a8729 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/chem.dm @@ -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) + ..() diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/ghost.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/ghost.dm new file mode 100644 index 00000000000..06703cc2106 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/ghost.dm @@ -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, "Someone else already took this spider.") + return + key = user.key + for(var/mob/dead/observer/G in player_list) + G.show_message("A ghost has taken control of [src]. ([ghost_follow_link(src, ghost=G)]).") + diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm new file mode 100644 index 00000000000..42c16cc7666 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm @@ -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("[src] buries grey fangs deep into the [inject_target] of [target]!") + else + visible_message("[src] bites [target], but cannot inject venom into their [inject_target]!") + L.attack_animal(src) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm new file mode 100644 index 00000000000..669449a6ae3 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm @@ -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("[src] rams into [L], knocking them to the floor!") + L.Weaken(5) + L.Stun(5) + else + ..() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm new file mode 100644 index 00000000000..33480f9509c --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm @@ -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("[src] growls, flexing its fangs!") + 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("[src] retracts its fangs a little.") + melee_damage_lower = melee_damage_lower_rage0 + melee_damage_upper = melee_damage_upper_rage0 + else if(health < (maxHealth/2)) + enrage = 2 + visible_message("[src] growls, spreading its fangs wide!") + 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("[src] retracts its fangs a little.") + melee_damage_lower = melee_damage_lower_rage0 + melee_damage_upper = melee_damage_upper_rage0 + ..() diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm new file mode 100644 index 00000000000..67683d39b39 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm @@ -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("[src] bows in respect for the terrifying presence of [target].") + else if(T.spider_tier == spider_tier) + visible_message("[src] nuzzles [target].") + else if(T.spider_tier < spider_tier && spider_tier >= 4) + visible_message("[src] gives [target] a stern look.") + else + visible_message("[src] harmlessly nuzzles [target].") + 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("\The [src] pries open the firedoor!") + 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 += "It appears to be dead.\n" + else + if(key) + msgs += "Its eyes regard you with a curious intelligence." + if(health > (maxHealth*0.95)) + msgs += "It is in excellent health." + else if(health > (maxHealth*0.75)) + msgs += "It has a few injuries." + else if(health > (maxHealth*0.55)) + msgs += "It has many injuries." + else if(health > (maxHealth*0.25)) + msgs += "It is barely clinging on to life!" + else if(health < maxHealth && regen_points > regen_points_per_kill) + msgs += "It appears to be regenerating quickly." + if(killcount >= 1) + msgs += "It has blood dribbling from its mouth." + to_chat(usr,msgs.Join("
")) + + +/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 = "(Click to control)", 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("\The dead body of the [src] decomposes!") + 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, "TerrorSense: [msgtext]") + +/mob/living/simple_animal/hostile/poison/terror_spider/proc/CheckFaction() + if(faction.len != 1 || (!("terrorspiders" in faction)) || master_commander != null) + visible_message("[src] writhes in pain!") + 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, "Closing doors does not help us.") + else if(D.welded) + to_chat(src, "The door is welded shut.") + else if(D.locked) + to_chat(src, "The door is bolted shut.") + else if(D.allowed(src)) + D.open(1) + else if(D.arePowerSystemsOn() && (spider_opens_doors != 2)) + to_chat(src, "The door's motors resist your efforts to force it.") + else if(!spider_opens_doors) + to_chat(src, "Your type of spider is not strong enough to force open doors.") + else + visible_message("[src] pries open the door!") + playsound(src.loc, "sparks", 100, 1) + D.open(1) \ No newline at end of file diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css index dad1ab1a340..3a4ff4c3770 100644 --- a/goon/browserassets/css/browserOutput.css +++ b/goon/browserassets/css/browserOutput.css @@ -291,6 +291,8 @@ h1.alert, h2.alert {color: #000000;} .alien {color: #543354;} .noticealien {color: #00c000;} .alertalien {color: #00c000; font-weight: bold;} +.terrorspider {color: #320E32;} + .sinister {color: #800080; font-weight: bold; font-style: italic;} /* /vg/ */ .blob {color: #006221; font-weight: bold; font-style: italic;} diff --git a/icons/mob/terrorspider.dmi b/icons/mob/terrorspider.dmi new file mode 100644 index 00000000000..a5d678f3f38 Binary files /dev/null and b/icons/mob/terrorspider.dmi differ diff --git a/paradise.dme b/paradise.dme index e18f8500930..1f9b3430ba4 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1679,6 +1679,15 @@ #include "code\modules\mob\living\simple_animal\hostile\retaliate\pet.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\undead.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\__defines.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\actions.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\black.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\chem.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\ghost.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\gray.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\prince.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\red.dm" +#include "code\modules\mob\living\simple_animal\hostile\terror_spiders\terror_spiders.dm" #include "code\modules\mob\new_player\login.dm" #include "code\modules\mob\new_player\logout.dm" #include "code\modules\mob\new_player\new_player.dm"