Merge pull request #11618 from Arturlang/Garlic
Adds garlic, and tweaks bloodsuckers a bunch.
This commit is contained in:
@@ -1,12 +1,6 @@
|
||||
// INTEGRATION: Adding Procs and Datums to existing "classes"
|
||||
/mob/living/proc/AmBloodsucker(falseIfInDisguise=FALSE)
|
||||
// No Datum
|
||||
if(!mind || !mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/proc/HaveBloodsuckerBodyparts(var/displaymessage="") // displaymessage can be something such as "rising from death" for Torpid Sleep. givewarningto is the person receiving messages.
|
||||
/mob/living/proc/HaveBloodsuckerBodyparts(displaymessage = "") // displaymessage can be something such as "rising from death" for Torpid Sleep. givewarningto is the person receiving messages.
|
||||
if(!getorganslot(ORGAN_SLOT_HEART))
|
||||
if(displaymessage != "")
|
||||
to_chat(src, "<span class='warning'>Without a heart, you are incapable of [displaymessage].</span>")
|
||||
@@ -21,33 +15,6 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
// GET DAMAGE
|
||||
|
||||
|
||||
// Do NOT count the damage on prosthetics for this.
|
||||
/mob/living/proc/getBruteLoss_nonProsthetic()
|
||||
return getBruteLoss()
|
||||
|
||||
/mob/living/proc/getFireLoss_nonProsthetic()
|
||||
return getFireLoss()
|
||||
|
||||
/mob/living/carbon/getBruteLoss_nonProsthetic()
|
||||
var/amount = 0
|
||||
for(var/obj/item/bodypart/BP in bodyparts)
|
||||
if(BP.status < 2)
|
||||
amount += BP.brute_dam
|
||||
return amount
|
||||
|
||||
/mob/living/carbon/getFireLoss_nonProsthetic()
|
||||
var/amount = 0
|
||||
for(var/obj/item/bodypart/BP in bodyparts)
|
||||
if(BP.status < 2)
|
||||
amount += BP.burn_dam
|
||||
return amount
|
||||
|
||||
/mob/living/carbon
|
||||
// EXAMINING
|
||||
/mob/living/carbon/human/proc/ReturnVampExamine(var/mob/viewer)
|
||||
if(!mind || !viewer.mind)
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/LifeTick()// Should probably run from life.dm, same as handle_changeling, but will be an utter pain to move
|
||||
set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side.
|
||||
var/notice_healing = FALSE
|
||||
var/notice_healing
|
||||
while(owner && !AmFinalDeath()) // owner.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) == src
|
||||
if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_DEATHCOMA)) // Deduct Blood
|
||||
AddBloodVolume(-0.1) // -.15 (before tick went from 10 to 30, but we also charge more for faking life now)
|
||||
AddBloodVolume(passive_blood_drain) // -.1 currently
|
||||
if(HandleHealing(1)) // Heal
|
||||
if(notice_healing == FALSE && owner.current.blood_volume > 0)
|
||||
to_chat(owner, "<span class='notice'>The power of your blood begins knitting your wounds...</span>")
|
||||
@@ -25,7 +25,7 @@
|
||||
HandleStarving() // Death
|
||||
HandleDeath() // Standard Update
|
||||
update_hud()// Daytime Sleep in Coffin
|
||||
if (SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker"))
|
||||
if(SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker"))
|
||||
if(istype(owner.current.loc, /obj/structure/closet/crate/coffin))
|
||||
Torpor_Begin()
|
||||
// Wait before next pass
|
||||
@@ -39,12 +39,12 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/AddBloodVolume(value)
|
||||
owner.current.blood_volume = CLAMP(owner.current.blood_volume + value, 0, maxBloodVolume)
|
||||
owner.current.blood_volume = CLAMP(owner.current.blood_volume + value, 0, max_blood_volume)
|
||||
update_hud()
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/HandleFeeding(mob/living/carbon/target, mult=1)
|
||||
// mult: SILENT feed is 1/3 the amount
|
||||
var/blood_taken = min(feedAmount, target.blood_volume) * mult // Starts at 15 (now 8 since we doubled the Feed time)
|
||||
var/blood_taken = min(feed_amount, target.blood_volume) * mult // Starts at 15 (now 8 since we doubled the Feed time)
|
||||
target.blood_volume -= blood_taken
|
||||
// Simple Animals lose a LOT of blood, and take damage. This is to keep cats, cows, and so forth from giving you insane amounts of blood.
|
||||
if(!ishuman(target))
|
||||
@@ -82,38 +82,40 @@
|
||||
/datum/antagonist/bloodsucker/proc/HandleHealing(mult = 1)
|
||||
// NOTE: Mult of 0 is just a TEST to see if we are injured and need to go into Torpor!
|
||||
//It is called from your coffin on close (by you only)
|
||||
var/actual_regen = regen_rate + additional_regen
|
||||
if(poweron_masquerade == TRUE || owner.current.AmStaked())
|
||||
return FALSE
|
||||
owner.current.adjustStaminaLoss(-1.5 + (regenRate * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more.
|
||||
owner.current.adjustCloneLoss(-0.1 * (regenRate * 2) * mult, 0)
|
||||
owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0)
|
||||
if(owner.current.reagents.has_reagent(/datum/reagent/consumable/garlic))
|
||||
return FALSE
|
||||
if(istype(owner.current.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace))
|
||||
return FALSE
|
||||
owner.current.adjustStaminaLoss(-1.5 + (actual_regen * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more.
|
||||
owner.current.adjustCloneLoss(-0.1 * (actual_regen * 2) * mult, 0)
|
||||
owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (actual_regen * 4) * mult)
|
||||
// No Bleeding
|
||||
if(ishuman(owner.current)) //NOTE Current bleeding is horrible, not to count the amount of blood ballistics delete.
|
||||
/*if(ishuman(owner.current)) //NOTE Current bleeding is horrible, not to count the amount of blood ballistics delete.
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
H.bleed_rate = 0
|
||||
if(H.bleed_rate > 0) //Only heal bleeding if we are actually bleeding
|
||||
H.bleed_rate =- 0.5 + actual_regen * 0.2 */
|
||||
if(iscarbon(owner.current)) // Damage Heal: Do I have damage to ANY bodypart?
|
||||
var/mob/living/carbon/C = owner.current
|
||||
var/costMult = 1 // Coffin makes it cheaper
|
||||
var/fireheal = 0 // BURN: Heal in Coffin while Fakedeath, or when damage above maxhealth (you can never fully heal fire)
|
||||
var/amInCoffinWhileTorpor = istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_DEATHCOMA)) // Check for mult 0 OR death coma. (mult 0 means we're testing from coffin)
|
||||
var/amInCoffinWhileTorpor = istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_FAKEDEATH)) // Check for mult 0 OR death coma. (mult 0 means we're testing from coffin)
|
||||
if(amInCoffinWhileTorpor)
|
||||
mult *= 4 // Increase multiplier if we're sleeping in a coffin.
|
||||
fireheal = min(C.getFireLoss_nonProsthetic(), regenRate) // NOTE: Burn damage ONLY heals in torpor.
|
||||
costMult = 0.25
|
||||
fireheal = min(C.getFireLoss(), regen_rate) // NOTE: Burn damage ONLY heals in torpor.
|
||||
C.ExtinguishMob()
|
||||
CureDisabilities() // Extinguish Fire
|
||||
C.remove_all_embedded_objects() // Remove Embedded!
|
||||
owner.current.regenerate_organs() // Heal Organs (will respawn original eyes etc. but we replace right away, next)
|
||||
CheckVampOrgans() // Heart, Eyes
|
||||
else
|
||||
if(owner.current.blood_volume <= 0) // No Blood? Lower Mult
|
||||
mult = 0.25
|
||||
// Crit from burn? Lower damage to maximum allowed.
|
||||
//if (C.getFireLoss() > owner.current.getMaxHealth())
|
||||
// fireheal = regenRate / 2
|
||||
if(check_limbs(costMult))
|
||||
return TRUE
|
||||
|
||||
// BRUTE: Always Heal
|
||||
var/bruteheal = min(C.getBruteLoss_nonProsthetic(), regenRate)
|
||||
var/toxinheal = min(C.getToxLoss(), regenRate)
|
||||
var/bruteheal = min(C.getBruteLoss(), actual_regen)
|
||||
var/toxinheal = min(C.getToxLoss(), actual_regen)
|
||||
// Heal if Damaged
|
||||
if(bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return.
|
||||
if(mult == 0)
|
||||
@@ -127,28 +129,29 @@
|
||||
//C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above.
|
||||
AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + toxinheal * -0.2) / mult * costMult) // Costs blood to heal
|
||||
return TRUE // Healed! Done for this tick.
|
||||
if(amInCoffinWhileTorpor) // Limbs? (And I have no other healing)
|
||||
var/list/missing = owner.current.get_missing_limbs() // Heal Missing
|
||||
if (missing.len) // Cycle through ALL limbs and regen them!
|
||||
for (var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it.
|
||||
owner.current.regenerate_limb(targetLimbZone, 0) // regenerate_limbs() <--- If you want to EXCLUDE certain parts, do it like this ----> regenerate_limbs(0, list("head"))
|
||||
var/obj/item/bodypart/L = owner.current.get_bodypart( targetLimbZone ) // 2) Limb returns Damaged
|
||||
AddBloodVolume(50 * costMult) // Costs blood to heal
|
||||
L.brute_dam = 60
|
||||
to_chat(owner.current, "<span class='notice'>Your flesh knits as it regrows [L]!</span>")
|
||||
playsound(owner.current, 'sound/magic/demon_consume.ogg', 50, 1)
|
||||
// DONE! After regenerating ANY number of limbs, we stop here.
|
||||
return TRUE
|
||||
/*else // REMOVED: For now, let's just leave prosthetics on. Maybe you WANT to be a robovamp.
|
||||
// Remove Prosthetic/False Limb
|
||||
for(var/obj/item/bodypart/BP in C.bodyparts)
|
||||
message_admins("T1: [BP] ")
|
||||
if (istype(BP) && BP.status == 2)
|
||||
message_admins("T2: [BP] ")
|
||||
BP.drop_limb()
|
||||
return TRUE */
|
||||
// NOTE: Limbs have a "status", like their hosts "stat". 2 is dead (aka Prosthetic). 1 seems to be idle/alive.*/
|
||||
return FALSE
|
||||
|
||||
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/check_limbs(costMult)
|
||||
var/limb_regen_cost = 50 * costMult
|
||||
var/mob/living/carbon/C = owner.current
|
||||
var/list/missing = C.get_missing_limbs()
|
||||
if(missing.len && C.blood_volume < limb_regen_cost + 5)
|
||||
return FALSE
|
||||
for(var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it.
|
||||
C.regenerate_limb(targetLimbZone, FALSE) // regenerate_limbs() <--- If you want to EXCLUDE certain parts, do it like this ----> regenerate_limbs(0, list("head"))
|
||||
AddBloodVolume(50)
|
||||
var/obj/item/bodypart/L = C.get_bodypart(targetLimbZone) // 2) Limb returns Damaged
|
||||
L.brute_dam = 60
|
||||
to_chat(C, "<span class='notice'>Your flesh knits as it regrows your [L]!</span>")
|
||||
playsound(C, 'sound/magic/demon_consume.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
/*for(var/obj/item/bodypart/BP in C.bodyparts)
|
||||
if(!istype(BP) && !BP.status == 2)
|
||||
return FALSE
|
||||
to_chat(C, "<span class='notice'>Your body expels the [BP]!</span>")
|
||||
BP.drop_limb()
|
||||
return TRUE */
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/CureDisabilities()
|
||||
var/mob/living/carbon/C = owner.current
|
||||
@@ -179,7 +182,16 @@
|
||||
if(owner.current.blood_volume < BLOOD_VOLUME_BAD / 2)
|
||||
owner.current.blur_eyes(8 - 8 * (owner.current.blood_volume / BLOOD_VOLUME_BAD))
|
||||
// Nutrition
|
||||
owner.current.nutrition = min(owner.current.blood_volume, NUTRITION_LEVEL_FED) // <-- 350 //NUTRITION_LEVEL_FULL
|
||||
owner.current.nutrition = clamp(owner.current.blood_volume, 545, 0) //The amount of blood is how full we are.
|
||||
//A bit higher regeneration based on blood volume
|
||||
if(owner.current.blood_volume < 700)
|
||||
additional_regen = 0.4
|
||||
else if(owner.current.blood_volume < BLOOD_VOLUME_NORMAL)
|
||||
additional_regen = 0.3
|
||||
else if(owner.current.blood_volume < BLOOD_VOLUME_OKAY)
|
||||
additional_regen = 0.2
|
||||
else if(owner.current.blood_volume < BLOOD_VOLUME_BAD)
|
||||
additional_regen = 0.1
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// DEATH
|
||||
@@ -189,7 +201,7 @@
|
||||
/datum/antagonist/bloodsucker/proc/HandleDeath()
|
||||
// FINAL DEATH
|
||||
// Fire Damage? (above double health)
|
||||
if(owner.current.getFireLoss_nonProsthetic() >= owner.current.maxHealth * 2.5)
|
||||
if(owner.current.getFireLoss() >= owner.current.maxHealth * 3)
|
||||
FinalDeath()
|
||||
return
|
||||
// Staked while "Temp Death" or Asleep
|
||||
@@ -209,8 +221,8 @@
|
||||
// for (var/datum/action/bloodsucker/masquerade/P in powers)
|
||||
// P.Deactivate()
|
||||
// TEMP DEATH
|
||||
var/total_brute = owner.current.getBruteLoss_nonProsthetic()
|
||||
var/total_burn = owner.current.getFireLoss_nonProsthetic()
|
||||
var/total_brute = owner.current.getBruteLoss()
|
||||
var/total_burn = owner.current.getFireLoss()
|
||||
var/total_toxloss = owner.current.getToxLoss() //This is neater than just putting it in total_damage
|
||||
var/total_damage = total_brute + total_burn + total_toxloss
|
||||
// Died? Convert to Torpor (fake death)
|
||||
@@ -218,27 +230,25 @@
|
||||
Torpor_Begin()
|
||||
to_chat(owner, "<span class='danger'>Your immortal body will not yet relinquish your soul to the abyss. You enter Torpor.</span>")
|
||||
sleep(30) //To avoid spam
|
||||
if (poweron_masquerade == TRUE)
|
||||
if(poweron_masquerade == TRUE)
|
||||
to_chat(owner, "<span class='warning'>Your wounds will not heal until you disable the <span class='boldnotice'>Masquerade</span> power.</span>")
|
||||
// End Torpor:
|
||||
else // No damage, OR toxin healed AND brute healed and NOT in coffin (since you cannot heal burn)
|
||||
if(total_damage <= 0 || total_toxloss <= 0 && total_brute <= 0 && !istype(owner.current.loc, /obj/structure/closet/crate/coffin))
|
||||
// Not Daytime, Not in Torpor
|
||||
if(!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker"))
|
||||
if(!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker"))
|
||||
Torpor_End()
|
||||
// Fake Unconscious
|
||||
if(poweron_masquerade == TRUE && total_damage >= owner.current.getMaxHealth() - HEALTH_THRESHOLD_FULLCRIT)
|
||||
owner.current.Unconscious(20,1)
|
||||
//HEALTH_THRESHOLD_CRIT 0
|
||||
//HEALTH_THRESHOLD_FULLCRIT -30
|
||||
//HEALTH_THRESHOLD_DEAD -100
|
||||
owner.current.Unconscious(20, 1)
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/Torpor_Begin(amInCoffin=FALSE)
|
||||
/datum/antagonist/bloodsucker/proc/Torpor_Begin(amInCoffin = FALSE)
|
||||
owner.current.stat = UNCONSCIOUS
|
||||
owner.current.fakedeath("bloodsucker") // Come after UNCONSCIOUS or else it fails
|
||||
owner.current.apply_status_effect(STATUS_EFFECT_UNCONSCIOUS)
|
||||
ADD_TRAIT(owner.current, TRAIT_FAKEDEATH, "bloodsucker") // Come after UNCONSCIOUS or else it fails
|
||||
ADD_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker") // Without this, you'll just keep dying while you recover.
|
||||
ADD_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever.
|
||||
ADD_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever.
|
||||
ADD_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in space. Otherwise you just...heal forever.
|
||||
ADD_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker")
|
||||
// Visuals
|
||||
owner.current.update_sight()
|
||||
owner.current.reload_fullscreen()
|
||||
@@ -247,10 +257,10 @@
|
||||
if(power.active && !power.can_use_in_torpor)
|
||||
power.DeactivatePower()
|
||||
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/Torpor_End()
|
||||
owner.current.stat = SOFT_CRIT
|
||||
owner.current.cure_fakedeath("bloodsucker") // Come after SOFT_CRIT or else it fails
|
||||
owner.current.remove_status_effect(STATUS_EFFECT_UNCONSCIOUS)
|
||||
REMOVE_TRAIT(owner.current, TRAIT_FAKEDEATH, "bloodsucker")
|
||||
REMOVE_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker")
|
||||
REMOVE_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker")
|
||||
REMOVE_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker")
|
||||
@@ -283,18 +293,19 @@
|
||||
// Free my Vassals!
|
||||
FreeAllVassals()
|
||||
// Elders get Dusted
|
||||
if(vamplevel >= 4) // (vamptitle)
|
||||
if(bloodsucker_level >= 4) // (bloodsucker_title)
|
||||
owner.current.visible_message("<span class='warning'>[owner.current]'s skin crackles and dries, their skin and bones withering to dust. A hollow cry whips from what is now a sandy pile of remains.</span>", \
|
||||
"<span class='userdanger'>Your soul escapes your withering body as the abyss welcomes you to your Final Death.</span>", \
|
||||
"<span class='italics'>You hear a dry, crackling sound.</span>")
|
||||
sleep(50)
|
||||
owner.current.dust()
|
||||
// Fledglings get Gibbed
|
||||
else
|
||||
owner.current.visible_message("<span class='warning'>[owner.current]'s skin bursts forth in a spray of gore and detritus. A horrible cry echoes from what is now a wet pile of decaying meat.</span>", \
|
||||
"<span class='userdanger'>Your soul escapes your withering body as the abyss welcomes you to your Final Death.</span>", \
|
||||
"<span class='italics'>You hear a wet, bursting sound.</span>")
|
||||
owner.current.gib(TRUE, FALSE, FALSE)//Brain cloning is wierd and allows hellbounds. Lets destroy the brain for safety.
|
||||
playsound(owner.current.loc, 'sound/effects/tendril_destroyed.ogg', 40, 1)
|
||||
owner.current.gib(TRUE, FALSE, FALSE) //Brain cloning is wierd and allows hellbounds. Lets destroy the brain for safety.
|
||||
playsound(owner.current, 'sound/effects/tendril_destroyed.ogg', 40, TRUE)
|
||||
|
||||
|
||||
|
||||
@@ -304,15 +315,15 @@
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/mob/proc/CheckBloodsuckerEatFood(var/food_nutrition)
|
||||
if (!isliving(src))
|
||||
/mob/proc/CheckBloodsuckerEatFood(food_nutrition)
|
||||
if(!isliving(src))
|
||||
return
|
||||
var/mob/living/L = src
|
||||
if(!L.AmBloodsucker())
|
||||
if(!AmBloodsucker(L))
|
||||
return
|
||||
// We're a vamp? Try to eat food...
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
bloodsuckerdatum.handle_eat_human_food(food_nutrition)
|
||||
// We're a bloodsucker? Try to eat food...
|
||||
var/datum/antagonist/bloodsucker/B = L.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
B.handle_eat_human_food(food_nutrition)
|
||||
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/handle_eat_human_food(food_nutrition, puke_blood = TRUE, masquerade_override) // Called from snacks.dm and drinks.dm
|
||||
|
||||
@@ -93,6 +93,14 @@
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>You have a stake in your chest! Your powers are useless.</span>")
|
||||
return FALSE
|
||||
if(istype(owner.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace))
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'The necklace on your neck is interfering with your powers!</span>")
|
||||
return FALSE
|
||||
if(owner.reagents?.has_reagent(/datum/reagent/consumable/garlic))
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>Garlic in your blood is interfering with your powers!</span>")
|
||||
return FALSE
|
||||
// Incap?
|
||||
if(must_be_capacitated)
|
||||
var/mob/living/L = owner
|
||||
|
||||
@@ -141,23 +141,23 @@
|
||||
if(!bloodsuckerdatum.warn_sun_locker)
|
||||
to_chat(M, "<span class='warning'>Your skin sizzles. The [M.current.loc] doesn't protect well against UV bombardment.</span>")
|
||||
bloodsuckerdatum.warn_sun_locker = TRUE
|
||||
M.current.adjustFireLoss(0.5 + bloodsuckerdatum.vamplevel / 2) // M.current.fireloss += 0.5 + bloodsuckerdatum.vamplevel / 2 // Do DIRECT damage. Being spaced was causing this to not occur. setFireLoss(bloodsuckerdatum.vamplevel)
|
||||
M.current.adjustFireLoss(0.5 + bloodsuckerdatum.bloodsucker_level / 2) // M.current.fireloss += 0.5 + bloodsuckerdatum.bloodsucker_level / 2 // Do DIRECT damage. Being spaced was causing this to not occur. setFireLoss(bloodsuckerdatum.bloodsucker_level)
|
||||
M.current.updatehealth()
|
||||
SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_1)
|
||||
// Out in the Open? Buh Bye
|
||||
else
|
||||
if(!bloodsuckerdatum.warn_sun_burn)
|
||||
if(bloodsuckerdatum.vamplevel > 0)
|
||||
if(bloodsuckerdatum.bloodsucker_level > 0)
|
||||
to_chat(M, "<span class='userdanger'>The solar flare sets your skin ablaze!</span>")
|
||||
else
|
||||
to_chat(M, "<span class='userdanger'>The solar flare scalds your neophyte skin!</span>")
|
||||
bloodsuckerdatum.warn_sun_burn = TRUE
|
||||
if(M.current.fire_stacks <= 0)
|
||||
M.current.fire_stacks = 0
|
||||
if(bloodsuckerdatum.vamplevel > 0)
|
||||
M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.vamplevel / 10)
|
||||
if(bloodsuckerdatum.bloodsucker_level > 0)
|
||||
M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.bloodsucker_level / 10)
|
||||
M.current.IgniteMob()
|
||||
M.current.adjustFireLoss(2 + bloodsuckerdatum.vamplevel) // M.current.fireloss += 2 + bloodsuckerdatum.vamplevel // Do DIRECT damage. Being spaced was causing this to not occur. //setFireLoss(2 + bloodsuckerdatum.vamplevel)
|
||||
M.current.adjustFireLoss(2 + bloodsuckerdatum.bloodsucker_level) // M.current.fireloss += 2 + bloodsuckerdatum.bloodsucker_level // Do DIRECT damage. Being spaced was causing this to not occur. //setFireLoss(2 + bloodsuckerdatum.bloodsucker_level)
|
||||
M.current.updatehealth()
|
||||
SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_2)
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
job_rank = ROLE_BLOODSUCKER
|
||||
threat = 5
|
||||
// NAME
|
||||
var/vampname // My Dracula name
|
||||
var/vamptitle // My Dracula title
|
||||
var/vampreputation // My "Surname" or description of my deeds
|
||||
var/bloodsucker_name // My Dracula style name
|
||||
var/bloodsucker_title // My Dracula style title
|
||||
var/bloodsucker_reputation // My "Surname" or description of my deeds
|
||||
// CLAN
|
||||
var/datum/team/vampireclan/clan
|
||||
var/list/datum/antagonist/vassal/vassals = list()// Vassals under my control. Periodically remove the dead ones.
|
||||
@@ -20,35 +20,33 @@
|
||||
var/poweron_feed = FALSE // Am I feeding?
|
||||
var/poweron_masquerade = FALSE
|
||||
// STATS
|
||||
var/vamplevel = 0
|
||||
var/vamplevel_unspent = 1
|
||||
var/regenRate = 0.4 // How many points of Brute do I heal per tick?
|
||||
var/feedAmount = 15 // Amount of blood drawn from a target per tick.
|
||||
var/maxBloodVolume = 600 // Maximum blood a Vamp can hold via feeding. // BLOOD_VOLUME_NORMAL 550 // BLOOD_VOLUME_SAFE 475 //BLOOD_VOLUME_OKAY 336 //BLOOD_VOLUME_BAD 224 // BLOOD_VOLUME_SURVIVE 122
|
||||
var/bloodsucker_level
|
||||
var/bloodsucker_level_unspent = 1
|
||||
var/regen_rate = 0.3 // How fast do I regenerate?
|
||||
var/additional_regen // How much additional blood regen we gain from bonuses such as high blood.
|
||||
var/feed_amount = 15 // Amount of blood drawn from a target per tick.
|
||||
var/max_blood_volume = 600 // Maximum blood a Vamp can hold via feeding.
|
||||
// OBJECTIVES
|
||||
var/list/datum/objective/objectives_given = list() // For removal if needed.
|
||||
var/area/lair
|
||||
var/obj/structure/closet/crate/coffin
|
||||
// TRACKING
|
||||
var/foodInGut = 0 // How much food to throw up later. You shouldn't have eaten that.
|
||||
var/warn_sun_locker = FALSE // So we only get the locker burn message once per day.
|
||||
var/warn_sun_burn = FALSE // So we only get the sun burn message once per day.
|
||||
var/had_toxlover = FALSE
|
||||
var/foodInGut // How much food to throw up later. You shouldn't have eaten that.
|
||||
var/warn_sun_locker // So we only get the locker burn message once per day.
|
||||
var/warn_sun_burn // So we only get the sun burn message once per day.
|
||||
var/had_toxlover
|
||||
var/level_bloodcost
|
||||
var/passive_blood_drain = -0.1 //The amount of blood we loose each bloodsucker life() tick
|
||||
// LISTS
|
||||
var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_NIGHT_VISION, \
|
||||
TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE)
|
||||
// NOTES: TRAIT_AGEUSIA <-- Doesn't like flavors.
|
||||
// REMOVED: TRAIT_NODEATH
|
||||
// TO ADD:
|
||||
//var/static/list/defaultOrgans = list (/obj/item/organ/heart/vampheart,/obj/item/organ/heart/vampeyes)
|
||||
|
||||
/datum/antagonist/bloodsucker/on_gain()
|
||||
SSticker.mode.bloodsuckers |= owner // Add if not already in here (and you might be, if you were picked at round start)
|
||||
SSticker.mode.check_start_sunlight()// Start Sunlight? (if first Vamp)
|
||||
SelectFirstName()// Name & Title
|
||||
SelectTitle(am_fledgling=TRUE) // If I have a creator, then set as Fledgling.
|
||||
SelectReputation(am_fledgling=TRUE)
|
||||
SelectTitle(am_fledgling = TRUE) // If I have a creator, then set as Fledgling.
|
||||
SelectReputation(am_fledgling = TRUE)
|
||||
AssignStarterPowersAndStats()// Give Powers & Stats
|
||||
forge_bloodsucker_objectives()// Objectives & Team
|
||||
update_bloodsucker_icons_added(owner.current, "bloodsucker") // Add Antag HUD
|
||||
@@ -68,18 +66,18 @@
|
||||
|
||||
/datum/antagonist/bloodsucker/greet()
|
||||
var/fullname = ReturnFullName(TRUE)
|
||||
to_chat(owner, "<span class='userdanger'>You are [fullname], a bloodsucking vampire!</span><br>")
|
||||
to_chat(owner, "<span class='userdanger'>You are [fullname], a strain of vampire dubbed bloodsucker!</span><br>")
|
||||
owner.announce_objectives()
|
||||
to_chat(owner, "<span class='boldannounce'>* You regenerate your health slowly, you're weak to fire, and you depend on blood to survive. Allow your stolen blood to run too low, and you will find yourself at \
|
||||
risk of being discovered!</span><br>")
|
||||
//to_chat(owner, "<span class='boldannounce'>As an immortal, your power is linked to your age. The older you grow, the more abilities you will have access to.<span>")
|
||||
var/vamp_greet
|
||||
vamp_greet += "<span class='boldannounce'>* Other Bloodsuckers are not necessarily your friends, but your survival may depend on cooperation. Betray them at your own discretion and peril.</span><br>"
|
||||
vamp_greet += "<span class='boldannounce'><i>* Use \",b\" to speak your ancient Bloodsucker language.</span><br>"
|
||||
vamp_greet += "<span class='announce'>Bloodsucker Tip: Rest in a <i>Coffin</i> to claim it, and that area, as your lair.</span><br>"
|
||||
vamp_greet += "<span class='announce'>Bloodsucker Tip: Fear the daylight! Solar flares will bombard the station periodically, and only your coffin can guarantee your safety.</span><br>"
|
||||
vamp_greet += "<span class='announce'>Bloodsucker Tip: You wont loose blood if you are unconcious or sleeping. Use this to your advantage to conserve blood.</span><br>"
|
||||
to_chat(owner, vamp_greet)
|
||||
var/bloodsucker_greet
|
||||
bloodsucker_greet += "<span class='boldannounce'>* Other Bloodsuckers are not necessarily your friends, but your survival may depend on cooperation. Betray them at your own discretion and peril.</span><br>"
|
||||
bloodsucker_greet += "<span class='boldannounce'><i>* Use \",b\" to speak your ancient Bloodsucker language.</span><br>"
|
||||
bloodsucker_greet += "<span class='announce'>Bloodsucker Tip: Rest in a <i>Coffin</i> to claim it, and that area, as your lair.</span><br>"
|
||||
bloodsucker_greet += "<span class='announce'>Bloodsucker Tip: Fear the daylight! Solar flares will bombard the station periodically, and only your coffin can guarantee your safety.</span><br>"
|
||||
bloodsucker_greet += "<span class='announce'>Bloodsucker Tip: You wont loose blood if you are unconcious or sleeping. Use this to your advantage to conserve blood.</span><br>"
|
||||
to_chat(owner, bloodsucker_greet)
|
||||
|
||||
owner.current.playsound_local(null, 'sound/bloodsucker/BloodsuckerAlert.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
antag_memory += "Although you were born a mortal, in un-death you earned the name <b>[fullname]</b>.<br>"
|
||||
@@ -92,13 +90,13 @@
|
||||
owner.current.blood_volume = max(owner.current.blood_volume,BLOOD_VOLUME_SAFE)
|
||||
|
||||
/datum/antagonist/bloodsucker/threat()
|
||||
return ..()+3*vamplevel
|
||||
return ..() + 3 * bloodsucker_level
|
||||
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/SelectFirstName()
|
||||
// Names (EVERYONE gets one))
|
||||
if(owner.current.gender == MALE)
|
||||
vampname = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \
|
||||
bloodsucker_name = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \
|
||||
"Sveyn","Aurel","Alexe","Iustin","Theodor","Dimitrie","Octav","Damien","Magnus","Caine","Abel", // Romanian/Ancient
|
||||
"Lucius","Gaius","Otho","Balbinus","Arcadius","Romanos","Alexios","Vitellius", // Latin
|
||||
"Melanthus","Teuthras","Orchamus","Amyntor","Axion", // Greek
|
||||
@@ -106,7 +104,7 @@
|
||||
"Dio")
|
||||
|
||||
else
|
||||
vampname = pick("Islana","Tyrra","Greganna","Pytra","Hilda","Andra","Crina","Viorela","Viorica","Anemona","Camelia","Narcisa","Sorina","Alessia","Sophia","Gladda","Arcana","Morgan","Lasarra","Ioana","Elena", \
|
||||
bloodsucker_name = pick("Islana","Tyrra","Greganna","Pytra","Hilda","Andra","Crina","Viorela","Viorica","Anemona","Camelia","Narcisa","Sorina","Alessia","Sophia","Gladda","Arcana","Morgan","Lasarra","Ioana","Elena", \
|
||||
"Alina","Rodica","Teodora","Denisa","Mihaela","Svetla","Stefania","Diyana","Kelssa","Lilith", // Romanian/Ancient
|
||||
"Alexia","Athanasia","Callista","Karena","Nephele","Scylla","Ursa", // Latin
|
||||
"Alcestis","Damaris","Elisavet","Khthonia","Teodora", // Greek
|
||||
@@ -114,57 +112,57 @@
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/SelectTitle(am_fledgling = 0, forced = FALSE)
|
||||
// Already have Title
|
||||
if (!forced && vamptitle != null)
|
||||
if(!forced && bloodsucker_title != null)
|
||||
return
|
||||
// Titles [Master]
|
||||
if (!am_fledgling)
|
||||
if(!am_fledgling)
|
||||
if(owner.current.gender == MALE)
|
||||
vamptitle = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master")
|
||||
bloodsucker_title = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master")
|
||||
else
|
||||
vamptitle = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress")
|
||||
bloodsucker_title = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress")
|
||||
to_chat(owner, "<span class='announce'>You have earned a title! You are now known as <i>[ReturnFullName(TRUE)]</i>!</span>")
|
||||
// Titles [Fledgling]
|
||||
else
|
||||
vamptitle = null
|
||||
bloodsucker_title = null
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/SelectReputation(am_fledgling = 0, forced=FALSE)
|
||||
// Already have Reputation
|
||||
if(!forced && vampreputation != null)
|
||||
if(!forced && bloodsucker_reputation != null)
|
||||
return
|
||||
// Reputations [Master]
|
||||
if(!am_fledgling)
|
||||
vampreputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \
|
||||
bloodsucker_reputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \
|
||||
"Inqisitor","Harvester","Reviled","Robust","Betrayer","Destructor","Damned","Accursed","Terrible","Vicious","Profane","Vile","Depraved","Foul","Slayer","Manslayer","Sovereign","Slaughterer", \
|
||||
"Forsaken","Mad","Dragon","Savage","Villainous","Nefarious","Inquisitor","Marauder","Horrible","Immortal","Undying","Overlord","Corrupt","Hellspawn","Tyrant","Sanguineous")
|
||||
if(owner.current.gender == MALE)
|
||||
if(prob(10)) // Gender override
|
||||
vampreputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King")
|
||||
bloodsucker_reputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King")
|
||||
else
|
||||
if(prob(10)) // Gender override
|
||||
vampreputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen")
|
||||
bloodsucker_reputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen")
|
||||
|
||||
to_chat(owner, "<span class='announce'>You have earned a reputation! You are now known as <i>[ReturnFullName(TRUE)]</i>!</span>")
|
||||
|
||||
// Reputations [Fledgling]
|
||||
else
|
||||
vampreputation = pick ("Crude","Callow","Unlearned","Neophyte","Novice","Unseasoned","Fledgling","Young","Neonate","Scrapling","Untested","Unproven","Unknown","Newly Risen","Born","Scavenger","Unknowing",\
|
||||
bloodsucker_reputation = pick ("Crude","Callow","Unlearned","Neophyte","Novice","Unseasoned","Fledgling","Young","Neonate","Scrapling","Untested","Unproven","Unknown","Newly Risen","Born","Scavenger","Unknowing",\
|
||||
"Unspoiled","Disgraced","Defrocked","Shamed","Meek","Timid","Broken")//,"Fresh")
|
||||
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/AmFledgling()
|
||||
return !vamptitle
|
||||
return !bloodsucker_title
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/ReturnFullName(var/include_rep=0)
|
||||
|
||||
var/fullname
|
||||
// Name First
|
||||
fullname = (vampname ? vampname : owner.current.name)
|
||||
fullname = (bloodsucker_name ? bloodsucker_name : owner.current.name)
|
||||
// Title
|
||||
if(vamptitle)
|
||||
fullname = vamptitle + " " + fullname
|
||||
if(bloodsucker_title)
|
||||
fullname = bloodsucker_title + " " + fullname
|
||||
// Rep
|
||||
if(include_rep && vampreputation)
|
||||
fullname = fullname + " the " + vampreputation
|
||||
if(include_rep && bloodsucker_reputation)
|
||||
fullname = fullname + " the " + bloodsucker_reputation
|
||||
|
||||
return fullname
|
||||
|
||||
@@ -199,15 +197,12 @@
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/datum/species/S = H.dna.species
|
||||
// Make Changes
|
||||
H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank!
|
||||
H.physiology.brute_mod *= 0.8
|
||||
H.physiology.cold_mod = 0
|
||||
H.physiology.stun_mod *= 0.5
|
||||
H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1
|
||||
//S.heatmod += 0.5 // Heat shouldn't affect. Only Fire.
|
||||
//S.punchstunthreshold = 8 //damage at which punches from this race will stun 9
|
||||
S.punchdamagelow += 1 //lowest possible punch damage 0
|
||||
S.punchdamagehigh += 1 //highest possible punch damage 9
|
||||
// Clown
|
||||
if(istype(H) && owner.assigned_role == "Clown")
|
||||
H.dna.remove_mutation(CLOWNMUT)
|
||||
to_chat(H, "As a vampiric clown, you are no longer a danger to yourself. Your nature is subdued.")
|
||||
@@ -215,8 +210,6 @@
|
||||
CheckVampOrgans() // Heart, Eyes
|
||||
// Language
|
||||
owner.current.grant_language(/datum/language/vampiric)
|
||||
// Soul
|
||||
//owner.current.hellbound = TRUE Causes wierd stuff
|
||||
owner.hasSoul = FALSE // If false, renders the character unable to sell their soul.
|
||||
owner.isholy = FALSE // is this person a chaplain or admin role allowed to use bibles
|
||||
// Disabilities
|
||||
@@ -248,7 +241,6 @@
|
||||
// Clown
|
||||
if(istype(H) && owner.assigned_role == "Clown")
|
||||
H.dna.add_mutation(CLOWNMUT)
|
||||
// NOTE: Use initial() to return things to default!
|
||||
// Physiology
|
||||
owner.current.regenerate_organs()
|
||||
// Update Health
|
||||
@@ -264,13 +256,13 @@
|
||||
set waitfor = FALSE
|
||||
if(!owner || !owner.current)
|
||||
return
|
||||
vamplevel_unspent ++
|
||||
bloodsucker_level_unspent ++
|
||||
// Spend Rank Immediately?
|
||||
if(istype(owner.current.loc, /obj/structure/closet/crate/coffin))
|
||||
SpendRank()
|
||||
else
|
||||
to_chat(owner, "<EM><span class='notice'>You have grown more ancient! Sleep in a coffin that you have claimed to thicken your blood and become more powerful.</span></EM>")
|
||||
if(vamplevel_unspent >= 2)
|
||||
if(bloodsucker_level_unspent >= 2)
|
||||
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks.</span><br>")
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/LevelUpPowers()
|
||||
@@ -279,10 +271,10 @@
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
set waitfor = FALSE
|
||||
if(vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current))
|
||||
if(bloodsucker_level_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current))
|
||||
return
|
||||
var/mob/living/L = owner.current
|
||||
level_bloodcost = maxBloodVolume * 0.2
|
||||
level_bloodcost = max_blood_volume * 0.2
|
||||
//If the blood volume of the bloodsucker is lower than the cost to level up, return and inform the bloodsucker
|
||||
|
||||
//TODO: Make this into a radial, or perhaps a tgui next UI
|
||||
@@ -298,7 +290,7 @@
|
||||
if(options.len > 1)
|
||||
var/choice = input(owner.current, "You have the opportunity to grow more ancient at the cost of [level_bloodcost] units of blood. Select a power to advance your Rank.", "Your Blood Thickens...") in options
|
||||
// Cheat-Safety: Can't keep opening/closing coffin to spam levels
|
||||
if(vamplevel_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal.
|
||||
if(bloodsucker_level_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal.
|
||||
return
|
||||
if(!istype(owner.current.loc, /obj/structure/closet/crate/coffin))
|
||||
to_chat(owner.current, "<span class='warning'>Return to your coffin to advance your Rank.</span>")
|
||||
@@ -329,20 +321,20 @@
|
||||
// More Health
|
||||
owner.current.setMaxHealth(owner.current.maxHealth + 10)
|
||||
// Vamp Stats
|
||||
regenRate += 0.05 // Points of brute healed (starts at 0.3)
|
||||
feedAmount += 2 // Increase how quickly I munch down vics (15)
|
||||
maxBloodVolume += 100 // Increase my max blood (600)
|
||||
regen_rate += 0.05 // Points of brute healed (starts at 0.3)
|
||||
feed_amount += 2 // Increase how quickly I munch down vics (15)
|
||||
max_blood_volume += 100 // Increase my max blood (600)
|
||||
/////////
|
||||
vamplevel ++
|
||||
vamplevel_unspent --
|
||||
bloodsucker_level ++
|
||||
bloodsucker_level_unspent --
|
||||
|
||||
// Assign True Reputation
|
||||
if(vamplevel == 4)
|
||||
if(bloodsucker_level == 4)
|
||||
SelectReputation(am_fledgling = FALSE, forced = TRUE)
|
||||
to_chat(owner.current, "<span class='notice'>You are now a rank [vamplevel] Bloodsucker. Your strength, health, feed rate, regen rate, and maximum blood have all increased!</span>")
|
||||
to_chat(owner.current, "<span class='notice'>You are now a rank [bloodsucker_level] Bloodsucker. Your strength, health, feed rate, regen rate, can have up to [bloodsucker_level - count_vassals(owner.current.mind)] vassals, and maximum blood have all increased!</span>")
|
||||
to_chat(owner.current, "<span class='notice'>Your existing powers have all ranked up as well!</span>")
|
||||
update_hud(TRUE)
|
||||
owner.current.playsound_local(null, 'sound/effects/pope_entry.ogg', 25, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head.
|
||||
owner.current.playsound_local(null, 'sound/effects/pope_entry.ogg', 25, TRUE, pressure_affected = FALSE)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -654,13 +646,13 @@
|
||||
var/datum/antagonist/vassal/mob_V = M.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
// Check 2) If they are a BLOODSUCKER, then are they my Master?
|
||||
if (mob_V && atom_B == mob_V.master)
|
||||
return TRUE // SUCCESS!
|
||||
return TRUE
|
||||
// Check 3) If I am a BLOODSUCKER, then are they my Vassal?
|
||||
if (mob_B && atom_V && (atom_V in mob_B.vassals))
|
||||
return TRUE // SUCCESS!
|
||||
return TRUE
|
||||
// Check 4) If we are both VASSAL, then do we have the same master?
|
||||
if (atom_V && mob_V && atom_V.master == mob_V.master)
|
||||
return TRUE // SUCCESS!
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -705,10 +697,10 @@
|
||||
|
||||
// Update Rank Counter
|
||||
if(owner.current.hud_used.vamprank_display)
|
||||
var/valuecolor = vamplevel_unspent ? "#FFFF00" : "#FF0000"
|
||||
owner.current.hud_used.vamprank_display.update_counter(vamplevel, valuecolor)
|
||||
var/valuecolor = bloodsucker_level_unspent ? "#FFFF00" : "#FF0000"
|
||||
owner.current.hud_used.vamprank_display.update_counter(bloodsucker_level, valuecolor)
|
||||
if(updateRank) // Only change icon on special request.
|
||||
owner.current.hud_used.vamprank_display.icon_state = (vamplevel_unspent > 0) ? "rank_up" : "rank"
|
||||
owner.current.hud_used.vamprank_display.icon_state = (bloodsucker_level_unspent > 0) ? "rank_up" : "rank"
|
||||
|
||||
|
||||
/obj/screen/bloodsucker
|
||||
@@ -718,12 +710,12 @@
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/obj/screen/bloodsucker/proc/update_counter(value, valuecolor)
|
||||
invisibility = 0 // Make Visible
|
||||
invisibility = 0
|
||||
|
||||
/obj/screen/bloodsucker/blood_counter // NOTE: Look up /obj/screen/devil/soul_counter in _onclick / hud / human.dm
|
||||
icon = 'icons/mob/actions/bloodsucker.dmi'//'icons/mob/screen_gen.dmi'
|
||||
/obj/screen/bloodsucker/blood_counter
|
||||
icon = 'icons/mob/actions/bloodsucker.dmi'
|
||||
name = "Blood Consumed"
|
||||
icon_state = "blood_display"//"power_display"
|
||||
icon_state = "blood_display"
|
||||
screen_loc = ui_blood_display
|
||||
|
||||
/obj/screen/bloodsucker/blood_counter/update_counter(value, valuecolor)
|
||||
@@ -748,22 +740,27 @@
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/update_sunlight(value, amDay = FALSE)
|
||||
// No Hud? Get out.
|
||||
if (!owner.current.hud_used)
|
||||
if(!owner.current.hud_used)
|
||||
return
|
||||
// Update Sun Time
|
||||
if (owner.current.hud_used.sunlight_display)
|
||||
if(owner.current.hud_used.sunlight_display)
|
||||
var/valuecolor = "#BBBBFF"
|
||||
if (amDay)
|
||||
if(amDay)
|
||||
valuecolor = "#FF5555"
|
||||
else if(value <= 25)
|
||||
valuecolor = "#FFCCCC"
|
||||
else if(value < 10)
|
||||
valuecolor = "#FF5555"
|
||||
var/value_string = (value >= 60) ? "[round(value / 60, 1)] m" : "[round(value,1)] s"
|
||||
var/value_string = (value >= 60) ? "[round(value / 60, 1)] m" : "[round(value, 1)] s"
|
||||
owner.current.hud_used.sunlight_display.update_counter( value_string, valuecolor )
|
||||
owner.current.hud_used.sunlight_display.icon_state = "sunlight_" + (amDay ? "day":"night")
|
||||
|
||||
|
||||
/obj/screen/bloodsucker/sunlight_counter/update_counter(value, valuecolor)
|
||||
..()
|
||||
maptext = "<div align='center' valign='bottom' style='position:relative; top:0px; left:6px'><font color='[valuecolor]'>[value]</font></div>"
|
||||
maptext = "<div align='center' valign='bottom' style='position:relative; top:0px; left:6px'><font color='[valuecolor]'>[value]</font></div>"
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/count_vassals(datum/mind/master)
|
||||
var/datum/antagonist/bloodsucker/B = master.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
var/vassal_amount = B.vassals.len
|
||||
return vassal_amount
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
var/obj/item/organ/O
|
||||
// Heart
|
||||
O = owner.current.getorganslot(ORGAN_SLOT_HEART)
|
||||
if(!istype(O, /obj/item/organ/heart/vampheart))
|
||||
|
||||
if(!istype(O, /obj/item/organ/heart/vampheart) && !istype(O, /obj/item/organ/heart/demon))
|
||||
qdel(O)
|
||||
var/obj/item/organ/heart/vampheart/H = new
|
||||
H.Insert(owner.current)
|
||||
|
||||
@@ -115,13 +115,15 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/examine(mob/user)
|
||||
var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
. = ..()
|
||||
if(isvamp(user) || isobserver(user))
|
||||
if(B || isobserver(user))
|
||||
. += {"<span class='cult'>This is the vassal rack, which allows you to thrall crewmembers into loyal minions in your service.</span>"}
|
||||
. += {"<span class='cult'>You need to first secure the vassal rack by clicking on it while it is in your lair.</span>"}
|
||||
. += {"<span class='cult'>Simply click and hold on a victim, and then drag their sprite on the vassal rack. Alt click on the vassal rack to unbuckle them.</span>"}
|
||||
. += {"<span class='cult'>Make sure that the victim is handcuffed, or else they can simply run away or resist, as the process is not instant.</span>"}
|
||||
. += {"<span class='cult'>To convert the victim, simply click on the vassal rack itself. Sharp weapons work faster than other tools.</span>"}
|
||||
. += {"<span class='cult'> You have only the power for [B.bloodsucker_level - B.count_vassals(user.mind)] vassals</span>"}
|
||||
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
. += {"<span class='cult'>This is the vassal rack, which allows your master to thrall crewmembers into his minions.\n
|
||||
Aid your master in bringing their victims here and keeping them secure.\n
|
||||
@@ -130,7 +132,7 @@
|
||||
/obj/structure/bloodsucker/vassalrack/MouseDrop_T(atom/movable/O, mob/user)
|
||||
if(!O.Adjacent(src) || O == user || !isliving(O) || !isliving(user) || useLock || has_buckled_mobs() || user.incapacitated())
|
||||
return
|
||||
if(!anchored && isvamp(user))
|
||||
if(!anchored && AmBloodsucker(user))
|
||||
to_chat(user, "<span class='danger'>Until this rack is secured in place, it cannot serve its purpose.</span>")
|
||||
return
|
||||
// PULL TARGET: Remember if I was pullin this guy, so we can restore this
|
||||
@@ -183,7 +185,7 @@
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/user_unbuckle_mob(mob/living/M, mob/user)
|
||||
// Attempt Unbuckle
|
||||
if(!isvamp(user))
|
||||
if(!AmBloodsucker(user))
|
||||
if(M == user)
|
||||
M.visible_message("<span class='danger'>[user] tries to release themself from the rack!</span>",\
|
||||
"<span class='danger'>You attempt to release yourself from the rack!</span>") // For sound if not seen --> "<span class='italics'>You hear a squishy wet noise.</span>")
|
||||
@@ -222,15 +224,15 @@
|
||||
// Go away. Torturing.
|
||||
if(useLock)
|
||||
return
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
// CHECK ONE: Am I claiming this? Is it in the right place?
|
||||
if(istype(bloodsuckerdatum) && !owner)
|
||||
if(!bloodsuckerdatum.lair)
|
||||
if(istype(B) && !owner)
|
||||
if(!B.lair)
|
||||
to_chat(user, "<span class='danger'>You don't have a lair. Claim a coffin to make that location your lair.</span>")
|
||||
if(bloodsuckerdatum.lair != get_area(src))
|
||||
to_chat(user, "<span class='danger'>You may only activate this structure in your lair: [bloodsuckerdatum.lair].</span>")
|
||||
if(B.lair != get_area(src))
|
||||
to_chat(user, "<span class='danger'>You may only activate this structure in your lair: [B.lair].</span>")
|
||||
return
|
||||
switch(alert(user,"Do you wish to afix this structure here? Be aware you wont be able to unsecure it anymore","Secure [src]","Yes", "No"))
|
||||
switch(alert(user,"Do you wish to afix this structure here? Be aware you wont be able to unsecure it anymore", "Secure [src]", "Yes", "No"))
|
||||
if("Yes")
|
||||
owner = user
|
||||
density = FALSE
|
||||
@@ -241,27 +243,31 @@
|
||||
return
|
||||
// CHECK TWO: Am I a non-bloodsucker?
|
||||
var/mob/living/carbon/C = pick(buckled_mobs)
|
||||
if(!istype(bloodsuckerdatum))
|
||||
if(!istype(B))
|
||||
// Try to release this guy
|
||||
user_unbuckle_mob(C, user)
|
||||
return
|
||||
// Bloodsucker Owner! Let the boy go.
|
||||
if(C.mind)
|
||||
var/datum/antagonist/vassal/vassaldatum = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
if(istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD)
|
||||
var/datum/antagonist/vassal/V = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
if(istype(V) && V.master == B || C.stat >= DEAD)
|
||||
unbuckle_mob(C)
|
||||
useLock = FALSE // Failsafe
|
||||
return
|
||||
// Just torture the boy
|
||||
torture_victim(user, C)
|
||||
|
||||
#define CONVERT_COST 150
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/proc/torture_victim(mob/living/user, mob/living/target)
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
// Check Bloodmob/living/M, force = FALSE, check_loc = TRUE
|
||||
var/convert_cost = 200 + 200 * bloodsuckerdatum.vassals
|
||||
if(user.blood_volume < convert_cost + 5)
|
||||
if(user.blood_volume < CONVERT_COST + 5)
|
||||
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target].</span>")
|
||||
return
|
||||
if(B.count_vassals(user.mind) > B.bloodsucker_level)
|
||||
to_chat(user, "<span class='notice'>Your power is yet too weak to bring more vassals under your control....</span>")
|
||||
return
|
||||
// Prep...
|
||||
useLock = TRUE
|
||||
// Step One: Tick Down Conversion from 3 to 0
|
||||
@@ -302,12 +308,13 @@
|
||||
useLock = FALSE
|
||||
return
|
||||
// Check: Blood
|
||||
if(user.blood_volume < convert_cost)
|
||||
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target], you need [convert_cost - user.blood_volume] units more!</span>")
|
||||
if(user.blood_volume < CONVERT_COST)
|
||||
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target], you need [CONVERT_COST - user.blood_volume] units more!</span>")
|
||||
useLock = FALSE
|
||||
return
|
||||
bloodsuckerdatum.AddBloodVolume(-convert_cost)
|
||||
target.add_mob_blood(user)
|
||||
B.AddBloodVolume(-CONVERT_COST)
|
||||
target.add_mob_blood(user, "<span class='danger'>Youve used [CONVERT_COST] amount of blood to gain a new vassal!</span>")
|
||||
to_chat(user, )
|
||||
user.visible_message("<span class='notice'>[user] marks a bloody smear on [target]'s forehead and puts a wrist up to [target.p_their()] mouth!</span>", \
|
||||
"<span class='notice'>You paint a bloody marking across [target]'s forehead, place your wrist to [target.p_their()] mouth, and subject [target.p_them()] to the Dark Communion.</span>")
|
||||
if(!do_mob(user, src, 50))
|
||||
@@ -315,21 +322,22 @@
|
||||
useLock = FALSE
|
||||
return
|
||||
// Convert to Vassal!
|
||||
if(bloodsuckerdatum && bloodsuckerdatum.attempt_turn_vassal(target))
|
||||
if(B && B.attempt_turn_vassal(target))
|
||||
//remove_loyalties(target) // In case of Mindshield, or appropriate Antag (Traitor, Internal, etc)
|
||||
//if (!target.buckled)
|
||||
// to_chat(user, "<span class='danger'><i>The ritual has been interrupted!</i></span>")
|
||||
// useLock = FALSE
|
||||
// return
|
||||
user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head.
|
||||
target.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head.
|
||||
target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head.
|
||||
user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE)
|
||||
target.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE)
|
||||
target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE)
|
||||
target.Jitter(25)
|
||||
target.emote("laugh")
|
||||
//remove_victim(target) // Remove on CLICK ONLY!
|
||||
useLock = FALSE
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/proc/do_torture(mob/living/user, mob/living/target, mult=1)
|
||||
#undef CONVERT_COST
|
||||
/obj/structure/bloodsucker/vassalrack/proc/do_torture(mob/living/user, mob/living/target, mult = 1)
|
||||
var/torture_time = 15 // Fifteen seconds if you aren't using anything. Shorter with weapons and such.
|
||||
var/torture_dmg_brute = 2
|
||||
var/torture_dmg_burn = 0
|
||||
@@ -454,7 +462,7 @@
|
||||
|
||||
/obj/structure/bloodsucker/candelabrum/examine(mob/user)
|
||||
. = ..()
|
||||
if((isvamp()) || isobserver(user))
|
||||
if((AmBloodsucker(user)) || isobserver(user))
|
||||
. += {"<span class='cult'>This is a magical candle which drains at the sanity of mortals who are not under your command while it is active.</span>"}
|
||||
. += {"<span class='cult'>You can alt click on it from any range to turn it on remotely, or simply be next to it and click on it to turn it on and off normally.</span>"}
|
||||
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
@@ -463,12 +471,12 @@
|
||||
|
||||
/obj/structure/bloodsucker/candelabrum/attack_hand(mob/user)
|
||||
var/datum/antagonist/vassal/T = user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
if(isvamp(user) || istype(T))
|
||||
if(AmBloodsucker(user) || istype(T))
|
||||
toggle()
|
||||
|
||||
/obj/structure/bloodsucker/candelabrum/AltClick(mob/user)
|
||||
// Bloodsuckers can turn their candles on from a distance. SPOOOOKY.
|
||||
if(isvamp(user))
|
||||
if(AmBloodsucker(user))
|
||||
toggle()
|
||||
|
||||
/obj/structure/bloodsucker/candelabrum/proc/toggle(mob/user)
|
||||
@@ -485,7 +493,7 @@
|
||||
if(lit)
|
||||
for(var/mob/living/carbon/human/H in viewers(7, src))
|
||||
var/datum/antagonist/vassal/T = H.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
if(isvamp(H) || T) //We dont want vassals or vampires affected by this
|
||||
if(AmBloodsucker(H) || T) //We dont want vassals or vampires affected by this
|
||||
return
|
||||
H.hallucination = 20
|
||||
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "vampcandle", /datum/mood_event/vampcandle)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/datum/action/bloodsucker/cloak
|
||||
name = "Cloak of Darkness"
|
||||
desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas."
|
||||
desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas, and you cannot dissapear while mortals watch you."
|
||||
button_icon_state = "power_cloak"
|
||||
bloodcost = 5
|
||||
cooldown = 50
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
to_chat(user, "<span class='notice'>You lean quietly toward [target] and secretly draw out your fangs...</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You pull [target] close to you and draw out your fangs...</span>")
|
||||
if(!do_mob(user, target, feed_time,0,1,extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10)
|
||||
if(!do_mob(user, target, feed_time, 0, 1, extra_checks = CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10)
|
||||
to_chat(user, "<span class='warning'>Your feeding was interrupted.</span>")
|
||||
//DeactivatePower(user,target)
|
||||
return
|
||||
@@ -166,7 +166,7 @@
|
||||
var/deadmessage = target.stat == DEAD ? "" : " <i>[target.p_they(TRUE)] looks dazed, and will not remember this.</i>"
|
||||
user.visible_message("<span class='notice'>[user] puts [target]'s wrist up to [user.p_their()] mouth.</span>", \
|
||||
"<span class='notice'>You secretly slip your fangs into [target]'s wrist.[deadmessage]</span>", \
|
||||
vision_distance = notice_range, ignored_mobs=target) // Only people who AREN'T the target will notice this action.
|
||||
vision_distance = notice_range, ignored_mobs = target) // Only people who AREN'T the target will notice this action.
|
||||
// Warn Feeder about Witnesses...
|
||||
var/was_unnoticed = TRUE
|
||||
for(var/mob/living/M in viewers(notice_range, owner))
|
||||
@@ -257,11 +257,11 @@
|
||||
to_chat(user, "<span class='notice'>Your victim is dead. [target.p_their(TRUE)] blood barely nourishes you.</span>")
|
||||
warning_target_dead = TRUE
|
||||
// Full?
|
||||
if(!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume)
|
||||
if(!warning_full && user.blood_volume >= bloodsuckerdatum.max_blood_volume)
|
||||
to_chat(user, "<span class='notice'>You are full. Further blood will be wasted.</span>")
|
||||
warning_full = TRUE
|
||||
// Blood Remaining? (Carbons/Humans only)
|
||||
if(iscarbon(target) && !target.AmBloodsucker(1))
|
||||
if(iscarbon(target) && !AmBloodsucker(target, TRUE))
|
||||
if(target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD)
|
||||
to_chat(user, "<span class='warning'>Your victim's blood volume is fatally low!</span>")
|
||||
else if(target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY)
|
||||
@@ -275,8 +275,9 @@
|
||||
break
|
||||
|
||||
// Blood Gulp Sound
|
||||
owner.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head.
|
||||
|
||||
owner.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE)
|
||||
if(!amSilent)
|
||||
target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE)
|
||||
// DONE!
|
||||
//DeactivatePower(user,target)
|
||||
if(amSilent)
|
||||
@@ -294,12 +295,12 @@
|
||||
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
|
||||
// Bad Vampire. You shouldn't do that.
|
||||
// Bad Bloodsucker. You shouldn't do that.
|
||||
if(target && target.stat >= DEAD && ishuman(target))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankkilled", /datum/mood_event/drankkilled) // BAD // in bloodsucker_life.dm
|
||||
|
||||
/datum/action/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target)
|
||||
return ..() && target && (!target_grappled || user.pulling == target)// Active, and still Antag,
|
||||
return ..() && target && (!target_grappled || user.pulling == target) && blood_sucking_checks(target, TRUE, TRUE) // Active, and still antag,
|
||||
// NOTE: We only care about pulling if target started off that way. Mostly only important for Aggressive feed.
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target)
|
||||
|
||||
@@ -33,6 +33,15 @@
|
||||
if(was_running)
|
||||
user.toggle_move_intent()
|
||||
while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN)
|
||||
if(istype(user.buckled, /obj/vehicle)) //We dont want people using fortitude being able to use vehicles
|
||||
var/obj/vehicle/V = user.buckled
|
||||
var/datum/component/riding/VRD = V.GetComponent(/datum/component/riding)
|
||||
if(VRD)
|
||||
VRD.force_dismount(user)
|
||||
to_chat(user, "<span class='notice'>You trip off the [V], your muscles too heavy for it to support you.</span>")
|
||||
else
|
||||
V.unbuckle_mob(user, force = TRUE)
|
||||
to_chat(user, "<span class='notice'>You fall off the [V], your weight making you too heavy to be supported by it.</span>")
|
||||
// Pay Blood Toll (if awake)
|
||||
if(user.stat == CONSCIOUS)
|
||||
bloodsuckerdatum.AddBloodVolume(-0.5) // Used to be 0.3 blood per 2 seconds, but we're making it more expensive to keep on.
|
||||
|
||||
@@ -179,6 +179,18 @@
|
||||
tastes = list("bread" = 1)
|
||||
foodtype = GRAIN
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/garlicbread
|
||||
name = "garlic bread"
|
||||
desc = "Alas, it is limited."
|
||||
icon = 'icons/obj/food/burgerbread.dmi'
|
||||
icon_state = "garlicbread"
|
||||
item_state = "garlicbread"
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin= 4, /datum/reagent/consumable/garlic = 2)
|
||||
bitesize = 3
|
||||
tastes = list("bread" = 1, "garlic" = 1, "butter" = 1)
|
||||
foodtype = GRAIN
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/deepfryholder
|
||||
name = "Deep Fried Foods Holder Obj"
|
||||
desc = "If you can see this description the code for the deep fryer fucked up."
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
name = "raw khinkali"
|
||||
desc = "One hundred khinkalis? Do I look like a pig?"
|
||||
icon_state = "khinkali"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1, /datum/reagent/consumable/garlic = 1)
|
||||
cooked_type = /obj/item/reagent_containers/food/snacks/khinkali
|
||||
tastes = list("meat" = 1, "onions" = 1, "garlic" = 1)
|
||||
foodtype = MEAT
|
||||
@@ -216,7 +216,7 @@
|
||||
name = "khinkali"
|
||||
desc = "One hundred khinkalis? Do I look like a pig?"
|
||||
icon_state = "khinkali"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/garlic = 1)
|
||||
bitesize = 3
|
||||
filling_color = "#F0F0F0"
|
||||
tastes = list("meat" = 1, "onions" = 1, "garlic" = 1)
|
||||
|
||||
@@ -125,6 +125,16 @@
|
||||
result = /obj/item/reagent_containers/food/snacks/baguette
|
||||
subcategory = CAT_BREAD
|
||||
|
||||
/datum/crafting_recipe/food/garlicbread
|
||||
name = "Garlic Bread"
|
||||
time = 40
|
||||
reqs = list(/obj/item/reagent_containers/food/snacks/grown/garlic = 1,
|
||||
/obj/item/reagent_containers/food/snacks/breadslice/plain = 1,
|
||||
/obj/item/reagent_containers/food/snacks/butter = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/garlicbread
|
||||
subcategory = CAT_BREAD
|
||||
|
||||
/datum/crafting_recipe/food/butterbiscuit
|
||||
name = "Butter Biscuit"
|
||||
reqs = list(
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
name = "Raw Khinkali"
|
||||
reqs = list(
|
||||
/obj/item/reagent_containers/food/snacks/doughslice = 1,
|
||||
/obj/item/reagent_containers/food/snacks/faggot = 1
|
||||
/obj/item/reagent_containers/food/snacks/faggot = 1,
|
||||
/obj/item/reagent_containers/food/snacks/grown/garlic = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/rawkhinkali
|
||||
subcategory = CAT_MISCFOOD
|
||||
|
||||
29
code/modules/hydroponics/grown/garlic.dm
Normal file
29
code/modules/hydroponics/grown/garlic.dm
Normal file
@@ -0,0 +1,29 @@
|
||||
/obj/item/seeds/garlic
|
||||
name = "pack of garlic seeds"
|
||||
desc = "A packet of extremely pungent seeds."
|
||||
icon_state = "seed-garlic"
|
||||
species = "garlic"
|
||||
plantname = "Garlic Sprouts"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/garlic
|
||||
yield = 6
|
||||
potency = 25
|
||||
growthstages = 3
|
||||
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
|
||||
reagents_add = list(/datum/reagent/consumable/garlic = 0.15, /datum/reagent/consumable/nutriment = 0.1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/garlic
|
||||
seed = /obj/item/seeds/garlic
|
||||
name = "garlic"
|
||||
desc = "Delicious, but with a potentially overwhelming odor."
|
||||
icon_state = "garlic"
|
||||
filling_color = "#C0C9A0"
|
||||
bitesize_mod = 2
|
||||
tastes = list("garlic" = 1)
|
||||
wine_power = 10
|
||||
|
||||
/obj/item/clothing/neck/garlic_necklace
|
||||
name = "garlic necklace"
|
||||
desc = "A clove of garlic on a cable, tied to itself in a circle, just might fit around your neck. For <strike>loonies<strike> people who fear getting their blood sucked."
|
||||
icon_state = "garlic_necklace"
|
||||
item_state = "garlic_necklace"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
weed_chance = 3
|
||||
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
|
||||
reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1)
|
||||
mutatelist = list(/obj/item/seeds/onion/red)
|
||||
mutatelist = list(/obj/item/seeds/onion/red, /obj/item/seeds/garlic)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/onion
|
||||
seed = /obj/item/seeds/onion
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
make_podman = 1
|
||||
break
|
||||
else
|
||||
if(M.ckey == ckey && M.stat == DEAD && !M.suiciding)
|
||||
if(M.ckey == ckey && M.stat == DEAD && !M.suiciding && AmBloodsucker(M))
|
||||
make_podman = 1
|
||||
if(isliving(M))
|
||||
var/mob/living/L = M
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// VAMPIRE LANGUAGE //
|
||||
// BLOODSUCKER LANGUAGE //
|
||||
|
||||
/datum/language/vampiric
|
||||
name = "Blah-Sucker"
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
slot = "hivecore"
|
||||
force = 0
|
||||
actions_types = list(/datum/action/item_action/organ_action/use)
|
||||
var/inert = 0
|
||||
var/preserved = 0
|
||||
var/inert
|
||||
var/preserved
|
||||
|
||||
/obj/item/organ/regenerative_core/Initialize()
|
||||
. = ..()
|
||||
@@ -38,7 +38,9 @@
|
||||
go_inert()
|
||||
|
||||
/obj/item/organ/regenerative_core/proc/preserved(implanted = 0)
|
||||
inert = FALSE
|
||||
if(inert)
|
||||
name = initial(name)
|
||||
inert = FALSE
|
||||
preserved = TRUE
|
||||
update_icon()
|
||||
desc = "All that remains of a hivelord. It is preserved, allowing you to use it to heal completely without danger of decay."
|
||||
@@ -69,14 +71,15 @@
|
||||
|
||||
/obj/item/organ/regenerative_core/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(proximity_flag && ishuman(target))
|
||||
if(proximity_flag)
|
||||
apply_healing_core(target, user)
|
||||
|
||||
/obj/item/organ/regenerative_core/proc/apply_healing_core(atom/target, mob/user)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(inert)
|
||||
to_chat(user, "<span class='notice'>[src] has decayed and can no longer be used to heal.</span>")
|
||||
return
|
||||
if(isvamp(user))
|
||||
to_chat(user, "<span class='notice'>[src] breaks down as it fails to heal your unholy self</span>")
|
||||
return
|
||||
else
|
||||
if(H.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'>[src] are useless on the dead.</span>")
|
||||
@@ -87,22 +90,16 @@
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.</span>")
|
||||
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self"))
|
||||
H.revive(full_heal = 1)
|
||||
if(AmBloodsucker(H))
|
||||
H.revive(full_heal = FALSE)
|
||||
else
|
||||
H.revive(full_heal = TRUE)
|
||||
qdel(src)
|
||||
user.log_message("[user] used [src] to heal [H]! Wake the fuck up, Samurai!", LOG_ATTACK, color="green") //Logging for 'old' style legion core use, when clicking on a sprite of yourself or another.
|
||||
|
||||
/obj/item/organ/regenerative_core/attack_self(mob/user) //Knouli's first hack! Allows for the use of the core in hand rather than needing to click on the target, yourself, to selfheal. Its a rip of the proc just above - but skips on distance check and only uses 'user' rather than 'target'
|
||||
if(ishuman(user)) //Check if user is human, no need for distance check as it's self heal
|
||||
var/mob/living/carbon/human/H = user //Set H to user rather than target
|
||||
if(inert) //Inert cores are useless
|
||||
to_chat(user, "<span class='notice'>[src] has decayed and can no longer be used to heal.</span>")
|
||||
return
|
||||
else //Skip on check if the target to be healed is dead as, if you are dead, you're not going to be able to use it on yourself!
|
||||
to_chat(user, "<span class='notice'>You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.</span>")
|
||||
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self"))
|
||||
H.revive(full_heal = 1)
|
||||
qdel(src)
|
||||
H.log_message("[H] used [src] to heal themselves! Making use of Knouli's sexy and intelligent use-in-hand proc!", LOG_ATTACK, color="green") //Logging for 'new' style legion core use, when using the core in-hand.
|
||||
. = ..()
|
||||
apply_healing_core(user)
|
||||
|
||||
|
||||
/obj/item/organ/regenerative_core/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
|
||||
@@ -247,13 +247,13 @@
|
||||
|
||||
/proc/CanHug(mob/living/M)
|
||||
if(!istype(M))
|
||||
return 0
|
||||
return FALSE
|
||||
if(M.stat == DEAD)
|
||||
return 0
|
||||
return FALSE
|
||||
if(M.getorgan(/obj/item/organ/alien/hivenode))
|
||||
return 0
|
||||
if(isvamp(M))
|
||||
return 0
|
||||
return FALSE
|
||||
if(AmBloodsucker(M))
|
||||
return FALSE
|
||||
|
||||
if(ismonkey(M))
|
||||
return 1
|
||||
@@ -262,9 +262,9 @@
|
||||
if(ishuman(C) && !(SLOT_WEAR_MASK in C.dna.species.no_equip))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(H.is_mouth_covered(head_only = 1))
|
||||
return 0
|
||||
return 1
|
||||
return 0
|
||||
return FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
#undef MIN_ACTIVE_TIME
|
||||
#undef MAX_ACTIVE_TIME
|
||||
|
||||
@@ -854,7 +854,7 @@
|
||||
/mob/living/carbon/proc/can_defib()
|
||||
var/tlimit = DEFIB_TIME_LIMIT * 10
|
||||
var/obj/item/organ/heart = getorgan(/obj/item/organ/heart)
|
||||
if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK))
|
||||
if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK) || AmBloodsucker(src))
|
||||
return
|
||||
if((world.time - timeofdeath) > tlimit)
|
||||
return
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
C.faction |= "slime"
|
||||
|
||||
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
|
||||
if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for vampires
|
||||
if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for blooduskers
|
||||
return
|
||||
if(!H.blood_volume)
|
||||
H.blood_volume += 5
|
||||
|
||||
@@ -81,6 +81,9 @@
|
||||
if(H.blood_volume >= BLOOD_VOLUME_MAXIMUM)
|
||||
to_chat(H, "<span class='notice'>You're already full!</span>")
|
||||
return
|
||||
//This checks whether or not they are wearing a garlic clove on their neck
|
||||
if(!blood_sucking_checks(victim, TRUE, FALSE))
|
||||
return
|
||||
if(victim.stat == DEAD)
|
||||
to_chat(H, "<span class='notice'>You need a living victim!</span>")
|
||||
return
|
||||
@@ -92,6 +95,9 @@
|
||||
to_chat(victim, "<span class='warning'>[H] tries to bite you, but stops before touching you!</span>")
|
||||
to_chat(H, "<span class='warning'>[victim] is blessed! You stop just in time to avoid catching fire.</span>")
|
||||
return
|
||||
//Here we check now for both the garlic cloves on the neck and for blood in the victims bloodstream.
|
||||
if(!blood_sucking_checks(victim, TRUE, TRUE))
|
||||
return
|
||||
if(!do_after(H, 30, target = victim))
|
||||
return
|
||||
var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
speed = 0
|
||||
maxHealth = 250
|
||||
health = 250
|
||||
blood_volume = 0
|
||||
gender = NEUTER
|
||||
mob_biotypes = NONE
|
||||
|
||||
|
||||
@@ -353,7 +353,7 @@
|
||||
if(m_intent == MOVE_INTENT_RUN)
|
||||
m_intent = MOVE_INTENT_WALK
|
||||
else
|
||||
if (HAS_TRAIT(src,TRAIT_NORUNNING)) // FULPSTATION 7/10/19 So you can't run during fortitude.
|
||||
if (HAS_TRAIT(src,TRAIT_NORUNNING))
|
||||
to_chat(src, "You find yourself unable to run.")
|
||||
return FALSE
|
||||
m_intent = MOVE_INTENT_RUN
|
||||
|
||||
@@ -284,7 +284,7 @@
|
||||
if(L.mind)
|
||||
L.mind.transfer_to(S)
|
||||
if(owner)
|
||||
to_chat(S, "<span class='userdanger'>You are an animate statue. You cannot move when monitored, but are nearly invincible and deadly when unobserved! Do not harm [owner], your creator.</span>")
|
||||
to_chat(S, "<span class='userdanger'>You are an animated statue. You cannot move when monitored, but are nearly invincible and deadly when unobserved! Do not harm [owner], your creator.</span>")
|
||||
P.forceMove(S)
|
||||
return
|
||||
else
|
||||
|
||||
@@ -214,7 +214,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
|
||||
//For easy bloodsucker disgusting and blood removal
|
||||
/datum/reagent/proc/disgust_bloodsucker(mob/living/carbon/C, disgust, blood_change, blood_puke = TRUE, force)
|
||||
if(isvamp(C))
|
||||
if(AmBloodsucker(C))
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = C.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
if(disgust)
|
||||
bloodsuckerdatum.handle_eat_human_food(disgust, blood_puke, force)
|
||||
|
||||
@@ -579,7 +579,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
value = 1.3
|
||||
|
||||
/datum/reagent/consumable/ethanol/bloody_mary/on_mob_life(mob/living/carbon/C)
|
||||
if(isvamp(C))
|
||||
if(AmBloodsucker(C))
|
||||
disgust_bloodsucker(FALSE, 1) //Bloodsuckers get SOME blood from it, for style reasons.
|
||||
if(C.blood_volume < (BLOOD_VOLUME_NORMAL*C.blood_ratio))
|
||||
C.blood_volume = min((BLOOD_VOLUME_NORMAL*C.blood_ratio), C.blood_volume + 3) //Bloody Mary quickly restores blood loss.
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
/datum/reagent/consumable/on_mob_life(mob/living/carbon/M)
|
||||
current_cycle++
|
||||
M.nutrition += nutriment_factor
|
||||
M.CheckBloodsuckerEatFood(nutriment_factor)
|
||||
holder.remove_reagent(type, metabolization_rate)
|
||||
|
||||
/datum/reagent/consumable/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
|
||||
@@ -423,6 +424,50 @@
|
||||
M.emote(pick("twitch","giggle"))
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/garlic //NOTE: having garlic in your blood stops vampires from biting you.
|
||||
name = "Garlic Juice"
|
||||
//id = "garlic"
|
||||
description = "Crushed garlic. Chefs love it, but it can make you smell bad."
|
||||
color = "#FEFEFE"
|
||||
taste_description = "garlic"
|
||||
metabolization_rate = 0.15 * REAGENTS_METABOLISM
|
||||
|
||||
/datum/reagent/consumable/garlic/on_mob_life(mob/living/carbon/M)
|
||||
if(isvampire(M)) //incapacitating but not lethal. Unfortunately, vampires cannot vomit.
|
||||
if(prob(min(25, current_cycle)))
|
||||
to_chat(M, "<span class='danger'>You can't get the scent of garlic out of your nose! You can barely think...</span>")
|
||||
M.Stun(10)
|
||||
M.Jitter(10)
|
||||
return
|
||||
|
||||
else if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.job == "Cook")
|
||||
if(prob(20)) //stays in the system much longer than sprinkles/banana juice, so heals slower to partially compensate
|
||||
H.heal_bodypart_damage(1, 1, 0)
|
||||
. = 1
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/garlic/reaction_mob(mob/living/M, method, reac_volume)
|
||||
if(AmBloodsucker(M, TRUE)) //Theyll be immune to garlic as long as they masquarade, but they cant do it if they already have it.
|
||||
switch(method)
|
||||
if(INGEST)
|
||||
if(prob(min(30, current_cycle)))
|
||||
to_chat(M, "<span class='warning'>You cant get the smell of garlic out of your nose! You cant think straight because of it!</span>")
|
||||
M.Jitter(15)
|
||||
if(prob(min(15, current_cycle)))
|
||||
M.visible_message("<span class='danger'>Something you ate is burning your stomach!</span>", "<span class='warning'>[M] clutches their stomach and falls to the ground!</span>")
|
||||
M.Knockdown(20)
|
||||
M.emote("scream")
|
||||
if(prob(min(5, current_cycle)) && iscarbon(M))
|
||||
var/mob/living/carbon/C
|
||||
C.vomit()
|
||||
if(INJECT)
|
||||
if(prob(min(20, current_cycle)))
|
||||
to_chat(M, "<span class='warning'>You feel like your veins are boiling!</span>")
|
||||
M.emote("scream")
|
||||
M.adjustFireLoss(5)
|
||||
..()
|
||||
/datum/reagent/consumable/sprinkles
|
||||
name = "Sprinkles"
|
||||
value = 3
|
||||
|
||||
Reference in New Issue
Block a user