More fixes. Urgh

This commit is contained in:
Artur
2019-12-08 21:47:25 +02:00
parent 4711eb0987
commit 9773b530f8
21 changed files with 201 additions and 238 deletions
+1 -1
View File
@@ -130,7 +130,7 @@
#define TRAIT_COLDBLOODED "coldblooded" // Your body is literal room temperature. Does not make you immune to the temp. #define TRAIT_COLDBLOODED "coldblooded" // Your body is literal room temperature. Does not make you immune to the temp.
#define TRAIT_NONATURALHEAL "nonaturalheal" // Only Admins can heal you. NOTHING else does it unless it's given the god tag. #define TRAIT_NONATURALHEAL "nonaturalheal" // Only Admins can heal you. NOTHING else does it unless it's given the god tag.
#define TRAIT_NORUNNING "norunning" // You walk! #define TRAIT_NORUNNING "norunning" // You walk!
#define TRAIT_NOMARROW "nomarrow" // You don't make blood. #define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites.
#define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat. #define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat.
+1 -2
View File
@@ -110,7 +110,7 @@
totitemdamage *= 0.5 totitemdamage *= 0.5
//CIT CHANGES END HERE //CIT CHANGES END HERE
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE) if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
if(prob(33)) if(prob(33))
I.add_mob_blood(src) I.add_mob_blood(src)
var/turf/location = get_turf(src) var/turf/location = get_turf(src)
@@ -163,4 +163,3 @@
/obj/item/proc/getweight() /obj/item/proc/getweight()
return total_mass || w_class * 1.25 return total_mass || w_class * 1.25
@@ -201,5 +201,45 @@
/datum/mood_event/vampcandle /datum/mood_event/vampcandle
description = "<span class='umbra'>Something is making your mind feel... loose...</span>\n" description = "<span class='umbra'>Something is making your mind feel... loose...</span>\n"
mood_change = -20 mood_change = -20
timeout = 1 MINUTES timeout = 1 MINUTES
/datum/mood_event/drankblood_bad
description = "<span class='boldwarning'>I drank the blood of a lesser creature. Disgusting.</span>\n"
mood_change = -4
timeout = 900
/datum/mood_event/drankblood_dead
description = "<span class='boldwarning'>I drank dead blood. I am better than this.</span>\n"
mood_change = -7
timeout = 900
/datum/mood_event/drankblood_synth
description = "<span class='boldwarning'>I drank synthetic blood. What is wrong with me?</span>\n"
mood_change = -7
timeout = 900
/datum/mood_event/drankkilled
description = "<span class='boldwarning'>I drank from my victim until they died. I feel...less human.</span>\n"
mood_change = -12
timeout = 6000
/datum/mood_event/madevamp
description = "<span class='boldwarning'>A soul has been cursed to undeath by my own hand.</span>\n"
mood_change = -10
timeout = 10000
/datum/mood_event/vampatefood
description = "<span class='boldwarning'>Mortal nourishment no longer sustains me. I feel unwell.</span>\n"
mood_change = -6
timeout = 1000
/datum/mood_event/daylight_1
description = "<span class='boldwarning'>I slept poorly in a makeshift coffin during the day.</span>\n"
mood_change = -3
timeout = 1000
/datum/mood_event/daylight_2
description = "<span class='boldwarning'>I have been scorched by the unforgiving rays of the sun.</span>\n"
mood_change = -6
timeout = 1200
@@ -134,6 +134,15 @@
mood_change = 3 mood_change = 3
timeout = 3000 timeout = 3000
/datum/mood_event/drankblood
description = "<span class='nicegreen'>I have fed greedly from that which nourishes me.</span>\n"
mood_change = 10
timeout = 900
/datum/mood_event/coffinsleep
description = "<span class='nicegreen'>I slept in a coffin during the day. I feel whole again.</span>\n"
mood_change = 8
timeout = 1200
//Cursed stuff below. //Cursed stuff below.
/datum/mood_event/orgasm /datum/mood_event/orgasm
+5 -5
View File
@@ -420,12 +420,12 @@ SLIME SCANNER
blood_type = R.name blood_type = R.name
else else
blood_type = blood_id blood_type = blood_id
if(C.blood_volume <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.blood_volume > (BLOOD_VOLUME_OKAY*C.blood_ratio)) if(C.scan_blood_volume() <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.scan_blood_volume() > (BLOOD_VOLUME_OKAY*C.blood_ratio))
msg += "<span class='danger'>LOW blood level [blood_percent] %, [C.blood_volume] cl,</span> <span class='info'>type: [blood_type]</span>\n" msg += "<span class='danger'>LOW blood level [blood_percent] %, [C.scan_blood_volume()] cl,</span> <span class='info'>type: [blood_type]</span>\n"
else if(C.blood_volume <= (BLOOD_VOLUME_OKAY*C.blood_ratio)) else if(C.scan_blood_volume() <= (BLOOD_VOLUME_OKAY*C.blood_ratio))
msg += "<span class='danger'>CRITICAL blood level [blood_percent] %, [C.blood_volume] cl,</span> <span class='info'>type: [blood_type]</span>\n" msg += "<span class='danger'>CRITICAL blood level [blood_percent] %, [C.scan_blood_volume()] cl,</span> <span class='info'>type: [blood_type]</span>\n"
else else
msg += "<span class='info'>Blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]</span>\n" msg += "<span class='info'>Blood level [blood_percent] %, [C.scan_blood_volume()] cl, type: [blood_type]</span>\n"
var/cyberimp_detect var/cyberimp_detect
for(var/obj/item/organ/cyberimp/CI in C.internal_organs) for(var/obj/item/organ/cyberimp/CI in C.internal_organs)
@@ -73,56 +73,6 @@
// Blood Gulp Sound // Blood Gulp Sound
owner.current.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.current.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.
/datum/mood_event/drankblood
description = "<span class='nicegreen'>I have fed greedly from that which nourishes me.</span>\n"
mood_change = 10
timeout = 900
/datum/mood_event/drankblood_bad
description = "<span class='boldwarning'>I drank the blood of a lesser creature. Disgusting.</span>\n"
mood_change = -4
timeout = 900
/datum/mood_event/drankblood_dead
description = "<span class='boldwarning'>I drank dead blood. I am better than this.</span>\n"
mood_change = -7
timeout = 900
/datum/mood_event/drankblood_synth
description = "<span class='boldwarning'>I drank synthetic blood. What is wrong with me?</span>\n"
mood_change = -7
timeout = 900
/datum/mood_event/drankkilled
description = "<span class='boldwarning'>I drank from my victim until they died. I feel...less human.</span>\n"
mood_change = -12
timeout = 6000
/datum/mood_event/madevamp
description = "<span class='boldwarning'>A soul has been cursed to undeath by my own hand.</span>\n"
mood_change = -10
timeout = 10000
/datum/mood_event/vampatefood
description = "<span class='boldwarning'>Mortal nourishment no longer sustains me. I feel unwell.</span>\n"
mood_change = -6
timeout = 1000
/datum/mood_event/coffinsleep
description = "<span class='nicegreen'>I slept in a coffin during the day. I feel whole again.</span>\n"
mood_change = 8
timeout = 1200
/datum/mood_event/daylight_1
description = "<span class='boldwarning'>I slept poorly in a makeshift coffin during the day.</span>\n"
mood_change = -3
timeout = 1000
/datum/mood_event/daylight_2
description = "<span class='boldwarning'>I have been scorched by the unforgiving rays of the sun.</span>\n"
mood_change = -6
timeout = 1200
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HEALING // HEALING
@@ -138,10 +88,10 @@
owner.current.adjustCloneLoss(-1 * (regenRate * 4) * mult, 0) owner.current.adjustCloneLoss(-1 * (regenRate * 4) * mult, 0)
owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0) owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0)
// No Bleeding // 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 var/mob/living/carbon/human/H = owner.current
H.bleed_rate = 0 H.bleed_rate = 0
if (iscarbon(owner.current)) // Damage Heal: Do I have damage to ANY bodypart? if(iscarbon(owner.current)) // Damage Heal: Do I have damage to ANY bodypart?
var/mob/living/carbon/C = owner.current var/mob/living/carbon/C = owner.current
var/costMult = 1 // Coffin makes it cheaper 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/fireheal = 0 // BURN: Heal in Coffin while Fakedeath, or when damage above maxhealth (you can never fully heal fire)
@@ -150,9 +100,10 @@
mult *= 5 // Increase multiplier if we're sleeping in a coffin. mult *= 5 // Increase multiplier if we're sleeping in a coffin.
fireheal = min(C.getFireLoss_nonProsthetic(), regenRate) // NOTE: Burn damage ONLY heals in torpor. fireheal = min(C.getFireLoss_nonProsthetic(), regenRate) // NOTE: Burn damage ONLY heals in torpor.
costMult = 0.25 costMult = 0.25
C.ExtinguishMob() // Extinguish Fire C.ExtinguishMob()
CureDisabilities() // Extinguish Fire
else else
if (owner.current.blood_volume <= 0) // No Blood? Lower Mult if(owner.current.blood_volume <= 0) // No Blood? Lower Mult
mult = 0.25 mult = 0.25
// Crit from burn? Lower damage to maximum allowed. // Crit from burn? Lower damage to maximum allowed.
//if (C.getFireLoss() > owner.current.getMaxHealth()) //if (C.getFireLoss() > owner.current.getMaxHealth())
@@ -161,8 +112,8 @@
var/bruteheal = min(C.getBruteLoss_nonProsthetic(), regenRate) var/bruteheal = min(C.getBruteLoss_nonProsthetic(), regenRate)
var/toxinheal = min(C.getToxLoss(), regenRate) var/toxinheal = min(C.getToxLoss(), regenRate)
// Heal if Damaged // Heal if Damaged
if (bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return. if(bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return.
if (mult == 0) if(mult == 0)
return TRUE return TRUE
// We have damage. Let's heal (one time) // We have damage. Let's heal (one time)
C.adjustBruteLoss(-bruteheal * mult, forced=TRUE)// Heal BRUTE / BURN in random portions throughout the body. C.adjustBruteLoss(-bruteheal * mult, forced=TRUE)// Heal BRUTE / BURN in random portions throughout the body.
@@ -171,7 +122,7 @@
//C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above. //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) / mult * costMult) // Costs blood to heal AddBloodVolume((bruteheal * -0.5 + fireheal * -1) / mult * costMult) // Costs blood to heal
return TRUE // Healed! Done for this tick. return TRUE // Healed! Done for this tick.
if (amInCoffinWhileTorpor) // Limbs? (And I have no other healing) if(amInCoffinWhileTorpor) // Limbs? (And I have no other healing)
var/list/missing = owner.current.get_missing_limbs() // Heal Missing var/list/missing = owner.current.get_missing_limbs() // Heal Missing
if (missing.len) // Cycle through ALL limbs and regen them! if (missing.len) // Cycle through ALL limbs and regen them!
for (var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it. for (var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it.
@@ -193,7 +144,6 @@
return TRUE return TRUE
// NOTE: Limbs have a "status", like their hosts "stat". 2 is dead (aka Prosthetic). 1 seems to be idle/alive. // NOTE: Limbs have a "status", like their hosts "stat". 2 is dead (aka Prosthetic). 1 seems to be idle/alive.
*/ */
CureDisabilities() // Cure Final Disabilities
C.remove_all_embedded_objects() // Remove Embedded! C.remove_all_embedded_objects() // Remove Embedded!
owner.current.regenerate_organs() // Heal Organs (will respawn original eyes etc. but we replace right away, next) owner.current.regenerate_organs() // Heal Organs (will respawn original eyes etc. but we replace right away, next)
CheckVampOrgans() // Heart, Eyes CheckVampOrgans() // Heart, Eyes
@@ -328,7 +278,7 @@
var/mob/living/carbon/C = owner.current var/mob/living/carbon/C = owner.current
C.remove_all_embedded_objects() C.remove_all_embedded_objects()
// Make me UN-CLONEABLE // Make me UN-CLONEABLE
owner.current.hellbound = TRUE // This was done during creation, but let's do it again one more time...to make SURE this guy stays dead. owner.current.hellbound = TRUE // This was done during creation, but let's do it again one more time...to make SURE this guy stays dead, but they dont stay dead because brains can be cloned!
// Free my Vassals! // Free my Vassals!
FreeAllVassals() FreeAllVassals()
// Elders get Dusted // Elders get Dusted
@@ -342,7 +292,7 @@
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>", \ 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='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>") "<span class='italics'>You hear a wet, bursting sound.</span>")
owner.current.gib() 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) playsound(owner.current.loc, 'sound/effects/tendril_destroyed.ogg', 40, 1)
@@ -24,18 +24,18 @@
time_til_cycle = TIME_BLOODSUCKER_NIGHT time_til_cycle = TIME_BLOODSUCKER_NIGHT
// Part 1: Night (all is well) // Part 1: Night (all is well)
while (time_til_cycle > TIME_BLOODSUCKER_DAY_WARN) while(time_til_cycle > TIME_BLOODSUCKER_DAY_WARN)
sleep(10) sleep(10)
if (cancel_me) if(cancel_me)
return return
//sleep(TIME_BLOODSUCKER_NIGHT - TIME_BLOODSUCKER_DAY_WARN) //sleep(TIME_BLOODSUCKER_NIGHT - TIME_BLOODSUCKER_DAY_WARN)
warn_daylight(1,"<span class = 'danger'>Solar Flares will bombard the station with dangerous UV in [TIME_BLOODSUCKER_DAY_WARN / 60] minutes. <b>Prepare to seek cover in a coffin or closet.</b></span>") // time2text <-- use Help On warn_daylight(1,"<span class = 'danger'>Solar Flares will bombard the station with dangerous UV in [TIME_BLOODSUCKER_DAY_WARN / 60] minutes. <b>Prepare to seek cover in a coffin or closet.</b></span>") // time2text <-- use Help On
give_home_power() // Give VANISHING ACT power to all vamps with a lair! give_home_power() // Give VANISHING ACT power to all vamps with a lair!
// Part 2: Night Ending // Part 2: Night Ending
while (time_til_cycle > TIME_BLOODSUCKER_DAY_FINAL_WARN) while(time_til_cycle > TIME_BLOODSUCKER_DAY_FINAL_WARN)
sleep(10) sleep(10)
if (cancel_me) if(cancel_me)
return return
//sleep(TIME_BLOODSUCKER_DAY_WARN - TIME_BLOODSUCKER_DAY_FINAL_WARN) //sleep(TIME_BLOODSUCKER_DAY_WARN - TIME_BLOODSUCKER_DAY_FINAL_WARN)
message_admins("BLOODSUCKER NOTICE: Daylight beginning in [TIME_BLOODSUCKER_DAY_FINAL_WARN] seconds.)") message_admins("BLOODSUCKER NOTICE: Daylight beginning in [TIME_BLOODSUCKER_DAY_FINAL_WARN] seconds.)")
@@ -43,7 +43,7 @@
"<span class = 'danger'>In [TIME_BLOODSUCKER_DAY_FINAL_WARN / 10], your master will be at risk of a Solar Flare. Make sure they find cover!</span>") "<span class = 'danger'>In [TIME_BLOODSUCKER_DAY_FINAL_WARN / 10], your master will be at risk of a Solar Flare. Make sure they find cover!</span>")
// (FINAL LIL WARNING) // (FINAL LIL WARNING)
while (time_til_cycle > 5) while(time_til_cycle > 5)
sleep(10) sleep(10)
if (cancel_me) if (cancel_me)
return return
@@ -90,56 +90,56 @@
while(!cancel_me) while(!cancel_me)
// Update all Bloodsucker sunlight huds // Update all Bloodsucker sunlight huds
for (var/datum/mind/M in SSticker.mode.bloodsuckers) for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if (!istype(M) || !istype(M.current)) if(!istype(M) || !istype(M.current))
continue continue
var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (istype(bloodsuckerdatum)) if(istype(bloodsuckerdatum))
bloodsuckerdatum.update_sunlight(max(0, time_til_cycle), amDay) // This pings all HUDs bloodsuckerdatum.update_sunlight(max(0, time_til_cycle), amDay) // This pings all HUDs
sleep(10) sleep(10)
time_til_cycle -- time_til_cycle --
/obj/effect/sunlight/proc/warn_daylight(danger_level=0, vampwarn = "", vassalwarn = "") /obj/effect/sunlight/proc/warn_daylight(danger_level=0, vampwarn = "", vassalwarn = "")
for (var/datum/mind/M in SSticker.mode.bloodsuckers) for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if (!istype(M)) if(!istype(M))
continue continue
to_chat(M,vampwarn) to_chat(M,vampwarn)
if (M.current) if(M.current)
if (danger_level == 1) if(danger_level == 1)
M.current.playsound_local(null, 'sound/chatter/griffin_3.ogg', 50 + danger_level, 1) M.current.playsound_local(null, 'sound/chatter/griffin_3.ogg', 50 + danger_level, 1)
else if (danger_level == 2) else if(danger_level == 2)
M.current.playsound_local(null, 'sound/chatter/griffin_5.ogg', 50 + danger_level, 1) M.current.playsound_local(null, 'sound/chatter/griffin_5.ogg', 50 + danger_level, 1)
else if (danger_level == 3) else if(danger_level == 3)
M.current.playsound_local(null, 'sound/effects/alert.ogg', 75, 1) M.current.playsound_local(null, 'sound/effects/alert.ogg', 75, 1)
else if (danger_level == 4) else if(danger_level == 4)
M.current.playsound_local(null, 'sound/ambience/ambimystery.ogg', 100, 1) M.current.playsound_local(null, 'sound/ambience/ambimystery.ogg', 100, 1)
else if (danger_level == 5) else if(danger_level == 5)
M.current.playsound_local(null, 'sound/spookoween/ghosty_wind.ogg', 90, 1) M.current.playsound_local(null, 'sound/spookoween/ghosty_wind.ogg', 90, 1)
if (vassalwarn != "") if(vassalwarn != "")
for (var/datum/mind/M in SSticker.mode.vassals) for(var/datum/mind/M in SSticker.mode.vassals)
if (!istype(M)) if(!istype(M))
continue continue
to_chat(M,vassalwarn) to_chat(M,vassalwarn)
/obj/effect/sunlight/proc/punish_vamps() /obj/effect/sunlight/proc/punish_vamps()
// Cycle through all vamp antags and check if they're inside a closet. // Cycle through all vamp antags and check if they're inside a closet.
for (var/datum/mind/M in SSticker.mode.bloodsuckers) for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if (!istype(M) || !istype(M.current)) if(!istype(M) || !istype(M.current))
continue continue
var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (!istype(bloodsuckerdatum)) if(!istype(bloodsuckerdatum))
continue continue
// Closets offer SOME protection // Closets offer SOME protection
if (istype(M.current.loc, /obj/structure)) if(istype(M.current.loc, /obj/structure))
// Coffins offer the BEST protection // Coffins offer the BEST protection
if (istype(M.current.loc, /obj/structure/closet/crate/coffin)) if(istype(M.current.loc, /obj/structure/closet/crate/coffin))
SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/coffinsleep) SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/coffinsleep)
continue continue
else else
if (!bloodsuckerdatum.warn_sun_locker) 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>") 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 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.vamplevel / 2) // M.current.fireloss += 0.5 + bloodsuckerdatum.vamplevel / 2 // Do DIRECT damage. Being spaced was causing this to not occur. setFireLoss(bloodsuckerdatum.vamplevel)
@@ -147,15 +147,15 @@
SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_1) SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_1)
// Out in the Open? Buh Bye // Out in the Open? Buh Bye
else else
if (!bloodsuckerdatum.warn_sun_burn) if(!bloodsuckerdatum.warn_sun_burn)
if (bloodsuckerdatum.vamplevel > 0) if(bloodsuckerdatum.vamplevel > 0)
to_chat(M, "<span class='userdanger'>The solar flare sets your skin ablaze!</span>") to_chat(M, "<span class='userdanger'>The solar flare sets your skin ablaze!</span>")
else else
to_chat(M, "<span class='userdanger'>The solar flare scalds your neophyte skin!</span>") to_chat(M, "<span class='userdanger'>The solar flare scalds your neophyte skin!</span>")
bloodsuckerdatum.warn_sun_burn = TRUE bloodsuckerdatum.warn_sun_burn = TRUE
if (M.current.fire_stacks <= 0) if(M.current.fire_stacks <= 0)
M.current.fire_stacks = 0 M.current.fire_stacks = 0
if (bloodsuckerdatum.vamplevel > 0) if(bloodsuckerdatum.vamplevel > 0)
M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.vamplevel / 10) M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.vamplevel / 10)
M.current.IgniteMob() 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.vamplevel) // M.current.fireloss += 2 + bloodsuckerdatum.vamplevel // Do DIRECT damage. Being spaced was causing this to not occur. //setFireLoss(2 + bloodsuckerdatum.vamplevel)
@@ -163,36 +163,36 @@
SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_2) SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_2)
/obj/effect/sunlight/proc/day_end() /obj/effect/sunlight/proc/day_end()
for (var/datum/mind/M in SSticker.mode.bloodsuckers) for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if (!istype(M) || !istype(M.current)) if(!istype(M) || !istype(M.current))
continue continue
var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (!istype(bloodsuckerdatum)) if(!istype(bloodsuckerdatum))
continue continue
// Reset Warnings // Reset Warnings
bloodsuckerdatum.warn_sun_locker = FALSE bloodsuckerdatum.warn_sun_locker = FALSE
bloodsuckerdatum.warn_sun_burn = FALSE bloodsuckerdatum.warn_sun_burn = FALSE
// Remove Dawn Powers // Remove Dawn Powers
for(var/datum/action/bloodsucker/P in bloodsuckerdatum.powers) for(var/datum/action/bloodsucker/P in bloodsuckerdatum.powers)
if (istype(P, /datum/action/bloodsucker/gohome)) if(istype(P, /datum/action/bloodsucker/gohome))
bloodsuckerdatum.powers -= P bloodsuckerdatum.powers -= P
P.Remove(M.current) P.Remove(M.current)
/obj/effect/sunlight/proc/vamps_rank_up() /obj/effect/sunlight/proc/vamps_rank_up()
set waitfor = FALSE set waitfor = FALSE
// Cycle through all vamp antags and check if they're inside a closet. // Cycle through all vamp antags and check if they're inside a closet.
for (var/datum/mind/M in SSticker.mode.bloodsuckers) for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if (!istype(M) || !istype(M.current)) if(!istype(M) || !istype(M.current))
continue continue
var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (istype(bloodsuckerdatum)) if(istype(bloodsuckerdatum))
bloodsuckerdatum.RankUp() // Rank up! Must still be in a coffin to level! bloodsuckerdatum.RankUp() // Rank up! Must still be in a coffin to level!
/obj/effect/sunlight/proc/give_home_power() /obj/effect/sunlight/proc/give_home_power()
// It's late...! Give the "Vanishing Act" gohome power to bloodsuckers. // It's late...! Give the "Vanishing Act" gohome power to bloodsuckers.
for (var/datum/mind/M in SSticker.mode.bloodsuckers) for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if (!istype(M) || !istype(M.current)) if(!istype(M) || !istype(M.current))
continue continue
var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (istype(bloodsuckerdatum) && bloodsuckerdatum.lair && !(locate(/datum/action/bloodsucker/gohome) in bloodsuckerdatum.powers)) if(istype(bloodsuckerdatum) && bloodsuckerdatum.lair && !(locate(/datum/action/bloodsucker/gohome) in bloodsuckerdatum.powers))
bloodsuckerdatum.BuyPower(new /datum/action/bloodsucker/gohome) bloodsuckerdatum.BuyPower(new /datum/action/bloodsucker/gohome)
@@ -36,7 +36,7 @@
// LISTS // LISTS
var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_NIGHT_VISION, \ var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_NIGHT_VISION, \
TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE) TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_NOCLONE)
// NOTES: TRAIT_AGEUSIA <-- Doesn't like flavors. // NOTES: TRAIT_AGEUSIA <-- Doesn't like flavors.
// REMOVED: TRAIT_NODEATH // REMOVED: TRAIT_NODEATH
// TO ADD: // TO ADD:
@@ -187,6 +187,8 @@
// Traits // Traits
for (var/T in defaultTraits) for (var/T in defaultTraits)
ADD_TRAIT(owner.current, T, "bloodsucker") ADD_TRAIT(owner.current, T, "bloodsucker")
if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you
REMOVE_TRAIT(owner.current, TRAIT_TOXINLOVER, "species")
// Traits: Species // Traits: Species
if (ishuman(owner.current)) if (ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current var/mob/living/carbon/human/H = owner.current
@@ -233,14 +235,14 @@
power.Remove(owner.current) power.Remove(owner.current)
// owner.RemoveSpell(power) // owner.RemoveSpell(power)
// Traits // Traits
for (var/T in defaultTraits) for(var/T in defaultTraits)
REMOVE_TRAIT(owner.current, T, "bloodsucker") REMOVE_TRAIT(owner.current, T, "bloodsucker")
// Traits: Species // Traits: Species
if (ishuman(owner.current)) if(ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current var/mob/living/carbon/human/H = owner.current
H.set_species(H.dna.species.type) H.set_species(H.dna.species.type)
// Stats // Stats
if (ishuman(owner.current)) if(ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current var/mob/living/carbon/human/H = owner.current
H.set_species(H.dna.species.type) H.set_species(H.dna.species.type)
// Clown // Clown
@@ -260,15 +262,15 @@
datum/antagonist/bloodsucker/proc/RankUp() datum/antagonist/bloodsucker/proc/RankUp()
set waitfor = FALSE set waitfor = FALSE
if (!owner || !owner.current) if(!owner || !owner.current)
return return
vamplevel_unspent ++ vamplevel_unspent ++
// Spend Rank Immediately? // Spend Rank Immediately?
if (istype(owner.current.loc, /obj/structure/closet/crate/coffin)) if(istype(owner.current.loc, /obj/structure/closet/crate/coffin))
SpendRank() SpendRank()
else 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>") 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(vamplevel_unspent >= 2)
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, they can be built from wooden planks.</span><br>") to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, they can be built from wooden planks.</span><br>")
datum/antagonist/bloodsucker/proc/LevelUpPowers() datum/antagonist/bloodsucker/proc/LevelUpPowers()
@@ -287,19 +289,19 @@ datum/antagonist/bloodsucker/proc/SpendRank()
for(var/pickedpower in typesof(/datum/action/bloodsucker)) for(var/pickedpower in typesof(/datum/action/bloodsucker))
var/datum/action/bloodsucker/power = pickedpower var/datum/action/bloodsucker/power = pickedpower
// If I don't own it, and I'm allowed to buy it. // If I don't own it, and I'm allowed to buy it.
if (!(locate(power) in powers) && initial(power.bloodsucker_can_buy)) if(!(locate(power) in powers) && initial(power.bloodsucker_can_buy))
options[initial(power.name)] = power // TESTING: After working with TGUI, it seems you can use initial() to view the variables inside a path? options[initial(power.name)] = power // TESTING: After working with TGUI, it seems you can use initial() to view the variables inside a path?
options["\[ Not Now \]"] = null options["\[ Not Now \]"] = null
// Abort? // Abort?
if (options.len > 1) if(options.len > 1)
var/choice = input(owner.current, "You have the opportunity to grow more ancient. Select a power to advance your Rank.", "Your Blood Thickens...") in options var/choice = input(owner.current, "You have the opportunity to grow more ancient. Select a power to advance your Rank.", "Your Blood Thickens...") in options
// Cheat-Safety: Can't keep opening/closing coffin to spam levels // 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(vamplevel_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal.
return return
if (!istype(owner.current.loc, /obj/structure/closet/crate/coffin)) 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>") to_chat(owner.current, "<span class='warning'>Return to your coffin to advance your Rank.</span>")
return return
if (!choice || !options[choice] || (locate(options[choice]) in powers)) // ADDED: Check to see if you already have this power, due to window stacking. if(!choice || !options[choice] || (locate(options[choice]) in powers)) // ADDED: Check to see if you already have this power, due to window stacking.
to_chat(owner.current, "<span class='notice'>You prevent your blood from thickening just yet, but you may try again later.</span>") to_chat(owner.current, "<span class='notice'>You prevent your blood from thickening just yet, but you may try again later.</span>")
return return
// Buy New Powers // Buy New Powers
@@ -313,7 +315,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
LevelUpPowers() LevelUpPowers()
//////// ////////
// Advance Stats // Advance Stats
if (ishuman(owner.current)) if(ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current var/mob/living/carbon/human/H = owner.current
var/datum/species/S = H.dna.species var/datum/species/S = H.dna.species
S.burnmod += 0.025 // Slightly more burn damage S.burnmod += 0.025 // Slightly more burn damage
@@ -331,7 +333,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
vamplevel_unspent -- vamplevel_unspent --
// Assign True Reputation // Assign True Reputation
if (vamplevel == 4) if(vamplevel == 4)
SelectReputation(am_fledgling=FALSE, forced=TRUE) SelectReputation(am_fledgling=FALSE, forced=TRUE)
to_chat(owner.current, "<span class='notice'>You are now a rank [vamplevel] Bloodsucker. Your strength, resistence, health, feed rate, regen rate, and maximum blood have all increased!</span>") to_chat(owner.current, "<span class='notice'>You are now a rank [vamplevel] Bloodsucker. Your strength, resistence, health, feed rate, regen rate, and maximum blood have all increased!</span>")
to_chat(owner.current, "<span class='notice'>Your existing powers have all ranked up as well!</span>") to_chat(owner.current, "<span class='notice'>Your existing powers have all ranked up as well!</span>")
@@ -485,7 +487,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
// - Warms up the body // - Warms up the body
// - Creates a heartbeat // - Creates a heartbeat
// - Fake blood amount (550) // - Fake blood amount (550)
// Feign DEATH: // Feign DEATH: Not yet done
// - When lying down or sitting, you appear "dead and lifeless" // - When lying down or sitting, you appear "dead and lifeless"
// * Bloodsuckers REGENERATE // * Bloodsuckers REGENERATE
@@ -109,38 +109,17 @@
var/disloyalty_offered = FALSE // Has the popup been issued? Don't spam them. var/disloyalty_offered = FALSE // Has the popup been issued? Don't spam them.
var/convert_cost = 10 var/convert_cost = 10
//obj/structure/kitchenspike/vassalrack/crowbar_act()
// // Do Nothing (Cancel crowbar deconstruct)
// return FALSE
/obj/structure/bloodsucker/vassalrack/deconstruct(disassembled = TRUE) /obj/structure/bloodsucker/vassalrack/deconstruct(disassembled = TRUE)
new /obj/item/stack/sheet/metal(src.loc, 4) new /obj/item/stack/sheet/metal(src.loc, 4)
new /obj/item/stack/rods(loc, 4) new /obj/item/stack/rods(loc, 4)
qdel(src) qdel(src)
/*
/obj/structure/closet/CtrlShiftClick(mob/living/user)
if(!user.has_trait(TRAIT_SKITTISH))
return ..()
if(!user.canUseTopic(src) || !isturf(user.loc))
return
dive_into(user)
*/
// adding a STRAP on top of an icon: look at update_icon in closets.dm, and the use of overlays.dm cut_overlay() and add_overlay()
/obj/structure/bloodsucker/vassalrack/MouseDrop_T(atom/movable/O, mob/user) /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()) if (!O.Adjacent(src) || O == user || !isliving(O) || !isliving(user) || useLock || has_buckled_mobs() || user.incapacitated())
return return
if (!anchored && user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) if (!anchored && user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
to_chat(user, "<span class='danger'>Until this rack is secured in place, it cannot serve its purpose.</span>") to_chat(user, "<span class='danger'>Until this rack is secured in place, it cannot serve its purpose.</span>")
return return
// PULL TARGET: Remember if I was pullin this guy, so we can restore this // PULL TARGET: Remember if I was pullin this guy, so we can restore this
var/waspulling = (O == owner.pulling) var/waspulling = (O == owner.pulling)
var/wasgrabstate = owner.grab_state var/wasgrabstate = owner.grab_state
@@ -463,7 +442,7 @@
///obj/structure/bloodsucker/candelabrum/is_hot() // candle.dm ///obj/structure/bloodsucker/candelabrum/is_hot() // candle.dm
//return FALSE //return FALSE
/datum/component/nanites/Destroy() /obj/structure/bloodsucker/candelabrum/Destroy()
STOP_PROCESSING(SSobj, src) STOP_PROCESSING(SSobj, src)
/obj/structure/bloodsucker/candelabrum/update_icon() /obj/structure/bloodsucker/candelabrum/update_icon()
@@ -33,73 +33,60 @@
/datum/antagonist/bloodsucker/proc/RunLair() /datum/antagonist/bloodsucker/proc/RunLair()
set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side. set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side.
while(!AmFinalDeath() && coffin && lair)
while (!AmFinalDeath() && coffin && lair) // WAit 2 min and Repeat
sleep(120)
// WAit 1 min and Repeat
sleep(60)
// Coffin Moved SOMEHOW? // Coffin Moved SOMEHOW?
if (lair != get_area(coffin)) if(lair != get_area(coffin))
if (coffin) if(coffin)
coffin.UnclaimCoffin() coffin.UnclaimCoffin()
//lair = get_area(coffin) //lair = get_area(coffin)
break // DONE break // DONE
var/list/turf/area_turfs = get_area_turfs(lair) var/list/turf/area_turfs = get_area_turfs(lair)
// Create Dirt etc. // Create Dirt etc.
var/turf/T_Dirty = pick(area_turfs) var/turf/T_Dirty = pick(area_turfs)
if (T_Dirty && !T_Dirty.density) if(T_Dirty && !T_Dirty.density)
// Default: Dirt // Default: Dirt
// CHECK: Cobweb already there? // CHECK: Cobweb already there?
//if (!locate(var/obj/effect/decal/cleanable/cobweb) in T_Dirty) // REMOVED! Cleanables don't stack. //if (!locate(var/obj/effect/decal/cleanable/cobweb) in T_Dirty) // REMOVED! Cleanables don't stack.
// STEP ONE: COBWEBS // STEP ONE: COBWEBS
// CHECK: Wall to North? // CHECK: Wall to North?
var/turf/check_N = get_step(T_Dirty, NORTH) var/turf/check_N = get_step(T_Dirty, NORTH)
if (istype(check_N, /turf/closed/wall)) if(istype(check_N, /turf/closed/wall))
// CHECK: Wall to West? // CHECK: Wall to West?
var/turf/check_W = get_step(T_Dirty, WEST) var/turf/check_W = get_step(T_Dirty, WEST)
if (istype(check_W, /turf/closed/wall)) if(istype(check_W, /turf/closed/wall))
new /obj/effect/decal/cleanable/cobweb (T_Dirty) new /obj/effect/decal/cleanable/cobweb (T_Dirty)
// CHECK: Wall to East? // CHECK: Wall to East?
var/turf/check_E = get_step(T_Dirty, EAST) var/turf/check_E = get_step(T_Dirty, EAST)
if (istype(check_E, /turf/closed/wall)) if(istype(check_E, /turf/closed/wall))
new /obj/effect/decal/cleanable/cobweb/cobweb2 (T_Dirty) new /obj/effect/decal/cleanable/cobweb/cobweb2 (T_Dirty)
// STEP TWO: DIRT // STEP TWO: DIRT
new /obj/effect/decal/cleanable/dirt (T_Dirty) new /obj/effect/decal/cleanable/dirt (T_Dirty)
// Find Animals in Area // Find Animals in Area
if (rand(0,2) == 0) if(rand(0,2) == 0)
var/mobCount = 0 var/mobCount = 0
var/mobMax = CLAMP(area_turfs.len / 25, 1, 4) var/mobMax = CLAMP(area_turfs.len / 25, 1, 4)
for (var/turf/T in area_turfs) for (var/turf/T in area_turfs)
if (!T) continue if(!T) continue
var/mob/living/simple_animal/SA = locate() in T var/mob/living/simple_animal/SA = locate() in T
if (SA) if(SA)
mobCount ++ mobCount ++
if (mobCount >= mobMax) // Already at max if (mobCount >= mobMax) // Already at max
break break
// Spawn One // Spawn One
if (mobCount < mobMax) if(mobCount < mobMax)
// Seek Out Location // Seek Out Location
while (area_turfs.len > 0) while(area_turfs.len > 0)
sleep(240) //We dont want this to happen often
var/turf/T = pick(area_turfs) // We use while&pick instead of a for/loop so it's random, rather than from the top of the list. var/turf/T = pick(area_turfs) // We use while&pick instead of a for/loop so it's random, rather than from the top of the list.
if (T && !T.density) if(T && !T.density)
var/mob/living/simple_animal/SA = /mob/living/simple_animal/mouse // pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse, var/mob/living/simple_animal/SA = /mob/living/simple_animal/mouse // pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
new SA (T) new SA (T)
break break
area_turfs -= T area_turfs -= T
// NOTE: area_turfs is now cleared out! // NOTE: area_turfs is now cleared out!
if (coffin) if(coffin)
coffin.UnclaimCoffin() coffin.UnclaimCoffin()
// Done (somehow) // Done (somehow)
lair = null lair = null
@@ -22,22 +22,24 @@
return return
. = TRUE . = TRUE
// Break Out of Restraints! (And then cancel) // Break Out of Restraints! (And then cancel)
if (CheckBreakRestraints()) if(CheckBreakRestraints())
//PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!DEACTIVATE! //PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!DEACTIVATE!
. = FALSE //return FALSE . = FALSE //return FALSE
// Throw Off Attacker! (And then cancel) // Throw Off Attacker! (And then cancel)
if (CheckEscapePuller()) if(CheckEscapePuller())
//PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!DEACTIVATE! //PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!DEACTIVATE!
. = FALSE //return FALSE . = FALSE //return FALSE
// Did we successfuly use power to BREAK CUFFS and/or ESCAPE PULLER? /*if(CheckBreakLocker())
.= FALSE */
// Did we successfuly use power to BREAK CUFFS and/or ESCAPE PULLER and/or escape from a locker?
// Then PAY COST! // Then PAY COST!
if (. == FALSE) if(. == FALSE)
PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!DEACTIVATE! PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!DEACTIVATE!
// NOTE: We use . = FALSE so that we can break cuffs AND throw off our attacker in one use! // NOTE: We use . = FALSE so that we can break cuffs AND throw off our attacker in one use!
//return TRUE //return TRUE
/datum/action/bloodsucker/targeted/brawn/CheckValidTarget(atom/A) /datum/action/bloodsucker/targeted/brawn/CheckValidTarget(atom/A)
return isliving(A) || istype(A, /obj/machinery/door) || istype(A, /obj/structure/closet) return isliving(A) || istype(A, /obj/machinery/door))
/datum/action/bloodsucker/targeted/brawn/CheckCanTarget(atom/A, display_error) /datum/action/bloodsucker/targeted/brawn/CheckCanTarget(atom/A, display_error)
// DEFAULT CHECKS (Distance) // DEFAULT CHECKS (Distance)
@@ -53,10 +55,7 @@
if(isliving(A)) if(isliving(A))
return TRUE return TRUE
// Target Type: Door // Target Type: Door
else if(upgrade_canDoor && istype(A, /obj/machinery/door)) else if(istype(A, /obj/machinery/door))
return TRUE
// Target Type: Closet
else if(upgrade_canLocker && istype(A, /obj/structure/closet))
return TRUE return TRUE
return ..() // yes, FALSE! You failed if you got here! BAD TARGET return ..() // yes, FALSE! You failed if you got here! BAD TARGET
@@ -88,30 +87,21 @@
owner.newtonian_move(send_dir) // Bounce back in 0 G owner.newtonian_move(send_dir) // Bounce back in 0 G
target.throw_at(T, powerlevel, TRUE, owner) //new /datum/forced_movement(target, get_ranged_target_turf(target, send_dir, (hitStrength / 4)), 1, FALSE) target.throw_at(T, powerlevel, TRUE, owner) //new /datum/forced_movement(target, get_ranged_target_turf(target, send_dir, (hitStrength / 4)), 1, FALSE)
// Target Type: Door // Target Type: Door
else if (upgrade_canDoor && istype(target, /obj/machinery/door)) else if(istype(target, /obj/machinery/door))
var/obj/machinery/door/D = target
playsound(get_turf(usr), 'sound/machines/airlock_alien_prying.ogg', 40, 1, -1) playsound(get_turf(usr), 'sound/machines/airlock_alien_prying.ogg', 40, 1, -1)
if (do_mob(usr,target,25)) to_chat(user, "<span class='notice'>You prepare to tear open [D].</span>")
var/obj/machinery/door/D = target if(do_mob(usr,target,25))
if (D.Adjacent(user)) if (D.Adjacent(user))
to_chat(user, "<span class='notice'>You prepare to tear open [D].</span>") to_chat(user, "<span class='notice'>You tear open the [D].</span>")
user.Stun(10) user.Stun(10)
user.do_attack_animation(D, ATTACK_EFFECT_SMASH) user.do_attack_animation(D, ATTACK_EFFECT_SMASH)
playsound(get_turf(D), 'sound/effects/bang.ogg', 30, 1, -1) playsound(get_turf(D), 'sound/effects/bang.ogg', 30, 1, -1)
D.open(2) // open(2) is like a crowbar or jaws of life. D.open(2) // open(2) is like a crowbar or jaws of life.
// Target Type: Closet // Target Type: Closet
else if (upgrade_canLocker && istype(target, /obj/structure/closet))
playsound(get_turf(usr), 'sound/machines/airlock_alien_prying.ogg', 40, 1, -1)
if (do_mob(usr,target,25))
var/obj/structure/closet/C = target
to_chat(user, "<span class='notice'>You prepare to tear open the [C].</span>")
user.Stun(10)
user.do_attack_animation(C, ATTACK_EFFECT_SMASH)
playsound(get_turf(C), 'sound/effects/bang.ogg', 30, 1, -1)
C.bust_open()
/datum/action/bloodsucker/targeted/brawn/proc/CheckBreakRestraints() /datum/action/bloodsucker/targeted/brawn/proc/CheckBreakRestraints()
if(!iscarbon(owner)) // || !owner.restrained()
if (!iscarbon(owner)) // || !owner.restrained()
return FALSE return FALSE
// (NOTE: Just like biodegrade.dm, we only remove one thing per use // // (NOTE: Just like biodegrade.dm, we only remove one thing per use //
// Destroy Cuffs // Destroy Cuffs
@@ -125,18 +115,18 @@
user_C.clear_cuffs(O,TRUE) user_C.clear_cuffs(O,TRUE)
playsound(get_turf(usr), 'sound/effects/grillehit.ogg', 80, 1, -1) playsound(get_turf(usr), 'sound/effects/grillehit.ogg', 80, 1, -1)
return TRUE return TRUE
/* Doesnt work
// Destroy Straightjacket // Destroy Straightjacket
if (ishuman(owner)) if(ishuman(owner))
var/mob/living/carbon/human/user_H = owner var/mob/living/carbon/human/user_H = owner
if(user_H.wear_suit && user_H.wear_suit.breakouttime) if(user_H.wear_suit && user_H.wear_suit.breakouttime)
var/obj/item/clothing/suit/S = user_H.get_item_by_slot(ITEM_SLOT_ICLOTHING) var/obj/item/clothing/suit/straight_jacket/S = user_H.get_item_by_slot(ITEM_SLOT_ICLOTHING)
if(istype(S)) if(istype(S))
user_C.visible_message("<span class='warning'>[user_C] attempts to remove [S]!</span>", \ user_C.visible_message("<span class='warning'>[user_C] attempts to remove [S]!</span>", \
"<span class='warning'>You rip through [S] like it's nothing!</span>") "<span class='warning'>You rip through [S] like it's nothing!</span>")
user_C.clear_cuffs(S,TRUE) user_C.clear_cuffs(S,TRUE)
playsound(get_turf(usr), 'sound/effects/grillehit.ogg', 80, 1, -1) playsound(get_turf(usr), 'sound/effects/grillehit.ogg', 80, 1, -1)
return TRUE return TRUE */
// Destroy Leg Cuffs // Destroy Leg Cuffs
if(user_C.legcuffed) if(user_C.legcuffed)
var/obj/O = user_C.get_item_by_slot(SLOT_LEGCUFFED) var/obj/O = user_C.get_item_by_slot(SLOT_LEGCUFFED)
@@ -149,7 +139,7 @@
return FALSE return FALSE
/datum/action/bloodsucker/targeted/brawn/proc/CheckEscapePuller() /datum/action/bloodsucker/targeted/brawn/proc/CheckEscapePuller()
if (!owner.pulledby)// || owner.pulledby.grab_state <= GRAB_PASSIVE) if(!owner.pulledby)// || owner.pulledby.grab_state <= GRAB_PASSIVE)
return FALSE return FALSE
var/mob/M = owner.pulledby var/mob/M = owner.pulledby
var/pull_power = M.grab_state var/pull_power = M.grab_state
@@ -169,3 +159,16 @@
"<span class='warning'>You shrug off [M]'s grasp!</span>") "<span class='warning'>You shrug off [M]'s grasp!</span>")
owner.pulledby = null // It's already done, but JUST IN CASE. owner.pulledby = null // It's already done, but JUST IN CASE.
return TRUE return TRUE
/* Doesnt work
/datum/action/bloodsucker/targeted/brawn/proc/CheckBreakLocker()
if(!istype(owner.loc, /obj/structure/closet))
return FALSE
playsound(get_turf(owner), 'sound/machines/airlock_alien_prying.ogg', 40, 1, -1)
if(do_mob(owner ,target, 25))
var/obj/structure/closet/C = owner.loc
to_chat(owner, "<span class='notice'>You prepare to tear open the [C].</span>")
owner.do_attack_animation(C, ATTACK_EFFECT_SMASH)
playsound(get_turf(C), 'sound/effects/bang.ogg', 30, 1, -1)
C.bust_open()
return TRUE
*/
@@ -11,9 +11,6 @@
warn_constant_cost = TRUE warn_constant_cost = TRUE
var/light_min = 0.5 // If lum is above this, no good. var/light_min = 0.5 // If lum is above this, no good.
var/remember_start_loc // Where this power was activated, so it can be checked from ContinueActive
// Level Up
var/upgrade_canMove = FALSE // Can I move around with this power?
/datum/action/bloodsucker/cloak/CheckCanUse(display_error) /datum/action/bloodsucker/cloak/CheckCanUse(display_error)
. = ..() . = ..()
@@ -30,19 +27,11 @@
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
var/mob/living/user = owner var/mob/living/user = owner
remember_start_loc = user.loc
// Freeze in Place (so you don't auto-cancel)
//user.mobility_flags &= ~MOBILITY_MOVE
while (bloodsuckerdatum && ContinueActive(user)) while (bloodsuckerdatum && ContinueActive(user))
//if (!do_mob(user, user, 10, 0, 0, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
// return
// Fade from sight // Fade from sight
owner.alpha = max(0, owner.alpha - min(75, 20 + 15 * level_current)) owner.alpha = max(0, owner.alpha - min(75, 20 + 15 * level_current))
bloodsuckerdatum.AddBloodVolume(-0.2) bloodsuckerdatum.AddBloodVolume(-0.2)
ADD_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
sleep(5) sleep(5)
/datum/action/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target) /datum/action/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target)
@@ -52,12 +41,8 @@
if(user.stat == !CONSCIOUS) if(user.stat == !CONSCIOUS)
to_chat(owner, "<span class='warning'>Your cloak failed due to you falling unconcious! </span>") to_chat(owner, "<span class='warning'>Your cloak failed due to you falling unconcious! </span>")
return FALSE return FALSE
// Must be SAME LOCATION
var/turf/T = owner.loc
if (!upgrade_canMove && T != remember_start_loc)
to_chat(owner, "<span class='warning'>Your cloak is not yet powerfull enough to allow you to move!</span>")
return FALSE
// Must be DARK // Must be DARK
var/turf/T = owner.loc
if(istype(T) && T.get_lumcount() > light_min) if(istype(T) && T.get_lumcount() > light_min)
to_chat(owner, "<span class='warning'>Your cloak failed due to there being too much light!</span>") to_chat(owner, "<span class='warning'>Your cloak failed due to there being too much light!</span>")
return FALSE return FALSE
@@ -66,4 +51,5 @@
/datum/action/bloodsucker/cloak/DeactivatePower(mob/living/user = owner, mob/living/target) /datum/action/bloodsucker/cloak/DeactivatePower(mob/living/user = owner, mob/living/target)
..() ..()
REMOVE_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
user.alpha = 255 user.alpha = 255
@@ -94,7 +94,7 @@
puff.set_up(3, 0, get_turf(owner)) puff.set_up(3, 0, get_turf(owner))
puff.start() puff.start()
// TELEPORT: Move to Coffin & Close it! // TELEPORT: Move to Coffin & Close it!
do_teleport(owner, bloodsuckerdatum.coffin, no_effects=TRUE) // in teleport.dm? do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE) // in teleport.dm?
// SLEEP // SLEEP
user.resting = TRUE user.resting = TRUE
//user.Unconscious(30,0) //user.Unconscious(30,0)
@@ -20,10 +20,14 @@
if(!.) if(!.)
return return
// Being Grabbed // Being Grabbed
if (owner.pulledby && owner.pulledby.grab_state >= GRAB_AGGRESSIVE) if(owner.pulledby && owner.pulledby.grab_state >= GRAB_AGGRESSIVE)
if (display_error) if(display_error)
to_chat(owner, "<span class='warning'>You're being grabbed!</span>") to_chat(owner, "<span class='warning'>You're being grabbed!</span>")
return FALSE return FALSE
if(!owner.has_gravity(owner.loc)) //We dont want people to be able to use this to fly around in space
if(display_error)
to_chat(owner, "<span class='warning'>You cant dash while floating!</span>")
return FALSE
return TRUE return TRUE
/datum/action/bloodsucker/targeted/haste/CheckValidTarget(atom/A) /datum/action/bloodsucker/targeted/haste/CheckValidTarget(atom/A)
@@ -67,9 +71,6 @@
if (rand(0, 5) < level_current) if (rand(0, 5) < level_current)
playsound(get_turf(newtarget), "sound/weapons/punch[rand(1,4)].ogg", 15, 1, -1) playsound(get_turf(newtarget), "sound/weapons/punch[rand(1,4)].ogg", 15, 1, -1)
newtarget.Knockdown(10 + level_current * 5) newtarget.Knockdown(10 + level_current * 5)
newtarget.adjustStaminaLoss(10 + 5 * level_current)
newtarget.Stun(5 + level_current * 2)
newtarget.adjustStaminaLoss(5 + 3 * level_current)
if(newtarget.IsStun()) if(newtarget.IsStun())
newtarget.spin(10,1) newtarget.spin(10,1)
if (rand(0,4)) if (rand(0,4))
@@ -17,10 +17,14 @@
if(!..(display_error))// DEFAULT CHECKS if(!..(display_error))// DEFAULT CHECKS
return FALSE return FALSE
// Being Grabbed // Being Grabbed
if (owner.pulledby && owner.pulledby.grab_state >= GRAB_AGGRESSIVE) if(owner.pulledby && owner.pulledby.grab_state >= GRAB_AGGRESSIVE)
if (display_error) if(display_error)
to_chat(owner, "<span class='warning'>You're being grabbed!</span>") to_chat(owner, "<span class='warning'>You're being grabbed!</span>")
return FALSE return FALSE
if(!owner.has_gravity(owner.loc))//TODO figure out how to check if theyre able to move while in nograv
if(display_error)
to_chat(owner, "<span class='warning'>You cant lunge while floating!</span>")
return FALSE
return TRUE return TRUE
/datum/action/bloodsucker/targeted/lunge/CheckValidTarget(atom/A) /datum/action/bloodsucker/targeted/lunge/CheckValidTarget(atom/A)
@@ -28,7 +32,7 @@
/datum/action/bloodsucker/targeted/lunge/CheckCanTarget(atom/A, display_error) /datum/action/bloodsucker/targeted/lunge/CheckCanTarget(atom/A, display_error)
// Check: Self // Check: Self
if (target == owner) if(target == owner)
return FALSE return FALSE
// Check: Range // Check: Range
//if (!(target in view(target_range, get_turf(owner)))) //if (!(target in view(target_range, get_turf(owner))))
@@ -36,11 +40,11 @@
// to_chat(owner, "<span class='warning'>Your victim is too far away.</span>") // to_chat(owner, "<span class='warning'>Your victim is too far away.</span>")
// return FALSE // return FALSE
// DEFAULT CHECKS (Distance) // DEFAULT CHECKS (Distance)
if (!..()) if(!..())
return FALSE return FALSE
// Check: Turf // Check: Turf
var/mob/living/L = A var/mob/living/L = A
if (!isturf(L.loc)) if(!isturf(L.loc))
return FALSE return FALSE
return TRUE return TRUE
@@ -56,6 +60,7 @@
// Step One: Heatseek toward Target's Turf // Step One: Heatseek toward Target's Turf
walk_towards(owner, T, 0.1, 10) // NOTE: this runs in the background! to cancel it, you need to use walk(owner.current,0), or give them a new path. walk_towards(owner, T, 0.1, 10) // NOTE: this runs in the background! to cancel it, you need to use walk(owner.current,0), or give them a new path.
addtimer(CALLBACK(owner, .proc/_walk, 0), 2 SECONDS)
if(get_turf(owner) != T && !(isliving(target) && target.Adjacent(owner)) && owner.incapacitated() && owner.resting) if(get_turf(owner) != T && !(isliving(target) && target.Adjacent(owner)) && owner.incapacitated() && owner.resting)
var/send_dir = get_dir(owner, T) var/send_dir = get_dir(owner, T)
new /datum/forced_movement(owner, get_ranged_target_turf(owner, send_dir, 1), 1, FALSE) new /datum/forced_movement(owner, get_ranged_target_turf(owner, send_dir, 1), 1, FALSE)
@@ -64,7 +69,7 @@
sleep(1) sleep(1)
if(target.Adjacent(owner)) if(target.Adjacent(owner))
// LEVEL 2: If behind target, mute or unconscious! // LEVEL 2: If behind target, mute or unconscious!
if (do_knockdown) // && level_current >= 1) if(do_knockdown) // && level_current >= 1)
target.Knockdown(15 + 10 * level_current,1) target.Knockdown(15 + 10 * level_current,1)
target.adjustStaminaLoss(40 + 10 * level_current) target.adjustStaminaLoss(40 + 10 * level_current)
// Cancel Walk (we were close enough to contact them) // Cancel Walk (we were close enough to contact them)
@@ -94,8 +94,8 @@
if(do_mob(user, target, 40, 0, TRUE, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target))) if(do_mob(user, target, 40, 0, TRUE, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN! PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!
target.silent += 100 + level_current * 15
var/power_time = 90 + level_current * 15 var/power_time = 90 + level_current * 15
target.silent += power_time + 50
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 100 + level_current * 15) target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 100 + level_current * 15)
to_chat(user, "<span class='notice'>[target] is fixed in place by your hypnotic gaze.</span>") to_chat(user, "<span class='notice'>[target] is fixed in place by your hypnotic gaze.</span>")
target.Stun(power_time) target.Stun(power_time)
@@ -101,7 +101,7 @@
// Move & Freeze // Move & Freeze
if (isturf(target_turf)) if (isturf(target_turf))
do_teleport(owner, target_turf, no_effects=TRUE) // in teleport.dm? do_teleport(owner, target_turf, no_effects=TRUE, forced = TRUE) // in teleport.dm?
user.next_move = world.time + mist_delay / 2 user.next_move = world.time + mist_delay / 2
user.Stun(mist_delay / 2, ignore_canstun = TRUE) user.Stun(mist_delay / 2, ignore_canstun = TRUE)
@@ -33,7 +33,7 @@
C.heal_overall_damage(bruteheal) C.heal_overall_damage(bruteheal)
C.blood_volume -= 0.6 C.blood_volume -= 0.6
if (C.getStaminaLoss() < 60) if (C.getStaminaLoss() < 60)
C.adjustStaminaLoss(25, forced = TRUE) C.adjustStaminaLoss(10, forced = TRUE)
// Stop Bleeding // Stop Bleeding
if (istype(H) && H.bleed_rate > 0 && rand(20) == 0) if (istype(H) && H.bleed_rate > 0 && rand(20) == 0)
H.bleed_rate -- H.bleed_rate --
@@ -41,7 +41,7 @@
C.Jitter(5) C.Jitter(5)
sleep(20) sleep(10)
// DONE! // DONE!
//DeactivatePower(owner) //DeactivatePower(owner)
@@ -177,6 +177,8 @@
bodies = old_species.bodies bodies = old_species.bodies
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H) /datum/species/jelly/slime/spec_life(mob/living/carbon/human/H)
if((HAS_TRAIT(H, TRAIT_NOMARROW)))
return
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT) if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
if(prob(5)) if(prob(5))
to_chat(H, "<span class='notice'>You feel very bloated!</span>") to_chat(H, "<span class='notice'>You feel very bloated!</span>")
+1 -1
View File
@@ -180,7 +180,7 @@
else else
new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color()) new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color())
if(iscarbon(L)) if(iscarbon(L) && !HAS_TRAIT(L, TRAIT_NOMARROW))
var/mob/living/carbon/C = L var/mob/living/carbon/C = L
C.bleed(damage) C.bleed(damage)
else else
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB