diff --git a/code/__defines/_reagents.dm b/code/__defines/_reagents.dm index f88f49a06f..7d0e14230d 100644 --- a/code/__defines/_reagents.dm +++ b/code/__defines/_reagents.dm @@ -1256,6 +1256,8 @@ #define REAGENT_ID_PHORON "phoron" #define REAGENT_SPIDERTOXIN "Spidertoxin" #define REAGENT_ID_SPIDERTOXIN "spidertoxin" +#define REAGENT_WARNINGTOXIN "Warningtoxin" +#define REAGENT_ID_WARNINGTOXIN "warningtoxin" #define REAGENT_LEAD "Lead" #define REAGENT_ID_LEAD "lead" #define REAGENT_PLASTICIDE "Plasticide" diff --git a/code/game/objects/effects/spiders_vr.dm b/code/game/objects/effects/spiders_vr.dm index 65829b95ac..c30b3a7b6e 100644 --- a/code/game/objects/effects/spiders_vr.dm +++ b/code/game/objects/effects/spiders_vr.dm @@ -1,2 +1,2 @@ /obj/effect/spider/spiderling/virgo - grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/hunter) + grow_as = list(/mob/living/simple_mob/animal/giant_spider/event, /mob/living/simple_mob/animal/giant_spider/hunter/event) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/_giant_spider.dm b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/_giant_spider.dm index 9d957b4b79..a86a1dcb09 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/_giant_spider.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/_giant_spider.dm @@ -124,6 +124,10 @@ pain_emote_1p = list("chitter", "click") pain_emote_3p = list("chitters", "clicks") + var/warning_warmup = 2 SECONDS // How long the leap telegraphing is. + var/warning_sound = 'sound/weapons/spiderlunge.ogg' + + /mob/living/simple_mob/animal/giant_spider/Initialize(mapload) . = ..() AddComponent(/datum/component/swarming) @@ -161,5 +165,53 @@ if(poison_per_bite) poison_per_bite *= 1.3 +// A different type of much weaker bite with different effects for event spawned spiders before becoming hostile +/mob/living/simple_mob/animal/giant_spider/proc/warning_bite(mob/living/A) + set waitfor = FALSE + set_AI_busy(TRUE) + + // Telegraph, since getting bitten suddenly feels bad. + do_windup_animation(A, warning_warmup) + addtimer(CALLBACK(src, PROC_REF(warning_leap), A), warning_warmup) // For the telegraphing. + +/mob/living/simple_mob/animal/giant_spider/proc/warning_leap(mob/living/A) + // Do the actual leap. + status_flags |= LEAPING // Lets us pass over everything. + visible_message(span_danger("\The [src] leaps at \the [A]!")) + throw_at(get_step(get_turf(A), get_turf(src)), 4, 1, src) + playsound(src, warning_sound, 75, 1) + + addtimer(CALLBACK(src, PROC_REF(warning_finish), A), 0.5 SECONDS) // For the throw to complete. It won't hold up the AI ticker due to waitfor being false. + +/mob/living/simple_mob/animal/giant_spider/proc/warning_finish(mob/living/A) + if(status_flags & LEAPING) + status_flags &= ~LEAPING // Revert special passage ability. + + . = FALSE + + // Now for the bite. + var/mob/living/victim = null + for(var/mob/living/L in oview(1,src)) // So player-controlled spiders only need to click the tile to stun them. + if(L == src) + continue + + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(H.check_shields(damage = 0, damage_source = src, attacker = src, def_zone = null, attack_text = "the leap")) + continue // We were blocked. + + victim = L + break + + if(victim) + A.reagents.add_reagent(REAGENT_ID_WARNINGTOXIN, poison_per_bite) + victim.visible_message(span_danger("\The [src] has bitten \the [victim]!")) + to_chat(victim, span_critical("\The [src] bites you and retreats!")) + . = TRUE + + step_away(src,victim,3) + + set_AI_busy(FALSE) + /decl/mob_organ_names/spider hit_zones = list("cephalothorax", "abdomen", "left forelegs", "right forelegs", "left hind legs", "right hind legs", "pedipalp", "mouthparts") diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/event_spiders.dm b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/event_spiders.dm new file mode 100644 index 0000000000..12eded7d4f --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/event_spiders.dm @@ -0,0 +1,87 @@ +////// Spiders that are spawned for the security event now have a specific unique AI that only does warning bites on non-hostiles. + +/mob/living/simple_mob/animal/giant_spider/event + ai_holder_type = /datum/ai_holder/simple_mob/melee/event_spider + +/mob/living/simple_mob/animal/giant_spider/hunter/event + ai_holder_type = /datum/ai_holder/simple_mob/melee/event_spider + +/datum/ai_holder/simple_mob/melee/event_spider + hostile = FALSE + retaliate = TRUE + var/next_warning = 0 + +/datum/ai_holder/simple_mob/melee/event_spider/handle_stance_strategical() + ai_log("++++++++++ Slow Process Beginning ++++++++++", AI_LOG_TRACE) + ai_log("handle_stance_strategical() : Called.", AI_LOG_TRACE) + + //We got left around for some reason. Goodbye cruel world. + if(!holder) + qdel(src) + + ai_log("handle_stance_strategical() : LTT=[lose_target_time]", AI_LOG_TRACE) + if(lose_target_time && (lose_target_time + lose_target_timeout < world.time)) // We were tracking an enemy but they are gone. + ai_log("handle_stance_strategical() : Giving up a chase.", AI_LOG_DEBUG) + remove_target() + + if(stance in STANCES_COMBAT) + request_help() // Call our allies. + + switch(stance) + if(STANCE_IDLE) + if(istype(holder,/mob/living/simple_mob/animal/giant_spider) && (world.time > next_warning)) + do_warning_bite() + + if(speak_chance) // In the long loop since otherwise it wont shut up. + handle_idle_speaking() + + if(hostile || vore_hostile) + ai_log("handle_stance_strategical() : STANCE_IDLE, going to find_target().", AI_LOG_TRACE) + find_target() + + if(should_go_home()) + ai_log("handle_stance_tactical() : STANCE_IDLE, going to go home.", AI_LOG_TRACE) + go_home() + + else if(should_follow_leader()) + ai_log("handle_stance_tactical() : STANCE_IDLE, going to follow leader.", AI_LOG_TRACE) + set_stance(STANCE_FOLLOW) + + else if(should_wander()) + ai_log("handle_stance_tactical() : STANCE_IDLE, going to wander randomly.", AI_LOG_TRACE) + handle_wander_movement() + + if(STANCE_APPROACH) + if(target) + ai_log("handle_stance_strategical() : STANCE_APPROACH, going to calculate_path([target]).", AI_LOG_TRACE) + calculate_path(target) + walk_to_target() + if(STANCE_MOVE) + if(hostile && find_target()) // This will switch its stance. + ai_log("handle_stance_strategical() : STANCE_MOVE, found target and was interrupted.", AI_LOG_TRACE) + return + if(STANCE_FOLLOW) + if(hostile && find_target()) // This will switch its stance. + ai_log("handle_stance_strategical() : STANCE_FOLLOW, found target and was interrupted.", AI_LOG_TRACE) + return + else if(leader) + ai_log("handle_stance_strategical() : STANCE_FOLLOW, going to calculate_path([leader]).", AI_LOG_TRACE) + calculate_path(leader) + walk_to_leader() + + ai_log("handle_stance_strategical() : Exiting.", AI_LOG_TRACE) + ai_log("++++++++++ Slow Process Ending ++++++++++", AI_LOG_TRACE) + +/datum/ai_holder/simple_mob/melee/event_spider/proc/do_warning_bite() + if(!istype(holder,/mob/living/simple_mob/animal/giant_spider)) + return + var/list/intruders = list() + var/mob/living/intruder + var/mob/living/simple_mob/animal/giant_spider/S = holder + for(var/mob/living/L in oview(S,3)) + if(can_attack(L)) + intruders |= L + if(intruders.len) + intruder = pick(intruders) + next_warning = world.time + 30 SECONDS + S.warning_bite(intruder) diff --git a/code/modules/reagents/reagents/toxins.dm b/code/modules/reagents/reagents/toxins.dm index d931393d04..5b8e7f890b 100644 --- a/code/modules/reagents/reagents/toxins.dm +++ b/code/modules/reagents/reagents/toxins.dm @@ -139,6 +139,21 @@ color = "#2CE893" strength = 5 +/datum/reagent/toxin/warningtoxin + name = REAGENT_WARNINGTOXIN + id = REAGENT_ID_WARNINGTOXIN + description = "A weaker toxin produced by giant spiders applied only in warning bites, known to slow a people down a lot." + color = "#2CE893" + strength = 1 + +/datum/reagent/toxin/warningtoxin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + var/poison_strength = strength * M.species.chem_strength_tox + if(strength && alien != IS_DIONA) + M.adjustToxLoss(poison_strength * removed) + M.druggy = max(M.druggy, 10) + M.make_jittery(5) + M.add_chemical_effect(CE_SLOWDOWN, 5) + /datum/reagent/toxin/phoron name = REAGENT_PHORON id = REAGENT_ID_PHORON diff --git a/vorestation.dme b/vorestation.dme index d0007806d0..281c09724d 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -3540,6 +3540,7 @@ #include "code\modules\mob\living\simple_mob\subtypes\animal\giant_spider\webslinger.dm" #include "code\modules\mob\living\simple_mob\subtypes\animal\hyena\hyena.dm" #include "code\modules\mob\living\simple_mob\subtypes\animal\passive\armadillo_ch.dm" +#include "code\modules\mob\living\simple_mob\subtypes\animal\giant_spider\event_spiders.dm" #include "code\modules\mob\living\simple_mob\subtypes\animal\passive\cockroach.dm" #include "code\modules\mob\living\simple_mob\subtypes\animal\passive\crab.dm" #include "code\modules\mob\living\simple_mob\subtypes\animal\passive\fish.dm"