diff --git a/ModularTegustation/Teguicons/96x48.dmi b/ModularTegustation/Teguicons/96x48.dmi index dc0daa343c83..c104292bfef1 100644 Binary files a/ModularTegustation/Teguicons/96x48.dmi and b/ModularTegustation/Teguicons/96x48.dmi differ diff --git a/ModularTegustation/Teguicons/tegumobs.dmi b/ModularTegustation/Teguicons/tegumobs.dmi index af8d95b24e0b..ecdba5c1980a 100644 Binary files a/ModularTegustation/Teguicons/tegumobs.dmi and b/ModularTegustation/Teguicons/tegumobs.dmi differ diff --git a/ModularTegustation/tegu_items/debug_items.dm b/ModularTegustation/tegu_items/debug_items.dm index ff3276c3f2a3..f26562c64dda 100644 --- a/ModularTegustation/tegu_items/debug_items.dm +++ b/ModularTegustation/tegu_items/debug_items.dm @@ -374,3 +374,26 @@ say("Restarting...") SLEEP_CHECK_DEATH(10) DeepsCheckStart() + +//breach tester +/obj/item/breachtester//for testing many abnormalities very quickly + name = "Breach tester" + desc = "For testing use only, DO NOT DISTRIBUTE! Breach types can be checked under _DEFINES/abnormalities.dm" + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "nanoimplant" + var/breach_type = BREACH_NORMAL + var/list/breach_list = list( + BREACH_NORMAL, BREACH_PINK, BREACH_MINING, + ) + +/obj/item/breachtester/attack_self(mob/user) + breach_type = input(user, "Which breach will you test?") as null|anything in breach_list + +/obj/item/breachtester/attack(mob/living/simple_animal/hostile/abnormality/target, mob/living/carbon/human/user) + if(!isabnormalitymob(target)) + to_chat(user, span_warning("\"[target]\" isn't an Abnormality.")) + return + target.BreachEffect(user, breach_type) + to_chat(user, span_nicegreen("You triggered a [breach_type] breach!")) + + diff --git a/code/__DEFINES/abnormalities.dm b/code/__DEFINES/abnormalities.dm index 71b708ef510b..5a254c6f0d93 100644 --- a/code/__DEFINES/abnormalities.dm +++ b/code/__DEFINES/abnormalities.dm @@ -14,6 +14,7 @@ // Breach types #define BREACH_NORMAL 0 #define BREACH_PINK 1 +#define BREACH_MINING 2 // List #define THREAT_TO_NAME list(\ diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/army_in_black.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/army_in_black.dm index f134732caea4..d3834f71db58 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/army_in_black.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/army_in_black.dm @@ -150,9 +150,14 @@ GLOBAL_LIST_EMPTY(army) //*--Combat Mechanics--* /mob/living/simple_animal/hostile/abnormality/army/BreachEffect(mob/living/carbon/human/user, breach_type) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ABNORMALITY_BREACH, src) - FearEffect() - Blackify() - SpawnAdds()//set its alpha to 0 and make it non-dense + if(breach_type == BREACH_MINING) + for(var/i = 1 to 3) + var/mob/living/simple_animal/hostile/army_enemy/E = new(get_turf(src)) + RegisterSignal(E, COMSIG_PARENT_QDELETING, PROC_REF(ArmyDeath)) + else + FearEffect() + Blackify() + SpawnAdds()//set its alpha to 0 and make it non-dense for(var/mob/living/L in protected_targets) L.remove_status_effect(STATUS_EFFECT_PROTECTION) density = FALSE diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/blue_star.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/blue_star.dm index ec9e78aa5d29..3d89216cc30d 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/blue_star.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/blue_star.dm @@ -138,6 +138,7 @@ . = ..() var/turf/T = pick(GLOB.department_centers) soundloop.start() - forceMove(T) + if(breach_type != BREACH_MINING) + forceMove(T) BluePulse() return diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/distortedform.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/distortedform.dm index 5d5d8e8b2053..d5ec87b66aae 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/distortedform.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/distortedform.dm @@ -300,6 +300,9 @@ //Breach /mob/living/simple_animal/hostile/abnormality/distortedform/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + qdel(src) + return . = ..() if(breached) return diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/last_shot.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/last_shot.dm index 9a6efb684e8f..c4c330f0c483 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/last_shot.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/last_shot.dm @@ -61,7 +61,9 @@ GLOBAL_LIST_EMPTY(meat_list) /mob/living/simple_animal/hostile/abnormality/last_shot/Move() return FALSE -/mob/living/simple_animal/hostile/abnormality/last_shot/BreachEffect() +/mob/living/simple_animal/hostile/abnormality/last_shot/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + return ..() var/turf/T = pick(GLOB.department_centers) forceMove(T) ..() diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/nobody_is.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/nobody_is.dm index 8e967b5c9a37..12a16847f9ef 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/nobody_is.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/nobody_is.dm @@ -231,7 +231,7 @@ datum_reference.qliphoth_change(-1) /mob/living/simple_animal/hostile/abnormality/nobody_is/BreachEffect(mob/living/carbon/human/user, breach_type) - if(!(status_flags & GODMODE)) // Already breaching + if(current_stage > 1) return if(reflect_timer) deltimer(reflect_timer) @@ -240,6 +240,8 @@ return CheckMirrorIcon() //Clear overlays next_stage() + if(breach_type == BREACH_MINING) + return // Teleport us somewhere where nobody will see us at first var/list/priority_list = list() for(var/turf/T in GLOB.xeno_spawn) diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/seasons.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/seasons.dm index 58e3f6ce6d54..171f5fb9fc99 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/seasons.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/seasons.dm @@ -322,8 +322,9 @@ ZeroQliphoth() return . = ..() - var/turf/T = pick(GLOB.department_centers) - forceMove(T) + if(breach_type != BREACH_MINING) + var/turf/T = pick(GLOB.department_centers) + forceMove(T) //Weather controlling /mob/living/simple_animal/hostile/abnormality/seasons/proc/CheckWeather() diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/silent_orchestra.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/silent_orchestra.dm index f59c6b39bbe2..cb096b1608f4 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/silent_orchestra.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/silent_orchestra.dm @@ -154,8 +154,9 @@ /mob/living/simple_animal/hostile/abnormality/silentorchestra/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() - var/turf/T = pick(GLOB.department_centers) - forceMove(T) + if(breach_type != BREACH_MINING) + var/turf/T = pick(GLOB.department_centers) + forceMove(T) DamagePulse() return diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/space_lady.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/space_lady.dm index 7bf0e34b9883..b1fd4da49eef 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/space_lady.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/space_lady.dm @@ -261,7 +261,8 @@ /mob/living/simple_animal/hostile/abnormality/space_lady/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() - Teleport() + if(breach_type != BREACH_MINING) + Teleport() //Bullets diff --git a/code/modules/mob/living/simple_animal/abnormality/aleph/white_night.dm b/code/modules/mob/living/simple_animal/abnormality/aleph/white_night.dm index eb7ece82cc32..48aadcbbf7dd 100644 --- a/code/modules/mob/living/simple_animal/abnormality/aleph/white_night.dm +++ b/code/modules/mob/living/simple_animal/abnormality/aleph/white_night.dm @@ -221,6 +221,9 @@ GLOBAL_LIST_EMPTY(apostles) return /mob/living/simple_animal/hostile/abnormality/white_night/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + qdel(src) + return holy_revival_cooldown = world.time + holy_revival_cooldown_base . = ..() for(var/mob/M in GLOB.player_list) diff --git a/code/modules/mob/living/simple_animal/abnormality/he/doomsday_calendar.dm b/code/modules/mob/living/simple_animal/abnormality/he/doomsday_calendar.dm index acc1dcd9d956..fbdb5c13350a 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/doomsday_calendar.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/doomsday_calendar.dm @@ -188,9 +188,10 @@ //***Breach Mechanics***// /mob/living/simple_animal/hostile/abnormality/doomsday_calendar/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() - var/turf/T = pick(GLOB.department_centers) + if(breach_type != BREACH_MINING) + var/turf/T = pick(GLOB.department_centers) + forceMove(T) icon_state = "doomsday_active" - forceMove(T) AnnounceBreach() SpawnAdds() diff --git a/code/modules/mob/living/simple_animal/abnormality/he/highway_devotee.dm b/code/modules/mob/living/simple_animal/abnormality/he/highway_devotee.dm index f10a2c18fd2e..d6905489f1c7 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/highway_devotee.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/highway_devotee.dm @@ -90,8 +90,9 @@ /mob/living/simple_animal/hostile/abnormality/highway_devotee/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() - var/turf/T = pick(GLOB.xeno_spawn) - forceMove(T) + if(breach_type != BREACH_MINING) + var/turf/T = pick(GLOB.xeno_spawn) + forceMove(T) addtimer(CALLBACK(src, PROC_REF(KillYourself)), 3 MINUTES) dir = pick(list(NORTH, SOUTH, WEST, EAST)) for(var/turf/open/U in range(2, src)) diff --git a/code/modules/mob/living/simple_animal/abnormality/he/jangsan.dm b/code/modules/mob/living/simple_animal/abnormality/he/jangsan.dm index ca564b2af7ac..d174dd476145 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/jangsan.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/jangsan.dm @@ -193,7 +193,8 @@ . = ..() if(!datum_reference.abno_radio) AbnoRadio() - addtimer(CALLBACK(src, PROC_REF(TryTeleport)), 5) + if(breach_type != BREACH_MINING) + addtimer(CALLBACK(src, PROC_REF(TryTeleport)), 5) /mob/living/simple_animal/hostile/abnormality/jangsan/proc/TryTeleport() //stolen from knight of despair dir = 2 diff --git a/code/modules/mob/living/simple_animal/abnormality/he/laetitia.dm b/code/modules/mob/living/simple_animal/abnormality/he/laetitia.dm index 5cde37ce7594..80860ea1aa6c 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/laetitia.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/laetitia.dm @@ -42,6 +42,10 @@ You look lonely too, I hope my present will make you laugh as well!" attack_action_types = list(/datum/action/cooldown/laetitia_gift, /datum/action/cooldown/laetitia_summon) + var/breaching = FALSE + var/summon_cooldown + var/summon_cooldown_time = 60 SECONDS + var/summon_count = 0 /datum/action/cooldown/laetitia_summon name = "Call for Friends" @@ -49,7 +53,7 @@ button_icon_state = "prank_gift" check_flags = AB_CHECK_CONSCIOUS transparent_when_unavailable = TRUE - cooldown_time = 40 SECONDS + cooldown_time = 60 SECONDS var/delete_timer var/delete_cooldown = 30 SECONDS var/mob/living/simple_animal/hostile/gift/G1 @@ -139,6 +143,12 @@ qdel(src) opening = FALSE +/mob/living/simple_animal/hostile/abnormality/laetitia/Life() + . = ..() + if(!breaching) + return + if((summon_cooldown < world.time) && !(status_flags & GODMODE)) + SummonAdds() /mob/living/simple_animal/hostile/abnormality/laetitia/NeutralEffect(mob/living/carbon/human/user, work_type, pe) . = ..() @@ -168,6 +178,19 @@ P.TriggerPrank() return +/mob/living/simple_animal/hostile/abnormality/laetitia/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + breaching = TRUE + return ..() + +/mob/living/simple_animal/hostile/abnormality/laetitia/proc/SummonAdds()//Mining breach summon + summon_cooldown = world.time + summon_cooldown_time + if(summon_count > 9)//this list is not subtracted when minions are killed. Limited to 10 per breach + return + var/turf/target_turf = get_turf(src) + new /mob/living/simple_animal/hostile/gift(target_turf) + summon_count += 1 + //Her friend /mob/living/simple_animal/hostile/gift name = "Little Witch's Friend" diff --git a/code/modules/mob/living/simple_animal/abnormality/he/porccubus.dm b/code/modules/mob/living/simple_animal/abnormality/he/porccubus.dm index cff432a39da1..61c0d49e426b 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/porccubus.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/porccubus.dm @@ -59,6 +59,7 @@ var/teleport_cooldown_time = 5 MINUTES var/teleport_cooldown var/damage_taken = FALSE + var/noteleport = FALSE //PLAYABLE ATTACKS attack_action_types = list(/datum/action/innate/abnormality_attack/toggle/porccubus_dash_toggle) @@ -132,11 +133,13 @@ //it does have a dash that makes it able to jump around, but it can't properly "roam" per say. /mob/living/simple_animal/hostile/abnormality/porccubus/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() + if(breach_type == BREACH_MINING) + noteleport = TRUE playsound(src, 'sound/abnormalities/porccubus/head_explode_laugh.ogg', 50, FALSE, 4) icon_living = "porrcubus" icon_state = icon_living ranged_cooldown = world.time + ranged_cooldown_time - if(!IsCombatMap()) + if(!IsCombatMap() && (breach_type != BREACH_MINING)) var/turf/T = pick(GLOB.xeno_spawn) forceMove(T) teleport_cooldown = world.time + teleport_cooldown_time @@ -148,7 +151,7 @@ . = ..() if(status_flags & GODMODE) return - if(IsCombatMap()) + if(IsCombatMap() || noteleport) return if(teleport_cooldown < world.time) //if porccubus hasn't taken damage for 5 minutes we make him move so he doesn't stay stuck in whatever cell he got thrown in. teleport_cooldown = world.time + teleport_cooldown_time diff --git a/code/modules/mob/living/simple_animal/abnormality/he/red_shoes.dm b/code/modules/mob/living/simple_animal/abnormality/he/red_shoes.dm index 75cb8f4e67e1..6bdccdbf3e12 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/red_shoes.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/red_shoes.dm @@ -201,8 +201,6 @@ //BreachEffect and combat /mob/living/simple_animal/hostile/abnormality/red_shoes/BreachEffect(mob/living/carbon/human/user, breach_type) - if(!(status_flags & GODMODE)) - return soundloop.stop() for(var/mob/living/carbon/human/H in GLOB.mob_living_list)//stops possessing people, prevents runtimes. Panicked players are ghosted so use mob_living_list UnPossess(H) diff --git a/code/modules/mob/living/simple_animal/abnormality/he/singing_machine.dm b/code/modules/mob/living/simple_animal/abnormality/he/singing_machine.dm index 613a8844b531..3ece41992ef4 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/singing_machine.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/singing_machine.dm @@ -10,8 +10,9 @@ Finally, an abnormality that DOESN'T have to do any fancy movement shit. It's a icon_state = "singingmachine_closed_clean" icon_living = "singingmachine_closed_clean" portrait = "singing_machine" - maxHealth = 200 - health = 200 + maxHealth = 3000 + health = 3000 + damage_coeff = list(RED_DAMAGE = 0.7, WHITE_DAMAGE = 0.7, BLACK_DAMAGE = 1.5, PALE_DAMAGE = 1) threat_level = HE_LEVEL start_qliphoth = 2 work_chances = list( @@ -71,6 +72,12 @@ Finally, an abnormality that DOESN'T have to do any fancy movement shit. It's a to_chat(H, span_warning("That terrible grinding noise...")) return ..() +/mob/living/simple_animal/hostile/abnormality/singing_machine/Move() + return FALSE + +/mob/living/simple_animal/hostile/abnormality/singing_machine/CanAttack(atom/the_target) + return FALSE + /mob/living/simple_animal/hostile/abnormality/singing_machine/AttemptWork(mob/living/carbon/human/user, work_type) if(work_type == ABNORMALITY_WORK_INSTINCT) if(datum_reference.qliphoth_meter > 0) // Sets bonus damage on instinct work. @@ -148,6 +155,10 @@ Finally, an abnormality that DOESN'T have to do any fancy movement shit. It's a playStatus = 1 return +/mob/living/simple_animal/hostile/abnormality/singing_machine/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + ZeroQliphoth() + /mob/living/simple_animal/hostile/abnormality/singing_machine/proc/removeAddict(mob/living/carbon/human/addict) if(addict) musicalAddicts -= addict // Your five minutes are over, you're free. diff --git a/code/modules/mob/living/simple_animal/abnormality/he/snow_queen.dm b/code/modules/mob/living/simple_animal/abnormality/he/snow_queen.dm index 8e369030d8a1..5e178edc8ede 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/snow_queen.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/snow_queen.dm @@ -163,7 +163,7 @@ faction += "pink_midnight" //Call root code but with normal breach . = ..(null, BREACH_NORMAL) - if(!IsCombatMap()) + if(!IsCombatMap() && breach_type != BREACH_MINING) var/turf/T = pick(GLOB.department_centers) forceMove(T) update_icon() diff --git a/code/modules/mob/living/simple_animal/abnormality/he/you_strong.dm b/code/modules/mob/living/simple_animal/abnormality/he/you_strong.dm index fc03e9af235c..8bae5b5800bf 100644 --- a/code/modules/mob/living/simple_animal/abnormality/he/you_strong.dm +++ b/code/modules/mob/living/simple_animal/abnormality/he/you_strong.dm @@ -5,8 +5,9 @@ icon_state = "you_strong_pause" icon_living = "you_strong_pause" portrait = "grown_strong" - maxHealth = 200 - health = 200 + maxHealth = 2000 + health = 2000 + damage_coeff = list(RED_DAMAGE = 1, WHITE_DAMAGE = 1.5, BLACK_DAMAGE = 1.5, PALE_DAMAGE = 0) threat_level = HE_LEVEL start_qliphoth = 3 work_chances = list( @@ -61,6 +62,10 @@ var/datum/looping_sound/server/soundloop var/operating = FALSE + var/breaching = FALSE + var/summon_cooldown + var/summon_cooldown_time = 120 SECONDS + var/summon_count = 0 /mob/living/simple_animal/hostile/abnormality/you_strong/Initialize(mapload) . = ..() @@ -68,6 +73,20 @@ soundloop.volume = 75 soundloop.extra_range = 0 +/mob/living/simple_animal/hostile/abnormality/you_strong/Move() + return FALSE + +/mob/living/simple_animal/hostile/abnormality/you_strong/CanAttack(atom/the_target) + return FALSE + +/mob/living/simple_animal/hostile/abnormality/you_strong/Life() + . = ..() + if(!breaching) + return + if((summon_cooldown < world.time) && !(status_flags & GODMODE)) + SummonAdds() + return + /mob/living/simple_animal/hostile/abnormality/you_strong/WorkComplete(mob/living/carbon/human/user, work_type, pe, work_time, canceled) . = ..() if(work_type == ABNORMALITY_WORK_REPRESSION) @@ -123,14 +142,28 @@ icon_state = "you_strong_work" SLEEP_CHECK_DEATH(30 SECONDS) soundloop.stop() - src.datum_reference.qliphoth_change(3) + if(datum_reference) + src.datum_reference.qliphoth_change(3) icon_state = "you_strong_make" SLEEP_CHECK_DEATH(6) for(var/i = 1 to 3) new /mob/living/simple_animal/hostile/grown_strong(get_step(src, EAST)) + if(breaching) + summon_count += 1 SLEEP_CHECK_DEATH(6) icon_state = "you_strong_pause" +/mob/living/simple_animal/hostile/abnormality/you_strong/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + breaching = TRUE + return ..() + +/mob/living/simple_animal/hostile/abnormality/you_strong/proc/SummonAdds() + summon_cooldown = world.time + summon_cooldown_time + if(summon_count > 9)//this list is not subtracted when minions are killed. Limited to 10 per breach + return + ZeroQliphoth() + /mob/living/simple_animal/hostile/abnormality/you_strong/attacked_by(obj/item/I, mob/living/user) if(!(I.type in taken_parts)) return ..() diff --git a/code/modules/mob/living/simple_animal/abnormality/teth/blood_bath.dm b/code/modules/mob/living/simple_animal/abnormality/teth/blood_bath.dm index eb0badeb1c16..6371d6695dd5 100644 --- a/code/modules/mob/living/simple_animal/abnormality/teth/blood_bath.dm +++ b/code/modules/mob/living/simple_animal/abnormality/teth/blood_bath.dm @@ -4,8 +4,17 @@ icon = 'ModularTegustation/Teguicons/48x64.dmi' icon_state = "bloodbath" portrait = "blood_bath" - maxHealth = 400 - health = 400 + maxHealth = 1000 + health = 1000 + move_to_delay = 3 + attack_sound = 'sound/abnormalities/ichthys/slap.ogg' + attack_verb_continuous = "mauls" + attack_verb_simple = "maul" + melee_damage_lower = 6 + melee_damage_upper = 12 + melee_damage_type = WHITE_DAMAGE + damage_coeff = list(RED_DAMAGE = 1.6, WHITE_DAMAGE = 1, BLACK_DAMAGE = 1.4, PALE_DAMAGE = 1.5) + ranged = TRUE threat_level = TETH_LEVEL work_chances = list( ABNORMALITY_WORK_INSTINCT = list(55, 55, 50, 50, 50), @@ -38,6 +47,8 @@ observation_fail_message = "You looked away.
This is not the first time you ignore them.
It will be the same afterwards." var/hands = 0 + var/can_act = TRUE + var/special_attack_cooldown /mob/living/simple_animal/hostile/abnormality/bloodbath/PostWorkEffect(mob/living/carbon/human/user, work_type, pe, work_time) // any work performed with level 1 Fort and Temperance makes you panic and die @@ -67,3 +78,50 @@ datum_reference.max_boxes = max_boxes icon_state = "bloodbath" return + +/mob/living/simple_animal/hostile/abnormality/bloodbath/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type != BREACH_MINING && breach_type != BREACH_PINK) + return + if(breach_type == BREACH_PINK) + maxHealth = 4000 + melee_damage_lower = 20 + melee_damage_upper = 40 + ..() + icon_state = "bloodbath_DF" + pixel_x = -8 + base_pixel_x = -8 + update_icon() + +/mob/living/simple_animal/hostile/abnormality/bloodbath/OpenFire() + if(!can_act) + return + if(special_attack_cooldown > world.time) + return + BloodBathSlam() + +/mob/living/simple_animal/hostile/abnormality/bloodbath/proc/BloodBathSlam()//weaker version of the DF form + if(!can_act) + return + special_attack_cooldown = world.time + 5 SECONDS + can_act = FALSE + for(var/turf/L in view(3, src)) + new /obj/effect/temp_visual/cult/sparks(L) + playsound(get_turf(src), 'sound/abnormalities/ichthys/jump.ogg', 100, FALSE, 6) + icon_state = "bloodbath_slamprepare" + SLEEP_CHECK_DEATH(12) + for(var/turf/T in view(3, src)) + var/obj/effect/temp_visual/small_smoke/halfsecond/FX = new(T) + FX.color = "#b52e19" + for(var/mob/living/carbon/human/H in HurtInTurf(T, list(), 50, WHITE_DAMAGE, null, null, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE)) + if(H.sanity_lost) + H.gib() + playsound(get_turf(src), 'sound/abnormalities/bloodbath/Bloodbath_EyeOn.ogg', 125, FALSE, 6) + icon_state = "bloodbath_slam" + SLEEP_CHECK_DEATH(3) + icon_state = "bloodbath_DF" + can_act = TRUE + +/mob/living/simple_animal/hostile/abnormality/bloodbath/Move() + if(!can_act) + return FALSE + ..() diff --git a/code/modules/mob/living/simple_animal/abnormality/teth/book.dm b/code/modules/mob/living/simple_animal/abnormality/teth/book.dm index 580e9768ee69..51bff4da9187 100644 --- a/code/modules/mob/living/simple_animal/abnormality/teth/book.dm +++ b/code/modules/mob/living/simple_animal/abnormality/teth/book.dm @@ -41,6 +41,9 @@ ) var/meltdown_cooldown //no spamming the meltdown effect var/meltdown_cooldown_time = 30 SECONDS + var/breaching = FALSE + var/summon_count = 0 + /mob/living/simple_animal/hostile/abnormality/book/PostWorkEffect(mob/living/carbon/human/user, work_type, pe, work_time) if(work_type == ABNORMALITY_WORK_REPRESSION) @@ -103,6 +106,23 @@ if((initial(abno.threat_level)) <= TETH_LEVEL) nasties += abno +/mob/living/simple_animal/hostile/abnormality/book/Life() + . = ..() + if(!breaching) + return + if(summon_count > 15) + qdel(src) + return + if((meltdown_cooldown < world.time) && !(status_flags & GODMODE)) + MeltdownEffect() + meltdown_cooldown = world.time + meltdown_cooldown_time + +/mob/living/simple_animal/hostile/abnormality/book/Move() + return FALSE + +/mob/living/simple_animal/hostile/abnormality/book/CanAttack(atom/the_target) + return FALSE + /mob/living/simple_animal/hostile/abnormality/book/proc/RipPages() var/mob/living/simple_animal/newspawn if(wordcount >= 3) @@ -138,7 +158,7 @@ /mob/living/simple_animal/hostile/abnormality/book/ZeroQliphoth(mob/living/carbon/human/user) datum_reference.qliphoth_change(start_qliphoth) //no need for qliphoth to be stuck at 0 - if(meltdown_cooldown > world.time) + if(meltdown_cooldown < world.time) return meltdown_cooldown = world.time + meltdown_cooldown_time MeltdownEffect() @@ -151,3 +171,9 @@ sleep(0.5 SECONDS) newspawn = pick(nasties) SpawnMob(newspawn) + if(breaching) + summon_count += 1 + +/mob/living/simple_animal/hostile/abnormality/book/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + breaching = TRUE diff --git a/code/modules/mob/living/simple_animal/abnormality/teth/faelantern.dm b/code/modules/mob/living/simple_animal/abnormality/teth/faelantern.dm index 71d826514fe1..b2f8702d595a 100644 --- a/code/modules/mob/living/simple_animal/abnormality/teth/faelantern.dm +++ b/code/modules/mob/living/simple_animal/abnormality/teth/faelantern.dm @@ -108,6 +108,12 @@ /mob/living/simple_animal/hostile/abnormality/faelantern/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() + if(breach_type == BREACH_MINING) + fairy_enabled = TRUE + fairy_health = health + can_act = TRUE + icon_state = icon_living + return INVOKE_ASYNC(src, PROC_REF(BreachDig)) return diff --git a/code/modules/mob/living/simple_animal/abnormality/teth/falada.dm b/code/modules/mob/living/simple_animal/abnormality/teth/falada.dm index 90c185e75414..9e5a4b7e514d 100644 --- a/code/modules/mob/living/simple_animal/abnormality/teth/falada.dm +++ b/code/modules/mob/living/simple_animal/abnormality/teth/falada.dm @@ -69,6 +69,11 @@ datum_reference.qliphoth_change(1) return +/mob/living/simple_animal/hostile/abnormality/falada/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + pissed() + qdel(src) + /mob/living/simple_animal/hostile/abnormality/falada/WorkChance(mob/living/carbon/human/user, chance) if(happy) chance+=30 diff --git a/code/modules/mob/living/simple_animal/abnormality/teth/meat_lantern.dm b/code/modules/mob/living/simple_animal/abnormality/teth/meat_lantern.dm index 1b5dbb190dc8..c338f2c9d611 100644 --- a/code/modules/mob/living/simple_animal/abnormality/teth/meat_lantern.dm +++ b/code/modules/mob/living/simple_animal/abnormality/teth/meat_lantern.dm @@ -146,6 +146,9 @@ return /mob/living/simple_animal/hostile/abnormality/meat_lantern/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING)//as funny as it sounds, this abnormality would be unreachable + qdel(src) + return . = ..() update_icon() density = FALSE diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/alriune.dm b/code/modules/mob/living/simple_animal/abnormality/waw/alriune.dm index 96ccecb95f18..cca14b4beade 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/alriune.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/alriune.dm @@ -160,7 +160,8 @@ /mob/living/simple_animal/hostile/abnormality/alriune/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() petals_next = world.time + petals_next_time + 30 - TeleportAway() + if(breach_type != BREACH_MINING)//in ER you get a few seconds to smack it down + TeleportAway() icon_state = "alriune_active" return diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/black_swan.dm b/code/modules/mob/living/simple_animal/abnormality/waw/black_swan.dm index aeb3656a878c..d0fd2b5cab59 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/black_swan.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/black_swan.dm @@ -157,7 +157,8 @@ if(!LAZYLEN(teleport_potential)) return FALSE var/turf/teleport_target = pick(teleport_potential) - forceMove(teleport_target) + if(breach_type != BREACH_MINING) + forceMove(teleport_target) playsound(get_turf(src), 'sound/abnormalities/blackswan/sis_transformation.ogg', 30, 0, 4) return diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/contract.dm b/code/modules/mob/living/simple_animal/abnormality/waw/contract.dm index 37200420daf4..12998c0d431e 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/contract.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/contract.dm @@ -52,6 +52,10 @@ var/list/just_havers = list() var/list/spawnables = list() var/total_per_contract = 4 + var/breaching + var/summon_count = 0 + var/summon_cooldown + var/summon_cooldown_time = 60 SECONDS /mob/living/simple_animal/hostile/abnormality/contract/Initialize() . = ..() @@ -65,6 +69,16 @@ if((initial(abno.threat_level)) <= WAW_LEVEL) spawnables += abno +/mob/living/simple_animal/hostile/abnormality/contract/Life() + . = ..() + if(!breaching) + return + if(summon_count > 4) + return + if((summon_cooldown < world.time) && !(status_flags & GODMODE)) + Summon() + summon_cooldown = world.time + summon_cooldown_time + /mob/living/simple_animal/hostile/abnormality/contract/WorkChance(mob/living/carbon/human/user, chance, work_type) . = chance if(!(user in total_havers)) @@ -147,8 +161,17 @@ //Meltdown /mob/living/simple_animal/hostile/abnormality/contract/ZeroQliphoth(mob/living/carbon/human/user) + Summon() + datum_reference.qliphoth_change(2) + +/mob/living/simple_animal/hostile/abnormality/contract/BreachEffect(mob/living/carbon/human/user, breach_type)//causes a runtime + if(breach_type == BREACH_MINING) + breaching = TRUE + ..() + +/mob/living/simple_animal/hostile/abnormality/contract/proc/Summon(mob/living/carbon/human/user) // Don't need to lazylen this. If this is empty there is a SERIOUS PROBLEM. - var/mob/living/simple_animal/hostile/abnormality/spawning = pick(spawnables) + var/mob/living/simple_animal/hostile/abnormality/spawning = pick(spawnables) var/mob/living/simple_animal/hostile/abnormality/spawned = new spawning(get_turf(src)) spawned.BreachEffect() spawned.color = "#000000" //Make it black to look cool @@ -156,7 +179,7 @@ spawned.desc = "What is that thing?" spawned.faction = list("hostile") spawned.core_enabled = FALSE - datum_reference.qliphoth_change(2) + summon_count += 1 /* Work effects */ /mob/living/simple_animal/hostile/abnormality/contract/SuccessEffect(mob/living/carbon/human/user, work_type, pe) @@ -167,7 +190,6 @@ work_damage_amount = initial(work_damage_amount) return - /mob/living/simple_animal/hostile/abnormality/contract/NeutralEffect(mob/living/carbon/human/user, work_type, pe) . = ..() NewContract(user, work_type) diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/ebony_queen.dm b/code/modules/mob/living/simple_animal/abnormality/waw/ebony_queen.dm index e79af2a806aa..7a0c8047b25b 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/ebony_queen.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/ebony_queen.dm @@ -141,7 +141,8 @@ /mob/living/simple_animal/hostile/abnormality/ebony_queen/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() - addtimer(CALLBACK(src, PROC_REF(TryTeleport)), 5) + if(breach_type != BREACH_MINING) + addtimer(CALLBACK(src, PROC_REF(TryTeleport)), 5) /mob/living/simple_animal/hostile/abnormality/ebony_queen/Move() if(!can_act) diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/hatred_queen.dm b/code/modules/mob/living/simple_animal/abnormality/waw/hatred_queen.dm index 26589e5d4daa..7065c908cf86 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/hatred_queen.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/hatred_queen.dm @@ -693,6 +693,8 @@ return ..() /mob/living/simple_animal/hostile/abnormality/hatred_queen/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + friendly = FALSE death_counter = 0 if(friendly) friendly = TRUE diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/luna.dm b/code/modules/mob/living/simple_animal/abnormality/waw/luna.dm index 69e549cfa40f..ce12a31beecc 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/luna.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/luna.dm @@ -6,8 +6,8 @@ icon = 'ModularTegustation/Teguicons/96x48.dmi' icon_state = "dellaluna" portrait = "luna" - maxHealth = 400 - health = 400 + maxHealth = 4000 + health = 4000 damage_coeff = list(RED_DAMAGE = 1.2, WHITE_DAMAGE = 0, BLACK_DAMAGE = 1, PALE_DAMAGE = 2) start_qliphoth = 3 threat_level = WAW_LEVEL @@ -50,6 +50,17 @@ var/breached_monster var/killspawn +/mob/living/simple_animal/hostile/abnormality/luna/Move() + return FALSE + +/mob/living/simple_animal/hostile/abnormality/luna/CanAttack(atom/the_target) + return FALSE + +/mob/living/simple_animal/hostile/abnormality/luna/death(gibbed) + if(breached_monster) + qdel(breached_monster) + ..() + /mob/living/simple_animal/hostile/abnormality/luna/NeutralEffect(mob/living/carbon/human/user, work_type, pe) . = ..() if(prob(50)) diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/my_form_empties.dm b/code/modules/mob/living/simple_animal/abnormality/waw/my_form_empties.dm index 7e7cd7e3da92..5ad97db4a3fb 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/my_form_empties.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/my_form_empties.dm @@ -178,7 +178,8 @@ But, you feel that whatever it is, is not a joyous thing." var/turf/T = pick(GLOB.department_centers) icon_state = icon_living soundloop.start() - forceMove(T) + if(breach_type != BREACH_MINING) + forceMove(T) for(var/i = 1, i <= minion_amount ,i++) var/karma_vis = new /obj/effect/karma_halo var/picked = pick(pick(possible_minion_list)) diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/pygmalion.dm b/code/modules/mob/living/simple_animal/abnormality/waw/pygmalion.dm index b09f01c02142..90c976b9b969 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/pygmalion.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/pygmalion.dm @@ -165,7 +165,7 @@ if(client) to_chat(src, span_userdanger("The sculptor is in danger. It is now your duty to protect them!")) - threat_level = TETH_LEVEL + fear_level = TETH_LEVEL var/datum/attribute/user_attribute = sculptor.attributes[PRUDENCE_ATTRIBUTE] var/user_attribute_level = max(1, user_attribute.level) if (user_attribute_level > PRUDENCE_CAP) diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/rose_sign.dm b/code/modules/mob/living/simple_animal/abnormality/waw/rose_sign.dm index c0ec8662ac94..257a79d26f5c 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/rose_sign.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/rose_sign.dm @@ -55,6 +55,7 @@ var/list/work_roses = list() var/list/work_damages = list() var/list/summoned_roses = list() + var/rose_type = /mob/living/simple_animal/hostile/rose_summoned var/rose_max = 4 var/rose_cooldown var/rose_cooldown_time = 160 SECONDS @@ -204,7 +205,10 @@ work_roses -= R qdel(R) var/turf/T = pick(GLOB.department_centers) - forceMove(T) + if(breach_type != BREACH_MINING)//TODO: create attacking roses for this breach type + forceMove(T) + else + rose_type = /mob/living/simple_animal/hostile/rose_summoned/combat /mob/living/simple_animal/hostile/abnormality/rose_sign/proc/PickTargets()//this is called by life() rose_cooldown = world.time + rose_cooldown_time @@ -227,11 +231,14 @@ sound_to_playing_players_on_level("sound/abnormalities/rosesign/rose_summon.ogg", 100, zlevel = z) /mob/living/simple_animal/hostile/abnormality/rose_sign/proc/SpawnBreachRose(mob/living/carbon/human/target, turf/T) + if(rose_type == /mob/living/simple_animal/hostile/rose_summoned/combat)//during a mining breach, these are spawned around players + T = get_ranged_target_turf(get_turf(target), pick(GLOB.alldirs), 1) if(locate(/mob/living/simple_animal/hostile/rose_summoned) in get_turf(T))//Needs to be tested in a multiplayer environment T = get_ranged_target_turf(T, pick(GLOB.alldirs), 1)//This will move the target's turf to an adjacent one, preventing stacking and visual clutter to some degree. var/list/flower_damtype = list() var/damtype - var/mob/living/simple_animal/hostile/rose_summoned/R = new(T)//Spawns the rose + var/mob/living/simple_animal/hostile/rose_summoned/R + R = new rose_type(T)//Spawns the rose summoned_roses += R for(var/obj/item/W in target.held_items + target.get_equipped_items())//Searches the human for any E.G.O and adds them to a list. if(is_ego_melee_weapon(W)) //FIXME!!!! The above line doesn't actually check suit storage slots, could be more efficient too @@ -338,6 +345,7 @@ pull_force = INFINITY generic_canpass = FALSE movement_type = PHASING | FLYING + damtype = BLACK_DAMAGE var/root_damage = 30 //Black Damage layer = POINT_LAYER//should always be visible. @@ -351,7 +359,7 @@ for(var/turf/T in view(0, target_turf)) new /obj/effect/temp_visual/thornspike(T) for(var/mob/living/L in T) - L.deal_damage(root_damage, BLACK_DAMAGE) + L.deal_damage(root_damage, damtype) if(L.stat == DEAD) if(L.has_status_effect(/datum/status_effect/stacking/crownthorns))//Stops a second crucifix from appearing L.remove_status_effect(STATUS_EFFECT_THORNS) @@ -362,6 +370,15 @@ N.buckle_mob(L) qdel(src) +/obj/effect/roseRoot/red + damtype = RED_DAMAGE + +/obj/effect/roseRoot/white + damtype = WHITE_DAMAGE + +/obj/effect/roseRoot/pale + damtype = PALE_DAMAGE + //***Breach Roses***// /mob/living/simple_animal/hostile/rose_summoned @@ -374,7 +391,7 @@ maxHealth = 500 health = 500 damage_coeff = list(RED_DAMAGE = 0.5, WHITE_DAMAGE = 0.5, BLACK_DAMAGE = 0.5, PALE_DAMAGE = 0.5) - del_on_death = FALSE + del_on_death = TRUE var/flower_damage_type var/mob/living/simple_animal/hostile/abnormality/rose_sign/master var/mob/living/status_target @@ -401,7 +418,7 @@ /mob/living/simple_animal/hostile/rose_summoned/CanAttack(atom/the_target) return FALSE -/mob/living/simple_animal/hostile/rose_summoned/death() +/mob/living/simple_animal/hostile/rose_summoned/Destroy() if(!killed || !status_target) return ..() if(flower_damage_type && master) @@ -409,11 +426,44 @@ master.ChangeResistance(flower_damage_type, (master.damage_coeff.getCoeff(flower_damage_type) + 0.3), update = TRUE) if(status_target.has_status_effect(/datum/status_effect/stacking/crownthorns)) status_target.remove_status_effect(STATUS_EFFECT_THORNS) - density = FALSE - animate(src, alpha = 0, time = 10 SECONDS) - QDEL_IN(src, 10 SECONDS) ..() +/mob/living/simple_animal/hostile/rose_summoned/combat//mining breach variant + maxHealth = 1000 + health = 1000 + ranged = TRUE + var/root_type = /obj/effect/roseRoot + var/can_act = TRUE + +/mob/living/simple_animal/hostile/rose_summoned/combat/CanAttack(atom/the_target) + if(prob(30)) + return OpenFire() + +/mob/living/simple_animal/hostile/rose_summoned/combat/OpenFire() + if(!can_act) + return + rootBarrage(target)//Ebony queen-style basic attack + +/mob/living/simple_animal/hostile/rose_summoned/combat/PickColor(picked_color) + ..() + switch(picked_color) + if(RED_DAMAGE) + root_type = /obj/effect/roseRoot/red + if(WHITE_DAMAGE) + root_type = /obj/effect/roseRoot/white + if(PALE_DAMAGE) + root_type = /obj/effect/roseRoot/pale + +/mob/living/simple_animal/hostile/rose_summoned/combat/proc/rootBarrage(target, picked_color)//Ebony queen's basic attack, fired at a low rate. + can_act = FALSE + playsound(get_turf(target), 'sound/creatures/venus_trap_hurt.ogg', 75, 0, 5) + SLEEP_CHECK_DEATH(3) + var/turf/target_turf = get_turf(target) + for(var/turf/T in view(0, target_turf)) + new root_type(T) + SLEEP_CHECK_DEATH(3) + can_act = TRUE + //***Work-Based Roses***// /obj/structure/rose_work gender = NEUTER diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/screenwriter.dm b/code/modules/mob/living/simple_animal/abnormality/waw/screenwriter.dm index a69ac701449a..79cdd74bd23b 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/screenwriter.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/screenwriter.dm @@ -11,6 +11,9 @@ Defeating the murderer also surpresses the abnormality. icon = 'ModularTegustation/Teguicons/32x32.dmi' icon_state = "screenwriter" portrait = "screenwriter" + maxHealth = 4000 + health = 4000 + damage_coeff = list(RED_DAMAGE = 1.3, WHITE_DAMAGE = 0.5, BLACK_DAMAGE = 1.3, PALE_DAMAGE = 1.5) faction = list("hostile") threat_level = WAW_LEVEL start_qliphoth = 2 @@ -56,6 +59,18 @@ Defeating the murderer also surpresses the abnormality. preferred_work_type = pick(work_chances) SpawnIcon() +/mob/living/simple_animal/hostile/abnormality/screenwriter/Move() + return FALSE + +/mob/living/simple_animal/hostile/abnormality/screenwriter/CanAttack(atom/the_target) + return FALSE + +/mob/living/simple_animal/hostile/abnormality/screenwriter/Destroy() + if(A) + A.death() + EndScenario() + ..() + //Work stuff /mob/living/simple_animal/hostile/abnormality/screenwriter/AttemptWork(mob/living/carbon/human/user, work_type) if(A) @@ -110,6 +125,10 @@ Defeating the murderer also surpresses the abnormality. MeltdownEffect() return +/mob/living/simple_animal/hostile/abnormality/screenwriter/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + MeltdownEffect() + /mob/living/simple_animal/hostile/abnormality/screenwriter/proc/MeltdownEffect() var/turf/actor_location = pick(GLOB.department_centers) //Spawn the murderer A = new (actor_location) diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/shrimp.dm b/code/modules/mob/living/simple_animal/abnormality/waw/shrimp.dm index 48b06b5b3e7a..810aafacf7ff 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/shrimp.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/shrimp.dm @@ -118,6 +118,11 @@ datum_reference.qliphoth_change(1) return +/mob/living/simple_animal/hostile/abnormality/shrimp_exec/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + pissed() + addtimer(CALLBACK(src, PROC_REF(pissed)), 20 SECONDS) + /mob/living/simple_animal/hostile/abnormality/shrimp_exec/AttemptWork(mob/living/carbon/human/user, work_type) if(work_type == liked || !liked) happy = TRUE diff --git a/code/modules/mob/living/simple_animal/abnormality/waw/snow_whites_apple.dm b/code/modules/mob/living/simple_animal/abnormality/waw/snow_whites_apple.dm index a059d5072b52..ffed8e347bf1 100644 --- a/code/modules/mob/living/simple_animal/abnormality/waw/snow_whites_apple.dm +++ b/code/modules/mob/living/simple_animal/abnormality/waw/snow_whites_apple.dm @@ -77,6 +77,7 @@ var/hedge_cooldown_delay = FLORAL_BARRIER_COOLDOWN var/teleport_cooldown = 0 var/teleport_cooldown_delay = 60 SECONDS + var/can_teleport = TRUE //Spell automatically given to the abnormality. var/obj/effect/proc_holder/spell/pointed/apple_barrier/barrier_spell //All iterations share this list between eachother. @@ -96,6 +97,8 @@ /mob/living/simple_animal/hostile/abnormality/snow_whites_apple/BreachEffect(mob/living/carbon/human/user, breach_type) . = ..() update_icon() + if(breach_type == BREACH_MINING)//TODO: create attacking roses for this breach type + can_teleport = FALSE /mob/living/simple_animal/hostile/abnormality/snow_whites_apple/Initialize() . = ..() @@ -198,6 +201,8 @@ dir = 2 if(teleport_cooldown > world.time) return FALSE + if(!can_teleport) + return FALSE teleport_cooldown = world.time + teleport_cooldown_delay var/list/teleport_potential = TeleportList() if(!LAZYLEN(teleport_potential)) diff --git a/code/modules/mob/living/simple_animal/abnormality/zayin/blubbering_toad.dm b/code/modules/mob/living/simple_animal/abnormality/zayin/blubbering_toad.dm index 4d09f09118e2..1bacb9cf8896 100644 --- a/code/modules/mob/living/simple_animal/abnormality/zayin/blubbering_toad.dm +++ b/code/modules/mob/living/simple_animal/abnormality/zayin/blubbering_toad.dm @@ -116,8 +116,15 @@ //Attack or approach it directly and it attacks you! /mob/living/simple_animal/hostile/abnormality/blubbering_toad/BreachEffect(mob/living/user, breach_type = BREACH_NORMAL) - if(breach_type == BREACH_PINK) + if(breach_type == BREACH_PINK || breach_type == BREACH_MINING) persistant = TRUE + if(breach_type == BREACH_MINING)//nerfed to a ZAYIN statline since this is something you'll typically fight roundstart + name = "Weakened " + name + maxHealth = 400 + melee_damage_lower = 9 + melee_damage_upper = 15 + tongue_damage = 10 + broken = TRUE SetIdiot(user) return ..() diff --git a/code/modules/mob/living/simple_animal/abnormality/zayin/bottle.dm b/code/modules/mob/living/simple_animal/abnormality/zayin/bottle.dm index c8b1e2e26dc9..261edb63064a 100644 --- a/code/modules/mob/living/simple_animal/abnormality/zayin/bottle.dm +++ b/code/modules/mob/living/simple_animal/abnormality/zayin/bottle.dm @@ -189,12 +189,15 @@ // Pink Midnight Breach /mob/living/simple_animal/hostile/abnormality/bottle/BreachEffect(mob/living/carbon/human/user, breach_type) - if(breach_type == BREACH_PINK) + if(breach_type == BREACH_PINK || breach_type == BREACH_MINING) ADD_TRAIT(src, TRAIT_MOVE_FLYING, INNATE_TRAIT) COOLDOWN_START(src, speak_damage_aura, speak_cooldown_time) icon_state = "bottle_breach" desc = "A floating bottle, leaking tears.\nYou can use an empty hand to drink from it." can_breach = TRUE + if(breach_type == BREACH_MINING) + speak_damage = 0 + speak_cooldown_time = 15 SECONDS return ..() /mob/living/simple_animal/hostile/abnormality/bottle/attack_hand(mob/living/carbon/human/M) diff --git a/code/modules/mob/living/simple_animal/abnormality/zayin/fairy_festival.dm b/code/modules/mob/living/simple_animal/abnormality/zayin/fairy_festival.dm index 8562c85400ce..730f442d3982 100644 --- a/code/modules/mob/living/simple_animal/abnormality/zayin/fairy_festival.dm +++ b/code/modules/mob/living/simple_animal/abnormality/zayin/fairy_festival.dm @@ -5,8 +5,14 @@ icon_state = "fairy" icon_living = "fairy" portrait = "fairy_festival" - maxHealth = 83 - health = 83 + maxHealth = 800 + health = 800 + move_to_delay = 5 + damage_coeff = list(RED_DAMAGE = 1, WHITE_DAMAGE = 1.2, BLACK_DAMAGE = 1.3, PALE_DAMAGE = 2) + melee_damage_lower = 8 + melee_damage_upper = 15 + stat_attack = DEAD + attack_sound = 'sound/abnormalities/fairyfestival/fairyqueen_hit.ogg' is_flying_animal = TRUE threat_level = ZAYIN_LEVEL work_chances = list( @@ -31,6 +37,14 @@ var/heal_cooldown = 2 SECONDS var/heal_cooldown_base = 2 SECONDS var/list/mob/living/carbon/human/protected_people = list() + var/summon_count = 0 + var/summon_type = /mob/living/simple_animal/hostile/mini_fairy + var/summon_cooldown + var/summon_cooldown_time = 30 SECONDS + var/summon_group_size = 6 + var/summon_maximum = 14 + var/eat_threshold = 0.8 + var/eat_target abnormality_origin = ABNORMALITY_ORIGIN_LOBOTOMY grouped_abnos = list( @@ -82,6 +96,10 @@ . = ..() if(protected_people.len) FairyHeal() + if(summon_count > summon_maximum) + return + if((summon_cooldown < world.time) && !(status_flags & GODMODE)) + SummonGuys(summon_type) /mob/living/simple_animal/hostile/abnormality/fairy_festival/proc/FairyEnd(mob/living/carbon/human/user) protected_people.Remove(user) @@ -116,18 +134,88 @@ /mob/living/simple_animal/hostile/abnormality/fairy_festival/BreachEffect(mob/living/carbon/human/user, breach_type) if(breach_type == BREACH_PINK) - SummonGuys() - addtimer(CALLBACK(src, PROC_REF(SummonGuys)), 20 SECONDS) + summon_cooldown_time = 20 SECONDS + SummonGuys(summon_type) + if(breach_type == BREACH_MINING) + can_breach = TRUE + summon_type = /mob/living/simple_animal/hostile/fairy_mass + summon_group_size = 1 + summon_maximum = 3 + SummonGuys(summon_type) + icon = 'ModularTegustation/Teguicons/96x48.dmi' + icon_state = "fairy_queen" + pixel_x = -16 + maxHealth = 500 + playsound(get_turf(src), "sound/abnormalities/seasons/fall_change.ogg", 100, FALSE) + playsound(get_turf(src), "sound/abnormalities/fairyfestival/fairyqueen_growl.ogg", 100, FALSE) return ..() -/mob/living/simple_animal/hostile/abnormality/fairy_festival/proc/SummonGuys() +/mob/living/simple_animal/hostile/abnormality/fairy_festival/AttackingTarget() + . = ..() + if(summon_type != /mob/living/simple_animal/hostile/fairy_mass)//does she have fairy masses? + return + if(istype(target, /mob/living/simple_animal/hostile/fairy_mass)) + var/mob/living/L = target + if(L.health > 0)//fairies have to be alive; scarred meat isn't tasty + L.gib() + ProcessKill() + playsound(get_turf(src), "sound/abnormalities/fairyfestival/fairyqueen_growl.ogg", 100, FALSE) + return + eat_threshold -= 0.2 + if(. && isliving(target)) + var/mob/living/L = target + if(isliving(target) && (L.health < 0 || L.stat == DEAD)) + L.gib() + playsound(get_turf(src), "sound/abnormalities/fairyfestival/fairyqueen_growl.ogg", 100, FALSE) + if(ishuman(L)) + ProcessKill() + return + if(L == eat_target) + eat_target = 0 + +//Cannibalism +/mob/living/simple_animal/hostile/abnormality/fairy_festival/adjustHealth(amount, updating_health = TRUE, forced = FALSE) + ..() + if(summon_type != /mob/living/simple_animal/hostile/fairy_mass)//does she have fairy masses? + return + if(health < (maxHealth * eat_threshold)) //80% health or lower, 20% less for each eat. + if(eat_target) + GiveTarget(eat_target) + return + var/fairy_hp = 300 + var/mob/living/mytarget + for(var/mob/living/simple_animal/hostile/fairy_mass/M in range(12, src))//finds the fairy with the lowest HP in the vicinity + if(M.health <= 0) + mytarget = M + break + if(M.health <= fairy_hp) + fairy_hp = M.health + mytarget = M + if(mytarget) + mytarget.faction = list("neutral") + LoseTarget() + GiveTarget(mytarget) + eat_target = mytarget + +/mob/living/simple_animal/hostile/abnormality/fairy_festival/proc/SummonGuys(summon_type) + summon_cooldown = world.time + summon_cooldown_time var/mob/living/simple_animal/hostile/ordeal/pink_midnight/pink = locate() in GLOB.mob_living_list - for(var/i = 1 to 6) + for(var/i = 1 to summon_group_size) var/turf/target_turf = get_turf(pink ? pink : src) - var/mob/living/simple_animal/hostile/mini_fairy/new_fairy = new(target_turf) + var/mob/living/simple_animal/hostile/mini_fairy/new_fairy + new_fairy = new summon_type(target_turf) + summon_count += 1 if(pink) new_fairy.faction += "pink_midnight" +/mob/living/simple_animal/hostile/abnormality/fairy_festival/proc/ProcessKill() + eat_target = 0 + eat_threshold -= 0.2 + adjustBruteLoss(-maxHealth)//FRESH MEAT! + playsound(get_turf(src), "sound/abnormalities/fairyfestival/fairyqueen_growl.ogg", 100, FALSE) + if(move_to_delay>1) + ChangeMoveToDelayBy(-1) + /datum/reagent/abnormality/fairy_festival name = "Nectar of an Unknown Flower" description = "The fairies got this for you..." @@ -187,3 +275,36 @@ continue else M.Goto(src,M.move_to_delay,M.minimum_distance) + +/mob/living/simple_animal/hostile/fairy_mass + name = "\improper Fairy Mass" + desc = "They wander in search of food." + icon = 'ModularTegustation/Teguicons/tegumobs.dmi' + icon_state = "fairy_mass" + icon_living = "fairy_mass" + icon_dead = "fairy_mass_dead" + maxHealth = 300 + health = 300 + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + is_flying_animal = TRUE + damage_coeff = list(BRUTE = 1, RED_DAMAGE = 1.2, WHITE_DAMAGE = 1.2, BLACK_DAMAGE = 1.2, PALE_DAMAGE = 1.2) + faction = list("hostile", "fairy") + melee_damage_lower = 1 + melee_damage_upper = 5 + melee_damage_type = RED_DAMAGE + obj_damage = 3 + rapid_melee = 3 + attack_sound = 'sound/abnormalities/fairyfestival/fairy_festival_bite.ogg' + density = FALSE + move_to_delay = 2 + stat_attack = DEAD + guaranteed_butcher_results = list(/obj/item/food/meat/slab = 1) + +/mob/living/simple_animal/hostile/fairy_mass/AttackingTarget() + . = ..() + if(ishuman(target)) + var/mob/living/L = target + if(L.health < 0 || L.stat == DEAD) + playsound(get_turf(src), 'sound/magic/demon_consume.ogg', 75, 0) + L.gib() diff --git a/code/modules/mob/living/simple_animal/abnormality/zayin/one_sin.dm b/code/modules/mob/living/simple_animal/abnormality/zayin/one_sin.dm index 74c4c9182002..8160bb4e7fea 100644 --- a/code/modules/mob/living/simple_animal/abnormality/zayin/one_sin.dm +++ b/code/modules/mob/living/simple_animal/abnormality/zayin/one_sin.dm @@ -7,6 +7,13 @@ portrait = "one_sin" maxHealth = 777 health = 777 + damage_coeff = list(RED_DAMAGE = 1.5, WHITE_DAMAGE = 1, BLACK_DAMAGE = 1, PALE_DAMAGE = 2) + melee_damage_lower = 8 + melee_damage_upper = 15 + melee_damage_type = WHITE_DAMAGE + attack_sound = 'sound/abnormalities/onesin/onesin_attack.ogg' + attack_verb_continuous = "smites" + attack_verb_simple = "smite" is_flying_animal = TRUE threat_level = ZAYIN_LEVEL work_chances = list( @@ -131,8 +138,16 @@ H.adjustSanityLoss(-H.maxSanity * heal_factor) /mob/living/simple_animal/hostile/abnormality/onesin/BreachEffect(mob/living/carbon/human/user, breach_type) + if(breach_type == BREACH_MINING) + update_icon() + ..() + return return FALSE // If someone wants him to breach for SOME REASON in the future, then exclude breach_type == BREACH_PINK +/mob/living/simple_animal/hostile/abnormality/onesin/AttackingTarget() + ..() + new /obj/effect/temp_visual/onesin_punishment(get_turf(target)) + /datum/reagent/abnormality/onesin name = "Holy Light" description = "It's calming, even if you can't quite look at it straight." diff --git a/code/modules/mob/living/simple_animal/abnormality/zayin/oracle.dm b/code/modules/mob/living/simple_animal/abnormality/zayin/oracle.dm index e39ad98d3a79..9efd6b4cc9a4 100644 --- a/code/modules/mob/living/simple_animal/abnormality/zayin/oracle.dm +++ b/code/modules/mob/living/simple_animal/abnormality/zayin/oracle.dm @@ -7,8 +7,8 @@ icon_state = "oracle" icon_living = "oracle" portrait = "oracle" - maxHealth = 50 - health = 50 + maxHealth = 1500 + health = 1500 damage_coeff = list(RED_DAMAGE = 2, WHITE_DAMAGE = 0, BLACK_DAMAGE = 2, PALE_DAMAGE = 2) threat_level = ZAYIN_LEVEL work_chances = list( @@ -22,7 +22,7 @@ work_damage_type = WHITE_DAMAGE ego_list = list( - /datum/ego_datum/weapon/dead_dream, + /datum/ego_datum/weapon/dead_dream, /datum/ego_datum/armor/dead_dream ) // gift_type = /datum/ego_gifts/oracle @@ -77,6 +77,11 @@ "A person in a blue coat... they fold into a book...", ) +/mob/living/simple_animal/hostile/abnormality/oracle/Move() + return FALSE + +/mob/living/simple_animal/hostile/abnormality/oracle/CanAttack(atom/the_target) + return FALSE /mob/living/simple_animal/hostile/abnormality/oracle/PostWorkEffect(mob/living/carbon/human/user, work_type, pe) if(work_type == ABNORMALITY_WORK_INSIGHT) @@ -97,7 +102,6 @@ to_chat(user, span_notice("[SSlobotomy_corp.next_ordeal.name]")) ..() - /mob/living/simple_animal/hostile/abnormality/oracle/Initialize(mob/living/carbon/human/user) . = ..() RegisterSignal(SSdcs, COMSIG_GLOB_ABNORMALITY_BREACH, PROC_REF(OnAbnoBreach)) @@ -127,3 +131,29 @@ if(H.IsSleeping()) continue //You need to be sleeping to get notified to_chat(H, "Oh.... [abno]... It has breached containment...") + +//ER stuff +/mob/living/simple_animal/hostile/abnormality/oracle/BreachEffect(mob/living/carbon/human/user, breach_type)//finish this shit + if(breach_type == BREACH_MINING) + var/chosenfake = pick(fakeordeals) + for(var/mob/living/L in livinginrange(48, src)) + if(L.z != z) + continue + if(faction_check_mob(L)) + continue + to_chat(L, span_userdanger("[chosenfake]")) + addtimer(CALLBACK(src, PROC_REF(NukeAttack)), 30 SECONDS) + return ..() + +/mob/living/simple_animal/hostile/abnormality/oracle/proc/NukeAttack() + if(stat == DEAD) + return + playsound(src, 'sound/magic/wandodeath.ogg', 100, FALSE, 40, falloff_distance = 10) + for(var/mob/living/L in livinginrange(48, src)) + if(L.z != z) + continue + if(faction_check_mob(L)) + continue + to_chat(L, span_userdanger("Visions of a horrible future flash before your eyes!")) + L.deal_damage((150 - get_dist(src, L)), WHITE_DAMAGE) + qdel(src) diff --git a/code/modules/mob/living/simple_animal/abnormality/zayin/quiet_day.dm b/code/modules/mob/living/simple_animal/abnormality/zayin/quiet_day.dm index 0549c06acd1e..8dc4c731b3fd 100644 --- a/code/modules/mob/living/simple_animal/abnormality/zayin/quiet_day.dm +++ b/code/modules/mob/living/simple_animal/abnormality/zayin/quiet_day.dm @@ -228,7 +228,7 @@ return FALSE /mob/living/simple_animal/hostile/abnormality/quiet_day/BreachEffect(mob/living/carbon/human/user, breach_type) - if(breach_type == BREACH_PINK) + if(breach_type == BREACH_PINK || breach_type == BREACH_MINING) AbnoRadio() Ramble() can_breach = TRUE diff --git a/code/modules/mob/living/simple_animal/distortion/monolith.dm b/code/modules/mob/living/simple_animal/distortion/monolith.dm index f746472ce6f3..59b2422631d1 100644 --- a/code/modules/mob/living/simple_animal/distortion/monolith.dm +++ b/code/modules/mob/living/simple_animal/distortion/monolith.dm @@ -133,7 +133,7 @@ var/mob/living/simple_animal/hostile/distortion/D = target if(D.monolith_abnormality) var/mob/living/simple_animal/hostile/abnormality/myAbno = new D.monolith_abnormality(get_turf(target)) - myAbno.BreachEffect() + myAbno.BreachEffect(null, BREACH_MINING) qdel(target) return TRUE return FALSE diff --git a/sound/abnormalities/fairyfestival/fairyqueen_eat.ogg b/sound/abnormalities/fairyfestival/fairyqueen_eat.ogg new file mode 100644 index 000000000000..85eb68fbf5a7 Binary files /dev/null and b/sound/abnormalities/fairyfestival/fairyqueen_eat.ogg differ diff --git a/sound/abnormalities/fairyfestival/fairyqueen_growl.ogg b/sound/abnormalities/fairyfestival/fairyqueen_growl.ogg new file mode 100644 index 000000000000..ff83bdba6c5b Binary files /dev/null and b/sound/abnormalities/fairyfestival/fairyqueen_growl.ogg differ diff --git a/sound/abnormalities/fairyfestival/fairyqueen_hit.ogg b/sound/abnormalities/fairyfestival/fairyqueen_hit.ogg new file mode 100644 index 000000000000..f359a470f88e Binary files /dev/null and b/sound/abnormalities/fairyfestival/fairyqueen_hit.ogg differ diff --git a/sound/abnormalities/onesin/onesin_attack.ogg b/sound/abnormalities/onesin/onesin_attack.ogg new file mode 100644 index 000000000000..e3d9a2843dbd Binary files /dev/null and b/sound/abnormalities/onesin/onesin_attack.ogg differ