diff --git a/.gitattributes b/.gitattributes index 313f1f7da817..5bf64551dd26 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,51 +1,51 @@ - -*.dmm eol=crlf -*.md eol=crlf -*.txt eol=crlf -*.html eol=crlf -#this breaks if its in crlf -code/__DEFINES/rust_g.dm eol=lf - - -## Enforce text mode and LF line breaks -*.bat text eol=lf -*.cjs text eol=lf -*.css text eol=lf -*.dm text eol=lf -*.dme text eol=lf -*.dmf text eol=lf -*.htm text eol=lf -*.html text eol=lf -*.js text eol=lf -*.json text eol=lf -*.jsx text eol=lf -*.md text eol=lf -*.ps1 text eol=lf -*.py text eol=lf -*.scss text eol=lf -*.sh text eol=lf -*.sql text eol=lf -*.svg text eol=lf -*.ts text eol=lf -*.tsx text eol=lf -*.txt text eol=lf -*.yaml text eol=lf -*.yml text eol=lf - -## Enforce binary mode -*.bmp binary -*.dll binary -*.dmb binary -*.exe binary -*.gif binary -*.jpg binary -*.png binary -*.so binary - - -# merger hooks, run tools/hooks/install.bat or install.sh to set up -*.dmm merge=dmm -*.dmi merge=dmi - -# force changelog merging to use union -html/changelog.html merge=union + +*.dmm eol=crlf +*.md eol=crlf +*.txt eol=crlf +*.html eol=crlf +#this breaks if its in crlf +code/__DEFINES/rust_g.dm eol=lf + + +## Enforce text mode and LF line breaks +*.bat text eol=lf +*.cjs text eol=lf +*.css text eol=lf +*.dm text eol=lf +*.dme text eol=lf +*.dmf text eol=lf +*.htm text eol=lf +*.html text eol=lf +*.js text eol=lf +*.json text eol=lf +*.jsx text eol=lf +*.md text eol=lf +*.ps1 text eol=lf +*.py text eol=lf +*.scss text eol=lf +*.sh text eol=lf +*.sql text eol=lf +*.svg text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.txt text eol=lf +*.yaml text eol=lf +*.yml text eol=lf + +## Enforce binary mode +*.bmp binary +*.dll binary +*.dmb binary +*.exe binary +*.gif binary +*.jpg binary +*.png binary +*.so binary + + +# merger hooks, run tools/hooks/install.bat or install.sh to set up +*.dmm merge=dmm +*.dmi merge=dmi + +# force changelog merging to use union +html/changelog.html merge=union diff --git a/code/__DEFINES/bloodsuckers.dm b/code/__DEFINES/bloodsuckers.dm index d8be795f7d80..64e0bf842f59 100644 --- a/code/__DEFINES/bloodsuckers.dm +++ b/code/__DEFINES/bloodsuckers.dm @@ -37,6 +37,7 @@ #define CLAN_GANGREL "Gangrel Clan" #define CLAN_LASOMBRA "Lasombra Clan" #define CLAN_TZIMISCE "Tzimisce Clan" +#define CLAN_HECATA "Hecata Clan" #define TRIPLECHEST_MONSTER "Triple Chest (300 Blood)" #define ARMMY_MONSTER "Armmy (100 Blood)" @@ -70,6 +71,8 @@ #define HUNTER_CAN_BUY (1<<4) /// This Power can be purchased by Tzimisce Bloodsuckers #define TZIMISCE_CAN_BUY (1<<5) +/// This Power can be purchased by Hecata Bloodsuckers +#define HECATA_CAN_BUY (1<<6) /// This Power is a Toggled Power #define BP_AM_TOGGLE (1<<0) @@ -82,4 +85,4 @@ // Signals -#define COMSIG_BLOODSUCKER_RANKS_SPENT \ No newline at end of file +#define COMSIG_BLOODSUCKER_RANKS_SPENT diff --git a/code/modules/antagonists/bloodsuckers/bloodsucker_flaws.dm b/code/modules/antagonists/bloodsuckers/bloodsucker_flaws.dm index f3f21fcc52e3..e907c5571efc 100644 --- a/code/modules/antagonists/bloodsuckers/bloodsucker_flaws.dm +++ b/code/modules/antagonists/bloodsuckers/bloodsucker_flaws.dm @@ -23,6 +23,7 @@ CLAN_GANGREL, CLAN_LASOMBRA, CLAN_TOREADOR, + CLAN_HECATA, ) var/list/options = list() options = clans @@ -30,7 +31,8 @@ to_chat(owner, span_announce("List of all Clans:\n\ Gangrel - Prone to Frenzy, strange outcomes from being on frenzy, special power.\n\ Lasombra - Life in the shadows, very weak to fire but no brute damage, upgradable abilities through tasks.\n\ - Toreador - More human then other bloodsucker, easily disguise among crew, but bound with morals.")) + Toreador - More human then other bloodsucker, easily disguise among crew, but bound with morals.\n\ + Hecata - Can raise the dead and summon wraiths, though incapable of silent feeding or benefitting from blood altars.")) var/answer = input("You have Ranked up far enough to remember your clan. Which clan are you part of?", "Your mind feels luxurious...") in options if(!answer) @@ -96,5 +98,26 @@ continue masquarade_spell.bloodcost = 0 masquarade_spell.constant_bloodcost = 0 //Wow very cool code, good job + if(CLAN_HECATA) + my_clan = CLAN_HECATA + to_chat(owner, span_announce("You have Ranked up enough to learn: You are part of the Hecata Clan!\n\ + * As part of the Hecata clan, you are an avid practioner of necromancy.\n\ + * You are capable of raising the dead as zombies, making them into temporary vassals loyal to you. Dead vassals are instead permanently revived\n\ + * You can also call for help from the beyond by summoning wraiths.\n\ + * In addition, you can send messages to all your vassals no matter their location via Deathly Communion.\n\ + * However, feeding on people causes them deep pain, making it impossible to feed silently.\n\ + * You also are unable to use the blood altar in order to gain tasks for ranks.\n\ + * Finally, your Favorite Vassal will transform into a zombie if they weren't one already, and gain the Spirit Call ability.")) + BuyPower(new /datum/action/bloodsucker/targeted/hecata/necromancy) + BuyPower(new /datum/action/bloodsucker/hecata/spiritcall) + BuyPower(new /datum/action/bloodsucker/hecata/communion) + bloodsucker.faction |= "bloodhungry" + var/datum/objective/bloodsucker/necromance/hecata_objective = new + hecata_objective.owner = owner + objectives += hecata_objective + for(var/datum/action/bloodsucker/feed/feed_spell in powers) + if(!istype(feed_spell)) + continue + feed_spell.suppressible = 0 owner.announce_objectives() diff --git a/code/modules/antagonists/bloodsuckers/bloodsucker_mobs.dm b/code/modules/antagonists/bloodsuckers/bloodsucker_mobs.dm index 9bf707dac7e3..37b9bb1da474 100644 --- a/code/modules/antagonists/bloodsuckers/bloodsucker_mobs.dm +++ b/code/modules/antagonists/bloodsuckers/bloodsucker_mobs.dm @@ -262,3 +262,43 @@ else new /obj/structure/bloodsucker/possessedarmor(src.loc) qdel(src) + + +/mob/living/simple_animal/hostile/bloodsucker/wraith + name = "wraith" + real_name = "Wraith" + desc = "An angry, tormented spirit, which looks to let out it's wrath on whoever is nearby." + gender = PLURAL + icon_state = "wraith" + mob_biotypes = list(MOB_SPIRIT) + maxHealth = 30 + health = 30 + spacewalk = TRUE + healable = 0 + speak_emote = list("hisses") + emote_hear = list("wails.","screeches.") + response_help = "puts their hand through" + response_disarm = "flails at" + response_harm = "punches" + speak_chance = 1 + melee_damage_lower = 6 + melee_damage_upper = 6 + attacktext = "torments" + minbodytemp = 0 + maxbodytemp = INFINITY + 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) + status_flags = 0 + status_flags = CANPUSH + movement_type = FLYING + +/mob/living/simple_animal/hostile/bloodsucker/wraith/Life() + . = ..() + if(!src) + return + if(src.stat != DEAD) //Wraith loses 1 health every 2 seconds, which means it will disperse after 60 seconds if not damaged. + adjustHealth(1) + +/mob/living/simple_animal/hostile/bloodsucker/wraith/death() + deathmessage = "withers away into nothing." + qdel(src) //Del on death for some reason doesn't work, might be due to previous code preventing it for /bloodsucker mobs. + ..() diff --git a/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm b/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm index 646a07bd6097..cbdeb24e555b 100644 --- a/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm +++ b/code/modules/antagonists/bloodsuckers/bloodsucker_objectives.dm @@ -427,3 +427,26 @@ if(bloodsuckerdatum && bloodsuckerdatum.vassals >= target_amount) return TRUE return FALSE + + +/// Necromance X amount of people +/datum/objective/bloodsucker/necromance + name = "necromance" + +/datum/objective/bloodsucker/necromance/New() + target_amount = rand(6,8) + ..() + + +/datum/objective/bloodsucker/necromance/update_explanation_text() + . = ..() + explanation_text = "Using Necromancy, revive people [target_amount] times." + +/datum/objective/bloodsucker/necromance/check_completion() + var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.current.mind.has_antag_datum(/datum/antagonist/bloodsucker) + if(!bloodsuckerdatum) + return FALSE + if(bloodsuckerdatum.clanprogress >= target_amount) + return TRUE + return FALSE + diff --git a/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm b/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm index 8e5cca8f492a..17e81d00574f 100644 --- a/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm +++ b/code/modules/antagonists/bloodsuckers/bloodsuckers_objects.dm @@ -389,5 +389,13 @@ Weakness: Immensely weak to burn damage." if(CLAN_TZIMISCE) dat += "The page is covered in blood..." + if(CLAN_HECATA) + dat += "This Clan seems to enjoy experimenting with the dead and researching them.
\ + They have a morbid curiosity of the dead, and may find it irrestible to not toy with them.
\ + They are interested in finding corpses and trying to reverse their death, however successful they may be.
\ + They have the ability to bring the dead back to a state of undeath and servitude to themself.
\ + Favorite Vassal: Their Favorite Vassal will always be a zombie, and has similar spirit calling abilities. \ + Strength: They can raise the dead and receive assistance from the beyond.
\ + Weakness: Unable to silently feed on others, and their vassals tend to have obvious undead forms." reader << browse("Penned by [author].
" + "[dat]", "window=book[window_size != null ? ";size=[window_size]" : ""]") diff --git a/code/modules/antagonists/bloodsuckers/powers/feed.dm b/code/modules/antagonists/bloodsuckers/powers/feed.dm index 123116cad0bc..b23764e4d546 100644 --- a/code/modules/antagonists/bloodsuckers/powers/feed.dm +++ b/code/modules/antagonists/bloodsuckers/powers/feed.dm @@ -40,6 +40,8 @@ var/warning_full = FALSE var/warning_target_bloodvol = 99999 var/was_alive = FALSE + //can you silently feed? Hecata can't. + var/suppressible = 1 /datum/action/bloodsucker/feed/CheckCanUse(mob/living/carbon/user) . = ..() @@ -86,6 +88,9 @@ if(NOBLOOD in target_user.dna.species.species_traits)// || owner.get_blood_id() != target.get_blood_id()) to_chat(owner, span_warning("Your victim's blood is not suitable for you to take.")) return FALSE + if(suppressible == 0 && owner.grab_state <= GRAB_PASSIVE) + to_chat(owner, span_warning("Feeding as a Hecata would cause enough pain to the victim to make silent feeding like this impossible.")) + return FALSE return TRUE /// If I'm not grabbing someone, find me someone nearby. diff --git a/code/modules/antagonists/bloodsuckers/powers/targeted/hecata.dm b/code/modules/antagonists/bloodsuckers/powers/targeted/hecata.dm new file mode 100644 index 000000000000..65b036b46e8d --- /dev/null +++ b/code/modules/antagonists/bloodsuckers/powers/targeted/hecata.dm @@ -0,0 +1,224 @@ +//Hecata, the unified clan of death. +//Focuses more on their vassals than other clans. +//Has to rely more on vassals for ranks and blood, as they cannot use the blood altar for leveling up and cannot silent feed. +//In exchange, they can raise the dead as temporary vassals to do their bidding, or permanently revive dead existing vassals. +//In addition, they can summon Wraiths (shades) around them for both offense and defense +//And can send messages to vassals anywhere globally via Dark Communion. +//In addition, raising the dead with Necromancy turns them into Sanguine Zombies +//They are pseudo zombies, which have high punch damage and special resistances, but aren't infectious nor can they use guns. + +/datum/action/bloodsucker/targeted/hecata + purchase_flags = HECATA_CAN_BUY + + button_icon = 'icons/mob/actions/actions_hecata_bloodsucker.dmi' + icon_icon = 'icons/mob/actions/actions_hecata_bloodsucker.dmi' + background_icon_state = "hecata_power_off" + background_icon_state_on = "hecata_power_on" + background_icon_state_off = "hecata_power_off" + +/datum/action/bloodsucker/targeted/hecata/necromancy + name = "Necromancy" + level_current = 1 + button_icon_state = "power_necromancy" + desc = "Raise the dead as temporary vassals, or revive a dead vassal as a zombie permanently. Temporary vassals last longer as this ability ranks up." + power_explanation = "Necromancy:\n\ + Click on a corpse in order to attempt to resurrect them.\n\ + Non-vassals will become temporary zombies that will follow your orders. Dead vassals are also turned, but last permanently.\n\ + Temporary vassals tend to not last long, their form quickly falling apart, make sure you set them out to do what you want as soon as possible.\n\ + Vassaling people this way does not grant ranks. In addition, after their time is up they will die and no longer be your vassal." + check_flags = BP_CANT_USE_IN_TORPOR|BP_CANT_USE_IN_FRENZY|BP_CANT_USE_WHILE_UNCONSCIOUS + power_flags = BP_AM_STATIC_COOLDOWN + bloodcost = 35 + cooldown = 45 SECONDS + target_range = 1 + prefire_message = "Select a target." + +/datum/action/bloodsucker/targeted/hecata/necromancy/CheckValidTarget(atom/target_atom) + . = ..() + if(!.) + return FALSE + return isliving(target_atom) + +/datum/action/bloodsucker/targeted/hecata/necromancy/CheckCanTarget(atom/target_atom) + . = ..() + if(!.) + return FALSE + var/mob/living/current_target = target_atom // We already know it's carbon due to CheckValidTarget() + // No mind + if(!current_target.mind) + to_chat(owner, span_warning("[current_target] is mindless.")) + return FALSE + // Bloodsucker + if(IS_BLOODSUCKER(current_target)) + to_chat(owner, span_notice("Bloodsuckers are immune to [src].")) + return FALSE + // Alive + if(current_target.stat != DEAD) + to_chat(owner, "[current_target] is still alive.") + return FALSE + return TRUE + +/datum/action/bloodsucker/targeted/hecata/necromancy/FireTargetedPower(atom/target_atom) + . = ..() + var/mob/living/target = target_atom + var/mob/living/user = owner + var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(/datum/antagonist/bloodsucker) + if(target.stat == DEAD && user.Adjacent(target)) + owner.balloon_alert(owner, "attempting to revive...") + if(!do_mob(user, target, 6 SECONDS, NONE, TRUE)) + return FALSE + + if(IS_VASSAL(target)) + PowerActivatedSuccessfully() + to_chat(user, span_warning("We revive [target]!")) + zombify(target) + bloodsuckerdatum.clanprogress++ //counts a succesful necromancy towards your objective progress + DeactivatePower() + return + if(IS_MONSTERHUNTER(target)) + to_chat(target, span_notice("Their body refuses to react...")) + DeactivatePower() + return + if(!bloodsuckerdatum_power.attempt_turn_vassal(target, TRUE)) + return FALSE + zombify(target) + PowerActivatedSuccessfully() + bloodsuckerdatum.clanprogress++ //counts a succesful necromancy towards your objective progress + to_chat(user, span_warning("We revive [target]!")) + var/living_time + if(level_current == 1) + living_time = 5 MINUTES + else if(level_current == 2) + living_time = 8 MINUTES + else if(level_current == 3) + living_time = 12 MINUTES + else if(level_current >= 4) + living_time = 15 MINUTES //in general, they don't last long, make the most of them. + addtimer(CALLBACK(src, PROC_REF(end_necromance), target), living_time) + else //extra check, but this shouldn't happen + owner.balloon_alert(owner, "Target is out of range or not dead yet.") + return FALSE + DeactivatePower() + + +/datum/action/bloodsucker/targeted/hecata/necromancy/proc/end_necromance(mob/living/user) + user.mind.remove_antag_datum(/datum/antagonist/vassal) + to_chat(user, span_warning("You feel the shadows around you weaken, your form falling limp like a puppet cut from its strings!")) + user.set_species(/datum/species/krokodil_addict) //they will turn into a fake zombie on death, that still retains blood and isnt so powerful. + user.death() + +/datum/action/bloodsucker/targeted/hecata/necromancy/proc/zombify(mob/living/user) + user.mind.grab_ghost() + user.revive(full_heal = TRUE, admin_revive = TRUE) + user.set_species(/datum/species/zombie/hecata) //imitation zombies that shamble around and beat people with their fists + user.visible_message(span_danger("[user] suddenly convulses, as [user.p_they()] stagger to their feet and gain a ravenous hunger in [user.p_their()] eyes!"), span_alien("You RISE!")) + playsound(owner.loc, 'sound/hallucinations/far_noise.ogg', 50, 1) + to_chat(user, span_warning("Your broken form is picked up by strange shadows. If you were previously not a vassal, it is unlikely these shadows will be strong enough to keep you going for very long.")) + to_chat(user, span_notice("You are resilient to many things like the vacuum of space, can punch harder, and can take more damage before dropping. However, you are unable to use guns and are slower.")) + +/datum/action/bloodsucker/hecata + purchase_flags = HECATA_CAN_BUY + button_icon = 'icons/mob/actions/actions_hecata_bloodsucker.dmi' + icon_icon = 'icons/mob/actions/actions_hecata_bloodsucker.dmi' + background_icon_state = "hecata_power_off" + background_icon_state_on = "hecata_power_on" + background_icon_state_off = "hecata_power_off" + +//summon wraiths (weakened shades) to attack anyone who isn't a zombie. This includes non-zombified vassals. However, you can get around this by zombifying your vassals. +//to do this, you can make someone your favorite vassal, or you can kill them and then revive them with necromancy. +/datum/action/bloodsucker/hecata/spiritcall + name = "Spirit Call" + level_current = 1 + desc = "Summon two angry wraiths which will attack anyone whose flesh is still alive. Summon amount increases as this ability levels up." + button_icon_state = "power_spiritcall" + power_explanation = "Spirit Call:\n\ + Summon angry wraiths which enact vengeance from beyond the grave on those still connected to this world.\n\ + Note, that includes any of your vassals who are not undead, as wraiths will seek to kill them too!\n\ + Summons more wraiths as this ability ranks up.\n\ + These wraiths aren't very powerful, and best serve as a distraction, but in a pinch can help in a fight. \n\ + The spirits will eventually return back to their realm if not otherwise destroyed." + check_flags = BP_CANT_USE_IN_TORPOR|BP_CANT_USE_IN_FRENZY|BP_CANT_USE_WHILE_UNCONSCIOUS + power_flags = BP_AM_STATIC_COOLDOWN + bloodcost = 15 + cooldown = 60 SECONDS + var/num_spirits = 2 + +/datum/action/bloodsucker/hecata/spiritcall/vassal //this variant has to exist, as hecata favorite vassals are technically in 'torpor' + check_flags = BP_CANT_USE_WHILE_INCAPACITATED|BP_CANT_USE_WHILE_UNCONSCIOUS + +/datum/action/bloodsucker/hecata/spiritcall/ActivatePower(mob/user = usr) + . = ..() + if(level_current == 2) + num_spirits = 3 + else if(level_current >= 3) + num_spirits = 4 + var/list/turf/locs = new + for(var/direction in GLOB.alldirs) //looking for spirit spawns + if(locs.len == num_spirits) //we found the number of spots needed and thats all we need + break + var/turf/T = get_step(usr, direction) //getting a loc in that direction + if(AStar(user, T, /turf/proc/Distance, 1, simulated_only = 0)) // if a path exists, so no dense objects in the way its valid salid + locs += T + + // pad with player location + for(var/i = locs.len + 1 to num_spirits) + locs += user.loc + + summonWraiths(locs, user = user) + cast_effect() // POOF + DeactivatePower() + + +/datum/action/bloodsucker/hecata/spiritcall/proc/summonWraiths(list/targets, mob/user = usr) + for(var/T in targets) + new /mob/living/simple_animal/hostile/bloodsucker/wraith(T) + +/datum/action/bloodsucker/hecata/spiritcall/proc/cast_effect() //same as veil of many faces, makes smoke and stuff when casted + // Effect + playsound(get_turf(owner), 'sound/magic/smoke.ogg', 20, 1) + var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/() + puff.effect_type = /obj/effect/particle_effect/fluid/smoke/vampsmoke + puff.set_up(3, 0, get_turf(owner)) + puff.attach(owner) //OPTIONAL + puff.start() + owner.spin(8, 1) //Spin around like a loon. + +/datum/action/bloodsucker/hecata/communion + name = "Deathly Communion" + level_current = 1 + desc = "Send a message to all your vassals." + button_icon_state = "power_communion" + power_explanation = "Deathly Communion:\n\ + Send a message directly to all vassals under your control, temporary or permanent.\n\ + They will not be able to respond to you through any supernatural means in the way you can.\n\ + Note, nearby humans can hear you talk when using this.\n\ + The cooldown of Communion will decrease as it levels up." + check_flags = BP_CANT_USE_IN_TORPOR|BP_CANT_USE_IN_FRENZY + power_flags = NONE + bloodcost = 8 + cooldown = 30 SECONDS + +/datum/action/bloodsucker/hecata/communion/ActivatePower() + . = ..() + var/input = stripped_input(usr, "Choose a message to tell your vassals.", "Voice of Blood", "") + if(!input || !IsAvailable()) + return FALSE + + deathly_commune(usr, input) + +/datum/action/bloodsucker/hecata/communion/proc/deathly_commune(mob/living/user, message) //code from Fulpstation + var/rendered = span_cultlarge("Master [user.real_name] announces: [message]") + user.log_talk(message, LOG_SAY, tag=ROLE_BLOODSUCKER) + var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(/datum/antagonist/bloodsucker) + for(var/datum/antagonist/vassal/receiver as anything in bloodsuckerdatum.vassals) + if(!receiver.owner.current) + continue + var/mob/receiver_mob = receiver.owner.current + to_chat(receiver_mob, rendered) + to_chat(user, rendered) // tell yourself, too. + + for(var/mob/dead_mob in GLOB.dead_mob_list) + var/link = FOLLOW_LINK(dead_mob, user) + to_chat(dead_mob, "[link] [rendered]") + DeactivatePower() + diff --git a/code/modules/antagonists/bloodsuckers/structures/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsuckers/structures/bloodsucker_crypt.dm index 27964f36ffa9..980ac05c6ddc 100644 --- a/code/modules/antagonists/bloodsuckers/structures/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsuckers/structures/bloodsucker_crypt.dm @@ -158,6 +158,9 @@ if(want_rank == "No" || QDELETED(src)) return var/mob/living/carbon/C = user + if(bloodsuckerdatum.my_clan == CLAN_HECATA) + to_chat(user, span_boldnotice("These blood bounties no longer interest you, get back on task.")) + return if(C.blood_volume < 50) to_chat(user, span_danger("You don't have enough blood to gain a task!")) return @@ -1142,6 +1145,8 @@ src.visible_message(span_danger("[buckled_mob][buckled_mob.stat==DEAD?"'s corpse":""] slides off of the candelabrum.")) update_icon() +/////////////////////////// + /// Blood Throne - Allows Bloodsuckers to remotely speak with their Vassals. - Code (Mostly) stolen from comfy chairs (armrests) and chairs (layers) /* broken currently /obj/structure/bloodsucker/bloodthrone diff --git a/code/modules/antagonists/bloodsuckers/vassal.dm b/code/modules/antagonists/bloodsuckers/vassal.dm index 6e9426e8c97e..1bbf08f4f8c2 100644 --- a/code/modules/antagonists/bloodsuckers/vassal.dm +++ b/code/modules/antagonists/bloodsuckers/vassal.dm @@ -136,6 +136,9 @@ if(CLAN_TOREADOR) BuyPower(/datum/action/bloodsucker/targeted/mesmerize) RegisterSignal(master, COMSIG_BLOODSUCKER_RANKS_SPENT, PROC_REF(toreador_levelup_mesmerize)) + if(CLAN_HECATA) + vassal.set_species(/datum/species/zombie/hecata) + BuyPower(new /datum/action/bloodsucker/hecata/spiritcall/vassal) /datum/antagonist/vassal/proc/toreador_levelup_mesmerize() //Don't need stupid args for(var/datum/action/bloodsucker/targeted/mesmerize/mesmerize_power in powers) diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 92841032dd5e..7ca133ba4448 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -121,6 +121,30 @@ mutanttongue = /obj/item/organ/tongue/zombie changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN +//Hecata necromancy bloodsucker zombie. Kind of like a weakened Szlachta that can also wear clothes still +/datum/species/zombie/hecata + name = "Sanguine Zombie" + id = "hecatazombie" + limbs_id = "zombie" + say_mod = "moans" + brutemod = 1.1 //more fragile, though they also dont enter soft crit. No burn weakness since sanguine recuperation wont heal it. + speedmod = 0.33 //slightly slower + stunmod = 0.5 + staminamod = 0.5 //difficult to subdue via nonlethal means + punchdamagelow = 13 + punchdamagehigh = 16 + punchstunthreshold = 17 //pretty good punch damage but no knockdown + inherent_traits = list(TRAIT_STABLELIVER, TRAIT_STABLEHEART, TRAIT_RESISTCOLD ,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_EASILY_WOUNDED,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH, TRAIT_NOGUNS, TRAIT_NOSOFTCRIT) //no guns or soft crit + changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN + +/datum/species/zombie/hecata/on_species_gain(mob/living/carbon/C, datum/species/old_species) + . = ..() + C.faction |= "bloodhungry" + +/datum/species/zombie/hecata/on_species_loss(mob/living/carbon/C) + . = ..() + C.faction -= "bloodhungry" + //The special zombie you get turned into in the zombie gamemode /datum/species/zombie/infectious/gamemode armor = 20 diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 7a309e7933ed..11ba06fb7c0d 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -76,7 +76,7 @@ All effects don't start immediately, but rather get worse over time; the rate is S.success_multiplier = max(0.1*power_multiplier, S.success_multiplier) // +10% success propability on each step, useful while operating in less-than-perfect conditions return ..() - + /datum/reagent/consumable/ethanol/beer name = "Beer" description = "An alcoholic beverage brewed since ancient times on Old Earth. Still popular today." diff --git a/html/changelog.html b/html/changelog.html index 6109702e1f3e..6f0edac8d341 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -57,6 +57,7 @@ -->
+

09 May 2023

22 May 2023

Code611 updated:

GoonStation 13 Development Team diff --git a/icons/mob/actions/actions_hecata_bloodsucker.dmi b/icons/mob/actions/actions_hecata_bloodsucker.dmi new file mode 100644 index 000000000000..0c58b842c153 Binary files /dev/null and b/icons/mob/actions/actions_hecata_bloodsucker.dmi differ diff --git a/icons/mob/bloodsucker_mobs.dmi b/icons/mob/bloodsucker_mobs.dmi index 20276e91d0cb..041f03dd78ed 100644 Binary files a/icons/mob/bloodsucker_mobs.dmi and b/icons/mob/bloodsucker_mobs.dmi differ diff --git a/yogstation.dme b/yogstation.dme index a26e1c0d0d6b..399137cac40b 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -1541,6 +1541,7 @@ #include "code\modules\antagonists\bloodsuckers\powers\targeted\_powers_targeted.dm" #include "code\modules\antagonists\bloodsuckers\powers\targeted\brawn.dm" #include "code\modules\antagonists\bloodsuckers\powers\targeted\haste.dm" +#include "code\modules\antagonists\bloodsuckers\powers\targeted\hecata.dm" #include "code\modules\antagonists\bloodsuckers\powers\targeted\lunge.dm" #include "code\modules\antagonists\bloodsuckers\powers\targeted\mesmerize.dm" #include "code\modules\antagonists\bloodsuckers\powers\targeted\trespass.dm"