done hopefully

This commit is contained in:
Seris02
2020-02-05 17:00:38 +08:00
176 changed files with 1479 additions and 1480 deletions
+4 -3
View File
@@ -343,12 +343,12 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set category = "Admin"
set name = "Aghost"
if(!holder)
return
return FALSE
if(isobserver(mob))
//re-enter
var/mob/dead/observer/ghost = mob
if(!ghost.mind || !ghost.mind.current) //won't do anything if there is no body
return
return FALSE
if(!ghost.can_reenter_corpse)
log_admin("[key_name(usr)] re-entered corpse")
message_admins("[key_name_admin(usr)] re-entered corpse")
@@ -357,6 +357,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin Reenter") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else if(isnewplayer(mob))
to_chat(src, "<font color='red'>Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.</font>")
return FALSE
else
//ghostize
log_admin("[key_name(usr)] admin ghosted.")
@@ -366,7 +367,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
if(body && !body.key)
body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin Ghost") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return TRUE
/client/proc/invisimin()
set name = "Invisimin"
+2 -1
View File
@@ -137,7 +137,8 @@ GLOBAL_LIST(round_end_notifiees)
return "The Database is not enabled!"
GLOB.bunker_passthrough |= ckey(params)
GLOB.bunker_passthrough[ckey(params)] = world.realtime
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
return "[params] has been added to the current round's bunker bypass list."
+4 -4
View File
@@ -1983,8 +1983,8 @@
var/atom/movable/AM = locate(href_list["adminplayerobservefollow"])
var/client/C = usr.client
if(!isobserver(usr))
C.admin_ghost()
if(!isobserver(usr) && !C.admin_ghost())
return
var/mob/dead/observer/A = C.mob
A.ManualFollow(AM)
@@ -2006,8 +2006,8 @@
var/z = text2num(href_list["Z"])
var/client/C = usr.client
if(!isobserver(usr))
C.admin_ghost()
if(!isobserver(usr) && !C.admin_ghost())
return
sleep(2)
C.jumptocoord(x,y,z)
@@ -58,7 +58,7 @@
if(isorgan(organ))
O = organ
O.Remove(C)
O.Remove()
else
I = organ
I.removed(C)
+3
View File
@@ -24,6 +24,8 @@
return
GLOB.bunker_passthrough |= ckey(ckeytobypass)
GLOB.bunker_passthrough[ckey(ckeytobypass)] = world.realtime
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
send2irc("Panic Bunker", "[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
@@ -37,6 +39,7 @@
return
GLOB.bunker_passthrough -= ckey(ckeytobypass)
SSpersistence.SavePanicBunker()
log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
send2irc("Panic Bunker", "[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
@@ -33,7 +33,7 @@
if(IC)
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "<span class='notice'>You pull [IC] out of [target]'s [target_zone].</span>")
user.put_in_hands(IC)
IC.Remove(target)
IC.Remove()
return 1
else
to_chat(user, "<span class='warning'>You don't find anything in [target]'s [target_zone]!</span>")
@@ -73,13 +73,14 @@
active_mind_control = FALSE
return TRUE
/obj/item/organ/heart/gland/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/gland/Remove(special = FALSE)
active = 0
if(initial(uses) == 1)
uses = initial(uses)
var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR]
hud.remove_from_hud(owner)
clear_mind_control()
if(!QDELETED(owner))
var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR]
hud.remove_from_hud(owner)
clear_mind_control()
..()
/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
@@ -14,6 +14,7 @@
/obj/item/organ/heart/gland/access/proc/free_access(datum/source, obj/O)
return TRUE
/obj/item/organ/heart/gland/access/Remove(mob/living/carbon/M, special = 0)
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
..()
/obj/item/organ/heart/gland/access/Remove(special = FALSE)
if(!QDELETED(owner))
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
return ..()
@@ -11,9 +11,10 @@
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
..()
/obj/item/organ/heart/gland/electric/Remove(special = FALSE)
if(!QDELETED(owner))
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
return ..()
/obj/item/organ/heart/gland/electric/activate()
owner.visible_message("<span class='danger'>[owner]'s skin starts emitting electric arcs!</span>",\
@@ -65,14 +65,14 @@
/obj/item/organ/heart/gland/heal/proc/reject_implant(obj/item/organ/cyberimp/implant)
owner.visible_message("<span class='warning'>[owner] vomits up his [implant.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [implant.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
implant.Remove(owner)
implant.Remove()
implant.forceMove(owner.drop_location())
/obj/item/organ/heart/gland/heal/proc/replace_liver(obj/item/organ/liver/liver)
if(liver)
owner.visible_message("<span class='warning'>[owner] vomits up his [liver.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [liver.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
liver.Remove(owner)
liver.Remove()
liver.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble in your bowels...</span>")
@@ -87,7 +87,7 @@
if(lungs)
owner.visible_message("<span class='warning'>[owner] vomits up his [lungs.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [lungs.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
lungs.Remove(owner)
lungs.Remove()
lungs.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble inside your chest...</span>")
@@ -102,7 +102,7 @@
if(eyes)
owner.visible_message("<span class='warning'>[owner]'s [eyes.name] fall out of their sockets!</span>", "<span class='userdanger'>Your [eyes.name] fall out of their sockets!</span>")
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
eyes.Remove(owner)
eyes.Remove()
eyes.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble behind your eye sockets...</span>")
@@ -84,7 +84,7 @@
//It is called from your coffin on close (by you only)
if(poweron_masquerade == TRUE || owner.current.AmStaked())
return FALSE
owner.current.adjustStaminaLoss(-2 + (regenRate * -8) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more.
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)
// No Bleeding
@@ -125,7 +125,7 @@
C.adjustFireLoss(-fireheal * mult, forced = TRUE)
C.adjustToxLoss(-toxinheal * mult * 2, forced = TRUE) //Toxin healing because vamps arent immune
//C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above.
AddBloodVolume((bruteheal * -0.5 + fireheal * -1) / mult * costMult) // Costs blood to heal
AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + 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
@@ -189,7 +189,7 @@
/datum/antagonist/bloodsucker/proc/HandleDeath()
// FINAL DEATH
// Fire Damage? (above double health)
if(owner.current.getFireLoss_nonProsthetic() >= owner.current.getMaxHealth() * 1.5)
if(owner.current.getFireLoss_nonProsthetic() >= owner.current.maxHealth * 2.5)
FinalDeath()
return
// Staked while "Temp Death" or Asleep
@@ -32,11 +32,11 @@
//var/not_bloodsucker = FALSE // This goes to Vassals or Hunters, but NOT bloodsuckers.
/datum/action/bloodsucker/New()
if (bloodcost > 0)
if(bloodcost > 0)
desc += "<br><br><b>COST:</b> [bloodcost] Blood" // Modify description to add cost.
if (warn_constant_cost)
if(warn_constant_cost)
desc += "<br><br><i>Your over-time blood consumption increases while [name] is active.</i>"
if (amSingleUse)
if(amSingleUse)
desc += "<br><br><i>Useable once per night.</i>"
..()
@@ -47,35 +47,35 @@
/datum/action/bloodsucker/Trigger()
// Active? DEACTIVATE AND END!
if (active && CheckCanDeactivate(TRUE))
if(active && CheckCanDeactivate(TRUE))
DeactivatePower()
return
if (!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
if(!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
return
PayCost()
if (amToggle)
if(amToggle)
active = !active
UpdateButtonIcon()
if (!amToggle || !active)
if(!amToggle || !active)
StartCooldown() // Must come AFTER UpdateButton(), otherwise icon will revert.
ActivatePower() // NOTE: ActivatePower() freezes this power in place until it ends.
if (active) // Did we not manually disable? Handle it here.
if(active) // Did we not manually disable? Handle it here.
DeactivatePower()
if (amSingleUse)
if(amSingleUse)
RemoveAfterUse()
/datum/action/bloodsucker/proc/CheckCanPayCost(display_error)
if(!owner || !owner.mind)
return FALSE
// Cooldown?
if (cooldownUntil > world.time)
if (display_error)
if(cooldownUntil > world.time)
if(display_error)
to_chat(owner, "[src] is unavailable. Wait [(cooldownUntil - world.time) / 10] seconds.")
return FALSE
// Have enough blood?
var/mob/living/L = owner
if (L.blood_volume < bloodcost)
if (display_error)
if(L.blood_volume < bloodcost)
if(display_error)
to_chat(owner, "<span class='warning'>You need at least [bloodcost] blood to activate [name]</span>")
return FALSE
return TRUE
@@ -1,4 +1,3 @@
#define TIME_BLOODSUCKER_NIGHT 900 // 15 minutes
#define TIME_BLOODSUCKER_DAY_WARN 90 // 1.5 minutes
#define TIME_BLOODSUCKER_DAY_FINAL_WARN 25 // 25 sec
#define TIME_BLOODSUCKER_DAY 60 // 1.5 minutes // 10 is a second, 600 is a minute.
@@ -11,6 +10,7 @@
var/cancel_me = FALSE
var/amDay = FALSE
var/time_til_cycle = 0
var/nightime_duration = 900 //15 Minutes
/obj/effect/sunlight/Initialize()
countdown()
@@ -21,7 +21,7 @@
while(!cancel_me)
time_til_cycle = TIME_BLOODSUCKER_NIGHT
time_til_cycle = nightime_duration
// Part 1: Night (all is well)
while(time_til_cycle > TIME_BLOODSUCKER_DAY_WARN)
@@ -81,7 +81,9 @@
"<span class = 'announce'>The solar flare has ended, and the daylight danger has passed...for now.</span>")
amDay = FALSE
day_end() // Remove VANISHING ACT power from all vamps who have it! Clear Warnings (sunlight, locker protection)
message_admins("BLOODSUCKER NOTICE: Daylight Ended. Resetting to Night (Lasts for [TIME_BLOODSUCKER_NIGHT / 60] minutes.)")
nightime_duration += 100 //Each day makes the night a minute longer.
message_admins("BLOODSUCKER NOTICE: Daylight Ended. Resetting to Night (Lasts for [nightime_duration / 60] minutes.)")
/obj/effect/sunlight/proc/hud_tick()
@@ -97,7 +99,7 @@
sleep(10)
time_til_cycle --
/obj/effect/sunlight/proc/warn_daylight(danger_level=0, vampwarn = "", vassalwarn = "")
/obj/effect/sunlight/proc/warn_daylight(danger_level =0, vampwarn = "", vassalwarn = "")
for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if(!istype(M))
continue
@@ -22,7 +22,7 @@
// STATS
var/vamplevel = 0
var/vamplevel_unspent = 1
var/regenRate = 0.3 // How many points of Brute do I heal per tick?
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
// OBJECTIVES
@@ -34,6 +34,7 @@
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/level_bloodcost
// 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)
@@ -98,7 +99,7 @@
/datum/antagonist/bloodsucker/proc/SelectFirstName()
// Names (EVERYONE gets one))
if (owner.current.gender == MALE)
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", \
"Sveyn","Aurel","Alexe","Iustin","Theodor","Dimitrie","Octav","Damien","Magnus","Caine","Abel", // Romanian/Ancient
"Lucius","Gaius","Otho","Balbinus","Arcadius","Romanos","Alexios","Vitellius", // Latin
@@ -119,7 +120,7 @@
return
// Titles [Master]
if (!am_fledgling)
if (owner.current.gender == MALE)
if(owner.current.gender == MALE)
vamptitle = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master")
else
vamptitle = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress")
@@ -130,18 +131,18 @@
/datum/antagonist/bloodsucker/proc/SelectReputation(am_fledgling = 0, forced=FALSE)
// Already have Reputation
if (!forced && vampreputation != null)
if(!forced && vampreputation != null)
return
// Reputations [Master]
if (!am_fledgling)
if(!am_fledgling)
vampreputation = 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
if(owner.current.gender == MALE)
if(prob(10)) // Gender override
vampreputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King")
else
if (prob(10)) // Gender override
if(prob(10)) // Gender override
vampreputation = 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>")
@@ -202,7 +203,7 @@
// Make Changes
H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank!
H.physiology.cold_mod = 0
H.physiology.stun_mod *= 0.35
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
@@ -261,7 +262,7 @@
owner.hasSoul = TRUE
//owner.current.hellbound = FALSE
datum/antagonist/bloodsucker/proc/RankUp()
/datum/antagonist/bloodsucker/proc/RankUp()
set waitfor = FALSE
if(!owner || !owner.current)
return
@@ -272,21 +273,23 @@ datum/antagonist/bloodsucker/proc/RankUp()
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)
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, they can be built from wooden planks.</span><br>")
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks.</span><br>")
datum/antagonist/bloodsucker/proc/LevelUpPowers()
/datum/antagonist/bloodsucker/proc/LevelUpPowers()
for(var/datum/action/bloodsucker/power in powers)
power.level_current ++
datum/antagonist/bloodsucker/proc/SpendRank()
/datum/antagonist/bloodsucker/proc/SpendRank()
set waitfor = FALSE
if (vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client)
if(vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current))
return
/////////
// Powers
//TODO: Make this into a radial
var/mob/living/L = owner.current
level_bloodcost = maxBloodVolume * 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
// Purchase Power Prompt
var/list/options = list() // Taken from gasmask.dm, for Clown Masks.
var/list/options = list()
for(var/pickedpower in typesof(/datum/action/bloodsucker))
var/datum/action/bloodsucker/power = pickedpower
// If I don't own it, and I'm allowed to buy it.
@@ -295,7 +298,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
options["\[ Not Now \]"] = null
// Abort?
if(options.len > 1)
var/choice = input(owner.current, "You have the opportunity to grow more ancient. Select a power to advance your Rank.", "Your Blood Thickens...") in options
var/choice = input(owner.current, "You have the opportunity to grow more ancient 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.
return
@@ -305,10 +308,14 @@ datum/antagonist/bloodsucker/proc/SpendRank()
if(!choice || !options[choice] || (locate(options[choice]) in powers)) // ADDED: Check to see if you already have this power, due to window stacking.
to_chat(owner.current, "<span class='notice'>You prevent your blood from thickening just yet, but you may try again later.</span>")
return
if(L.blood_volume < level_bloodcost)
to_chat(owner.current, "<span class='warning'>You dont have enough blood to thicken your blood, you need [level_bloodcost - L.blood_volume] units more!</span>")
return
// Buy New Powers
var/datum/action/bloodsucker/P = options[choice]
AddBloodVolume(-level_bloodcost)
BuyPower(new P)
to_chat(owner.current, "<span class='notice'>You have learned [initial(P.name)]!</span>")
to_chat(owner.current, "<span class='notice'>You have used [level_bloodcost] units of blood and learned [initial(P.name)]!</span>")
else
to_chat(owner.current, "<span class='notice'>You grow more ancient by the night!</span>")
/////////
@@ -326,7 +333,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
// Vamp Stats
regenRate += 0.05 // Points of brute healed (starts at 0.3)
feedAmount += 2 // Increase how quickly I munch down vics (15)
maxBloodVolume += 50 // Increase my max blood (600)
maxBloodVolume += 100 // Increase my max blood (600)
/////////
vamplevel ++
vamplevel_unspent --
@@ -8,7 +8,7 @@
return SSticker.mode.make_vassal(C,owner)
/datum/antagonist/bloodsucker/proc/FreeAllVassals()
for (var/datum/antagonist/vassal/V in vassals)
for(var/datum/antagonist/vassal/V in vassals)
SSticker.mode.remove_vassal(V.owner)
/datum/antagonist/vassal
@@ -22,7 +22,7 @@
/datum/antagonist/vassal/can_be_owned(datum/mind/new_owner)
// If we weren't created by a bloodsucker, then we cannot be a vassal (assigned from antag panel)
if (!master)
if(!master)
return FALSE
return ..()
@@ -63,9 +63,9 @@
/datum/antagonist/vassal/on_removal()
SSticker.mode.vassals -= owner // Add if not already in here (and you might be, if you were picked at round start)
// Mindslave Remove
if (master && master.owner)
if(master && master.owner)
master.vassals -= src
if (owner.enslaved_to == master.owner.current)
if(owner.enslaved_to == master.owner.current)
owner.enslaved_to = null
// Master Pinpointer
owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer/vassal_edition)
@@ -60,6 +60,8 @@
breakout_time = 600
pryLidTimer = 400
resistance_flags = NONE
integrity_failure = 70
armor = list("melee" = 50, "bullet" = 20, "laser" = 30, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
/obj/structure/closet/crate/coffin/meatcoffin
name = "meat coffin"
@@ -75,7 +77,9 @@
resistance_flags = NONE
material_drop = /obj/item/reagent_containers/food/snacks/meat/slab
material_drop_amount = 3
integrity_failure = 40
armor = list("melee" = 70, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100)
/obj/structure/closet/crate/coffin/metalcoffin
name = "metal coffin"
desc = "A big metal sardine can inside of another big metal sardine can, in space."
@@ -90,6 +94,8 @@
resistance_flags = NONE
material_drop = /obj/item/stack/sheet/metal
material_drop_amount = 5
integrity_failure = 60
armor = list("melee" = 40, "bullet" = 15, "laser" = 50, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
//////////////////////////////////////////////
@@ -107,7 +107,7 @@
var/convert_progress = 3 // Resets on each new character to be added to the chair. Some effects should lower it...
var/disloyalty_confirm = FALSE // Command & Antags need to CONFIRM they are willing to lose their role (and will only do it if the Vassal'ing succeeds)
var/disloyalty_offered = FALSE // Has the popup been issued? Don't spam them.
var/convert_cost = 100
/obj/structure/bloodsucker/vassalrack/deconstruct(disassembled = TRUE)
new /obj/item/stack/sheet/metal(src.loc, 4)
@@ -116,10 +116,10 @@
/obj/structure/bloodsucker/vassalrack/examine(mob/user)
. = ..()
if((user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) || isobserver(user))
if(isvamp(user) || 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.</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>"}
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
@@ -177,7 +177,7 @@
M.pixel_y = -2 //M.get_standard_pixel_y_offset(120)//180)
update_icon()
// Torture Stuff
convert_progress = 2 // Goes down unless you start over.
convert_progress = 4 // Goes down unless you start over.
disloyalty_confirm = FALSE // New guy gets the chance to say NO if he's special.
disloyalty_offered = FALSE // Prevents spamming torture window.
@@ -190,7 +190,7 @@
else
M.visible_message("<span class='danger'>[user] tries to pull [M] rack!</span>",\
"<span class='danger'>[user] attempts to release you from the rack!</span>") // For sound if not seen --> "<span class='italics'>You hear a squishy wet noise.</span>")
if(!do_mob(user, M, 100))
if(!do_mob(user, M, 200))
return
// Did the time. Now try to do it.
..()
@@ -248,7 +248,7 @@
// 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)
if(istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD)
unbuckle_mob(C)
useLock = FALSE // Failsafe
return
@@ -256,7 +256,9 @@
torture_victim(user, C)
/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)
// Check Bloodmob/living/M, force = FALSE, check_loc = TRUE
var/convert_cost = 200 + 200 * bloodsuckerdatum.vassals
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
@@ -275,7 +277,7 @@
// All done!
if(convert_progress <= 0)
// FAIL: Can't be Vassal
if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
if(!SSticker.mode.can_make_vassal(target, user, display_warning = FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
to_chat(user, "<span class='danger'>[target] doesn't respond to your persuasion. It doesn't appear they can be converted to follow you, they either have a mindshield or their external loyalties are too difficult for you to break.<i>\[ALT+click to release\]</span>")
convert_progress ++ // Pop it back up some. Avoids wasting Blood on a lost cause.
// SUCCESS: All done!
@@ -301,10 +303,9 @@
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].</span>")
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
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
bloodsuckerdatum.AddBloodVolume(-convert_cost)
target.add_mob_blood(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>", \
@@ -5,7 +5,7 @@
desc = "Snap restraints with ease, or deal terrible damage with your bare hands."
button_icon_state = "power_strength"
bloodcost = 10
cooldown = 130
cooldown = 90
target_range = 1
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -66,16 +66,14 @@
// Target Type: Mob
if(isliving(target))
var/mob/living/carbon/user_C = user
var/hitStrength = user_C.dna.species.punchdamagehigh * 1.3 + 5
var/hitStrength = user_C.dna.species.punchdamagehigh * 1.4 + 15
// Knockdown!
var/powerlevel = min(5, 1 + level_current)
if(rand(5 + powerlevel) >= 5)
target.visible_message("<span class='danger'>[user] lands a vicious punch, sending [target] away!</span>", \
"<span class='userdanger'>[user] has landed a horrifying punch on you, sending you flying!!</span>", null, COMBAT_MESSAGE_RANGE)
target.Knockdown(min(5, rand(10, 10 * powerlevel)) )
// Chance of KO
if(rand(6 + powerlevel) >= 6 && target.stat <= UNCONSCIOUS)
target.Unconscious(40)
// Attack!
playsound(get_turf(target), 'sound/weapons/punch4.ogg', 60, 1, -1)
user.do_attack_animation(target, ATTACK_EFFECT_SMASH)
@@ -22,12 +22,12 @@
return
// Wearing mask
var/mob/living/L = owner
if (L.is_mouth_covered())
if (display_error)
if(L.is_mouth_covered())
if(display_error)
to_chat(owner, "<span class='warning'>You cannot feed with your mouth covered! Remove your mask.</span>")
return FALSE
// Find my Target!
if (!FindMyTarget(display_error)) // Sets feed_target within after Validating
if(!FindMyTarget(display_error)) // Sets feed_target within after Validating
return FALSE
// Not in correct state
// DONE!
@@ -35,36 +35,36 @@
/datum/action/bloodsucker/feed/proc/ValidateTarget(mob/living/target, display_error) // Called twice: validating a subtle victim, or validating your grapple victim.
// Bloodsuckers + Animals MUST be grabbed aggressively!
if (!owner.pulling || target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE)
if(!owner.pulling || target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE)
// NOTE: It's OKAY that we are checking if(!target) below, AFTER animals here. We want passive check vs animal to warn you first, THEN the standard warning.
// Animals:
if (isliving(target) && !iscarbon(target))
if (display_error)
if(isliving(target) && !iscarbon(target))
if(display_error)
to_chat(owner, "<span class='warning'>Lesser beings require a tighter grip.</span>")
return FALSE
// Bloodsuckers:
else if (iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
if (display_error)
else if(iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
if(display_error)
to_chat(owner, "<span class='warning'>Other Bloodsuckers will not fall for your subtle approach.</span>")
return FALSE
// Must have Target
if (!target) // || !ismob(target)
if (display_error)
if(!target) // || !ismob(target)
if(display_error)
to_chat(owner, "<span class='warning'>You must be next to or grabbing a victim to feed from them.</span>")
return FALSE
// Not even living!
if (!isliving(target) || issilicon(target))
if (display_error)
if(!isliving(target) || issilicon(target))
if(display_error)
to_chat(owner, "<span class='warning'>You may only feed from living beings.</span>")
return FALSE
if (target.blood_volume <= 0)
if (display_error)
if(target.blood_volume <= 0)
if(display_error)
to_chat(owner, "<span class='warning'>Your victim has no blood to take.</span>")
return FALSE
if (ishuman(target))
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(NOBLOOD in H.dna.species.species_traits)// || owner.get_blood_id() != target.get_blood_id())
if (display_error)
if(display_error)
to_chat(owner, "<span class='warning'>Your victim's blood is not suitable for you to take.</span>")
return FALSE
return TRUE
@@ -75,9 +75,9 @@
feed_target = null
target_grappled = FALSE
// If you are pulling a mob, that's your target. If you don't like it, then release them.
if (owner.pulling && ismob(owner.pulling))
if(owner.pulling && ismob(owner.pulling))
// Check grapple target Valid
if (!ValidateTarget(owner.pulling, display_error)) // Grabbed targets display error.
if(!ValidateTarget(owner.pulling, display_error)) // Grabbed targets display error.
return FALSE
target_grappled = TRUE
feed_target = owner.pulling
@@ -86,11 +86,11 @@
var/list/mob/living/seen_targets = view(1, owner)
var/list/mob/living/seen_mobs = list()
for(var/mob/living/M in seen_targets)
if (isliving(M) && M != owner)
if(isliving(M) && M != owner)
seen_mobs += M
// None Seen!
if (seen_mobs.len == 0)
if (display_error)
if(seen_mobs.len == 0)
if(display_error)
to_chat(owner, "<span class='warning'>You must be next to or grabbing a victim to feed from them.</span>")
return FALSE
// Check Valids...
@@ -98,19 +98,19 @@
var/list/targets_dead = list()
for(var/mob/living/M in seen_mobs)
// Check adjecent Valid target
if (M != owner && ValidateTarget(M, display_error = FALSE)) // Do NOT display errors. We'll be doing this again in CheckCanUse(), which will rule out grabbed targets.
if(M != owner && ValidateTarget(M, display_error = FALSE)) // Do NOT display errors. We'll be doing this again in CheckCanUse(), which will rule out grabbed targets.
// Prioritize living, but remember dead as backup
if (M.stat < DEAD)
if(M.stat < DEAD)
targets_valid += M
else
targets_dead += M
// No Living? Try dead.
if (targets_valid.len == 0 && targets_dead.len > 0)
if(targets_valid.len == 0 && targets_dead.len > 0)
targets_valid = targets_dead
// No Targets
if (targets_valid.len == 0)
if(targets_valid.len == 0)
// Did I see targets? Then display at least one error
if (seen_mobs.len > 1)
if(seen_mobs.len > 1)
if (display_error)
to_chat(owner, "<span class='warning'>None of these are valid targets to feed from subtly.</span>")
else
@@ -136,28 +136,28 @@
// Initial Wait
var/feed_time = (amSilent ? 45 : 25) - (2.5 * level_current)
feed_time = max(15, feed_time)
if (amSilent)
if(amSilent)
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
// Put target to Sleep (Bloodsuckers are immune to their own bite's sleep effect)
if (!amSilent)
if(!amSilent)
ApplyVictimEffects(target) // Sleep, paralysis, immobile, unconscious, and mute
if(target.stat <= UNCONSCIOUS)
sleep(1)
// Wait, then Cancel if Invalid
if (!ContinueActive(user,target)) // Cancel. They're gone.
if(!ContinueActive(user,target)) // Cancel. They're gone.
//DeactivatePower(user,target)
return
// Pull Target Close
if (!target.density) // Pull target to you if they don't take up space.
if(!target.density) // Pull target to you if they don't take up space.
target.Move(user.loc)
// Broadcast Message
if (amSilent)
if(amSilent)
//if (!iscarbon(target))
// user.visible_message("<span class='notice'>[user] shifts [target] closer to [user.p_their()] mouth.</span>", \
// "<span class='notice'>You secretly slip your fangs into [target]'s flesh.</span>", \
@@ -173,7 +173,7 @@
if(M != owner && M != target && iscarbon(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
was_unnoticed = FALSE
break
if (was_unnoticed)
if(was_unnoticed)
to_chat(user, "<span class='notice'>You think no one saw you...</span>")
else
to_chat(user, "<span class='warning'>Someone may have noticed...</span>")
@@ -197,16 +197,16 @@
// FEEEEEEEEED!!! //
bloodsuckerdatum.poweron_feed = TRUE
while (bloodsuckerdatum && target && active)
while(bloodsuckerdatum && target && active)
//user.mobility_flags &= ~MOBILITY_MOVE // user.canmove = 0 // Prevents spilling blood accidentally.
// Abort? A bloody mistake.
if (!do_mob(user, target, 20, 0, 0, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
if(!do_mob(user, target, 20, 0, 0, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
// May have disabled Feed during do_mob
if (!active || !ContinueActive(user, target))
if(!active || !ContinueActive(user, target))
break
if (amSilent)
if(amSilent)
to_chat(user, "<span class='warning'>Your feeding has been interrupted...but [target.p_they()] didn't seem to notice you.<span>")
else
to_chat(user, "<span class='warning'>Your feeding has been interrupted!</span>")
@@ -214,11 +214,11 @@
"<span class='userdanger'>Your teeth are ripped from [target]'s throat. [target.p_their(TRUE)] blood sprays everywhere!</span>")
// Deal Damage to Target (should have been more careful!)
if (iscarbon(target))
if(iscarbon(target))
var/mob/living/carbon/C = target
C.bleed(15)
playsound(get_turf(target), 'sound/effects/splat.ogg', 40, 1)
if (ishuman(target))
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.bleed_rate += 5
target.add_splatter_floor(get_turf(target))
@@ -228,7 +228,7 @@
target.emote("scream")
// Killed Target?
if (was_alive)
if(was_alive)
CheckKilledTarget(user,target)
return
@@ -237,40 +237,40 @@
// Handle Feeding! User & Victim Effects (per tick)
bloodsuckerdatum.HandleFeeding(target, blood_take_mult)
amount_taken += amSilent ? 0.3 : 1
if (!amSilent)
if(!amSilent)
ApplyVictimEffects(target) // Sleep, paralysis, immobile, unconscious, and mute
if (amount_taken > 5 && target.stat < DEAD && ishuman(target))
if(amount_taken > 5 && target.stat < DEAD && ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood) // GOOD // in bloodsucker_life.dm
///////////////////////////////////////////////////////////
// Not Human?
if (!ishuman(target))
if(!ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood_bad) // BAD // in bloodsucker_life.dm
if (!warning_target_inhuman)
if(!warning_target_inhuman)
to_chat(user, "<span class='notice'>You recoil at the taste of a lesser lifeform.</span>")
warning_target_inhuman = TRUE
// Dead Blood?
if (target.stat >= DEAD)
if (ishuman(target))
if(target.stat >= DEAD)
if(ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood_dead) // BAD // in bloodsucker_life.dm
if (!warning_target_dead)
if(!warning_target_dead)
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.maxBloodVolume)
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 (target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD)
if(iscarbon(target) && !target.AmBloodsucker(1))
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)
else if(target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY)
to_chat(user, "<span class='warning'>Your victim's blood volume is dangerously low.</span>")
else if (target.blood_volume <= BLOOD_VOLUME_SAFE && warning_target_bloodvol > BLOOD_VOLUME_SAFE)
else if(target.blood_volume <= BLOOD_VOLUME_SAFE && warning_target_bloodvol > BLOOD_VOLUME_SAFE)
to_chat(user, "<span class='notice'>Your victim's blood is at an unsafe level.</span>")
warning_target_bloodvol = target.blood_volume // If we had a warning to give, it's been given by now.
// Done?
if (target.blood_volume <= 0)
if(target.blood_volume <= 0)
to_chat(user, "<span class='notice'>You have bled your victim dry.</span>")
break
@@ -279,7 +279,7 @@
// DONE!
//DeactivatePower(user,target)
if (amSilent)
if(amSilent)
to_chat(user, "<span class='notice'>You slowly release [target]'s wrist." + (target.stat == 0 ? " [target.p_their(TRUE)] face lacks expression, like you've already been forgotten.</span>" : ""))
else
user.visible_message("<span class='warning'>[user] unclenches their teeth from [target]'s neck.</span>", \
@@ -289,13 +289,13 @@
log_combat(owner, target, "fed on blood", addition="(and took [amount_taken] blood)")
// Killed Target?
if (was_alive)
if(was_alive)
CheckKilledTarget(user,target)
/datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
// Bad Vampire. You shouldn't do that.
if (target && target.stat >= DEAD && ishuman(target))
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)
@@ -304,18 +304,18 @@
/datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target)
// Bloodsuckers not affected by "the Kiss" of another vampire
if (!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
if(!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
target.Unconscious(50,0)
target.Knockdown(40 + 5 * level_current,1)
// NOTE: THis is based on level of power!
if (ishuman(target))
if(ishuman(target))
target.adjustStaminaLoss(5, forced = TRUE)// Base Stamina Damage
/datum/action/bloodsucker/feed/DeactivatePower(mob/living/user = owner, mob/living/target)
..() // activate = FALSE
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
// No longer Feeding
if (bloodsuckerdatum)
if(bloodsuckerdatum)
bloodsuckerdatum.poweron_feed = FALSE
feed_target = null
// My mouth is no longer full
@@ -6,7 +6,7 @@
name = "Fortitude"//"Cellular Emporium"
desc = "Withstand egregious physical wounds and walk away from attacks that would stun, pierce, and dismember lesser beings. You cannot run while active."
button_icon_state = "power_fortitude"
bloodcost = 5
bloodcost = 30
cooldown = 80
bloodsucker_can_buy = TRUE
amToggle = TRUE
@@ -23,7 +23,7 @@
ADD_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
ADD_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
ADD_TRAIT(user, TRAIT_NORUNNING, "fortitude")
if (ishuman(owner))
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
this_resist = max(0.3, 0.7 - level_current * 0.1)
H.physiology.brute_mod *= this_resist//0.5
@@ -34,7 +34,7 @@
user.toggle_move_intent()
while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN)
// Pay Blood Toll (if awake)
if (user.stat == CONSCIOUS)
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.
sleep(20) // Check every few ticks that we haven't disabled this power
// Return to Running (if you were before)
@@ -48,7 +48,7 @@
REMOVE_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
REMOVE_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
REMOVE_TRAIT(user, TRAIT_NORUNNING, "fortitude")
if (ishuman(owner))
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
H.physiology.brute_mod /= this_resist//0.5
H.physiology.burn_mod /= this_resist//0.5
@@ -7,7 +7,7 @@
background_icon_state_on = "vamp_power_off_oneshot" // Even though this never goes off.
background_icon_state_off = "vamp_power_off_oneshot"
bloodcost = 25
bloodcost = 100
cooldown = 99999 // It'll never come back.
amToggle = FALSE
amSingleUse = TRUE
@@ -23,11 +23,16 @@
return
// Have No Lair (NOTE: You only got this power if you had a lair, so this means it's destroyed)
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
if (display_error)
if(!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
if(display_error)
to_chat(owner, "<span class='warning'>Your coffin has been destroyed!</span>")
return FALSE
return TRUE
/datum/action/bloodsucker/gohome/proc/flicker_lights(var/flicker_range, var/beat_volume)
for(var/obj/machinery/light/L in view(flicker_range, get_turf(owner)))
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', beat_volume, 1)
/datum/action/bloodsucker/gohome/ActivatePower()
var/mob/living/carbon/user = owner
@@ -35,34 +40,31 @@
// IMPORTANT: Check for lair at every step! It might get destroyed.
to_chat(user, "<span class='notice'>You focus on separating your consciousness from your physical form...</span>")
// STEP ONE: Flicker Lights
for(var/obj/machinery/light/L in view(3, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
L.flicker(5)
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 20, 1)
flicker_lights(3, 20)
sleep(50)
for(var/obj/machinery/light/L in view(3, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
L.flicker(5)
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
flicker_lights(4, 40)
sleep(50)
for(var/obj/machinery/light/L in view(6, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
flicker_lights(4, 60)
for(var/obj/machinery/light/L in view(6, get_turf(owner)))
L.flicker(5)
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 60, 1)
// ( STEP TWO: Lights OFF? )
// CHECK: Still have Coffin?
if (!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
if(!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
to_chat(user, "<span class='warning'>Your coffin has been destroyed! You no longer have a destination.</span>")
return FALSE
if (!owner)
if(!owner)
return
// SEEN?: (effects ONLY if there are witnesses! Otherwise you just POOF)
// NOTE: Stolen directly from statue.dm, thanks guys!
var/am_seen = FALSE // Do Effects (seen by anyone)
var/drop_item = FALSE // Drop Stuff (seen by non-vamp)
if (isturf(owner.loc)) // Only check if I'm not in a Locker or something.
if(isturf(owner.loc)) // Only check if I'm not in a Locker or something.
// A) Check for Darkness (we can just leave)
var/turf/T = get_turf(user)
if(T && T.lighting_object && T.get_lumcount()>= 0.1)
// B) Check for Viewers
for(var/mob/living/M in viewers(owner))
for(var/mob/living/M in viewers(get_turf(owner)))
if(M != owner && isliving(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind) // M.client <--- add this in after testing!
am_seen = TRUE
if (!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
@@ -76,7 +78,7 @@
var/obj/O = user.legcuffed
user.dropItemToGround(O)
// SEEN!
if (drop_item)
if(drop_item)
// DROP: Clothes, held items, and cuffs etc
// NOTE: Taken from unequip_everything() in inventory.dm. We need to
// *force* all items to drop, so we had to just gut the code out of it.
@@ -86,30 +88,28 @@
user.dropItemToGround(I,TRUE)
for(var/obj/item/I in owner.held_items) // drop_all_held_items()
user.dropItemToGround(I, TRUE)
if (am_seen)
if(am_seen)
// POOF EFFECTS
playsound(get_turf(owner), 'sound/magic/summon_karp.ogg', 60, 1)
var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/()
puff.effect_type = /obj/effect/particle_effect/smoke/vampsmoke
puff.set_up(3, 0, get_turf(owner))
puff.start()
//STEP FIVE: Create animal at prev location
var/mob/living/simple_animal/SA = pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
new SA (owner.loc)
// TELEPORT: Move to Coffin & Close it!
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM) // in teleport.dm?
// SLEEP
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM)
user.resting = TRUE
//user.Unconscious(30,0)
user.Stun(30,1)
// CLOSE LID: If fail, force me in.
if (!bloodsuckerdatum.coffin.close(owner))
if(!bloodsuckerdatum.coffin.close(owner))
bloodsuckerdatum.coffin.insert(owner) // Puts me inside.
// The following was taken from close() proc in closets.dm
// (but we had to do it this way because there is no way to force entry)
playsound(bloodsuckerdatum.coffin.loc, bloodsuckerdatum.coffin.close_sound, 15, 1, -3)
bloodsuckerdatum.coffin.opened = FALSE
bloodsuckerdatum.coffin.density = TRUE
bloodsuckerdatum.coffin.update_icon()
// Lock Coffin
bloodsuckerdatum.coffin.LockMe(owner)
// ( STEP FIVE: Create animal at prev location? )
//var/mob/living/simple_animal/SA = /mob/living/simple_animal/hostile/retaliate/bat // pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
//new SA (owner.loc)
@@ -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 = 30
cooldown = 50
target_range = 15
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -6,7 +6,7 @@
desc = "Spring at your target and aggressively grapple them without warning. Attacks from concealment or the rear may even knock them down."
button_icon_state = "power_lunge"
bloodcost = 10
cooldown = 100
cooldown = 120
target_range = 3
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -28,7 +28,7 @@
return TRUE
/datum/action/bloodsucker/targeted/lunge/CheckValidTarget(atom/A)
return isliving(A)
return iscarbon(A)
/datum/action/bloodsucker/targeted/lunge/CheckCanTarget(atom/A, display_error)
// Check: Self
@@ -10,7 +10,7 @@
desc = "Dominate the mind of a mortal who can see your eyes."
button_icon_state = "power_mez"
bloodcost = 30
cooldown = 200
cooldown = 300
target_range = 1
power_activates_immediately = FALSE
message_Trigger = "Whom will you subvert to your will?"
@@ -6,7 +6,7 @@
button_icon_state = "power_tres"
bloodcost = 10
cooldown = 60
cooldown = 80
amToggle = FALSE
//target_range = 2
@@ -18,7 +18,7 @@
var/list/organs = user.getorganszone(BODY_ZONE_HEAD, 1)
for(var/obj/item/organ/I in organs)
I.Remove(user, 1)
I.Remove(TRUE)
explosion(get_turf(user), 0, 0, 2, 0, TRUE)
for(var/mob/living/carbon/human/H in range(2,user))
@@ -22,7 +22,7 @@
if(!istype(O))
continue
O.Remove(user)
O.Remove()
if(iscarbon(user))
var/mob/living/carbon/C = user
C.vomit(0, toxic = TRUE)
@@ -104,6 +104,6 @@
transfer_personality(H)
brainmob.fully_replace_character_name(null, "[braintype] [H.real_name]")
name = "[initial(name)] ([brainmob.name])"
B.Remove(H)
B.Remove()
qdel(B)
H.update_hair()
+1
View File
@@ -52,6 +52,7 @@
if(2) //steal
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
O.owner = owner
O.find_target()
objectives += O
if(3) //protect/kill
@@ -100,10 +100,9 @@
if(M.mind)
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
/obj/item/organ/heart/demon/Remove(mob/living/carbon/M, special = 0)
..()
if(M.mind)
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
/obj/item/organ/heart/demon/Remove(special = FALSE)
owner?.mind?.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
return ..()
/obj/item/organ/heart/demon/Stop()
return 0 // Always beating.
+1
View File
@@ -25,6 +25,7 @@
desc = "Hello brothers from the stars!!! Our fellow brethren have made contact at long last and gave us gifts man! They really did build the prymi- Connection Error- Bro well send you a sheet of advanced alien alloy."
cost = 15000
DropPodOnly = TRUE
contraband = TRUE
contains = list(/obj/item/stack/sheet/mineral/abductor)
crate_name = "alien bro alloy crate"
+1 -1
View File
@@ -114,7 +114,7 @@
for(var/X in CM.internal_organs)
var/destination = get_edge_target_turf(T, pick(GLOB.alldirs)) //Pick a random direction to toss them in
var/obj/item/organ/O = X
O.Remove(CM) //Note that this isn't the same proc as for lists
O.Remove() //Note that this isn't the same proc as for lists
O.forceMove(T) //Move the organ outta the body
O.throw_at(destination, 2, 3) //Thow the organ at a random tile 3 spots away
sleep(1)
+3 -1
View File
@@ -514,7 +514,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough))
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
message_admins("<span class='adminnotice'>Failed Login: [key] - New account attempting to connect during panic bunker</span>")
to_chat(src, "<span class='notice'>You must first join the Discord to verify your account before joining this server.<br>To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: <a href='https://discord.gg/E6SQuhz'>https://discord.gg/E6SQuhz</a></span>") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
to_chat(src, "<span class='notice'>You must first join the Discord to verify your account before joining this server.<br>To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: <a href='https://discord.gg/E6SQuhz'>https://discord.gg/E6SQuhz</a><br>If you have already done so, wait a few minutes then try again; sometimes the server needs to fully load before you can join.</span>") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
var/list/connectiontopic_a = params2list(connectiontopic)
var/list/panic_addr = CONFIG_GET(string/panic_server_address)
if(panic_addr && !connectiontopic_a["redirect"])
@@ -538,6 +538,8 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
if(!account_join_date)
account_join_date = "Error"
account_age = -1
else if(ckey in GLOB.bunker_passthrough)
GLOB.bunker_passthrough -= ckey
qdel(query_client_in_db)
var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
if(!query_get_client_age.Execute())
+29
View File
@@ -57,3 +57,32 @@
name = "blood-red magboots"
icon_state = "syndiemag0"
magboot_state = "syndiemag"
/obj/item/clothing/shoes/magboots/crushing
desc = "Normal looking magboots that are altered to increase magnetic pull to crush anything underfoot."
/obj/item/clothing/shoes/magboots/crushing/proc/crush(mob/living/user)
if (!isturf(user.loc) || !magpulse)
return
var/turf/T = user.loc
for (var/mob/living/A in T)
if (A != user && A.lying)
A.adjustBruteLoss(rand(10,13))
to_chat(A,"<span class='userdanger'>[user]'s magboots press down on you, crushing you!</span>")
A.emote("scream")
/obj/item/clothing/shoes/magboots/crushing/attack_self(mob/user)
. = ..()
if (magpulse)
RegisterSignal(user, COMSIG_MOVABLE_MOVED,.proc/crush)
else
UnregisterSignal(user,COMSIG_MOVABLE_MOVED)
/obj/item/clothing/shoes/magboots/crushing/equipped(mob/user,slot)
. = ..()
if (slot == SLOT_SHOES && magpulse)
RegisterSignal(user, COMSIG_MOVABLE_MOVED,.proc/crush)
/obj/item/clothing/shoes/magboots/crushing/dropped(mob/user)
. = ..()
UnregisterSignal(user,COMSIG_MOVABLE_MOVED)
@@ -244,6 +244,7 @@
/datum/reagent/consumable/spacemountainwind = 5
)
result = /obj/item/reagent_containers/food/snacks/snowcones/spacemountainwind
subcategory = CAT_ICE
/datum/crafting_recipe/food/pwrgame_sc
name = "Pwrgame snowcone"
@@ -273,4 +274,4 @@
/datum/reagent/colorful_reagent = 1 //Harder to make
)
result = /obj/item/reagent_containers/food/snacks/snowcones/rainbow
subcategory = CAT_ICE
subcategory = CAT_ICE
+1 -1
View File
@@ -59,7 +59,7 @@
/obj/machinery/seed_extractor/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Extracting <b>[seed_multiplier]</b> seed(s) per piece of produce.<br>Machine can store up to <b>[max_seeds]%</b> seeds.</span>"
. += "<span class='notice'>The status display reads: Extracting <b>[seed_multiplier]</b> seed(s) per piece of produce.<br>Machine can store up to <b>[max_seeds]</b> seeds.</span>"
/obj/machinery/seed_extractor/attackby(obj/item/O, mob/user, params)
File diff suppressed because one or more lines are too long
+4
View File
@@ -124,6 +124,10 @@
/datum/language_holder/drone/syndicate
only_speaks_language = null
/datum/language_holder/dwarf
languages = list(/datum/language/common, /datum/language/dwarf)
only_speaks_language = /datum/language/dwarf
/datum/language_holder/slime
languages = list(/datum/language/common, /datum/language/slime)
only_speaks_language = /datum/language/slime
@@ -111,8 +111,8 @@
preserved(TRUE)
owner.visible_message("<span class='notice'>[src] stabilizes as it's inserted.</span>")
/obj/item/organ/regenerative_core/Remove(mob/living/carbon/M, special = 0)
if(!inert && !special)
/obj/item/organ/regenerative_core/Remove(special = FALSE)
if(!inert && !special && !QDELETED(owner))
owner.visible_message("<span class='notice'>[src] rapidly decays as it's removed.</span>")
go_inert()
return ..()
@@ -159,6 +159,11 @@
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/bunny
name = "Bunny"
icon_state = "bunny"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/******************************************
*************** Furry Ears ****************
@@ -301,3 +306,7 @@
/datum/sprite_accessory/mam_ears/wolf
name = "Wolf"
icon_state = "wolf"
/datum/sprite_accessory/mam_ears/bunny
name = "Bunny"
icon_state = "bunny"
+6 -4
View File
@@ -55,16 +55,18 @@
//Update the body's icon so it doesnt appear debrained anymore
C.update_hair()
/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE)
..()
/obj/item/organ/brain/Remove(special = FALSE, no_id_transfer = FALSE)
. = ..()
var/mob/living/carbon/C = .
for(var/X in traumas)
var/datum/brain_trauma/BT = X
BT.on_lose(TRUE)
BT.owner = null
if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !no_id_transfer)
if((!QDELETED(src) || C) && !no_id_transfer)
transfer_identity(C)
C.update_hair()
if(C)
C.update_hair()
/obj/item/organ/brain/prepare_eat()
return // Too important to eat.
+12 -10
View File
@@ -20,9 +20,10 @@
M.AddAbility(P)
/obj/item/organ/alien/Remove(mob/living/carbon/M, special = 0)
for(var/obj/effect/proc_holder/alien/P in alien_powers)
M.RemoveAbility(P)
/obj/item/organ/alien/Remove(special = FALSE)
if(owner)
for(var/obj/effect/proc_holder/alien/P in alien_powers)
owner.RemoveAbility(P)
..()
/obj/item/organ/alien/prepare_eat()
@@ -100,11 +101,11 @@
var/mob/living/carbon/alien/A = M
A.updatePlasmaDisplay()
/obj/item/organ/alien/plasmavessel/Remove(mob/living/carbon/M, special = 0)
..()
if(isalien(M))
var/mob/living/carbon/alien/A = M
/obj/item/organ/alien/plasmavessel/Remove(special = FALSE)
if(owner && isalien(owner))
var/mob/living/carbon/alien/A = owner
A.updatePlasmaDisplay()
return ..()
#define QUEEN_DEATH_DEBUFF_DURATION 2400
@@ -121,9 +122,10 @@
..()
M.faction |= ROLE_ALIEN
/obj/item/organ/alien/hivenode/Remove(mob/living/carbon/M, special = 0)
M.faction -= ROLE_ALIEN
..()
/obj/item/organ/alien/hivenode/Remove(special = FALSE)
if(owner)
owner.faction -= ROLE_ALIEN
return ..()
//When the alien queen dies, all aliens suffer a penalty as punishment for failing to protect her.
/obj/item/organ/alien/hivenode/proc/queen_death()
@@ -252,7 +252,9 @@
return 0
if(M.getorgan(/obj/item/organ/alien/hivenode))
return 0
if(isvamp(M))
return 0
if(ismonkey(M))
return 1
+4 -4
View File
@@ -230,7 +230,7 @@
dat += "<BR><B>Back:</B> <A href='?src=[REF(src)];item=[SLOT_BACK]'>[back ? back : "Nothing"]</A>"
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS) && istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
dat += "<BR><A href='?src=[REF(src)];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
if(handcuffed)
@@ -249,7 +249,7 @@
..()
//strip panel
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["internal"])
if(href_list["internal"] && !HAS_TRAIT(src, TRAIT_NO_INTERNALS))
var/slot = text2num(href_list["internal"])
var/obj/item/ITEM = get_item_by_slot(slot)
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS))
@@ -533,7 +533,7 @@
break //Guess we're out of organs!
var/obj/item/organ/guts = pick(internal_organs)
var/turf/T = get_turf(src)
guts.Remove(src)
guts.Remove()
guts.forceMove(T)
var/atom/throw_target = get_edge_target_turf(guts, dir)
guts.throw_at(throw_target, power, 4, src)
@@ -872,7 +872,7 @@
var/obj/item/organ/O = X
if(prob(50))
organs_amt++
O.Remove(src)
O.Remove()
O.forceMove(drop_location())
if(organs_amt)
to_chat(user, "<span class='notice'>You retrieve some of [src]\'s internal organs!</span>")
+2 -2
View File
@@ -43,7 +43,7 @@
continue
var/org_zone = check_zone(O.zone) //both groin and chest organs.
if(org_zone == BODY_ZONE_CHEST)
O.Remove(src)
O.Remove()
O.forceMove(Tsec)
O.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
else
@@ -55,7 +55,7 @@
if(no_organs && !istype(I, /obj/item/organ/brain))
qdel(I)
continue
I.Remove(src)
I.Remove()
I.forceMove(Tsec)
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
+30 -32
View File
@@ -189,21 +189,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(brain && (replace_current || !should_have_brain))
if(!brain.decoy_override)//Just keep it if it's fake
brain.Remove(C,TRUE,TRUE)
brain.Remove(TRUE,TRUE)
QDEL_NULL(brain)
if(should_have_brain && !brain)
brain = new mutant_brain()
brain.Insert(C, TRUE, TRUE)
if(heart && (!should_have_heart || replace_current))
heart.Remove(C,1)
heart.Remove(TRUE)
QDEL_NULL(heart)
if(should_have_heart && !heart)
heart = new mutant_heart()
heart.Insert(C)
if(lungs && (!should_have_lungs || replace_current))
lungs.Remove(C,1)
lungs.Remove(TRUE)
QDEL_NULL(lungs)
if(should_have_lungs && !lungs)
if(mutantlungs)
@@ -213,7 +213,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
lungs.Insert(C)
if(liver && (!should_have_liver || replace_current))
liver.Remove(C,1)
liver.Remove(TRUE)
QDEL_NULL(liver)
if(should_have_liver && !liver)
if(mutantliver)
@@ -223,7 +223,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
liver.Insert(C)
if(stomach && (!should_have_stomach || replace_current))
stomach.Remove(C,1)
stomach.Remove(TRUE)
QDEL_NULL(stomach)
if(should_have_stomach && !stomach)
if(mutantstomach)
@@ -233,14 +233,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
stomach.Insert(C)
if(appendix && (!should_have_appendix || replace_current))
appendix.Remove(C,1)
appendix.Remove(TRUE)
QDEL_NULL(appendix)
if(should_have_appendix && !appendix)
appendix = new()
appendix.Insert(C)
if(tail && (!should_have_tail || replace_current))
tail.Remove(C,1)
tail.Remove(TRUE)
QDEL_NULL(tail)
if(should_have_tail && !tail)
tail = new mutanttail()
@@ -248,21 +248,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(C.get_bodypart(BODY_ZONE_HEAD))
if(eyes && (replace_current || !should_have_eyes))
eyes.Remove(C,1)
eyes.Remove(TRUE)
QDEL_NULL(eyes)
if(should_have_eyes && !eyes)
eyes = new mutanteyes
eyes.Insert(C, TRUE)
if(ears && (replace_current || !should_have_ears))
ears.Remove(C,1)
ears.Remove(TRUE)
QDEL_NULL(ears)
if(should_have_ears && !ears)
ears = new mutantears
ears.Insert(C)
if(tongue && (replace_current || !should_have_tongue))
tongue.Remove(C,1)
tongue.Remove(TRUE)
QDEL_NULL(tongue)
if(should_have_tongue && !tongue)
tongue = new mutanttongue
@@ -272,7 +272,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
for(var/mutantorgan in old_species.mutant_organs)
var/obj/item/organ/I = C.getorgan(mutantorgan)
if(I)
I.Remove(C)
I.Remove()
QDEL_NULL(I)
for(var/path in mutant_organs)
@@ -1585,7 +1585,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if (!HAS_TRAIT(target, TRAIT_PERMABONER))
stop_wagging_tail(target)
return FALSE
else if(aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
else if(!(user.client?.prefs.cit_toggles & NO_ASS_SLAP) && aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
if(target.client?.prefs.cit_toggles & NO_ASS_SLAP)
to_chat(user,"A force stays your hand, preventing you from slapping \the [target]'s ass!")
return FALSE
@@ -1601,7 +1601,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
"<span class='danger'>\The [user] slaps \the [target]'s ass!</span>",\
"<span class='notice'>You slap [user == target ? "your" : "\the [target]'s"] ass!</span>",\
"You hear a slap."
)
)
return FALSE
else if(attacker_style && attacker_style.disarm_act(user,target))
return 1
@@ -1884,6 +1884,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(get_turf(target) == target_oldturf)
shove_blocked = TRUE
var/append_message = ""
if(shove_blocked && !target.buckled)
var/directional_blocked = !target.Adjacent(target_shove_turf)
var/targetatrest = target.resting
@@ -1897,33 +1898,30 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL)
user.visible_message("<span class='danger'>[user.name] shoves [target.name] into [target_collateral_human.name]!</span>",
"<span class='danger'>You shove [target.name] into [target_collateral_human.name]!</span>", null, COMBAT_MESSAGE_RANGE)
log_combat(user, target, "shoved", "into [target_collateral_human.name]")
append_message += ", into [target_collateral_human.name]"
else
user.visible_message("<span class='danger'>[user.name] shoves [target.name]!</span>",
"<span class='danger'>You shove [target.name]!</span>", null, COMBAT_MESSAGE_RANGE)
var/target_held_item = target.get_active_held_item()
var/knocked_item = FALSE
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
if(target_held_item)
var/obj/item/target_held_item = target.get_active_held_item()
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
if(target_held_item)
if(!HAS_TRAIT(target_held_item, TRAIT_NODROP))
target.visible_message("<span class='danger'>[target.name]'s grip on \the [target_held_item] loosens!</span>",
"<span class='danger'>Your grip on \the [target_held_item] loosens!</span>", null, COMBAT_MESSAGE_RANGE)
addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
else if(target_held_item)
target.dropItemToGround(target_held_item)
knocked_item = TRUE
append_message += ", loosening their grip on [target_held_item]"
else
append_message += ", but couldn't loose their grip on [target_held_item]"
addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
else if(target_held_item)
if(target.dropItemToGround(target_held_item))
target.visible_message("<span class='danger'>[target.name] drops \the [target_held_item]!!</span>",
"<span class='danger'>You drop \the [target_held_item]!!</span>", null, COMBAT_MESSAGE_RANGE)
var/append_message = ""
if(target_held_item)
if(knocked_item)
append_message = "causing them to drop [target_held_item]"
else
append_message = "loosening their grip on [target_held_item]"
log_combat(user, target, "shoved", append_message)
append_message += ", causing them to drop [target_held_item]"
log_combat(user, target, "shoved", append_message)
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
var/hit_percent = (100-(blocked+armor))/100
@@ -31,6 +31,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
. = ..()
var/dwarf_hair = pick("Beard (Dwarf)", "Beard (Very Long)", "Beard (Long)") //beard roullette
var/mob/living/carbon/human/H = C
H.grant_language(/datum/language/dwarf)
H.facial_hair_style = dwarf_hair
H.update_hair()
H.transform = H.transform.Scale(1, 0.8) //We use scale, and yeah. Dwarves can become gnomes with DWARFISM.
@@ -41,6 +42,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
. = ..()
H.transform = H.transform.Scale(1, 1.25) //And we undo it.
UnregisterSignal(H, COMSIG_MOB_SAY) //We register handle_speech is not being used.
H.remove_language(/datum/language/dwarf)
//Dwarf Name stuff
/proc/dwarf_name() //hello caller: my name is urist mcuristurister
@@ -88,7 +88,7 @@
if(NT)
NT.Insert(H, drop_if_replaced = FALSE)
else
tail.Remove(H)
tail.Remove()
/proc/mass_purrbation()
for(var/M in GLOB.mob_list)
@@ -31,14 +31,15 @@
/datum/species/mush/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(!H.dna.features["caps"])
H.dna.features["caps"] = "Round"
handle_mutant_bodyparts(H)
H.faction |= "mushroom"
mush = new()
mush.teach(H, TRUE)
if(!ishuman(C))
return
var/mob/living/carbon/human/H = C
if(!H.dna.features["caps"])
H.dna.features["caps"] = "Round"
handle_mutant_bodyparts(H)
H.faction |= "mushroom"
mush = new()
mush.teach(H, TRUE)
RegisterSignal(C, COMSIG_MOB_ON_NEW_MIND, .proc/on_new_mind)
/datum/species/mush/proc/on_new_mind(mob/owner)
@@ -84,10 +84,10 @@
shadowwalk = SW
/obj/item/organ/brain/nightmare/Remove(mob/living/carbon/M, special = 0)
if(shadowwalk)
M.RemoveSpell(shadowwalk)
..()
/obj/item/organ/brain/nightmare/Remove(special = FALSE)
if(shadowwalk && owner)
owner.RemoveSpell(shadowwalk)
return ..()
/obj/item/organ/heart/nightmare
@@ -120,12 +120,12 @@
blade = new/obj/item/light_eater
M.put_in_hands(blade)
/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/nightmare/Remove(special = FALSE)
respawn_progress = 0
if(blade && special != HEART_SPECIAL_SHADOWIFY)
M.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
if(!QDELETED(owner) && blade && special != HEART_SPECIAL_SHADOWIFY)
owner.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
QDEL_NULL(blade)
..()
return ..()
/obj/item/organ/heart/nightmare/Stop()
return 0
@@ -146,7 +146,7 @@
owner.revive(full_heal = TRUE)
if(!(owner.dna.species.id == "shadow" || owner.dna.species.id == "nightmare"))
var/mob/living/carbon/old_owner = owner
Remove(owner, HEART_SPECIAL_SHADOWIFY)
Remove(HEART_SPECIAL_SHADOWIFY)
old_owner.set_species(/datum/species/shadow)
Insert(old_owner, HEART_SPECIAL_SHADOWIFY)
to_chat(owner, "<span class='userdanger'>You feel the shadows invade your skin, leaping into the center of your chest! You're alive!</span>")
+4 -3
View File
@@ -334,9 +334,10 @@
var/obj/item/clothing/check
var/internals = FALSE
for(check in GET_INTERNAL_SLOTS(src))
if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
internals = TRUE
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS))
for(check in GET_INTERNAL_SLOTS(src))
if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
internals = TRUE
if(internal)
if(internal.loc != src)
internal = null
@@ -38,7 +38,7 @@
var/obj/item/organ/tail/cat/tail = L.getorgan(/obj/item/organ/tail/cat)
if(!QDELETED(tail))
visible_message("[src] severs [L]'s tail in one swift swipe!", "<span class='notice'>You sever [L]'s tail in one swift swipe.</span>")
tail.Remove(L)
tail.Remove()
var/obj/item/organ/tail/cat/dropped_tail = new(target.drop_location())
dropped_tail.color = L.hair_color
return 1
@@ -61,7 +61,7 @@
time++
if(time >= EGG_INCUBATION_TIME)
Pop()
Remove(owner)
Remove()
qdel(src)
/obj/item/organ/body_egg/changeling_egg/proc/Pop()
+3 -9
View File
@@ -87,7 +87,7 @@ proc/get_top_level_mob(var/mob/S)
to_chat(user, "You cannot send IC messages (muted).")
return FALSE
else if(!params)
var/subtle_emote = stripped_multiline_input("Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN)
var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN)
if(subtle_emote && !check_invalid(user, subtle_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
@@ -109,7 +109,7 @@ proc/get_top_level_mob(var/mob/S)
if(!can_run_emote(user))
return FALSE
user.log_message(message, INDIVIDUAL_EMOTE_LOG)
user.log_message(message, LOG_EMOTE)
message = "<b>[user]</b> " + "<i>[message]</i>"
for(var/mob/M in GLOB.dead_mob_list)
@@ -123,10 +123,7 @@ proc/get_top_level_mob(var/mob/S)
user.audible_message(message=message,hearing_distance=1)
else
user.visible_message(message=message,self_message=message,vision_distance=1)
log_emote("[key_name(user)] : [message]")
message = null
emote_type = EMOTE_VISIBLE
///////////////// SUBTLE 2: NO GHOST BOOGALOO
@@ -173,16 +170,13 @@ proc/get_top_level_mob(var/mob/S)
if(!can_run_emote(user))
return FALSE
user.log_message(message, INDIVIDUAL_EMOTE_LOG)
user.log_message(message, LOG_SUBTLER)
message = "<b>[user]</b> " + "<i>[message]</i>"
if(emote_type == EMOTE_AUDIBLE)
user.audible_message(message=message,hearing_distance=1, ignored_mobs = GLOB.dead_mob_list)
else
user.visible_message(message=message,self_message=message,vision_distance=1, ignored_mobs = GLOB.dead_mob_list)
log_emote("[key_name(user)] : (SUBTLER) [message]")
message = null
///////////////// VERB CODE
/mob/living/verb/subtle()
+4 -4
View File
@@ -90,7 +90,7 @@
if(tr_flags & TR_KEEPORGANS)
for(var/X in O.internal_organs)
var/obj/item/organ/I = X
I.Remove(O, 1)
I.Remove(TRUE)
if(mind)
mind.transfer_to(O)
@@ -103,7 +103,7 @@
for(var/X in internal_organs)
var/obj/item/organ/I = X
int_organs += I
I.Remove(src, 1)
I.Remove(TRUE)
for(var/X in int_organs)
var/obj/item/organ/I = X
@@ -250,7 +250,7 @@
if(tr_flags & TR_KEEPORGANS)
for(var/X in O.internal_organs)
var/obj/item/organ/I = X
I.Remove(O, 1)
I.Remove(TRUE)
if(mind)
mind.transfer_to(O)
@@ -262,7 +262,7 @@
for(var/X in internal_organs)
var/obj/item/organ/I = X
int_organs += I
I.Remove(src, 1)
I.Remove(TRUE)
for(var/X in int_organs)
var/obj/item/organ/I = X
+40 -34
View File
@@ -13,6 +13,7 @@
w_class = WEIGHT_CLASS_SMALL
var/charge = 0 // note %age conveted to actual charge in New
var/maxcharge = 1000
var/start_charged = TRUE
materials = list(MAT_METAL=700, MAT_GLASS=50)
grind_results = list(/datum/reagent/lithium = 15, /datum/reagent/iron = 5, /datum/reagent/silicon = 5)
var/rigged = FALSE // true if rigged to explode
@@ -32,7 +33,8 @@
create_reagents(5, INJECTABLE | DRAINABLE)
if (override_maxcharge)
maxcharge = override_maxcharge
charge = maxcharge
if(start_charged)
charge = maxcharge
if(ratingdesc)
desc += " This one has a rating of [DisplayEnergy(maxcharge)], and you should not swallow it."
update_icon()
@@ -163,9 +165,8 @@
return rating * maxcharge
/* Cell variants*/
/obj/item/stock_parts/cell/empty/Initialize()
. = ..()
charge = 0
/obj/item/stock_parts/cell/empty
start_charged = FALSE
/obj/item/stock_parts/cell/crap
name = "\improper Nanotrasen brand rechargeable AA battery"
@@ -173,10 +174,8 @@
maxcharge = 500
materials = list(MAT_GLASS=40)
/obj/item/stock_parts/cell/crap/empty/Initialize()
. = ..()
charge = 0
update_icon()
/obj/item/stock_parts/cell/crap/empty
start_charged = FALSE
/obj/item/stock_parts/cell/upgraded
name = "upgraded power cell"
@@ -195,10 +194,8 @@
maxcharge = 1250 //25/12/6 disabler/laser/taser shots.
materials = list(MAT_GLASS=40)
/obj/item/stock_parts/cell/secborg/empty/Initialize()
. = ..()
charge = 0
update_icon()
/obj/item/stock_parts/cell/secborg/empty
start_charged = FALSE
/obj/item/stock_parts/cell/lascarbine
name = "laser carbine power supply"
@@ -231,10 +228,8 @@
maxcharge = 15000
chargerate = 2250
/obj/item/stock_parts/cell/high/empty/Initialize()
. = ..()
charge = 0
update_icon()
/obj/item/stock_parts/cell/high/empty
start_charged = FALSE
/obj/item/stock_parts/cell/super
name = "super-capacity power cell"
@@ -243,10 +238,8 @@
materials = list(MAT_GLASS=300)
chargerate = 2000
/obj/item/stock_parts/cell/super/empty/Initialize()
. = ..()
charge = 0
update_icon()
/obj/item/stock_parts/cell/super/empty
start_charged = FALSE
/obj/item/stock_parts/cell/hyper
name = "hyper-capacity power cell"
@@ -255,10 +248,8 @@
materials = list(MAT_GLASS=400)
chargerate = 3000
/obj/item/stock_parts/cell/hyper/empty/Initialize()
. = ..()
charge = 0
update_icon()
/obj/item/stock_parts/cell/hyper/empty
start_charged = FALSE
/obj/item/stock_parts/cell/bluespace
name = "bluespace power cell"
@@ -268,10 +259,8 @@
materials = list(MAT_GLASS=600)
chargerate = 4000
/obj/item/stock_parts/cell/bluespace/empty/Initialize()
. = ..()
charge = 0
update_icon()
/obj/item/stock_parts/cell/bluespace/empty
start_charged = FALSE
/obj/item/stock_parts/cell/infinite
name = "infinite-capacity power cell!"
@@ -321,15 +310,13 @@
maxcharge = 500
rating = 3
/obj/item/stock_parts/cell/emproof/empty/Initialize()
. = ..()
charge = 0
update_icon()
/obj/item/stock_parts/cell/emproof/empty/ComponentInitialize()
/obj/item/stock_parts/cell/emproof/ComponentInitialize()
. = ..()
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF)
/obj/item/stock_parts/cell/emproof/empty
start_charged = FALSE
/obj/item/stock_parts/cell/emproof/corrupt()
return
@@ -364,3 +351,22 @@
//found inside the inducers ordered from cargo.
/obj/item/stock_parts/cell/inducer_supply
maxcharge = 5000
/obj/item/stock_parts/cell/magnetic
name = "magrifle power supply"
maxcharge = 12000
chargerate = 600
/obj/item/stock_parts/cell/magnetic/empty
start_charged = FALSE
/obj/item/stock_parts/cell/magnetic/pistol
name = "magpistol power supply"
maxcharge = 6000
/obj/item/stock_parts/cell/magnetic/pistol/empty
start_charged = FALSE
/obj/item/stock_parts/cell/toymagburst
name = "toy mag burst rifle power supply"
maxcharge = 4000
@@ -565,7 +565,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
to_chat(C, "<span class='userdanger'>That was a really dense idea.</span>")
C.visible_message("<span class='userdanger'>A bright flare of radiation is seen from [C]'s head, shortly before you hear a sickening sizzling!</span>")
var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs
rip_u.Remove(C)
rip_u.Remove()
qdel(rip_u)
return
return ..()
+1 -1
View File
@@ -136,7 +136,7 @@
to_chat(C, "<span class='userdanger'>That was a shockingly dumb idea.</span>")
C.visible_message("<span class='userdanger'>A bright flare of lightning is seen from [C]'s head, shortly before you hear a sickening sizzling!</span>")
var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs
rip_u.Remove(C)
rip_u.Remove()
qdel(rip_u)
return
return ..()
@@ -0,0 +1,39 @@
/obj/item/ammo_casing/caseless/magnetic
desc = "A large ferromagnetic slug intended to be launched out of a compatible weapon."
caliber = "mag"
icon_state = "mag-casing-live"
click_cooldown_override = 2.5
delay = 3
var/energy_cost = 200
/obj/item/ammo_casing/caseless/magnetic
projectile_type = /obj/item/projectile/bullet/magnetic
/obj/item/ammo_casing/caseless/magnetic/disabler
desc = "A large, specialized ferromagnetic slug designed with a less-than-lethal payload."
projectile_type = /obj/item/projectile/bullet/magnetic/disabler
/obj/item/ammo_casing/caseless/magnetic/weak
desc = "A ferromagnetic slug intended to be launched out of a compatible weapon."
projectile_type = /obj/item/projectile/bullet/magnetic/weak
energy_cost = 125
/obj/item/ammo_casing/caseless/magnetic/weak/disabler
desc = "A specialized ferromagnetic slug designed with a less-than-lethal payload."
projectile_type = /obj/item/projectile/bullet/magnetic/weak/disabler
energy_cost = 125
/obj/item/ammo_casing/caseless/magnetic/hyper
desc = "A large block of speciallized ferromagnetic material designed to be fired out of the experimental Hyper-Burst Rifle."
caliber = "hypermag"
icon_state = "hyper-casing-live"
projectile_type = /obj/item/projectile/bullet/magnetic/hyper
pellets = 8
variance = 30
energy_cost = 1500
/obj/item/ammo_casing/caseless/magnetic/hyper/inferno
projectile_type = /obj/item/projectile/bullet/incendiary/mag_inferno
pellets = 1
variance = 0
@@ -63,3 +63,8 @@
projectile_type = /obj/item/projectile/bullet/reusable/foam_dart/riot
icon_state = "foamdart_riot"
materials = list(MAT_METAL = 1125)
/obj/item/ammo_casing/caseless/foam_dart/mag
name = "magfoam dart"
desc = "A foam dart with fun light-up projectiles powered by magnets!"
projectile_type = /obj/item/projectile/bullet/reusable/foam_dart/mag
@@ -62,6 +62,14 @@
/obj/item/ammo_casing/energy/laser/redtag/hitscan/holy
projectile_type = /obj/item/projectile/beam/lasertag/redtag/hitscan/holy
/obj/item/ammo_casing/energy/laser/magtag
projectile_type = /obj/item/projectile/beam/lasertag/mag
select_name = "magtag"
pellets = 3
variance = 30
e_cost = 1000
fire_sound = 'sound/weapons/magburst.ogg'
/obj/item/ammo_casing/energy/xray
projectile_type = /obj/item/projectile/beam/xray
e_cost = 50
@@ -87,7 +87,14 @@
max_ammo = 40
materials = list(MAT_METAL = 500)
/obj/item/ammo_box/foambox/mag
name = "ammo box (Magnetic Foam Darts)"
icon = 'icons/obj/guns/toy.dmi'
icon_state = "foambox"
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
max_ammo = 42
/obj/item/ammo_box/foambox/riot
icon_state = "foambox_riot"
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
materials = list(MAT_METAL = 50000)
materials = list(MAT_METAL = 50000)
@@ -0,0 +1,34 @@
/obj/item/ammo_box/magazine/mmag
icon_state = "mediummagmag"
ammo_type = /obj/item/ammo_casing/caseless/magnetic/disabler
caliber = "mag"
max_ammo = 24
multiple_sprites = 2
/obj/item/ammo_box/magazine/mmag/lethal
name = "magrifle magazine (lethal)"
ammo_type = /obj/item/ammo_casing/caseless/magnetic
/obj/item/ammo_box/magazine/mmag/small
name = "magpistol magazine (non-lethal disabler)"
icon_state = "smallmagmag"
ammo_type = /obj/item/ammo_casing/caseless/magnetic/weak/disabler
max_ammo = 15
/obj/item/ammo_box/magazine/mmag/small/lethal
name = "magpistol magazine (lethal)"
ammo_type = /obj/item/ammo_casing/caseless/magnetic/weak
/obj/item/ammo_box/magazine/mhyper
name = "hyper-burst rifle magazine"
icon_state = "hypermag"
ammo_type = /obj/item/ammo_casing/caseless/magnetic/hyper
caliber = "hypermag"
desc = "A magazine for the Hyper-Burst Rifle. Loaded with a special slug that fragments into 6 smaller shards which can absolutely puncture anything, but has rather short effective range."
max_ammo = 4
multiple_sprites = 4
/obj/item/ammo_box/magazine/mhyper/inferno
name = "hyper-burst rifle magazine (inferno)"
ammo_type = /obj/item/ammo_casing/caseless/magnetic/hyper/inferno
desc = "A magazine for the Hyper-Burst Rifle. Loaded with a special slug that violently reacts with whatever surface it strikes, generating massive amount of heat and light."
@@ -57,3 +57,11 @@
/obj/item/ammo_box/magazine/toy/m762/riot
icon_state = "a762-riot"
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
/obj/item/ammo_box/magazine/toy/foamag
name = "foam force magrifle magazine"
icon_state = "foamagmag"
max_ammo = 24
multiple_sprites = 2
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
materials = list(MAT_METAL = 200)
@@ -5,3 +5,7 @@
/obj/item/ammo_box/magazine/internal/shot/toy/crossbow
max_ammo = 5
/obj/item/ammo_box/magazine/internal/shot/toy/mag
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
max_ammo = 14
+1 -1
View File
@@ -163,7 +163,7 @@
user.visible_message("<span class='suicide'>[user] blows [user.p_their()] brain[user.p_s()] out with [src]!</span>")
playsound(src, 'sound/weapons/dink.ogg', 30, 1)
var/turf/target = get_ranged_target_turf(user, turn(user.dir, 180), BRAINS_BLOWN_THROW_RANGE)
B.Remove(user)
B.Remove()
B.forceMove(T)
if(iscarbon(user))
var/mob/living/carbon/C = user
@@ -0,0 +1,103 @@
/obj/item/gun/ballistic/automatic/magrifle
name = "\improper Magnetic Rifle"
desc = "A simple upscalling of the technologies used in the magpistol, the magrifle is capable of firing slightly larger slugs in bursts. Compatible with the magpistol's slugs."
icon_state = "magrifle"
item_state = "arg"
force = 10
slot_flags = NONE
mag_type = /obj/item/ammo_box/magazine/mmag
fire_sound = 'sound/weapons/magrifle.ogg'
can_suppress = FALSE
burst_size = 1
actions_types = null
fire_delay = 3
spread = 0
recoil = 0.1
casing_ejector = FALSE
inaccuracy_modifier = 0.5
dualwield_spread_mult = 1.4
weapon_weight = WEAPON_MEDIUM
var/obj/item/stock_parts/cell/cell
var/cell_type = /obj/item/stock_parts/cell/magnetic
/obj/item/gun/ballistic/automatic/magrifle/Initialize()
. = ..()
if(cell_type)
cell = new cell_type(src)
else
cell = new(src)
/obj/item/gun/ballistic/automatic/magrifle/examine(mob/user)
. = ..()
if(cell)
. += "<span class='notice'>[src]'s cell is [round(cell.charge / cell.maxcharge, 0.1) * 100]% full.</span>"
else
. += "<span class='notice'>[src] doesn't seem to have a cell!</span>"
/obj/item/gun/ballistic/automatic/magrifle/can_shoot()
if(QDELETED(cell))
return 0
var/obj/item/ammo_casing/caseless/magnetic/shot = chambered
if(!shot)
return 0
if(cell.charge < shot.energy_cost * burst_size)
return 0
. = ..()
/obj/item/gun/ballistic/automatic/magrifle/shoot_live_shot()
var/obj/item/ammo_casing/caseless/magnetic/shot = chambered
cell.use(shot.energy_cost)
. = ..()
/obj/item/gun/ballistic/automatic/magrifle/emp_act(severity)
. = ..()
if(!(. & EMP_PROTECT_CONTENTS))
cell.use(round(cell.charge / severity))
/obj/item/gun/ballistic/automatic/magrifle/get_cell()
return cell
/obj/item/gun/ballistic/automatic/magrifle/nopin
pin = null
spawnwithmagazine = FALSE
cell_type = /obj/item/stock_parts/cell/magnetic/empty
/obj/item/gun/ballistic/automatic/magrifle/hyperburst
name = "\improper Hyper-Burst Rifle"
desc = "An extremely beefed up version of a stolen Nanotrasen weapon prototype, this 'rifle' is more like a cannon, with an extremely large bore barrel capable of generating several smaller magnetic 'barrels' to simultaneously launch multiple projectiles at once."
icon_state = "hyperburst"
item_state = "arg"
mag_type = /obj/item/ammo_box/magazine/mhyper
fire_sound = 'sound/weapons/magburst.ogg'
fire_delay = 40
recoil = 2
weapon_weight = WEAPON_HEAVY
/obj/item/gun/ballistic/automatic/magrifle/hyperburst/update_icon()
..()
icon_state = "hyperburst[magazine ? "-[get_ammo()]" : ""][chambered ? "" : "-e"]"
///magpistol///
/obj/item/gun/ballistic/automatic/magrifle/pistol
name = "magpistol"
desc = "A handgun utilizing maglev technologies to propel a ferromagnetic slug to extreme velocities."
icon_state = "magpistol"
fire_sound = 'sound/weapons/magpistol.ogg'
mag_type = /obj/item/ammo_box/magazine/mmag/small
fire_delay = 2
inaccuracy_modifier = 0.25
cell_type = /obj/item/stock_parts/cell/magnetic/pistol
/obj/item/gun/ballistic/automatic/magrifle/pistol/update_icon()
..()
cut_overlays()
if(magazine)
add_overlay("magpistol-magazine")
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
/obj/item/gun/ballistic/automatic/magrifle/pistol/nopin
pin = null
spawnwithmagazine = FALSE
cell_type = /obj/item/stock_parts/cell/magnetic/pistol/empty
@@ -109,3 +109,36 @@
/obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted/riot
mag_type = /obj/item/ammo_box/magazine/toy/m762/riot
/obj/item/gun/ballistic/automatic/toy/magrifle
name = "foamag rifle"
desc = "A foam launching magnetic rifle. Ages 8 and up."
icon_state = "foamagrifle"
obj_flags = NONE
mag_type = /obj/item/ammo_box/magazine/toy/foamag
fire_sound = 'sound/weapons/magrifle.ogg'
burst_size = 1
actions_types = null
fire_delay = 3
spread = 60
recoil = 0.1
can_suppress = FALSE
inaccuracy_modifier = 0.5
weapon_weight = WEAPON_MEDIUM
dualwield_spread_mult = 1.4
w_class = WEIGHT_CLASS_BULKY
/obj/item/gun/ballistic/shotgun/toy/mag
name = "foam force magpistol"
desc = "A fancy toy sold alongside light-up foam force darts. Ages 8 and up."
icon_state = "toymag"
item_state = "gun"
mag_type = /obj/item/ammo_box/magazine/internal/shot/toy/mag
fire_sound = 'sound/weapons/magpistol.ogg'
fire_delay = 2
recoil = 0.1
inaccuracy_modifier = 0.25
dualwield_spread_mult = 1.4
slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_NORMAL
weapon_weight = WEAPON_MEDIUM
@@ -16,6 +16,19 @@
clumsy_check = 0
item_flags = NONE
/obj/item/gun/energy/laser/practice/hyperburst
name = "toy hyper-burst launcher"
desc = "A toy laser with a unique beam shaping lens that projects harmless bolts capable of going through objects. Compatible with existing laser tag systems."
ammo_type = list(/obj/item/ammo_casing/energy/laser/magtag)
icon_state = "toyburst"
obj_flags = NONE
fire_delay = 40
weapon_weight = WEAPON_HEAVY
selfcharge = EGUN_SELFCHARGE
charge_delay = 2
recoil = 2
cell_type = /obj/item/stock_parts/cell/toymagburst
/obj/item/gun/energy/laser/retro
name ="retro laser gun"
icon_state = "retro"
@@ -146,6 +146,15 @@
if(M.wear_suit.type in suit_types)
M.adjustStaminaLoss(34)
/obj/item/projectile/beam/lasertag/mag //the projectile, compatible with regular laser tag armor
icon_state = "magjectile-toy"
name = "lasertag magbolt"
movement_type = FLYING | UNSTOPPABLE //for penetration memes
range = 5 //so it isn't super annoying
light_range = 2
light_color = LIGHT_COLOR_YELLOW
eyeblur = 0
/obj/item/projectile/beam/lasertag/redtag
icon_state = "laser"
suit_types = list(/obj/item/clothing/suit/bluetag)
@@ -0,0 +1,49 @@
/obj/item/projectile/bullet/magnetic
icon_state = "magjectile"
damage = 20
armour_penetration = 20
light_range = 3
speed = 0.6
range = 35
light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/magnetic/disabler
icon_state = "magjectile-nl" //nl stands for non-lethal
damage = 2
armour_penetration = 10
stamina = 20
light_color = LIGHT_COLOR_BLUE
/obj/item/projectile/bullet/magnetic/weak
damage = 15
armour_penetration = 10
light_range = 2
range = 25
/obj/item/projectile/bullet/magnetic/weak/disabler
damage = 2
stamina = 20
/obj/item/projectile/bullet/magnetic/hyper
damage = 10
armour_penetration = 20
stamina = 10
movement_type = FLYING | UNSTOPPABLE
range = 6
light_range = 1
light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/incendiary/mag_inferno
icon_state = "magjectile-large"
damage = 10
armour_penetration = 20
movement_type = FLYING | UNSTOPPABLE
range = 20
speed = 0.8
light_range = 4
light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/incendiary/mag_inferno/on_hit(atom/target, blocked = FALSE)
..()
explosion(target, -1, 0, 0, 1, 2, flame_range = 2)
return BULLET_ACT_HIT
@@ -39,3 +39,10 @@
icon_state = "foamdart_riot_proj"
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
stamina = 25
/obj/item/projectile/bullet/reusable/foam_dart/mag
name = "magfoam dart"
icon_state = "magjectile-toy"
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
light_range = 2
light_color = LIGHT_COLOR_YELLOW
@@ -197,7 +197,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
var/obj/item/organ/eyes/eyes = M.getorganslot(ORGAN_SLOT_EYES)
if(HAS_TRAIT(M, TRAIT_BLIND))
if(eyes)
eyes.Remove(M)
eyes.Remove()
eyes.forceMove(get_turf(M))
to_chat(M, "<span class='userdanger'>You double over in pain as you feel your eyeballs liquify in your head!</span>")
M.emote("scream")
@@ -64,12 +64,7 @@
reagents.reaction(target, TOUCH, fraction)
var/mob/M = target
var/R
if(reagents)
for(var/datum/reagent/A in src.reagents.reagent_list)
R += A.type + " ("
R += num2text(A.volume) + "),"
log_combat(user, M, "squirted", R)
log_combat(user, M, "squirted", reagents.log_list())
trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You transfer [trans] unit\s of the solution.</span>")
@@ -584,7 +584,7 @@
id = "foam_magrifle"
build_type = AUTOYLATHE
materials = list(MAT_PLASTIC = 4000, MAT_METAL = 500)
build_path = /obj/item/gun/ballistic/automatic/magrifle/toy
build_path = /obj/item/gun/ballistic/automatic/toy/magrifle
category = list("initial", "Rifles")
/datum/design/foam_hyperburst
@@ -47,6 +47,44 @@
category = list("Ammo")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
//////////////////
//Mag-Rifle Mags//
//////////////////
/datum/design/mag_magrifle
name = "Magrifle Magazine (Lethal)"
desc = "A 24-round magazine for the Magrifle."
id = "mag_magrifle"
build_type = PROTOLATHE
materials = list(MAT_METAL = 8000, MAT_SILVER = 1000)
build_path = /obj/item/ammo_box/magazine/mmag/lethal
category = list("Ammo")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
/datum/design/mag_magrifle/nl
name = "Magrifle Magazine (Non-Lethal)"
desc = "A 24- round non-lethal magazine for the Magrifle."
id = "mag_magrifle_nl"
materials = list(MAT_METAL = 6000, MAT_SILVER = 500, MAT_TITANIUM = 500)
build_path = /obj/item/ammo_box/magazine/mmag
/datum/design/mag_magpistol
name = "Magpistol Magazine"
desc = "A 14 round magazine for the Magpistol."
id = "mag_magpistol"
build_type = PROTOLATHE
materials = list(MAT_METAL = 4000, MAT_SILVER = 500)
build_path = /obj/item/ammo_box/magazine/mmag/small/lethal
category = list("Ammo")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
/datum/design/mag_magpistol/nl
name = "Magpistol Magazine (Non-Lethal)"
desc = "A 14 round non-lethal magazine for the Magpistol."
id = "mag_magpistol_nl"
materials = list(MAT_METAL = 3000, MAT_SILVER = 250, MAT_TITANIUM = 250)
build_path = /obj/item/ammo_box/magazine/mmag/small
//////////////
//WT550 Mags//
//////////////
@@ -323,6 +361,26 @@
category = list("Weapons")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
/datum/design/magpistol
name = "Magpistol"
desc = "A weapon which fires ferromagnetic slugs."
id = "magpistol"
build_type = PROTOLATHE
materials = list(MAT_METAL = 7500, MAT_GLASS = 1000, MAT_URANIUM = 1000, MAT_TITANIUM = 5000, MAT_SILVER = 2000)
build_path = /obj/item/gun/ballistic/automatic/magrifle/pistol/nopin
category = list("Weapons")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
/datum/design/magrifle
name = "Magrifle"
desc = "An upscaled Magpistol in rifle form."
id = "magrifle"
build_type = PROTOLATHE
materials = list(MAT_METAL = 10000, MAT_GLASS = 2000, MAT_URANIUM = 2000, MAT_TITANIUM = 10000, MAT_SILVER = 4000, MAT_GOLD = 2000)
build_path = /obj/item/gun/ballistic/automatic/magrifle/nopin
category = list("Weapons")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
///////////
//Grenades/
///////////
@@ -697,6 +697,15 @@
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
/datum/techweb_node/magnetic_weapons
id = "magnetic_weapons"
display_name = "Magnetic Weapons"
description = "Weapons using magnetic technology"
prereq_ids = list("weaponry", "adv_weaponry", "emp_adv")
design_ids = list("magrifle", "magpistol", "mag_magrifle", "mag_magrifle_nl", "mag_magpistol", "mag_magpistol_nl")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
/datum/techweb_node/medical_weapons
id = "medical_weapons"
display_name = "Medical Weaponry"
+1 -1
View File
@@ -144,7 +144,7 @@
C.dropItemToGround(W)
for(var/X in C.internal_organs)
var/obj/item/organ/I = X
I.Remove(C)
I.Remove()
I.forceMove(body_turf)
var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf))
if(wheres_wizdo)
@@ -58,7 +58,7 @@
if(organ.owner)
// If this code ever runs I will be happy
log_combat(L, organ.owner, "magically removed [organ.name] from", addition="INTENT: [uppertext(L.a_intent)]")
organ.Remove(organ.owner)
organ.Remove()
else
while(!isturf(item_to_retrieve.loc) && infinite_recursion < 10) //if it's in something you get the whole thing.
if(isitem(item_to_retrieve.loc))
@@ -62,7 +62,7 @@
var/org_zone = check_zone(O.zone)
if(org_zone != BODY_ZONE_CHEST)
continue
O.Remove(C)
O.Remove()
O.forceMove(T)
organ_spilled = 1
. += X
@@ -141,11 +141,11 @@
//when a limb is dropped, the internal organs are removed from the mob and put into the limb
/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C)
Remove(C)
Remove()
forceMove(LB)
/obj/item/organ/brain/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/C)
Remove(C) //Changeling brain concerns are now handled in Remove
Remove() //Changeling brain concerns are now handled in Remove
forceMove(LB)
LB.brain = src
if(brainmob)
+1 -1
View File
@@ -17,7 +17,7 @@
var/list/organs = M.getorganszone("head") + M.getorganszone("eyes") + M.getorganszone("mouth")
for(var/internal_organ in organs)
var/obj/item/organ/I = internal_organ
I.Remove(M)
I.Remove()
I.forceMove(T)
head.drop_limb()
qdel(head)
+1 -1
View File
@@ -136,7 +136,7 @@
"[user] successfully extracts [I] from [target]'s [parse_zone(target_zone)]!",
"[user] successfully extracts something from [target]'s [parse_zone(target_zone)]!")
log_combat(user, target, "surgically removed [I.name] from", addition="INTENT: [uppertext(user.a_intent)]")
I.Remove(target)
I.Remove()
I.forceMove(get_turf(target))
else
display_results(user, target, "<span class='notice'>You can't extract anything from [target]'s [parse_zone(target_zone)]!</span>",
+5 -4
View File
@@ -27,10 +27,11 @@
icon_state = "appendix"
name = "appendix"
/obj/item/organ/appendix/Remove(mob/living/carbon/M, special = 0)
for(var/datum/disease/appendicitis/A in M.diseases)
A.cure()
inflamed = TRUE
/obj/item/organ/appendix/Remove(special = FALSE)
if(owner)
for(var/datum/disease/appendicitis/A in owner.diseases)
A.cure()
inflamed = TRUE
update_icon()
..()
+1 -1
View File
@@ -54,7 +54,7 @@
to_chat(user, "<span class='notice'>You modify [src] to be installed on the [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm.</span>")
update_icon()
/obj/item/organ/cyberimp/arm/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/cyberimp/arm/Remove(special = FALSE)
Retract()
..()
@@ -147,10 +147,10 @@
ion_trail = new
ion_trail.set_up(M)
/obj/item/organ/cyberimp/chest/thrusters/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/cyberimp/chest/thrusters/Remove(special = FALSE)
if(on)
toggle(silent = TRUE)
..()
toggle(TRUE)
return ..()
/obj/item/organ/cyberimp/chest/thrusters/ui_action_click()
toggle()
@@ -170,10 +170,11 @@
to_chat(owner, "<span class='notice'>You turn your thrusters set on.</span>")
else
ion_trail.stop()
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
owner.remove_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER)
if(!silent)
to_chat(owner, "<span class='notice'>You turn your thrusters set off.</span>")
if(!QDELETED(owner))
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
owner.remove_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER)
if(!silent)
to_chat(owner, "<span class='notice'>You turn your thrusters set off.</span>")
on = FALSE
update_icon()
+4 -4
View File
@@ -20,11 +20,11 @@
var/datum/atom_hud/H = GLOB.huds[HUD_type]
H.add_hud_to(M)
/obj/item/organ/cyberimp/eyes/hud/Remove(var/mob/living/carbon/M, var/special = 0)
if(HUD_type)
/obj/item/organ/cyberimp/eyes/hud/Remove(special = FALSE)
if(!QDELETED(owner) && HUD_type)
var/datum/atom_hud/H = GLOB.huds[HUD_type]
H.remove_hud_from(M)
..()
H.remove_hud_from(owner)
return ..()
/obj/item/organ/cyberimp/eyes/hud/medical
name = "Medical HUD implant"
@@ -89,10 +89,10 @@
stored_items = list()
/obj/item/organ/cyberimp/brain/anti_drop/Remove(var/mob/living/carbon/M, special = 0)
/obj/item/organ/cyberimp/brain/anti_drop/Remove(special = FALSE)
if(active)
ui_action_click()
..()
return ..()
/obj/item/organ/cyberimp/brain/anti_stun
+4 -3
View File
@@ -104,13 +104,14 @@
H.dna.features["ears"] = "Cat"
H.update_body()
/obj/item/organ/ears/cat/Remove(mob/living/carbon/human/H, special = 0)
..()
if(istype(H))
/obj/item/organ/ears/cat/Remove(special = FALSE)
if(!QDELETED(owner) && ishuman(owner))
var/mob/living/carbon/human/H = owner
color = H.hair_color
H.dna.features["ears"] = "None"
H.dna.species.mutant_bodyparts -= "ears"
H.update_body()
return ..()
/obj/item/organ/ears/bronze
name = "tin ears"
+20 -17
View File
@@ -47,17 +47,19 @@
M.update_tint()
owner.update_sight()
/obj/item/organ/eyes/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/eyes/Remove(special = FALSE)
clear_eye_trauma()
. = ..()
if(ishuman(M) && eye_color)
var/mob/living/carbon/human/H = M
H.eye_color = old_eye_color
var/mob/living/carbon/C = .
if(C)
if(ishuman(C) && eye_color)
var/mob/living/carbon/human/H = C
H.eye_color = old_eye_color
if(!special)
H.dna.species.handle_body()
if(!special)
H.dna.species.handle_body()
if(!special)
M.update_tint()
M.update_sight()
C.update_tint()
C.update_sight()
/obj/item/organ/eyes/on_life()
..()
@@ -185,13 +187,13 @@
eye.update_brightness(M)
M.become_blind("flashlight_eyes")
/obj/item/organ/eyes/robotic/flashlight/Remove(var/mob/living/carbon/M, special = FALSE)
eye.on = FALSE
eye.update_brightness(M)
eye.forceMove(src)
M.cure_blind("flashlight_eyes")
..()
/obj/item/organ/eyes/robotic/flashlight/Remove(special = FALSE)
if(!QDELETED(owner))
eye.on = FALSE
eye.update_brightness(owner)
eye.forceMove(src)
owner.cure_blind("flashlight_eyes")
return ..()
// Welding shield implant
/obj/item/organ/eyes/robotic/shield
@@ -227,7 +229,7 @@
terminate_effects()
. = ..()
/obj/item/organ/eyes/robotic/glow/Remove(mob/living/carbon/M, special = FALSE)
/obj/item/organ/eyes/robotic/glow/Remove(special = FALSE)
terminate_effects()
. = ..()
@@ -236,7 +238,6 @@
deactivate(TRUE)
active = FALSE
clear_visuals(TRUE)
STOP_PROCESSING(SSfastprocess, src)
/obj/item/organ/eyes/robotic/glow/ui_action_click(owner, action)
if(istype(action, /datum/action/item_action/organ_action/toggle))
@@ -255,6 +256,8 @@
if(!C || QDELETED(src) || QDELETED(user) || QDELETED(owner) || owner != user)
return
var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num
if(!isnum(range))
return
set_distance(CLAMP(range, 0, max_light_beam_distance))
assume_rgb(C)
+6 -6
View File
@@ -28,10 +28,10 @@
else
icon_state = "[icon_base]-off"
/obj/item/organ/heart/Remove(mob/living/carbon/M, special = 0)
..()
/obj/item/organ/heart/Remove(special = FALSE)
if(!special)
addtimer(CALLBACK(src, .proc/stop_if_unowned), 120)
addtimer(CALLBACK(src, .proc/stop_if_unowned), 12 SECONDS)
return ..()
/obj/item/organ/heart/proc/stop_if_unowned()
if(!owner)
@@ -145,9 +145,9 @@ obj/item/organ/heart/slime
if(owner)
to_chat(owner, "<span class ='userdanger'>Your heart has been replaced with a cursed one, you have to pump this one manually otherwise you'll die!</span>")
/obj/item/organ/heart/cursed/Remove(mob/living/carbon/M, special = 0)
..()
M.remove_client_colour(/datum/client_colour/cursed_heart_blood)
/obj/item/organ/heart/cursed/Remove(special = FALSE)
owner.remove_client_colour(/datum/client_colour/cursed_heart_blood)
return ..()
/datum/action/item_action/organ_action/cursed_heart
name = "Pump your blood"
+6 -6
View File
@@ -58,12 +58,12 @@
return S
//Just in case
/obj/item/organ/liver/Remove(mob/living/carbon/M, special = 0)
..()
if(!QDELETED(M))
M.remove_movespeed_modifier(LIVER_SWELLING_MOVE_MODIFY)
M.ResetBloodVol() //At the moment, this shouldn't allow application twice. You either have this OR a thirsty ferret.
sizeMoveMod(1, M)
/obj/item/organ/liver/Remove(special = FALSE)
if(!QDELETED(owner))
owner.remove_movespeed_modifier(LIVER_SWELLING_MOVE_MODIFY)
owner.ResetBloodVol() //At the moment, this shouldn't allow application twice. You either have this OR a thirsty ferret.
sizeMoveMod(1, owner)
return ..()
//Applies some of the effects to the patient.
/obj/item/organ/liver/proc/pharmacokinesis()
+14 -15
View File
@@ -33,7 +33,7 @@
var/obj/item/organ/replaced = M.getorganslot(slot)
if(replaced)
replaced.Remove(M, special = 1)
replaced.Remove(TRUE)
if(drop_if_replaced)
replaced.forceMove(get_turf(M))
else
@@ -54,21 +54,20 @@
return TRUE
//Special is for instant replacement like autosurgeons
/obj/item/organ/proc/Remove(mob/living/carbon/M, special = FALSE)
/obj/item/organ/proc/Remove(special = FALSE)
if(owner)
owner.internal_organs -= src
if(owner.internal_organs_slot[slot] == src)
owner.internal_organs_slot.Remove(slot)
if((organ_flags & ORGAN_VITAL) && !special && !(owner.status_flags & GODMODE))
owner.death()
for(var/X in actions)
var/datum/action/A = X
A.Remove(owner)
. = owner //for possible subtypes specific post-removal code.
owner = null
if(M)
M.internal_organs -= src
if(M.internal_organs_slot[slot] == src)
M.internal_organs_slot.Remove(slot)
if((organ_flags & ORGAN_VITAL) && !special && !(M.status_flags & GODMODE))
M.death()
for(var/X in actions)
var/datum/action/A = X
A.Remove(M)
START_PROCESSING(SSobj, src)
return TRUE
/obj/item/organ/proc/on_find(mob/living/finder)
return
@@ -185,7 +184,7 @@
if(owner)
// The special flag is important, because otherwise mobs can die
// while undergoing transformation into different mobs.
Remove(owner, TRUE)
Remove(TRUE)
return ..()
/obj/item/organ/attack(mob/living/carbon/M, mob/user)
@@ -338,7 +337,7 @@
T = new dna.species.mutanttongue()
else
T = new()
oT.Remove(src)
oT.Remove()
qdel(oT)
T.Insert(src)
+2 -2
View File
@@ -80,9 +80,9 @@
H.throw_alert("disgust", /obj/screen/alert/disgusted)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "disgust", /datum/mood_event/disgusted)
/obj/item/organ/stomach/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/stomach/Remove(special = FALSE)
var/mob/living/carbon/human/H = owner
if(istype(H))
if(H && istype(H))
H.clear_alert("disgust")
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "disgust")
..()
+12 -10
View File
@@ -8,10 +8,10 @@
slot = ORGAN_SLOT_TAIL
var/tail_type = "None"
/obj/item/organ/tail/Remove(mob/living/carbon/human/H, special = 0)
..()
if(H && H.dna && H.dna.species)
H.dna.species.stop_wagging_tail(H)
/obj/item/organ/tail/Remove(special = FALSE)
if(owner?.dna?.species)
owner.dna.species.stop_wagging_tail(owner)
return ..()
/obj/item/organ/tail/cat
name = "cat tail"
@@ -26,13 +26,14 @@
H.dna.features["tail_human"] = tail_type
H.update_body()
/obj/item/organ/tail/cat/Remove(mob/living/carbon/human/H, special = 0)
..()
if(istype(H))
/obj/item/organ/tail/cat/Remove(special = FALSE)
if(!QDELETED(owner) && ishuman(owner))
var/mob/living/carbon/human/H = owner
H.dna.features["tail_human"] = "None"
H.dna.species.mutant_bodyparts -= "tail_human"
color = H.hair_color
H.update_body()
return ..()
/obj/item/organ/tail/lizard
name = "lizard tail"
@@ -54,12 +55,13 @@
H.dna.species.mutant_bodyparts |= "spines"
H.update_body()
/obj/item/organ/tail/lizard/Remove(mob/living/carbon/human/H, special = 0)
..()
if(istype(H))
/obj/item/organ/tail/lizard/Remove(special = FALSE)
if(!QDELETED(owner) && ishuman(owner))
var/mob/living/carbon/human/H = owner
H.dna.species.mutant_bodyparts -= "tail_lizard"
H.dna.species.mutant_bodyparts -= "spines"
color = "#" + H.dna.features["mcolor"]
tail_type = H.dna.features["tail_lizard"]
spines = H.dna.features["spines"]
H.update_body()
return ..()
+8 -6
View File
@@ -23,6 +23,7 @@
/datum/language/aphasia,
/datum/language/slime,
/datum/language/vampiric,
/datum/language/dwarf,
))
healing_factor = STANDARD_ORGAN_HEALING*5 //Fast!!
decay_factor = STANDARD_ORGAN_DECAY/2
@@ -71,12 +72,13 @@
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
M.UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/organ/tongue/Remove(mob/living/carbon/M, special = 0)
..()
if(say_mod && M.dna && M.dna.species)
M.dna.species.say_mod = initial(M.dna.species.say_mod)
UnregisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
M.RegisterSignal(M, COMSIG_MOB_SAY, /mob/living/carbon/.proc/handle_tongueless_speech)
/obj/item/organ/tongue/Remove(special = FALSE)
if(!QDELETED(owner))
if(say_mod && owner.dna?.species)
owner.dna.species.say_mod = initial(owner.dna.species.say_mod)
UnregisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
owner.RegisterSignal(owner, COMSIG_MOB_SAY, /mob/living/carbon/.proc/handle_tongueless_speech)
return ..()
/obj/item/organ/tongue/could_speak_in_language(datum/language/dt)
return is_type_in_typecache(dt, languages_possible)
@@ -145,7 +145,7 @@
/datum/uplink_item/explosives/tearstache
name = "Teachstache Grenade"
desc = "A teargas grenade that launches sticky moustaches onto the face of anyone not wearing a clown or mime mask. The moustaches will \
remain attached to the face of all targets for one minute, preventing the use of breath masks and other such devices."
remain attached to the face of all targets for two minutes, preventing the use of breath masks and other such devices."
item = /obj/item/grenade/chem_grenade/teargas/moustache
cost = 3
surplus = 0
@@ -224,3 +224,10 @@
cost = 5 //Low ammo, and deals same as 10mm but emp-able
item = /obj/item/gun/energy/emitter
restricted_roles = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
/datum/uplink_item/role_restricted/crushmagboots
name = "Crushing Magboots"
desc = "A pair of extra-strength magboots that crush anyone you walk over."
cost = 2
item = /obj/item/clothing/shoes/magboots/crushing
restricted_roles = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
+4
View File
@@ -237,6 +237,8 @@
return
//Actual escaping
B.release_specific_contents(src,TRUE) //we might as well take advantage of that specific belly's handling. Else we stay blinded forever.
message_admins("[src] used OOC escape to escape from [B.owner]'s belly.")
log_consent("[src] used OOC escape to escape from [B.owner]'s belly.")
src.stop_sound_channel(CHANNEL_PREYLOOP)
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "fedprey", /datum/mood_event/fedprey)
for(var/mob/living/simple_animal/SA in range(10))
@@ -255,6 +257,8 @@
return
//Actual escaping
belly.go_out(src) //Just force-ejects from the borg as if they'd clicked the eject button.
message_admins("[src] used OOC escape from a dogborg sleeper.")
log_consent("[src] used OOC escape from a dogborg sleeper.")
else
to_chat(src,"<span class='alert'>You aren't inside anyone, though, is the thing.</span>")
+8 -7
View File
@@ -27,13 +27,14 @@
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/organ/zombie_infection/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/zombie_infection/Remove(special = FALSE)
if(owner)
if(iszombie(owner) && old_species)
owner.set_species(old_species)
if(timer_id)
deltimer(timer_id)
. = ..()
STOP_PROCESSING(SSobj, src)
if(iszombie(M) && old_species)
M.set_species(old_species)
if(timer_id)
deltimer(timer_id)
STOP_PROCESSING(SSobj, src) //Required to be done after the parent call to avoid conflicts with organ decay.
/obj/item/organ/zombie_infection/on_find(mob/living/finder)
to_chat(finder, "<span class='warning'>Inside the head is a disgusting black \
@@ -44,7 +45,7 @@
if(!owner)
return
if(!(src in owner.internal_organs))
Remove(owner)
Remove()
if (causes_damage && !iszombie(owner) && owner.stat != DEAD)
owner.adjustToxLoss(1)
if (prob(10))