Merge branch 'master' into Ghommie-cit679

This commit is contained in:
Ghom
2020-04-14 16:22:00 +02:00
committed by GitHub
208 changed files with 2331 additions and 1470 deletions
@@ -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.
@@ -8,7 +8,7 @@
desc = "Dash somewhere with supernatural speed. Those nearby may be knocked away, stunned, or left empty-handed."
button_icon_state = "power_speed"
bloodcost = 6
cooldown = 50
cooldown = 120
target_range = 15
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -28,8 +28,7 @@
action.Remove(user)
return
/obj/effect/proc_holder/changeling/Click()
var/mob/user = usr
/obj/effect/proc_holder/changeling/Trigger(mob/user)
if(!user || !user.mind || !user.mind.has_antag_datum(/datum/antagonist/changeling))
return
try_to_sting(user)
@@ -3,8 +3,7 @@
desc = "Stabby stabby."
var/sting_icon = null
/obj/effect/proc_holder/changeling/sting/Click()
var/mob/user = usr
/obj/effect/proc_holder/changeling/sting/Trigger(mob/user)
if(!user || !user.mind)
return
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
@@ -74,8 +73,7 @@
action_icon_state = "ling_sting_transform"
action_background_icon_state = "bg_ling"
/obj/effect/proc_holder/changeling/sting/transformation/Click()
var/mob/user = usr
/obj/effect/proc_holder/changeling/sting/transformation/Trigger(mob/user)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling.chosen_sting)
unset_sting(user)
@@ -35,7 +35,7 @@
var/span_for_name = "heavy_brass"
var/span_for_message = "brass"
/datum/action/innate/hierophant/IsAvailable()
/datum/action/innate/hierophant/IsAvailable(silent = FALSE)
if(!is_servant_of_ratvar(owner))
return FALSE
return ..()
@@ -12,7 +12,7 @@
var/obj/item/clockwork/weapon/weapon_type //The type of weapon to create
var/obj/item/clockwork/weapon/weapon
/datum/action/innate/call_weapon/IsAvailable()
/datum/action/innate/call_weapon/IsAvailable(silent = FALSE)
if(!is_servant_of_ratvar(owner))
qdel(src)
return
@@ -121,8 +121,8 @@
. = ..()
addtimer(CALLBACK(src, .proc/check_on_mob, user), 1) //dropped is called before the item is out of the slot, so we need to check slightly later
/obj/item/clockwork/slab/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clockwork/slab/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(isinhands && item_state && inhand_overlay)
var/mutable_appearance/M = mutable_appearance(icon_file, "slab_[inhand_overlay]")
. += M
@@ -232,7 +232,7 @@
background_icon_state = "bg_clock"
buttontooltipstyle = "clockcult"
/datum/action/innate/eminence/IsAvailable()
/datum/action/innate/eminence/IsAvailable(silent = FALSE)
if(!iseminence(owner))
qdel(src)
return
@@ -283,7 +283,7 @@
desc = "Initiates a mass recall, warping all servants to the Ark after a short delay. This can only be used once."
button_icon_state = "Spatial Gateway"
/datum/action/innate/eminence/mass_recall/IsAvailable()
/datum/action/innate/eminence/mass_recall/IsAvailable(silent = FALSE)
. = ..()
if(.)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
@@ -153,7 +153,7 @@
/obj/item/clothing/head/helmet/space,
/obj/item/clothing/shoes/magboots)) //replace this only if ratvar is up
/datum/action/innate/clockwork_armaments/IsAvailable()
/datum/action/innate/clockwork_armaments/IsAvailable(silent = FALSE)
if(!is_servant_of_ratvar(owner))
qdel(src)
return
+2 -2
View File
@@ -17,7 +17,7 @@
qdel(X)
..()
/datum/action/innate/cult/blood_magic/IsAvailable()
/datum/action/innate/cult/blood_magic/IsAvailable(silent = FALSE)
if(!iscultist(owner))
return FALSE
return ..()
@@ -118,7 +118,7 @@
hand_magic = null
..()
/datum/action/innate/cult/blood_spell/IsAvailable()
/datum/action/innate/cult/blood_spell/IsAvailable(silent = FALSE)
if(!iscultist(owner) || owner.incapacitated() || !charges)
return FALSE
return ..()
+10 -10
View File
@@ -6,7 +6,7 @@
buttontooltipstyle = "cult"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
/datum/action/innate/cult/IsAvailable()
/datum/action/innate/cult/IsAvailable(silent = FALSE)
if(!iscultist(owner))
return FALSE
return ..()
@@ -51,7 +51,7 @@
name = "Spiritual Communion"
desc = "Conveys a message from the spirit realm that all cultists can hear."
/datum/action/innate/cult/comm/spirit/IsAvailable()
/datum/action/innate/cult/comm/spirit/IsAvailable(silent = FALSE)
if(iscultist(owner.mind.current))
return TRUE
@@ -72,7 +72,7 @@
name = "Assert Leadership"
button_icon_state = "cultvote"
/datum/action/innate/cult/mastervote/IsAvailable()
/datum/action/innate/cult/mastervote/IsAvailable(silent = FALSE)
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!C?.cult_team || C.cult_team.cult_vote_called || !ishuman(owner))
return FALSE
@@ -140,7 +140,7 @@
to_chat(B.current,"<span class='cultlarge'>[Nominee] has won the cult's support and is now their master. Follow [Nominee.p_their()] orders to the best of your ability!</span>")
return TRUE
/datum/action/innate/cult/master/IsAvailable()
/datum/action/innate/cult/master/IsAvailable(silent = FALSE)
if(!owner.mind || !owner.mind.has_antag_datum(/datum/antagonist/cult/master) || GLOB.cult_narsie)
return 0
return ..()
@@ -226,9 +226,9 @@
CM.attached_action = src
..()
/datum/action/innate/cult/master/cultmark/IsAvailable()
/datum/action/innate/cult/master/cultmark/IsAvailable(silent = FALSE)
if(cooldown > world.time)
if(!CM.active)
if(!CM.active && !silent)
to_chat(owner, "<span class='cultlarge'><b>You need to wait [DisplayTimeText(cooldown - world.time)] before you can mark another target!</b></span>")
return FALSE
return ..()
@@ -308,7 +308,7 @@
name = "Mark a Blood Target for the Cult"
desc = "Marks a target for the entire cult to track."
/datum/action/innate/cult/master/cultmark/ghost/IsAvailable()
/datum/action/innate/cult/master/cultmark/ghost/IsAvailable(silent = FALSE)
if(istype(owner, /mob/dead/observer) && iscultist(owner.mind.current))
return TRUE
else
@@ -322,7 +322,7 @@
var/cooldown = 0
var/base_cooldown = 600
/datum/action/innate/cult/ghostmark/IsAvailable()
/datum/action/innate/cult/ghostmark/IsAvailable(silent = FALSE)
if(istype(owner, /mob/dead/observer) && iscultist(owner.mind.current))
return TRUE
else
@@ -401,11 +401,11 @@
PM.attached_action = src
..()
/datum/action/innate/cult/master/pulse/IsAvailable()
/datum/action/innate/cult/master/pulse/IsAvailable(silent = FALSE)
if(!owner.mind || !owner.mind.has_antag_datum(/datum/antagonist/cult/master))
return FALSE
if(cooldown > world.time)
if(!PM.active)
if(!PM.active && !silent)
to_chat(owner, "<span class='cultlarge'><b>You need to wait [DisplayTimeText(cooldown - world.time)] before you can pulse again!</b></span>")
return FALSE
return ..()
+4 -4
View File
@@ -222,7 +222,7 @@
phasein = /obj/effect/temp_visual/dir_setting/cult/phase
phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out
/datum/action/innate/dash/cult/IsAvailable()
/datum/action/innate/dash/cult/IsAvailable(silent = FALSE)
if(iscultist(holder) && current_charges)
return TRUE
else
@@ -242,7 +242,7 @@
sword = bastard
holder = user
/datum/action/innate/cult/spin2win/IsAvailable()
/datum/action/innate/cult/spin2win/IsAvailable(silent = FALSE)
if(iscultist(holder) && cooldown <= world.time)
return TRUE
else
@@ -451,8 +451,8 @@
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
return BLOCK_NONE
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands && current_charges)
. += mutable_appearance('icons/effects/cult_effects.dmi', "shield-cult", MOB_LAYER + 0.01)
@@ -14,7 +14,7 @@
var/obj/effect/temp_visual/cult/rune_spawn/rune_center_type
var/rune_color
/datum/action/innate/cult/create_rune/IsAvailable()
/datum/action/innate/cult/create_rune/IsAvailable(silent = FALSE)
if(!rune_type || cooldown > world.time)
return FALSE
return ..()
+61 -2
View File
@@ -179,8 +179,8 @@
/obj/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(resistance_flags & INDESTRUCTIBLE)
return FALSE
for(var/mob/living/L in contents)
if(!issilicon(L) && !isbrain(L))
for(var/mob/living/L in GetAllContents())
if(!ispAI(L) && !isbrain(L))
to_chat(S, "<span class='warning'>An organism has been detected inside this object. Aborting.</span>")
return FALSE
return ..()
@@ -416,6 +416,57 @@
to_chat(S, "<span class='warning'>Destroying this object would cause a catastrophic chain reaction. Aborting.</span>")
return FALSE
/obj/machinery/ore_silo/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object, however tempting it's, will disrupt the research development that may serve for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/rnd/server/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object, will disrupt the research development that may serve for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/pool/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) //pool's closed, but not.
to_chat(S, "<span class='warning'>The pool must not be closed, it will provide healthy fun for our masters in the future. Aborting.</span>")
return FALSE
/obj/structure/pool/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>The pool must not be closed, it will provide healthy fun for our masters in the future. Aborting.</span>")
return FALSE
/obj/structure/holosign/barrier/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/static/list/lazy_typecache = typecacheof(list(/obj/structure/holosign/barrier/engineering, /obj/structure/holosign/barrier/firelock, /obj/structure/holosign/barrier/atmos, /obj/structure/holosign/barrier/combifan))
if(lazy_typecache[type])
to_chat(S, "<span class='warning'>Destroying this holographic barrier may not benefit us. Aborting.</span>")
return FALSE
return ..()
/obj/machinery/dominator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This advanced piece of technology may be of use for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/computer/bsa_control/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This advanced piece of technology may be of use for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/bsa/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This advanced piece of technology may be of use for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/dna_vault/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This advanced piece of technology may be of use for our masters in the future. Aborting.</span>")
return FALSE
/obj/structure/filler/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This advanced piece of technology may be of use for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/computer/sat_control/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object will lower the station shielding against space debris. Aborting.</span>")
return FALSE
/obj/machinery/satellite/meteor_shield/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object will lower the station shielding against space debris. Aborting.</span>")
return FALSE
////END CTRL CLICK FOR SWARMERS////
/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(atom/fabrication_object,fabrication_cost = 0)
@@ -429,6 +480,14 @@
return new fabrication_object(loc)
/mob/living/simple_animal/hostile/swarmer/proc/Integrate(atom/movable/target)
if(isobj(target))
var/obj/O = target
if(O.resistance_flags & INDESTRUCTIBLE)
return FALSE
for(var/mob/living/L in GetAllContents())
if(!ispAI(L) && !isbrain(L))
to_chat(src, "<span class='warning'>An organism has been detected inside this object. Aborting.</span>")
return FALSE
var/resource_gain = target.IntegrateAmount()
if(resources + resource_gain > max_resources)
to_chat(src, "<span class='warning'>We cannot hold more materials!</span>")
@@ -1,10 +1,10 @@
/datum/round_event_control/spawn_swarmer
name = "Spawn Swarmer Shell"
typepath = /datum/round_event/spawn_swarmer
weight = 0
max_occurrences = 0
weight = 7
max_occurrences = 1 //Only once okay fam
earliest_start = 30 MINUTES
min_players = 15
min_players = 35
gamemode_blacklist = list("dynamic")
@@ -43,7 +43,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
else
owner_AI = owner
/datum/action/innate/ai/IsAvailable()
/datum/action/innate/ai/IsAvailable(silent = FALSE)
. = ..()
if(owner_AI && owner_AI.malf_cooldown > world.time)
return FALSE
+2 -3
View File
@@ -74,10 +74,9 @@
/datum/supply_pack/science/circuitry
name = "Circuitry Starter Pack Crate"
desc = "Journey into the mysterious world of Circuitry with this starter pack. Contains a circuit printer, analyzer, debugger and wirer. Power cells not included."
desc = "Journey into the mysterious world of Circuitry with this starter pack. Contains a circuit printer, debugger and wirer. Power cells not included."
cost = 1000
contains = list(/obj/item/integrated_electronics/analyzer,
/obj/item/integrated_circuit_printer,
contains = list(/obj/item/integrated_circuit_printer,
/obj/item/integrated_electronics/debugger,
/obj/item/integrated_electronics/wirer)
crate_name = "circuitry starter pack crate"
+43 -19
View File
@@ -150,7 +150,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"ipc_antenna" = "None",
"flavor_text" = "",
"meat_type" = "Mammalian",
"body_model" = MALE
"body_model" = MALE,
"body_size" = RESIZE_DEFAULT_SIZE
)
var/list/custom_names = list()
@@ -294,7 +295,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<a href='?_src_=prefs;preference=name;task=input'>[real_name]</a><BR>"
dat += "<a href='?_src_=prefs;preference=nameless'>Be nameless: [nameless ? "Yes" : "No"]</a><BR>"
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender;task=input'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
dat += "<b>Age:</b> <a style='display:block;width:30px' href='?_src_=prefs;preference=age;task=input'>[age]</a><BR>"
dat += "<b>Special Names:</b><BR>"
@@ -345,7 +346,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
dat += "[TextPreview(features["flavor_text"])]...<BR>"
dat += "<h2>Body</h2>"
dat += "<b>Gender:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=gender'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
dat += "<b>Gender:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=gender;task=input'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
if(gender != NEUTER && pref_species.sexes)
dat += "<b>Body Model:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=body_model'>[features["body_model"] == MALE ? "Masculine" : "Feminine"]</a><BR>"
dat += "<b>Species:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=species;task=input'>[pref_species.name]</a><BR>"
@@ -379,6 +380,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<span style='border: 1px solid #161616; background-color: #[features["mcolor3"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color3;task=input'>Change</a><BR>"
mutant_colors = TRUE
if (CONFIG_GET(number/body_size_min) != CONFIG_GET(number/body_size_max))
dat += "<b>Sprite Size:</b> <a href='?_src_=prefs;preference=body_size;task=input'>[features["body_size"]]%</a><br>"
if((EYECOLOR in pref_species.species_traits) && !(NOEYES in pref_species.species_traits))
if(!use_skintones && !mutant_colors)
@@ -2119,6 +2123,38 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_toggle_color)
hud_toggle_color = new_toggle_color
if("gender")
var/chosengender = input(user, "Select your character's gender.", "Gender Selection", gender) as null|anything in list(MALE,FEMALE,"nonbinary","object")
if(!chosengender)
return
switch(chosengender)
if("nonbinary")
chosengender = PLURAL
features["body_model"] = pick(MALE, FEMALE)
if("object")
chosengender = NEUTER
features["body_model"] = MALE
else
features["body_model"] = chosengender
gender = chosengender
facial_hair_style = random_facial_hair_style(gender)
hair_style = random_hair_style(gender)
if("body_size")
var/min = CONFIG_GET(number/body_size_min)
var/max = CONFIG_GET(number/body_size_max)
var/danger = CONFIG_GET(number/threshold_body_size_slowdown)
var/new_body_size = input(user, "Choose your desired sprite size:\n([min*100]%-[max*100]%), Warning: May make your character look distorted[danger > min ? ", and an exponential slowdown will occur for those smaller than [danger*100]%!" : "!"]", "Character Preference", features["body_size"]*100) as num|null
if (new_body_size)
new_body_size = CLAMP(new_body_size * 0.01, min, max)
var/dorfy
if(danger > new_body_size)
dorfy = alert(user, "The chosen size appears to be smaller than the threshold of [danger*100]%, which will lead to an added exponential slowdown. Are you sure about that?", "Dwarfism Alert", "Yes", "Move it to the threshold", "No")
if(!dorfy || dorfy == "Move it above the threshold")
new_body_size = danger
if(dorfy != "No")
features["body_size"] = new_body_size
else
switch(href_list["preference"])
//CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj
@@ -2171,22 +2207,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("publicity")
if(unlock_content)
toggles ^= MEMBER_PUBLIC
if("gender")
var/chosengender = input(user, "Select your character's gender.", "Gender Selection", gender) as null|anything in list(MALE,FEMALE,"nonbinary","object")
if(!chosengender)
return
switch(chosengender)
if("nonbinary")
chosengender = PLURAL
features["body_model"] = pick(MALE, FEMALE)
if("object")
chosengender = NEUTER
features["body_model"] = MALE
else
features["body_model"] = chosengender
gender = chosengender
facial_hair_style = random_facial_hair_style(gender)
hair_style = random_hair_style(gender)
if("body_model")
features["body_model"] = features["body_model"] == MALE ? FEMALE : MALE
@@ -2431,6 +2451,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
pref_species = new /datum/species/human
save_character()
var/old_size = character.dna.features["body_size"]
character.dna.features = features.Copy()
character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE)
character.dna.real_name = character.real_name
@@ -2452,6 +2474,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.give_genitals(TRUE) //character.update_genitals() is already called on genital.update_appearance()
character.dna.update_body_size(old_size)
SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks)
//let's be sure the character updates
@@ -395,6 +395,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["body_is_always_random"] >> be_random_body
S["gender"] >> gender
S["body_model"] >> features["body_model"]
S["body_size"] >> features["body_size"]
S["age"] >> age
S["hair_color"] >> hair_color
S["facial_hair_color"] >> facial_hair_color
@@ -568,6 +569,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["insect_markings"] = sanitize_inlist(features["insect_markings"], GLOB.insect_markings_list, "None")
features["insect_wings"] = sanitize_inlist(features["insect_wings"], GLOB.insect_wings_list)
var/static/size_min
if(!size_min)
size_min = CONFIG_GET(number/body_size_min)
var/static/size_max
if(!size_max)
size_max = CONFIG_GET(number/body_size_max)
features["body_size"] = sanitize_integer(features["body_size"], size_min, size_max, RESIZE_DEFAULT_SIZE)
var/static/list/B_sizes
if(!B_sizes)
var/list/L = CONFIG_GET(keyed_list/breasts_cups_prefs)
@@ -643,6 +652,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["body_is_always_random"] , be_random_body)
WRITE_FILE(S["gender"] , gender)
WRITE_FILE(S["body_model"] , features["body_model"])
WRITE_FILE(S["body_size"] , features["body_size"])
WRITE_FILE(S["age"] , age)
WRITE_FILE(S["hair_color"] , hair_color)
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
-194
View File
@@ -47,25 +47,12 @@
//Add a "exclude" string to do the opposite, making it only only species listed that can't wear it.
//You append this to clothing objects.
//Polychrome stuff:
var/hasprimary = FALSE //These vars allow you to choose which overlays a clothing has
var/hassecondary = FALSE
var/hastertiary = FALSE
var/primary_color = "#FFFFFF" //RGB in hexcode
var/secondary_color = "#FFFFFF"
var/tertiary_color = "#808080"
//No idea what this is but eh -tori
var/force_alternate_icon = FALSE
/obj/item/clothing/Initialize()
. = ..()
if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE))
actions_types += /datum/action/item_action/toggle_voice_box
if(ispath(pocket_storage_component_path))
LoadComponent(pocket_storage_component_path)
if(hasprimary | hassecondary | hastertiary) //Checks if polychrome is enabled
update_icon() //Applies the overlays and default colors onto the clothes on spawn.
/obj/item/clothing/MouseDrop(atom/over_object)
. = ..()
@@ -150,8 +137,6 @@
how_cool_are_your_threads += "Adding or removing items from [src] makes no noise.\n"
how_cool_are_your_threads += "</span>"
. += how_cool_are_your_threads.Join()
if(hasprimary | hassecondary | hastertiary) //Checks if polychrome is enabled
. += "<span class='notice'>Alt-click to recolor it.</span>"
/obj/item/clothing/obj_break(damage_flag)
if(!damaged_clothes)
@@ -195,173 +180,6 @@ BLIND // can't see anything
female_clothing_icon = fcopy_rsc(female_clothing_icon)
GLOB.female_clothing_icons[index] = female_clothing_icon
/obj/item/clothing/under/verb/toggle()
set name = "Adjust Suit Sensors"
set category = "Object"
set src in usr
var/mob/M = usr
if (istype(M, /mob/dead/))
return
if (!can_use(M))
return
if(src.has_sensor == LOCKED_SENSORS)
to_chat(usr, "The controls are locked.")
return 0
if(src.has_sensor == BROKEN_SENSORS)
to_chat(usr, "The sensors have shorted out!")
return 0
if(src.has_sensor <= NO_SENSORS)
to_chat(usr, "This suit does not have any sensors.")
return 0
var/list/modes = list("Off", "Binary vitals", "Exact vitals", "Tracking beacon")
var/switchMode = input("Select a sensor mode:", "Suit Sensor Mode", modes[sensor_mode + 1]) in modes
if(get_dist(usr, src) > 1)
to_chat(usr, "<span class='warning'>You have moved too far away!</span>")
return
sensor_mode = modes.Find(switchMode) - 1
if (src.loc == usr)
switch(sensor_mode)
if(0)
to_chat(usr, "<span class='notice'>You disable your suit's remote sensing equipment.</span>")
if(1)
to_chat(usr, "<span class='notice'>Your suit will now only report whether you are alive or dead.</span>")
if(2)
to_chat(usr, "<span class='notice'>Your suit will now only report your exact vital lifesigns.</span>")
if(3)
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
if(H.w_uniform == src)
H.update_suit_sensors()
/obj/item/clothing/under/CtrlClick(mob/user)
. = ..()
if (!(item_flags & IN_INVENTORY))
return
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(has_sensor == LOCKED_SENSORS)
to_chat(user, "The controls are locked.")
return
if(has_sensor == BROKEN_SENSORS)
to_chat(user, "The sensors have shorted out!")
return
if(has_sensor <= NO_SENSORS)
to_chat(user, "This suit does not have any sensors.")
return
sensor_mode = SENSOR_COORDS
to_chat(user, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.w_uniform == src)
H.update_suit_sensors()
/obj/item/clothing/under/AltClick(mob/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(attached_accessory)
remove_accessory(user)
else
rolldown()
// Polychrome stuff:
if(hasprimary | hassecondary | hastertiary)
var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays
switch(choice) //Lets the list's options actually lead to something
if("Primary Color")
var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it.
if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL.
primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly
update_icon() //updates the item icon
user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works.
if("Secondary Color")
var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null
if(secondary_color_input)
secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1)
update_icon()
user.regenerate_icons()
if("Tertiary Color")
var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null
if(tertiary_color_input)
tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1)
update_icon()
user.regenerate_icons()
return TRUE
/obj/item/clothing/neck/AltClick(mob/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
// Polychrome stuff:
if(hasprimary | hassecondary | hastertiary)
var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays
switch(choice) //Lets the list's options actually lead to something
if("Primary Color")
var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it.
if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL.
primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly
update_icon() //updates the item icon
user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works.
if("Secondary Color")
var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null
if(secondary_color_input)
secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1)
update_icon()
user.regenerate_icons()
if("Tertiary Color")
var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null
if(tertiary_color_input)
tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1)
update_icon()
user.regenerate_icons()
return TRUE
/obj/item/clothing/under/verb/jumpsuit_adjust()
set name = "Adjust Jumpsuit Style"
set category = null
set src in usr
rolldown()
/obj/item/clothing/under/proc/rolldown()
if(!can_use(usr))
return
if(!can_adjust)
to_chat(usr, "<span class='warning'>You cannot wear this suit any differently!</span>")
return
if(toggle_jumpsuit_adjust())
to_chat(usr, "<span class='notice'>You adjust the suit to wear it more casually.</span>")
else
to_chat(usr, "<span class='notice'>You adjust the suit back to normal.</span>")
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
H.update_inv_w_uniform()
H.update_body()
/obj/item/clothing/under/proc/toggle_jumpsuit_adjust()
adjusted = !adjusted
if(adjusted)
if(fitted != FEMALE_UNIFORM_TOP)
fitted = NO_FEMALE_UNIFORM
if(!alt_covers_chest) // for the special snowflake suits that expose the chest when adjusted
body_parts_covered &= ~CHEST
else
fitted = initial(fitted)
if(!alt_covers_chest)
body_parts_covered |= CHEST
return adjusted
/obj/item/clothing/proc/weldingvisortoggle(mob/user) //proc to toggle welding visors on helmets, masks, goggles, etc.
if(!can_use(user))
return FALSE
@@ -441,15 +259,3 @@ BLIND // can't see anything
return FALSE
return TRUE
/obj/item/clothing/update_overlays() // Polychrome stuff
. = ..()
if(hasprimary) //Checks if the overlay is enabled
var/mutable_appearance/primary_overlay = mutable_appearance(icon, "[item_state]-primary", color = primary_color) //Automagically picks overlays
. += primary_overlay //Applies the coloured overlay onto the item sprite. but NOT the mob sprite.
if(hassecondary)
var/mutable_appearance/secondary_overlay = mutable_appearance(icon, "[item_state]-secondary", color = secondary_color)
. += secondary_overlay
if(hastertiary)
var/mutable_appearance/tertiary_overlay = mutable_appearance(icon, "[item_state]-tertiary", color = tertiary_color)
. += tertiary_overlay
+2 -2
View File
@@ -346,8 +346,8 @@
add_atom_colour("#[user.eye_color]", FIXED_COLOUR_PRIORITY)
colored_before = TRUE
/obj/item/clothing/glasses/sunglasses/blindfold/white/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/glasses/sunglasses/blindfold/white/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands && ishuman(loc) && !colored_before)
var/mob/living/carbon/human/H = loc
var/mutable_appearance/M = mutable_appearance('icons/mob/clothing/eyes.dmi', "blindfoldwhite")
@@ -23,8 +23,8 @@
else
. += "<span class='notice'>[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again."
/obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/user, combatmodestate)
if(istype(user) && combatmodestate && world.time >= nextadrenalinepop)
/obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/living/user, was_forced = FALSE)
if(user.combat_flags & COMBAT_FLAG_COMBAT_TOGGLED && world.time >= nextadrenalinepop)
nextadrenalinepop = world.time + 5 MINUTES
user.reagents.add_reagent(/datum/reagent/syndicateadrenals, 5)
user.playsound_local(user, 'sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
+2 -2
View File
@@ -26,8 +26,8 @@
user.visible_message("<span class='suicide'>\the [src] are forcing [user]'s hands around [user.p_their()] neck! It looks like the gloves are possessed!</span>")
return OXYLOSS
/obj/item/clothing/gloves/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/gloves/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves")
+2 -2
View File
@@ -48,8 +48,8 @@
/obj/item/clothing/head/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/head/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet")
+1 -1
View File
@@ -124,7 +124,7 @@
playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing
update_icon()
/obj/item/clothing/head/hardhat/weldhat/worn_overlays(isinhands, icon_file, style_flags = NONE)
/obj/item/clothing/head/hardhat/weldhat/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
. += mutable_appearance('icons/mob/clothing/head.dmi', "weldhelmet")
+2 -2
View File
@@ -204,8 +204,8 @@
icon = S.icon
icon_state = S.icon_state
/obj/item/clothing/head/wig/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/head/wig/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
var/datum/sprite_accessory/S = GLOB.hair_styles_list[hair_style]
if(!S)
+2 -2
View File
@@ -28,8 +28,8 @@
/obj/item/clothing/mask/proc/handle_speech()
/obj/item/clothing/mask/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/mask/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
if(body_parts_covered & HEAD)
if(damaged_clothes)
+23 -46
View File
@@ -6,8 +6,8 @@
strip_delay = 40
equip_delay_other = 40
/obj/item/clothing/neck/worn_overlays(isinhands = FALSE, icon_flag, style_flags = NONE)
. = list()
/obj/item/clothing/neck/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
if(body_parts_covered & HEAD)
if(damaged_clothes)
@@ -169,54 +169,44 @@
name = "pet collar"
desc = "It's for pets. Though you probably could wear it yourself, you'd doubtless be the subject of ridicule. It seems to be made out of a polychromic material."
icon_state = "petcollar"
mob_overlay_icon = 'icons/mob/clothing/neck.dmi' //Because, as it appears, the item itself is normally not directly aware of its worn overlays, so this is about the easiest way, without adding a new var.
hasprimary = TRUE
primary_color = "#00BBBB"
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar
var/poly_states = 1
var/poly_colors = list("#00BBBB")
var/tagname = null
var/treat_path = /obj/item/reagent_containers/food/snacks/cookie
/obj/item/clothing/neck/petcollar/Initialize()
. = ..()
if(treat_path)
new treat_path(src)
/obj/item/clothing/neck/petcollar/ComponentInitialize()
. = ..()
if(!poly_states)
return
AddElement(/datum/element/polychromic, poly_colors, poly_states)
/obj/item/clothing/neck/petcollar/attack_self(mob/user)
tagname = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot", MAX_NAME_LEN)
name = "[initial(name)] - [tagname]"
/obj/item/clothing/neck/petcollar/worn_overlays(isinhands, icon_file, style_flags = NONE)
. = ..()
if(hasprimary | hassecondary | hastertiary)
if(!isinhands) //prevents the worn sprites from showing up if you're just holding them
if(hasprimary) //checks if overlays are enabled
var/mutable_appearance/primary_worn = mutable_appearance(mob_overlay_icon, "[icon_state]-primary") //automagical sprite selection
primary_worn.color = primary_color //colors the overlay
. += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite
if(hassecondary)
var/mutable_appearance/secondary_worn = mutable_appearance(mob_overlay_icon, "[icon_state]-secondary")
secondary_worn.color = secondary_color
. += secondary_worn
if(hastertiary)
var/mutable_appearance/tertiary_worn = mutable_appearance(mob_overlay_icon, "[icon_state]-tertiary")
tertiary_worn.color = tertiary_color
. += tertiary_worn
/obj/item/clothing/neck/petcollar/leather
name = "leather pet collar"
icon_state = "leathercollar"
hasprimary = TRUE
hassecondary = TRUE
primary_color = "#222222"
secondary_color = "#888888"
poly_states = 2
poly_colors = list("#222222", "#888888")
/obj/item/clothing/neck/petcollar/choker
desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel."
name = "choker"
icon_state = "choker"
hasprimary = TRUE
primary_color = "#222222"
poly_colors = list("#222222")
/obj/item/clothing/neck/petcollar/locked
name = "locked collar"
desc = "A collar that has a small lock on it to keep it from being removed."
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar/locked
treat_path = /obj/item/key/collar
var/lock = FALSE
/obj/item/clothing/neck/petcollar/locked/attackby(obj/item/K, mob/user, params)
@@ -238,32 +228,19 @@
/obj/item/clothing/neck/petcollar/locked/leather
name = "leather pet collar"
icon_state = "leathercollar"
hasprimary = TRUE
hassecondary = TRUE
primary_color = "#222222"
secondary_color = "#888888"
poly_states = 2
poly_colors = list("#222222", "#888888")
/obj/item/clothing/neck/petcollar/locked/choker
name = "choker"
desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel."
icon_state = "choker"
hasprimary = TRUE
primary_color = "#222222"
poly_colors = list("#222222")
/obj/item/key/collar
name = "Collar Key"
desc = "A key for a tiny lock on a collar or bag."
/obj/item/clothing/neck/petcollar/Initialize()
. = ..()
new /obj/item/reagent_containers/food/snacks/cookie(src)
/obj/item/clothing/neck/petcollar/locked/Initialize()
. = ..()
new /obj/item/key/collar(src)
//////////////
//DOPE BLING//
//////////////
+2 -2
View File
@@ -49,8 +49,8 @@
last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
last_blood_DNA = blood_dna[blood_dna.len]
/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
var/bloody = FALSE
if(blood_DNA)
@@ -377,3 +377,99 @@
name = "black cowboy boots"
desc = "A pair of black cowboy boots, pretty easy to scuff up."
icon_state = "cowboyboots_black"
/obj/item/clothing/shoes/wallwalkers
name = "wall walking boots"
desc = "Contrary to popular belief, these do not allow you to walk on walls. Through bluespace magic stolen from an organisation that hoards technology, they simply allow you to slip through the atoms that make up anything, but only while walking, for safety reasons. As well as this, they unfortunately cause minor breath loss as the majority of atoms in your lungs are sucked out into any solid object you walk through. Make sure not to overuse them."
icon_state = "walkboots"
var/walkcool = 0
var/wallcharges = 4
var/newlocobject = null
/obj/item/clothing/shoes/wallwalkers/equipped(mob/user,slot)
. = ..()
if(slot == SLOT_SHOES)
RegisterSignal(user, COMSIG_MOB_CLIENT_MOVE,.proc/intercept_user_move)
/obj/item/clothing/shoes/wallwalkers/dropped(mob/user)
. = ..()
UnregisterSignal(user, COMSIG_MOB_CLIENT_MOVE)
/obj/item/clothing/shoes/wallwalkers/attackby(obj/item/W, mob/user, params)
. = ..()
if(!istype(W, /obj/item/bluespacerecharge))
return
var/obj/item/bluespacerecharge/ER = W
if(ER.uses)
wallcharges += ER.uses
to_chat(user, "<span class='notice'>You charged the bluespace crystal in the [src]. It now has [wallcharges] charges left.</span>")
ER.uses = 0
ER.icon_state = "[initial(ER.icon_state)]0"
else
to_chat(user, "<span class='warning'>[ER] has no crystal on it.</span>")
/obj/item/clothing/shoes/wallwalkers/examine(mob/user)
. = ..()
. += "<span class='warning'>It has [wallcharges] charges left.</span>"
/obj/item/clothing/shoes/wallwalkers/proc/intercept_user_move(mob/living/m, client/client, dir, newloc, oldloc)
if (walkcool >= world.time || m.m_intent != MOVE_INTENT_WALK || wallcharges <= 0)
return
walkcool = world.time + m.movement_delay()
var/issolid = FALSE
var/turf/K = newloc
if (istype(K))
if (K.density)
issolid = TRUE
if (!issolid)
for (var/atom/T in newloc) //stuff on the new turf
if (!T.CanPass(m,newloc) && T != m)
issolid = TRUE
newlocobject = T
break
if (!issolid)
for (var/atom/T in oldloc) //directional shit on the old turf
if (!T.CanPass(m,newloc) && T != m && T != newlocobject)
issolid = TRUE
break
newlocobject = null //stopping structures from using two charges because of how shitty the canpass code is
m.forceMove(newloc)
if (!issolid)
return
m.adjustOxyLoss(rand(5,13))
if (prob(15))
m.adjustBruteLoss(rand(4,7))
to_chat(m,"<span class='warning'>You feel as if travelling through the solid object left something behind and it hurts!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, oldloc)
s.start()
flash_lighting_fx(3, 3, LIGHT_COLOR_ORANGE)
wallcharges--
/obj/item/bluespacerecharge
name = "bluespace crystal recharging device"
desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for replacing the crystals in bluespace devices."
icon = 'icons/obj/module.dmi'
icon_state = "bluespace_charge"
item_flags = NOBLUDGEON
w_class = WEIGHT_CLASS_TINY
var/uses = 6
/obj/item/bluespacerecharge/examine(mob/user)
. = ..()
if(uses)
. += "<span class='notice'>It can add up to [uses] charges to compatible devices.</span>"
else
. += "<span class='warning'>The crystal is gone.</span>"
/obj/item/bluespacerecharge/attackby(obj/item/I, mob/user, params)
..()
if(!istype(I, /obj/item/stack/ore/bluespace_crystal) || uses)
return
var/obj/item/stack/ore/bluespace_crystal/B = I
if (B.amount < 10)
return
uses += 3
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
B.use(10)
icon_state = initial(icon_state)
@@ -321,7 +321,7 @@
check_flags = AB_CHECK_CONSCIOUS //|AB_CHECK_INSIDE
var/obj/item/clothing/suit/space/chronos/chronosuit = null
/datum/action/innate/chrono_teleport/IsAvailable()
/datum/action/innate/chrono_teleport/IsAvailable(silent = FALSE)
return (chronosuit && chronosuit.activated && chronosuit.camera && !chronosuit.teleporting)
/datum/action/innate/chrono_teleport/Activate()
+6 -8
View File
@@ -30,16 +30,14 @@
/obj/item/clothing/head/helmet/space/hardsuit/attack_self(mob/user)
on = !on
icon_state = "[basestate][on]-[hardsuit_type]"
user.update_inv_head() //so our mob-overlays update
if(on)
set_light(brightness_on)
else
set_light(0)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
/obj/item/clothing/head/helmet/space/hardsuit/update_icon_state()
icon_state = "[basestate][on]-[hardsuit_type]"
/obj/item/clothing/head/helmet/space/hardsuit/dropped(mob/user)
..()
@@ -802,7 +800,7 @@
var/mob/living/carbon/human/C = loc
C.update_inv_wear_suit()
/obj/item/clothing/suit/space/hardsuit/shielded/worn_overlays(isinhands, icon_file, style_flags = NONE)
/obj/item/clothing/suit/space/hardsuit/shielded/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
var/file2use = style_flags & STYLE_ALL_TAURIC ? 'modular_citadel/icons/mob/64x32_effects.dmi' : 'icons/effects/effects.dmi'
@@ -959,7 +957,7 @@
. = ..()
. += mutable_appearance(icon, "knight_cydonia_overlay", color = energy_color)
/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER)
@@ -990,7 +988,7 @@
. = ..()
. += mutable_appearance(icon, "knight_cydonia_overlay", color = energy_color)
/obj/item/clothing/suit/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
/obj/item/clothing/suit/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER)
@@ -67,7 +67,7 @@
var/datum/action/A=X
A.UpdateButtonIcon()
/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(isinhands, icon_file, style_flags = NONE)
/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands && on)
. += mutable_appearance(icon_file, light_overlay)
+1 -1
View File
@@ -12,7 +12,7 @@
var/suittoggled = FALSE
mutantrace_variation = STYLE_DIGITIGRADE
/obj/item/clothing/suit/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
/obj/item/clothing/suit/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
if(damaged_clothes)
+11
View File
@@ -91,3 +91,14 @@
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE
/obj/item/clothing/neck/cloak/polychromic
name = "polychromic cloak"
desc = "For when you want to show off your horrible colour coordination skills."
icon_state = "polyce"
item_state = "qmcloak"
var/list/poly_colors = list("#FFFFFF", "#FFFFFF", "#808080")
/obj/item/clothing/neck/cloak/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
+4 -63
View File
@@ -974,70 +974,11 @@
icon_state = "coatpoly"
item_state = "coatpoly"
hoodtype = /obj/item/clothing/head/hooded/winterhood/polychromic
hasprimary = TRUE
hassecondary = TRUE
hastertiary = TRUE
primary_color = "#6A6964"
secondary_color = "#C4B8A6"
tertiary_color = "#0000FF"
/obj/item/clothing/suit/hooded/wintercoat/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#6A6964", "#C4B8A6", "#0000FF"), 3)
/obj/item/clothing/head/hooded/winterhood/polychromic
icon_state = "winterhood_poly"
item_state = "winterhood_poly"
/obj/item/clothing/head/hooded/winterhood/polychromic/worn_overlays(isinhands, icon_file, style_flags = NONE) //this is where the main magic happens.
. = ..()
if(suit.hasprimary | suit.hassecondary)
if(!isinhands) //prevents the worn sprites from showing up if you're just holding them
if(suit.hasprimary) //checks if overlays are enabled
var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[icon_state]-primary") //automagical sprite selection
primary_worn.color = suit.primary_color //colors the overlay
. += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite.
if(suit.hassecondary)
var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[icon_state]-secondary")
secondary_worn.color = suit.secondary_color
. += secondary_worn
/obj/item/clothing/suit/hooded/wintercoat/polychromic/worn_overlays(isinhands, icon_file, style_flags = NONE) //this is where the main magic happens.
. = ..()
if(hasprimary | hassecondary | hastertiary)
if(!isinhands) //prevents the worn sprites from showing up if you're just holding them
if(hasprimary) //checks if overlays are enabled
var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[icon_state]-primary[suittoggled ? "_t" : ""]") //automagical sprite selection
primary_worn.color = primary_color //colors the overlay
. += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite.
if(hassecondary)
var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[icon_state]-secondary[suittoggled ? "_t" : ""]")
secondary_worn.color = secondary_color
. += secondary_worn
if(hastertiary)
var/mutable_appearance/tertiary_worn = mutable_appearance(icon_file, "[icon_state]-tertiary[suittoggled ? "_t" : ""]")
tertiary_worn.color = tertiary_color
. += tertiary_worn
/obj/item/clothing/suit/hooded/wintercoat/AltClick(mob/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(hasprimary | hassecondary | hastertiary)
var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays
switch(choice) //Lets the list's options actually lead to something
if("Primary Color")
var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it.
if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL.
primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly
update_icon() //updates the item icon
user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works.
if("Secondary Color")
var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null
if(secondary_color_input)
secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1)
update_icon()
user.regenerate_icons()
if("Tertiary Color")
var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null
if(tertiary_color_input)
tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1)
update_icon()
user.regenerate_icons()
return TRUE
+14 -10
View File
@@ -6,7 +6,7 @@
var/hoodtype = /obj/item/clothing/head/hooded/winterhood //so the chaplain hoodie or other hoodies can override this
/obj/item/clothing/suit/hooded/New()
MakeHood()
hood = MakeHelmet()
..()
/obj/item/clothing/suit/hooded/Destroy()
@@ -14,11 +14,15 @@
qdel(hood)
hood = null
/obj/item/clothing/suit/hooded/proc/MakeHood()
/obj/item/clothing/suit/proc/MakeHelmet(obj/item/clothing/head/H)
SEND_SIGNAL(src, COMSIG_SUIT_MADE_HELMET, H)
return H
/obj/item/clothing/suit/hooded/MakeHelmet(obj/item/clothing/head/hooded/H)
if(!hood)
var/obj/item/clothing/head/hooded/W = new hoodtype(src)
W.suit = src
hood = W
H = new hoodtype(src)
H.suit = src
return ..()
/obj/item/clothing/suit/hooded/ui_action_click()
ToggleHood()
@@ -125,7 +129,7 @@
//Hardsuit toggle code
/obj/item/clothing/suit/space/hardsuit/Initialize()
MakeHelmet()
helmet = MakeHelmet()
. = ..()
/obj/item/clothing/suit/space/hardsuit/Destroy()
@@ -140,13 +144,13 @@
suit.helmet = null
return ..()
/obj/item/clothing/suit/space/hardsuit/proc/MakeHelmet()
/obj/item/clothing/suit/space/hardsuit/MakeHelmet(obj/item/clothing/head/helmet/space/hardsuit/H)
if(!helmettype)
return
if(!helmet)
var/obj/item/clothing/head/helmet/space/hardsuit/W = new helmettype(src)
W.suit = src
helmet = W
H = new helmettype(src)
H.suit = src
return ..()
/obj/item/clothing/suit/space/hardsuit/ui_action_click()
..()
+118 -16
View File
@@ -18,28 +18,14 @@
var/obj/item/clothing/accessory/attached_accessory
var/mutable_appearance/accessory_overlay
/obj/item/clothing/under/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/obj/item/clothing/under/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(isinhands)
return
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform")
if(blood_DNA)
. += mutable_appearance('icons/effects/blood.dmi', "uniformblood", color = blood_DNA_to_color())
if(accessory_overlay)
. += accessory_overlay
if(hasprimary) //checks if overlays are enabled
var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[icon_state]-primary") //automagical sprite selection
primary_worn.color = primary_color //colors the overlay
. += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite.
if(hassecondary)
var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[icon_state]-secondary")
secondary_worn.color = secondary_color
. += secondary_worn
if(hastertiary)
var/mutable_appearance/tertiary_worn = mutable_appearance(icon_file, "[icon_state]-tertiary")
tertiary_worn.color = tertiary_color
. += tertiary_worn
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
@@ -167,5 +153,121 @@
if(attached_accessory)
. += "\A [attached_accessory] is attached to it."
/obj/item/clothing/under/verb/toggle()
set name = "Adjust Suit Sensors"
set category = "Object"
set src in usr
var/mob/M = usr
if (istype(M, /mob/dead/))
return
if (!can_use(M))
return
if(src.has_sensor == LOCKED_SENSORS)
to_chat(usr, "The controls are locked.")
return 0
if(src.has_sensor == BROKEN_SENSORS)
to_chat(usr, "The sensors have shorted out!")
return 0
if(src.has_sensor <= NO_SENSORS)
to_chat(usr, "This suit does not have any sensors.")
return 0
var/list/modes = list("Off", "Binary vitals", "Exact vitals", "Tracking beacon")
var/switchMode = input("Select a sensor mode:", "Suit Sensor Mode", modes[sensor_mode + 1]) in modes
if(get_dist(usr, src) > 1)
to_chat(usr, "<span class='warning'>You have moved too far away!</span>")
return
sensor_mode = modes.Find(switchMode) - 1
if (src.loc == usr)
switch(sensor_mode)
if(0)
to_chat(usr, "<span class='notice'>You disable your suit's remote sensing equipment.</span>")
if(1)
to_chat(usr, "<span class='notice'>Your suit will now only report whether you are alive or dead.</span>")
if(2)
to_chat(usr, "<span class='notice'>Your suit will now only report your exact vital lifesigns.</span>")
if(3)
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
if(H.w_uniform == src)
H.update_suit_sensors()
/obj/item/clothing/under/CtrlClick(mob/user)
. = ..()
if (!(item_flags & IN_INVENTORY))
return
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(has_sensor == LOCKED_SENSORS)
to_chat(user, "The controls are locked.")
return
if(has_sensor == BROKEN_SENSORS)
to_chat(user, "The sensors have shorted out!")
return
if(has_sensor <= NO_SENSORS)
to_chat(user, "This suit does not have any sensors.")
return
sensor_mode = SENSOR_COORDS
to_chat(user, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.w_uniform == src)
H.update_suit_sensors()
/obj/item/clothing/under/AltClick(mob/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(attached_accessory)
remove_accessory(user)
else
rolldown()
/obj/item/clothing/under/verb/jumpsuit_adjust()
set name = "Adjust Jumpsuit Style"
set category = null
set src in usr
rolldown()
/obj/item/clothing/under/proc/rolldown()
if(!can_use(usr))
return
if(!can_adjust)
to_chat(usr, "<span class='warning'>You cannot wear this suit any differently!</span>")
return
if(toggle_jumpsuit_adjust())
to_chat(usr, "<span class='notice'>You adjust the suit to wear it more casually.</span>")
else
to_chat(usr, "<span class='notice'>You adjust the suit back to normal.</span>")
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
H.update_inv_w_uniform()
H.update_body()
/obj/item/clothing/under/proc/toggle_jumpsuit_adjust()
adjusted = !adjusted
if(adjusted)
if(fitted != FEMALE_UNIFORM_TOP)
fitted = NO_FEMALE_UNIFORM
if(!alt_covers_chest) // for the special snowflake suits that expose the chest when adjusted
body_parts_covered &= ~CHEST
else
fitted = initial(fitted)
if(!alt_covers_chest)
body_parts_covered |= CHEST
return adjusted
/obj/item/clothing/under/rank
dying_key = DYE_REGISTRY_UNDER
+4 -4
View File
@@ -91,13 +91,13 @@
name = "polychromic kilt"
desc = "It's not a skirt!"
icon_state = "polykilt"
hasprimary = TRUE
hassecondary = TRUE
primary_color = "#FFFFFF"
secondary_color = "#F08080"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
mutantrace_variation = NONE
/obj/item/clothing/under/costume/kilt/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#FFFFFF", "#F08080"), 2)
/obj/item/clothing/under/costume/gladiator
name = "gladiator uniform"
desc = "Are you not entertained? Is that not why you are here?"
+25 -27
View File
@@ -241,69 +241,67 @@
desc = "A fancy button-up shirt made with polychromic threads."
icon_state = "polysuit"
item_state = "sl_suit"
hasprimary = TRUE
hassecondary = TRUE
hastertiary = TRUE
primary_color = "#FFFFFF"
secondary_color = "#353535"
tertiary_color = "#353535"
mutantrace_variation = NONE
/obj/item/clothing/under/misc/poly_shirt/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#FFFFFF", "#353535", "#353535"), 3)
/obj/item/clothing/under/misc/polyshorts
name = "polychromic shorts"
desc = "For ease of movement and style."
icon_state = "polyshorts"
item_state = "rainbow"
hasprimary = TRUE
hassecondary = TRUE
hastertiary = TRUE
primary_color = "#353535"
secondary_color = "#808080"
tertiary_color = "#808080"
can_adjust = FALSE
body_parts_covered = CHEST|GROIN|ARMS
/obj/item/clothing/under/misc/polyshorts/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#353535", "#808080", "#808080"), 3)
/obj/item/clothing/under/misc/polyjumpsuit
name = "polychromic tri-tone jumpsuit"
desc = "A fancy jumpsuit made with polychromic threads."
icon_state = "polyjump"
item_state = "rainbow"
hasprimary = TRUE
hassecondary = TRUE
hastertiary = TRUE
primary_color = "#FFFFFF"
secondary_color = "#808080"
tertiary_color = "#FF3535"
can_adjust = FALSE
mutantrace_variation = NONE
/obj/item/clothing/under/misc/polyjumpsuit/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#FFFFFF", "#808080", "#353535"), 3)
/obj/item/clothing/under/misc/poly_bottomless
name = "polychromic bottomless shirt"
desc = "Great for showing off your junk in dubious style."
desc = "Great for showing off your underwear in dubious style."
icon_state = "polybottomless"
item_state = "rainbow"
primary_color = "#808080"
secondary_color = "#FF3535"
body_parts_covered = CHEST|ARMS //Because there's no bottom included
can_adjust = FALSE
mutantrace_variation = NONE
/obj/item/clothing/under/misc/poly_bottomless/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#808080", "#FF3535"), 2)
/obj/item/clothing/under/misc/poly_tanktop
name = "polychromic tank top"
desc = "For those lazy summer days."
icon_state = "polyshimatank"
item_state = "rainbow"
primary_color = "#808080"
secondary_color = "#FFFFFF"
tertiary_color = "#8CC6FF"
body_parts_covered = CHEST|GROIN
can_adjust = FALSE
mutantrace_variation = NONE
var/list/poly_states = 3
var/list/poly_colors = list("#808080", "#FFFFFF", "#8CC6FF")
/obj/item/clothing/under/misc/poly_tanktop/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, poly_states)
/obj/item/clothing/under/misc/poly_tanktop/female
name = "polychromic feminine tank top"
desc = "Great for showing off your chest in style. Not recommended for males."
icon_state = "polyfemtankpantsu"
hastertiary = FALSE
primary_color = "#808080"
secondary_color = "#FF3535"
poly_states = 2
poly_colors = list("#808080", "#FF3535")
+6 -7
View File
@@ -35,19 +35,18 @@
desc = "95% Polychrome, 5% Spandex!"
icon_state = "polyshortpants"
item_state = "rainbow"
hasprimary = TRUE
hassecondary = TRUE
primary_color = "#FFFFFF"
secondary_color = "#F08080"
mutantrace_variation = NONE
var/list/poly_colors = list("#FFFFFF", "#F08080")
/obj/item/clothing/under/shorts/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 2)
/obj/item/clothing/under/shorts/polychromic/pantsu
name = "polychromic panties"
desc = "Topless striped panties. Now with 120% more polychrome!"
icon_state = "polypantsu"
item_state = "rainbow"
hastertiary = FALSE
primary_color = "#FFFFFF"
secondary_color = "#8CC6FF"
body_parts_covered = GROIN
mutantrace_variation = NONE
poly_colors = list("#FFFFFF", "#8CC6FF")
+6 -9
View File
@@ -211,21 +211,18 @@
desc = "A fancy skirt made with polychromic threads."
icon_state = "polyskirt"
item_state = "rainbow"
hasprimary = TRUE
hassecondary = TRUE
hastertiary = TRUE
primary_color = "#FFFFFF"
secondary_color = "#F08080"
tertiary_color = "#808080"
mutantrace_variation = NONE
var/list/poly_colors = list("#FFFFFF", "#F08080", "#808080")
/obj/item/clothing/under/dress/skirt/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
/obj/item/clothing/under/dress/skirt/polychromic/pleated
name = "polychromic pleated skirt"
desc = "A magnificent pleated skirt complements the woolen polychromatic sweater."
icon_state = "polypleat"
item_state = "rainbow"
primary_color = "#8CC6FF"
secondary_color = "#808080"
tertiary_color = "#FF3535"
body_parts_covered = CHEST|GROIN|ARMS
mutantrace_variation = NONE
poly_colors = list("#8CC6FF", "#808080", "#FF3535")
+4 -6
View File
@@ -109,11 +109,9 @@
desc = "For when you want to show off your horrible colour coordination skills."
icon_state = "polysuit"
item_state = "sl_suit"
hasprimary = TRUE
hassecondary = TRUE
hastertiary = TRUE
primary_color = "#FFFFFF"
secondary_color = "#FFFFFF"
tertiary_color = "#808080"
can_adjust = FALSE
mutantrace_variation = NONE
/obj/item/clothing/under/suit/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#FFFFFF", "#FFFFFF", "#808080"), 3)
@@ -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)
+2 -2
View File
@@ -86,8 +86,8 @@
tag_overlay.pixel_y = boxes.len * 3
add_overlay(tag_overlay)
/obj/item/pizzabox/worn_overlays(isinhands, icon_file, style_flags = NONE)
. = list()
/obj/item/pizzabox/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
var/current_offset = 2
if(isinhands)
for(var/V in boxes) //add EXTRA BOX per box
@@ -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
+12 -1
View File
@@ -63,23 +63,34 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars_by_type, typecacheof_assoc_list(list(
var/src_min_x = 99999
var/src_min_y = 99999
var/src_max_x = 0
var/src_max_y = 0
var/list/refined_src = new/list()
for (var/turf/T in turfs_src)
src_min_x = min(src_min_x,T.x)
src_min_y = min(src_min_y,T.y)
src_max_x = max(src_max_x,T.y)
src_max_y = max(src_max_y,T.y)
for (var/turf/T in turfs_src)
refined_src[T] = "[T.x - src_min_x].[T.y - src_min_y]"
var/trg_min_x = 99999
var/trg_min_y = 99999
var/trg_max_x = 0
var/trg_max_y = 0
var/list/refined_trg = new/list()
for (var/turf/T in turfs_trg)
trg_min_x = min(trg_min_x,T.x)
trg_min_y = min(trg_min_y,T.y)
trg_max_x = max(trg_max_x,T.y)
trg_max_y = max(trg_max_y,T.y)
var/diff_x = round(((src_max_x - src_min_x) - (trg_max_x - trg_min_x))/2)
var/diff_y = round(((src_max_y - src_min_y) - (trg_max_y - trg_min_y))/2)
for (var/turf/T in turfs_trg)
refined_trg["[T.x - trg_min_x].[T.y - trg_min_y]"] = T
refined_trg["[T.x - trg_min_x + diff_x].[T.y - trg_min_y + diff_y]"] = T
var/list/toupdate = new/list()
+5 -4
View File
@@ -2,7 +2,10 @@
Holodeck Update
The on-station holodeck area is of type [holodeck_type].
All subtypes of [program_type] are loaded into the program cache or emag programs list.
All types found in GLOB.holodeck_areas_per_comp_type[src.type], generated on make_datum_references_lists(),
are loaded into the program cache or emag programs list.
Paths with their abstract_type variable equal to themselves will be skipped.
If init_program is null, a random program will be loaded on startup.
If you don't wish this, set it to the offline program or another of your choosing.
@@ -12,7 +15,6 @@
3) Create a new control console that uses those areas
Non-mapped areas should be skipped but you should probably comment them out anyway.
The base of program_type will always be ignored; only subtypes will be loaded.
*/
#define HOLODECK_CD 25
@@ -35,7 +37,6 @@
// Splitting this up allows two holodecks of the same size
// to use the same source patterns. Y'know, if you want to.
var/holodeck_type = /area/holodeck/rec_center // locate(this) to get the target holodeck
var/program_type = /area/holodeck/rec_center // subtypes of this (but not this itself) are loadable programs
var/active = FALSE
var/damaged = FALSE
@@ -181,7 +182,7 @@
return ..()
/obj/machinery/computer/holodeck/proc/generate_program_list()
for(var/typekey in subtypesof(program_type))
for(var/typekey in GLOB.holodeck_areas_prototypes[type])
var/area/holodeck/A = GLOB.areas_by_type[typekey]
if(!A || !A.contents.len)
continue
+29
View 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"
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
// VAMPIRE LANGUAGE //
// BLOODSUCKER LANGUAGE //
/datum/language/vampiric
name = "Blah-Sucker"
@@ -117,7 +117,7 @@
glass_overlay.appearance_flags = RESET_COLOR
. += glass_overlay
/obj/item/clothing/head/helmet/space/hostile_environment/worn_overlays(isinhands, icon_file, style_flags = NONE)
/obj/item/clothing/head/helmet/space/hostile_environment/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
var/mutable_appearance/M = mutable_appearance('icons/mob/clothing/head.dmi', "hostile_env_glass")
@@ -433,19 +433,23 @@
desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher."
icon_state = "vortex_talisman"
denied_type = /obj/item/crusher_trophy/vortex_talisman
var/vortex_cd
/obj/item/crusher_trophy/vortex_talisman/effect_desc()
return "mark detonation to create a barrier you can pass"
return "mark detonation to create a barrier you can pass that lasts for <b>7.5 seconds</b>, with a cooldown of <b>9 seconds</b> after creation."
/obj/item/crusher_trophy/vortex_talisman/on_mark_detonation(mob/living/target, mob/living/user)
if(vortex_cd >= world.time)
return
var/turf/T = get_turf(user)
new /obj/effect/temp_visual/hierophant/wall/crusher(T, user) //a wall only you can pass!
var/obj/effect/temp_visual/hierophant/wall/crusher/W = new (T, user) //a wall only you can pass!
var/turf/otherT = get_step(T, turn(user.dir, 90))
if(otherT)
new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
otherT = get_step(T, turn(user.dir, -90))
if(otherT)
new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
vortex_cd = world.time + W.duration * 1.2
/obj/effect/temp_visual/hierophant/wall/crusher
duration = 75
@@ -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)
@@ -21,14 +21,13 @@ Doesn't work on other aliens/AI.*/
. = ..()
action = new(src)
/obj/effect/proc_holder/alien/Click()
if(!iscarbon(usr))
return 1
var/mob/living/carbon/user = usr
if(cost_check(check_turf,user))
/obj/effect/proc_holder/alien/Trigger(mob/living/carbon/user, skip_cost_check)
if(!istype(user))
return TRUE
if(!skip_cost_check || cost_check(check_turf,user))
if(fire(user) && user) // Second check to prevent runtimes when evolving
user.adjustPlasma(-plasma_cost)
return 1
return TRUE
/obj/effect/proc_holder/alien/on_gain(mob/living/carbon/user)
return
@@ -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
+1 -1
View File
@@ -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
@@ -469,7 +469,7 @@
var/cooldown = 150
var/last_teleport = 0
/datum/action/innate/unstable_teleport/IsAvailable()
/datum/action/innate/unstable_teleport/IsAvailable(silent = FALSE)
if(..())
if(world.time > last_teleport + cooldown)
return 1
@@ -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
@@ -84,7 +84,7 @@
background_icon_state = "bg_alien"
required_mobility_flags = NONE
/datum/action/innate/regenerate_limbs/IsAvailable()
/datum/action/innate/regenerate_limbs/IsAvailable(silent = FALSE)
if(..())
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
@@ -223,7 +223,7 @@
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
/datum/action/innate/split_body/IsAvailable()
/datum/action/innate/split_body/IsAvailable(silent = FALSE)
if(..())
var/mob/living/carbon/human/H = owner
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
@@ -776,7 +776,7 @@
..()
species = _species
/datum/action/innate/use_extract/IsAvailable()
/datum/action/innate/use_extract/IsAvailable(silent = FALSE)
if(..())
if(species && species.current_extract && (world.time > species.extract_cooldown))
return TRUE
@@ -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
@@ -321,12 +321,16 @@ There are several things that need to be remembered:
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(client && hud_used && hud_used.inv_slots[SLOT_BACK])
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
inv.update_icon()
update_mutant_bodyparts()
if(head)
head.screen_loc = ui_head
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += head
update_observer_view(head,1)
remove_overlay(HEAD_LAYER)
var/obj/item/clothing/head/H = head
var/alt_icon = H.mob_overlay_icon || 'icons/mob/clothing/head.dmi'
@@ -348,6 +352,7 @@ There are several things that need to be remembered:
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
overlays_standing[HEAD_LAYER] = head_overlay
apply_overlay(HEAD_LAYER)
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_belt()
remove_overlay(BELT_LAYER)
@@ -457,11 +462,16 @@ There are several things that need to be remembered:
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(client && hud_used && hud_used.inv_slots[SLOT_WEAR_MASK])
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
inv.update_icon()
if(wear_mask)
wear_mask.screen_loc = ui_mask
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += wear_mask
update_observer_view(wear_mask,1)
var/obj/item/clothing/mask/M = wear_mask
remove_overlay(FACEMASK_LAYER)
var/alt_icon = M.mob_overlay_icon || 'icons/mob/clothing/mask.dmi'
@@ -515,22 +525,6 @@ There are several things that need to be remembered:
//human HUD updates for items in our inventory
//update whether our head item appears on our hud.
/mob/living/carbon/human/update_hud_head(obj/item/I)
I.screen_loc = ui_head
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += I
update_observer_view(I,1)
//update whether our mask item appears on our hud.
/mob/living/carbon/human/update_hud_wear_mask(obj/item/I)
I.screen_loc = ui_mask
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += I
update_observer_view(I,1)
//update whether our neck item appears on our hud.
/mob/living/carbon/human/update_hud_neck(obj/item/I)
I.screen_loc = ui_neck
@@ -579,13 +573,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state, style_flags = NONE, use_mob_overlay_icon = TRUE)
var/t_state
if(override_state)
t_state = override_state
else
if(isinhands && item_state)
t_state = item_state
else
t_state = icon_state
t_state = override_state || item_state || icon_state
//Find a valid icon file from variables+arguments
var/file2use
@@ -609,7 +597,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
//Get the overlays for this item when it's being worn
//eg: ammo counters, primed grenade flashes, etc.
var/list/worn_overlays = worn_overlays(isinhands, file2use, style_flags)
var/list/worn_overlays = worn_overlays(isinhands, file2use, t_state, style_flags)
if(worn_overlays && worn_overlays.len)
standing.overlays.Add(worn_overlays)
+7 -16
View File
@@ -90,9 +90,9 @@
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(client && hud_used && hud_used.inv_slots[SLOT_WEAR_MASK])
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
inv.update_icon()
inv?.update_icon()
if(wear_mask)
if(!(head && (head.flags_inv & HIDEMASK)))
@@ -110,7 +110,7 @@
if(wear_neck)
if(!(head && (head.flags_inv & HIDENECK)))
overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = 'icons/mob/clothing/neck.dmi', override_state = wear_mask.icon_state)
overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = 'icons/mob/clothing/neck.dmi', override_state = wear_neck.icon_state)
update_hud_neck(wear_neck)
apply_overlay(NECK_LAYER)
@@ -118,9 +118,9 @@
/mob/living/carbon/update_inv_back()
remove_overlay(BACK_LAYER)
if(client && hud_used && hud_used.inv_slots[SLOT_BACK])
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BACK]
inv.update_icon()
inv?.update_icon()
if(back)
overlays_standing[BACK_LAYER] = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = 'icons/mob/clothing/back.dmi', override_state = back.icon_state)
@@ -134,9 +134,9 @@
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(client && hud_used && hud_used.inv_slots[SLOT_BACK])
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
inv.update_icon()
inv?.update_icon()
if(head)
overlays_standing[HEAD_LAYER] = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/clothing/head.dmi', override_state = head.icon_state)
@@ -191,15 +191,6 @@
/mob/living/carbon/proc/update_hud_back(obj/item/I)
return
//Overlays for the worn overlay so you can overlay while you overlay
//eg: ammo counters, primed grenade flashing, etc.
//"icon_file" is used automatically for inhands etc. to make sure it gets the right inhand file
/obj/item/proc/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE)
. = list()
/mob/living/carbon/update_body()
update_body_parts()
+1 -1
View File
@@ -354,7 +354,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
if(cultslurring)
message = cultslur(message)
if(clockcultslurring)
message = CLOCK_CULT_SLUR(message)
@@ -400,10 +400,9 @@
action.button_icon_state = "wrap_[active]"
action.UpdateButtonIcon()
/obj/effect/proc_holder/wrap/Click()
if(!istype(usr, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
/obj/effect/proc_holder/wrap/Trigger(mob/living/simple_animal/hostile/poison/giant_spider/nurse/user)
if(!istype(user))
return TRUE
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/user = usr
activate(user)
return TRUE
@@ -444,7 +443,7 @@
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "lay_eggs"
/datum/action/innate/spider/lay_eggs/IsAvailable()
/datum/action/innate/spider/lay_eggs/IsAvailable(silent = FALSE)
if(..())
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
return 0
@@ -508,7 +507,7 @@
desc = "Send a command to all living spiders."
button_icon_state = "command"
/datum/action/innate/spider/comm/IsAvailable()
/datum/action/innate/spider/comm/IsAvailable(silent = FALSE)
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife))
return FALSE
return TRUE
@@ -11,6 +11,7 @@
speed = 0
maxHealth = 250
health = 250
blood_volume = 0
gender = NEUTER
mob_biotypes = NONE
@@ -11,7 +11,7 @@
background_icon_state = "bg_alien"
var/needs_growth = NO_GROWTH_NEEDED
/datum/action/innate/slime/IsAvailable()
/datum/action/innate/slime/IsAvailable(silent = FALSE)
if(..())
var/mob/living/simple_animal/slime/S = owner
if(needs_growth == GROWTH_NEEDED)
+1
View File
@@ -1,4 +1,5 @@
/mob/Logout()
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGOUT, client)
log_message("[key_name(src)] is no longer owning mob [src]([src.type])", LOG_OWNERSHIP)
SStgui.on_logout(src)
unset_machine()
+1 -1
View File
@@ -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
+1
View File
@@ -257,6 +257,7 @@
/obj/machinery/light/small/built
icon_state = "bulb-empty"
start_with_cell = FALSE
/obj/machinery/light/small/built/Initialize()
. = ..()
+1 -1
View File
@@ -513,7 +513,7 @@
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "sniper_zoom"
/datum/action/item_action/toggle_scope_zoom/IsAvailable()
/datum/action/item_action/toggle_scope_zoom/IsAvailable(silent = FALSE)
. = ..()
if(!.)
var/obj/item/gun/G = target
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+26 -16
View File
@@ -45,6 +45,12 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
/obj/effect/proc_holder/singularity_pull()
return
/obj/effect/proc_holder/Click()
return Trigger(usr, FALSE)
/obj/effect/proc_holder/proc/Trigger(mob/user)
return TRUE
/obj/effect/proc_holder/proc/InterceptClickOn(mob/living/caller, params, atom/A)
if(caller.ranged_ability != src || ranged_ability_user != caller) //I'm not actually sure how these would trigger, but, uh, safety, I guess?
to_chat(caller, "<span class='warning'><b>[caller.ranged_ability.name]</b> has been disabled.</span>")
@@ -150,8 +156,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(mobs_blacklist)
mobs_blacklist = typecacheof(mobs_blacklist)
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = FALSE, mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
if(!can_cast(user, skipcharge))
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = FALSE, mob/user = usr, skip_can_cast = FALSE) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
if(!skip_can_cast && !can_cast(user, skipcharge))
return FALSE
if(!skipcharge)
@@ -181,17 +187,22 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
return TRUE
/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount
var/mob/living/L
if(isliving(user))
L = user
switch(invocation_type)
if("shout")
if(prob(50))//Auto-mute? Fuck that noise
user.say(invocation, forced = "spell")
else
user.say(replacetext(invocation," ","`"), forced = "spell")
if(!L || L.can_speak_vocal(invocation))
if(prob(50))//Auto-mute? Fuck that noise
user.say(invocation, forced = "spell")
else
user.say(replacetext(invocation," ","`"), forced = "spell")
if("whisper")
if(prob(50))
user.whisper(invocation)
else
user.whisper(replacetext(invocation," ","`"))
if(!L || L.can_speak_vocal(invocation))
if(prob(50))
user.whisper(invocation)
else
user.whisper(replacetext(invocation," ","`"))
if("emote")
user.visible_message(invocation, invocation_emote_self) //same style as in mob/living/emote.dm
@@ -210,8 +221,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
qdel(action)
return ..()
/obj/effect/proc_holder/spell/Click()
if(cast_check())
/obj/effect/proc_holder/spell/Trigger(mob/user, skip_can_cast = TRUE)
if(cast_check(FALSE, user, skip_can_cast))
choose_targets()
return 1
@@ -432,7 +443,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
return 1
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr, skipcharge = FALSE, silent = FALSE)
var/magic_flags = SEND_SIGNAL(user, COMSIG_MOB_SPELL_CAST_CHECK, src)
var/magic_flags = SEND_SIGNAL(user, COMSIG_MOB_SPELL_CAN_CAST, src)
if(magic_flags & SPELL_SKIP_ALL_REQS)
return TRUE
@@ -448,9 +459,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
to_chat(user, "<span class='notice'>You can't cast this spell here.</span>")
return FALSE
if(!skipcharge)
if(!charge_check(user))
return FALSE
if(!skipcharge && !charge_check(user, silent))
return FALSE
if(user.stat && !stat_allowed && !(magic_flags & SPELL_SKIP_STAT))
if(!silent)
+2 -3
View File
@@ -11,12 +11,11 @@
var/current_amount = 0 //How many projectiles left.
var/projectiles_per_fire = 1 //Projectiles per fire. Probably not a good thing to use unless you override ready_projectile().
/obj/effect/proc_holder/spell/aimed/Click()
var/mob/living/user = usr
/obj/effect/proc_holder/spell/aimed/Trigger(mob/user, skip_can_cast = TRUE)
if(!istype(user))
return
var/msg
if(!can_cast(user, FALSE, TRUE))
if(!skip_can_cast && !can_cast(user, FALSE, TRUE))
msg = "<span class='warning'>You can no longer cast [name]!</span>"
remove_ranged_ability(msg)
return
+3 -3
View File
@@ -15,9 +15,9 @@
action_icon_state = "lightning"
/obj/effect/proc_holder/spell/targeted/tesla/Click()
if(!ready && cast_check())
StartChargeup()
/obj/effect/proc_holder/spell/targeted/tesla/Trigger(mob/user, skip_can_cast = TRUE)
if(!ready && cast_check(FALSE, user, skip_can_cast))
StartChargeup(user)
return 1
/obj/effect/proc_holder/spell/targeted/tesla/proc/StartChargeup(mob/user = usr)
+21 -27
View File
@@ -16,12 +16,12 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click()
if(usr && usr.mind)
if(!usr.mind.miming)
/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Trigger(mob/user, skip_can_cast = TRUE)
if(user.mind)
if(!user.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
return
invocation = "<B>[usr.real_name]</B> looks as if a wall is in front of [usr.p_them()]."
invocation = "<B>[user.real_name]</B> looks as if a wall is in front of [user.p_them()]."
else
invocation_type ="none"
..()
@@ -41,17 +41,12 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/targeted/mime/speak/Click()
if(!usr)
return
if(!ishuman(usr))
return
var/mob/living/carbon/human/H = usr
if(H.mind.miming)
/obj/effect/proc_holder/spell/targeted/mime/speak/Trigger(mob/user, skip_can_cast = TRUE)
if(user.mind?.miming)
still_recharging_msg = "<span class='warning'>You can't break your vow of silence that fast!</span>"
else
still_recharging_msg = "<span class='warning'>You'll have to wait before you can give your vow of silence again!</span>"
..()
return ..()
/obj/effect/proc_holder/spell/targeted/mime/speak/cast(list/targets,mob/user = usr)
for(var/mob/living/carbon/human/H in targets)
@@ -82,15 +77,15 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/targeted/forcewall/mime/Click()
if(usr && usr.mind)
if(!usr.mind.miming)
/obj/effect/proc_holder/spell/targeted/forcewall/mime/Trigger(mob/user, skip_can_cast = TRUE)
if(user.mind)
if(!user.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
return
invocation = "<B>[usr.real_name]</B> looks as if a blockade is in front of [usr.p_them()]."
invocation = "<B>[user.real_name]</B> looks as if a blockade is in front of [user.p_them()]."
else
invocation_type ="none"
..()
return ..()
/obj/effect/proc_holder/spell/aimed/finger_guns
name = "Finger Guns"
@@ -114,19 +109,18 @@
base_icon_state = "mime"
/obj/effect/proc_holder/spell/aimed/finger_guns/Click()
var/mob/living/carbon/human/owner = usr
if(owner.incapacitated())
to_chat(owner, "<span class='warning'>You can't properly point your fingers while incapacitated.</span>")
/obj/effect/proc_holder/spell/aimed/finger_guns/Trigger(mob/user, skip_can_cast = TRUE)
if(user.incapacitated())
to_chat(user, "<span class='warning'>You can't properly point your fingers while incapacitated.</span>")
return
if(usr && usr.mind)
if(!usr.mind.miming)
if(user.mind)
if(!user.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
return
invocation = "<B>[usr.real_name]</B> fires [usr.p_their()] finger gun!"
invocation = "<B>[user.real_name]</B> fires [user.p_their()] finger gun!"
else
invocation_type ="none"
..()
return ..()
/obj/effect/proc_holder/spell/targeted/touch/mimerope
name = "Invisible Rope"
@@ -144,8 +138,8 @@
action_background_icon_state = "bg_mime"
hand_path = /obj/item/melee/touch_attack/mimerope
/obj/effect/proc_holder/spell/targeted/touch/mimerope/Click()
if(usr && usr.mind)
/obj/effect/proc_holder/spell/targeted/touch/mimerope/Trigger(mob/user, skip_can_cast = TRUE)
if(user.mind)
if(!usr.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
return
+2 -2
View File
@@ -74,7 +74,7 @@
..()
cords = target
/datum/action/item_action/organ_action/colossus/IsAvailable()
/datum/action/item_action/organ_action/colossus/IsAvailable(silent = FALSE)
if(world.time < cords.next_command)
return FALSE
if(!owner)
@@ -632,7 +632,7 @@
..()
cords = target
/datum/action/item_action/organ_action/velvet/IsAvailable()
/datum/action/item_action/organ_action/velvet/IsAvailable(silent = FALSE)
return TRUE
/datum/action/item_action/organ_action/velvet/Trigger()
@@ -83,4 +83,10 @@
name = "Thieving Gloves"
desc = "A pair of gloves that are insulated and frictionless, allowing you to steal easily from anyone you see."
item = /obj/item/clothing/gloves/thief
cost = 4
cost = 4
/datum/uplink_item/suits/wallwalkers
name = "Wall Walking Boots"
desc = "Through bluespace magic stolen from an organisation that hoards technology, these boots simply allow you to slip through the atoms that make up anything, but only while walking, for safety reasons. As well as this, they unfortunately cause minor breath loss as the majority of atoms in your lungs are sucked out into any solid object you walk through."
item = /obj/item/clothing/shoes/wallwalkers
cost = 6
@@ -20,6 +20,12 @@
item = /obj/item/emagrecharge
cost = 2
/datum/uplink_item/device_tools/bluespacerecharge
name = "Bluespace Crystal Recharging Device"
desc = "A small device intended for recharging Wall Walking boots. Using it will add six charges to them. Use ten bluespace crystals on this recharger to add three more charges to it. "
item = /obj/item/bluespacerecharge
cost = 2
/datum/uplink_item/device_tools/phantomthief
name = "Syndicate Mask"
desc = "A cheap plastic mask fitted with an adrenaline autoinjector, which can be used by simply tensing your muscles"