d k daunkey kaung

This commit is contained in:
SandPoot
2024-01-03 22:42:03 -03:00
parent cb2251ea37
commit 7eaef36e11
106 changed files with 1683 additions and 936 deletions

View File

@@ -59,7 +59,7 @@
H.update_inv_wear_suit()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == ITEM_SLOT_OCLOTHING) //we only give the mob the ability to activate the vest if he's actually wearing it.

View File

@@ -216,7 +216,7 @@
return
// Disable Powers: Masquerade * NOTE * This should happen as a FLAW!
//if (stat >= UNCONSCIOUS)
// for (var/datum/action/bloodsucker/masquerade/P in powers)
// for (var/datum/action/cooldown/bloodsucker/masquerade/P in powers)
// P.Deactivate()
// TEMP DEATH
var/total_brute = owner.current.getBruteLoss_nonProsthetic()
@@ -252,7 +252,7 @@
owner.current.update_sight()
owner.current.reload_fullscreen()
// Disable ALL Powers
for(var/datum/action/bloodsucker/power in powers)
for(var/datum/action/cooldown/bloodsucker/power in powers)
if(power.active && !power.can_use_in_torpor)
power.DeactivatePower()
if(owner.current.suiciding)

View File

@@ -1,22 +1,26 @@
/datum/action/bloodsucker
/datum/action/cooldown/bloodsucker
name = "Vampiric Gift"
desc = "A vampiric gift."
button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the BACKGROUND icon
background_icon_state = "vamp_power_off" //And this is the state for the background icon
var/background_icon_state_on = "vamp_power_on" // FULP: Our "ON" icon alternative.
var/background_icon_state_off = "vamp_power_off" // FULP: Our "OFF" icon alternative.
icon_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the ACTION icon
button_icon_state = "power_feed" //And this is the state for the action icon
buttontooltipstyle = "cult"
transparent_when_unavailable = TRUE
/// Cooldown you'll have to wait between each use, decreases depending on level.
cooldown_time = 2 SECONDS
///Background icon when the Power is active.
var/background_icon_state_on = "vamp_power_on"
///Background icon when the Power is NOT active.
var/background_icon_state_off = "vamp_power_off"
// Action-Related
//var/amPassive = FALSE // REMOVED: Just made it its own kind. // Am I just "on" at all times? (aka NO ICON)
var/amTargetted = FALSE // Am I asked to choose a target when enabled? (Shows as toggled ON when armed)
var/amToggle = FALSE // Can I be actively turned on and off?
var/amSingleUse = FALSE // Am I removed after a single use?
var/active = FALSE
var/cooldown = 20 // 10 ticks, 1 second.
var/cooldownUntil = 0 // From action.dm: next_use_time = world.time + cooldown_time
// Power-Related
var/level_current = 0 // Can increase to yield new abilities. Each power goes up in strength each Rank.
//var/level_max = 1 //
@@ -32,7 +36,7 @@
//var/not_bloodsucker = FALSE // This goes to Vassals or Hunters, but NOT bloodsuckers.
var/must_be_concious = TRUE //Can't use this ability while unconcious.
/datum/action/bloodsucker/New()
/datum/action/cooldown/bloodsucker/New()
if(bloodcost > 0)
desc += "<br><br><b>COST:</b> [bloodcost] Blood" // Modify description to add cost.
if(warn_constant_cost)
@@ -46,7 +50,7 @@
// click.dm <--- Where we can take over mouse clicks
// spells.dm /add_ranged_ability() <--- How we take over the mouse click to use a power on a target.
/datum/action/bloodsucker/Trigger()
/datum/action/cooldown/bloodsucker/Trigger()
// Active? DEACTIVATE AND END!
if(active && CheckCanDeactivate(TRUE))
DeactivatePower()
@@ -56,7 +60,7 @@
PayCost()
if(amToggle)
active = !active
UpdateButtonIcon()
UpdateButtons()
if(!amToggle || !active)
StartCooldown() // Must come AFTER UpdateButton(), otherwise icon will revert.
ActivatePower() // NOTE: ActivatePower() freezes this power in place until it ends.
@@ -65,13 +69,13 @@
if(amSingleUse)
RemoveAfterUse()
/datum/action/bloodsucker/proc/CheckCanPayCost(display_error)
/datum/action/cooldown/bloodsucker/proc/CheckCanPayCost(display_error)
if(!owner || !owner.mind)
return FALSE
// Cooldown?
if(cooldownUntil > world.time)
if(next_use_time > world.time)
if(display_error)
to_chat(owner, "[src] is unavailable. Wait [(cooldownUntil - world.time) / 10] seconds.")
to_chat(owner, "[src] is unavailable. Wait [(next_use_time - world.time) / 10] seconds.")
return FALSE
// Have enough blood?
var/mob/living/L = owner
@@ -81,7 +85,7 @@
return FALSE
return TRUE
/datum/action/bloodsucker/proc/CheckCanUse(display_error) // These checks can be scanned every frame while a ranged power is on.
/datum/action/cooldown/bloodsucker/proc/CheckCanUse(display_error) // These checks can be scanned every frame while a ranged power is on.
if(!owner || !owner.mind)
return FALSE
// Torpor?
@@ -123,79 +127,43 @@
return FALSE
return TRUE
/datum/action/bloodsucker/proc/StartCooldown()
set waitfor = FALSE
// Alpha Out
button.color = rgb(128,0,0,128)
button.alpha = 100
// Calculate Cooldown (by power's level)
var/this_cooldown = (cooldown_static || amSingleUse) ? cooldown : max(cooldown / 2, cooldown - (cooldown / 16 * (level_current-1)))
// NOTE: With this formula, you'll hit half cooldown at level 8 for that power.
// Wait for cooldown
cooldownUntil = world.time + this_cooldown
spawn(this_cooldown)
// Alpha In
button.color = rgb(255,255,255,255)
button.alpha = 255
/datum/action/bloodsucker/proc/CheckCanDeactivate(display_error)
/datum/action/cooldown/bloodsucker/proc/CheckCanDeactivate(display_error)
return TRUE
/datum/action/bloodsucker/UpdateButtonIcon(force = FALSE)
/datum/action/cooldown/bloodsucker/UpdateButton(atom/movable/screen/movable/action_button/button, force = FALSE)
background_icon_state = active? background_icon_state_on : background_icon_state_off
..()//UpdateButtonIcon()
..()//UpdateButton()
/datum/action/bloodsucker/proc/PayCost()
/datum/action/cooldown/bloodsucker/proc/PayCost()
// owner for actions is the mob, not mind.
var/mob/living/L = owner
L.blood_volume -= bloodcost
/datum/action/bloodsucker/proc/ActivatePower()
/datum/action/cooldown/bloodsucker/proc/ActivatePower()
/datum/action/bloodsucker/proc/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/bloodsucker/proc/DeactivatePower(mob/living/user = owner, mob/living/target)
active = FALSE
UpdateButtonIcon()
UpdateButtons()
StartCooldown()
/datum/action/bloodsucker/proc/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
/datum/action/cooldown/bloodsucker/proc/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
return active && user && (!warn_constant_cost || user.blood_volume > 0)
/datum/action/bloodsucker/proc/RemoveAfterUse()
/datum/action/cooldown/bloodsucker/proc/RemoveAfterUse()
// Un-Learn Me! (GO HOME
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (istype(bloodsuckerdatum))
bloodsuckerdatum.powers -= src
Remove(owner)
/datum/action/bloodsucker/proc/Upgrade()
/datum/action/cooldown/bloodsucker/proc/Upgrade()
level_current ++
/////////////////////////////////// PASSIVE POWERS ///////////////////////////////////
// New Type: Passive (Always on, no button)
/datum/action/bloodsucker/passive
/datum/action/bloodsucker/passive/New()
// REMOVED: DO NOTHBING!
..()
// Don't Display Button! (it doesn't do anything anyhow)
button.screen_loc = DEFAULT_BLOODSPELLS
button.moved = DEFAULT_BLOODSPELLS
button.ordered = FALSE
/datum/action/bloodsucker/passive/Destroy()
if(owner)
Remove(owner)
target = null
return ..()
/////////////////////////////////// TARGETTED POWERS ///////////////////////////////////
/datum/action/bloodsucker/targeted
/datum/action/cooldown/bloodsucker/targeted
// NOTE: All Targeted spells are Toggles! We just don't bother checking here.
var/target_range = 99
var/message_Trigger = "Select a target."
@@ -204,7 +172,7 @@
var/power_in_use = FALSE // Is this power LOCKED due to being used?
/datum/action/bloodsucker/targeted/New(Target)
/datum/action/cooldown/bloodsucker/targeted/New(Target)
desc += "<br>\[<i>Targeted Power</i>\]" // Modify description to add notice that this is aimed.
..()
// Create Proc Holder for intercepting clicks
@@ -212,7 +180,7 @@
bs_proc_holder.linked_power = src
// Click power: Begin Aim
/datum/action/bloodsucker/targeted/Trigger()
/datum/action/cooldown/bloodsucker/targeted/Trigger()
if(active && CheckCanDeactivate(TRUE))
DeactivateRangedAbility()
DeactivatePower()
@@ -220,7 +188,7 @@
if(!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
return
active = !active
UpdateButtonIcon()
UpdateButtons()
// Create & Link Targeting Proc
var/mob/living/L = owner
if(L.ranged_ability)
@@ -230,7 +198,7 @@
if(message_Trigger != "")
to_chat(owner, "<span class='announce'>[message_Trigger]</span>")
/datum/action/bloodsucker/targeted/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/targeted/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -238,21 +206,21 @@
return FALSE // doesn't let you remove powers if you're not there. So, let's just cancel the power entirely.
return TRUE
/datum/action/bloodsucker/targeted/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/bloodsucker/targeted/DeactivatePower(mob/living/user = owner, mob/living/target)
// Don't run ..(), we don't want to engage the cooldown until we USE this power!
active = FALSE
UpdateButtonIcon()
UpdateButtons()
/datum/action/bloodsucker/targeted/proc/DeactivateRangedAbility()
/datum/action/cooldown/bloodsucker/targeted/proc/DeactivateRangedAbility()
// Only Turned off when CLICK is disabled...aka, when you successfully clicked (or
bs_proc_holder.remove_ranged_ability()
// Check if target is VALID (wall, turf, or character?)
/datum/action/bloodsucker/targeted/proc/CheckValidTarget(atom/A)
/datum/action/cooldown/bloodsucker/targeted/proc/CheckValidTarget(atom/A)
return FALSE // FALSE targets nothing.
// Check if valid target meets conditions
/datum/action/bloodsucker/targeted/proc/CheckCanTarget(atom/A, display_error)
/datum/action/cooldown/bloodsucker/targeted/proc/CheckCanTarget(atom/A, display_error)
// Out of Range
if(!(A in view(target_range, owner)))
if(display_error && target_range > 1) // Only warn for range if it's greater than 1. Brawn doesn't need to announce itself.
@@ -261,7 +229,7 @@
return istype(A)
// Click Target
/datum/action/bloodsucker/targeted/proc/ClickWithPower(atom/A)
/datum/action/cooldown/bloodsucker/targeted/proc/ClickWithPower(atom/A)
// CANCEL RANGED TARGET check
if(power_in_use || !CheckValidTarget(A))
return FALSE
@@ -276,21 +244,21 @@
power_in_use = FALSE
return TRUE
/datum/action/bloodsucker/targeted/proc/FireTargetedPower(atom/A)
/datum/action/cooldown/bloodsucker/targeted/proc/FireTargetedPower(atom/A)
// Like ActivatePower, but specific to Targeted (and takes an atom input). We don't use ActivatePower for targeted.
/datum/action/bloodsucker/targeted/proc/PowerActivatedSuccessfully()
/datum/action/cooldown/bloodsucker/targeted/proc/PowerActivatedSuccessfully()
// The power went off! We now pay the cost of the power.
PayCost()
DeactivateRangedAbility()
DeactivatePower()
StartCooldown() // Do AFTER UpdateIcon() inside of DeactivatePower. Otherwise icon just gets wiped.
/datum/action/bloodsucker/targeted/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
/datum/action/cooldown/bloodsucker/targeted/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
return ..()
// Target Proc Holder
/obj/effect/proc_holder/bloodsucker
var/datum/action/bloodsucker/targeted/linked_power
var/datum/action/cooldown/bloodsucker/targeted/linked_power
/obj/effect/proc_holder/bloodsucker/remove_ranged_ability(msg)
..()

View File

@@ -55,8 +55,8 @@
bloodsuckerdatum.warn_sun_locker = FALSE
bloodsuckerdatum.warn_sun_burn = FALSE
// Remove Dawn Powers
for(var/datum/action/bloodsucker/P in bloodsuckerdatum.powers)
if(istype(P, /datum/action/bloodsucker/gohome))
for(var/datum/action/cooldown/bloodsucker/P in bloodsuckerdatum.powers)
if(istype(P, /datum/action/cooldown/bloodsucker/gohome))
bloodsuckerdatum.powers -= P
P.Remove(M.current)
nighttime_duration += 100 //Each day makes the night a minute longer.
@@ -149,5 +149,5 @@
if(!istype(M) || !istype(M.current))
continue
var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if(istype(bloodsuckerdatum) && bloodsuckerdatum.lair && !(locate(/datum/action/bloodsucker/gohome) in bloodsuckerdatum.powers))
bloodsuckerdatum.BuyPower(new /datum/action/bloodsucker/gohome)
if(istype(bloodsuckerdatum) && bloodsuckerdatum.lair && !(locate(/datum/action/cooldown/bloodsucker/gohome) in bloodsuckerdatum.powers))
bloodsuckerdatum.BuyPower(new /datum/action/cooldown/bloodsucker/gohome)

View File

@@ -14,7 +14,7 @@
dat += "<HR>"
// Step One: Decide powers you CAN buy.
for(var/pickedpower in typesof(/datum/action/bloodsucker))
for(var/pickedpower in typesof(/datum/action/cooldown/bloodsucker))
var/obj/effect/proc_holder/spell/bloodsucker/power = pickedpower
// NAME
dat += "<A href='byond://?src=[REF(src)];[module.mod_pick_name]=1'>[power.name]</A>"

View File

@@ -168,7 +168,7 @@
return fullname
/datum/antagonist/bloodsucker/proc/BuyPower(datum/action/bloodsucker/power)//(obj/effect/proc_holder/spell/power)
/datum/antagonist/bloodsucker/proc/BuyPower(datum/action/cooldown/bloodsucker/power)//(obj/effect/proc_holder/spell/power)
powers += power
power.Grant(owner.current)// owner.AddSpell(power)
@@ -177,9 +177,9 @@
add_hud()
update_hud(TRUE) // Set blood value, current rank
// Powers
BuyPower(new /datum/action/bloodsucker/feed)
BuyPower(new /datum/action/bloodsucker/masquerade)
BuyPower(new /datum/action/bloodsucker/veil)
BuyPower(new /datum/action/cooldown/bloodsucker/feed)
BuyPower(new /datum/action/cooldown/bloodsucker/masquerade)
BuyPower(new /datum/action/cooldown/bloodsucker/veil)
// Traits
for(var/T in defaultTraits)
ADD_TRAIT(owner.current, T, BLOODSUCKER_TRAIT)
@@ -221,7 +221,7 @@
remove_hud()
// Powers
while(powers.len)
var/datum/action/bloodsucker/power = pick(powers)
var/datum/action/cooldown/bloodsucker/power = pick(powers)
powers -= power
power.Remove(owner.current)
// owner.RemoveSpell(power)
@@ -267,7 +267,7 @@
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()
for(var/datum/action/bloodsucker/power in powers)
for(var/datum/action/cooldown/bloodsucker/power in powers)
power.level_current ++
/datum/antagonist/bloodsucker/proc/SpendRank()
@@ -281,8 +281,8 @@
//TODO: Make this into a radial, or perhaps a tgui next UI
// Purchase Power Prompt
var/list/options = list()
for(var/pickedpower in typesof(/datum/action/bloodsucker))
var/datum/action/bloodsucker/power = pickedpower
for(var/pickedpower in typesof(/datum/action/cooldown/bloodsucker))
var/datum/action/cooldown/bloodsucker/power = pickedpower
// If I don't own it, and I'm allowed to buy it.
if(!(locate(power) in powers) && initial(power.bloodsucker_can_buy))
options[initial(power.name)] = power // TESTING: After working with TGUI, it seems you can use initial() to view the variables inside a path?
@@ -303,7 +303,7 @@
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]
var/datum/action/cooldown/bloodsucker/P = options[choice]
AddBloodVolume(-level_bloodcost)
BuyPower(new P)
to_chat(owner.current, "<span class='notice'>You have used [level_bloodcost] units of blood and learned [initial(P.name)]!</span>")

View File

@@ -26,7 +26,7 @@
//owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer/hunter_edition)
// Give Hunter Power
var/datum/action/P = new /datum/action/bloodsucker/trackvamp
var/datum/action/P = new /datum/action/cooldown/bloodsucker/trackvamp
P.Grant(owner.current)
// Give Hunter Martial Arts
@@ -69,7 +69,7 @@
// Take Hunter Power
if (owner.current)
for (var/datum/action/bloodsucker/P in owner.current.actions)
for (var/datum/action/cooldown/bloodsucker/P in owner.current.actions)
P.Remove(owner.current)
// Take Hunter Martial Arts
@@ -166,7 +166,7 @@
/*
/datum/action/bloodsucker/trackvamp/
/datum/action/cooldown/bloodsucker/trackvamp/
name = "Track Monster"//"Cellular Emporium"
desc = "Take a moment to look for clues of any nearby monsters.<br>These creatures are slippery, and often look like the crew."
button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the BACKGROUND icon
@@ -177,7 +177,7 @@
cooldown = 300 // 10 ticks, 1 second.
bloodcost = 0
/datum/action/bloodsucker/trackvamp/ActivatePower()
/datum/action/cooldown/bloodsucker/trackvamp/ActivatePower()
var/mob/living/user = owner
to_chat(user, "<span class='notice'>You look around, scanning your environment and discerning signs of any filthy, wretched affronts to the natural order.</span>")
@@ -192,7 +192,7 @@
// NOTE: DON'T DEACTIVATE!
//DeactivatePower()
/datum/action/bloodsucker/trackvamp/proc/display_proximity()
/datum/action/cooldown/bloodsucker/trackvamp/proc/display_proximity()
// Pick target
var/turf/my_loc = get_turf(owner)
//var/list/mob/living/carbon/vamps = list()

View File

@@ -38,7 +38,7 @@
// Master Pinpointer
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer/vassal_edition)
// Powers
var/datum/action/bloodsucker/vassal/recuperate/new_Recuperate = new ()
var/datum/action/cooldown/bloodsucker/vassal/recuperate/new_Recuperate = new ()
new_Recuperate.Grant(owner.current)
powers += new_Recuperate
// Give Vassal Objective

View File

@@ -1,11 +1,11 @@
/datum/action/bloodsucker/targeted/brawn
/datum/action/cooldown/bloodsucker/targeted/brawn
name = "Brawn"
desc = "Snap restraints with ease, or deal terrible damage with your bare hands."
button_icon_state = "power_strength"
bloodcost = 10
cooldown = 90
cooldown_time = 90
target_range = 1
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -16,7 +16,7 @@
var/upgrade_canLocker = FALSE
var/upgrade_canDoor = FALSE
/datum/action/bloodsucker/targeted/brawn/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/targeted/brawn/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -38,10 +38,10 @@
// NOTE: We use . = FALSE so that we can break cuffs AND throw off our attacker in one use!
//return TRUE
/datum/action/bloodsucker/targeted/brawn/CheckValidTarget(atom/A)
/datum/action/cooldown/bloodsucker/targeted/brawn/CheckValidTarget(atom/A)
return isliving(A) || istype(A, /obj/machinery/door)
/datum/action/bloodsucker/targeted/brawn/CheckCanTarget(atom/A, display_error)
/datum/action/cooldown/bloodsucker/targeted/brawn/CheckCanTarget(atom/A, display_error)
// DEFAULT CHECKS (Distance)
if(!..()) // Disable range notice for Brawn.
return FALSE
@@ -59,7 +59,7 @@
return TRUE
return ..() // yes, FALSE! You failed if you got here! BAD TARGET
/datum/action/bloodsucker/targeted/brawn/FireTargetedPower(atom/A)
/datum/action/cooldown/bloodsucker/targeted/brawn/FireTargetedPower(atom/A)
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
var/mob/living/carbon/target = A
var/mob/living/user = owner
@@ -97,7 +97,7 @@
D.open(2) // open(2) is like a crowbar or jaws of life.
// Target Type: Closet
/datum/action/bloodsucker/targeted/brawn/proc/CheckBreakRestraints()
/datum/action/cooldown/bloodsucker/targeted/brawn/proc/CheckBreakRestraints()
if(!iscarbon(owner)) // || !owner.restrained()
return FALSE
// (NOTE: Just like biodegrade.dm, we only remove one thing per use //
@@ -131,7 +131,7 @@
return TRUE
return FALSE
/datum/action/bloodsucker/targeted/brawn/proc/CheckEscapePuller()
/datum/action/cooldown/bloodsucker/targeted/brawn/proc/CheckEscapePuller()
if(!owner.pulledby)// || owner.pulledby.grab_state <= GRAB_PASSIVE)
return FALSE
var/mob/M = owner.pulledby
@@ -153,7 +153,7 @@
owner.pulledby = null // It's already done, but JUST IN CASE.
return TRUE
/* Doesnt work
/datum/action/bloodsucker/targeted/brawn/proc/CheckBreakLocker()
/datum/action/cooldown/bloodsucker/targeted/brawn/proc/CheckBreakLocker()
if(!istype(owner.loc, /obj/structure/closet))
return FALSE
playsound(get_turf(owner), 'sound/machines/airlock_alien_prying.ogg', 40, 1, -1)

View File

@@ -1,11 +1,11 @@
/datum/action/bloodsucker/cloak
/datum/action/cooldown/bloodsucker/cloak
name = "Cloak of Darkness"
desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas, and you cannot dissapear while mortals watch you."
button_icon_state = "power_cloak"
bloodcost = 5
cooldown = 50
cooldown_time = 50
bloodsucker_can_buy = TRUE
amToggle = TRUE
warn_constant_cost = TRUE
@@ -14,7 +14,7 @@
var/walk_threshold = 0.4 // arbitrary number, to be changed. edit in last commit: this is fine after testing on box station for a bit
var/lum
/datum/action/bloodsucker/cloak/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/cloak/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -24,7 +24,7 @@
return FALSE
return TRUE
/datum/action/bloodsucker/cloak/ActivatePower()
/datum/action/cooldown/bloodsucker/cloak/ActivatePower()
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
var/mob/living/user = owner
@@ -52,7 +52,7 @@
sleep(5) // Check every few ticks
/datum/action/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target)
/datum/action/cooldown/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target)
if (!..())
return FALSE
if(user.stat == !CONSCIOUS) // Must be CONSCIOUS
@@ -60,7 +60,7 @@
return FALSE
return TRUE
/datum/action/bloodsucker/cloak/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/bloodsucker/cloak/DeactivatePower(mob/living/user = owner, mob/living/target)
..()
REMOVE_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
user.alpha = 255

View File

@@ -1,12 +1,12 @@
/datum/action/bloodsucker/feed
/datum/action/cooldown/bloodsucker/feed
name = "Feed"
desc = "Draw the heartsblood of living victims in your grasp.<br><b>None/Passive:</b> Feed silently and unnoticed by your victim.<br><b>Aggressive: </b>Subdue your target quickly."
button_icon_state = "power_feed"
bloodcost = 0
cooldown = 30
cooldown_time = 30
amToggle = TRUE
bloodsucker_can_buy = TRUE
can_be_staked = TRUE
@@ -16,7 +16,7 @@
var/mob/living/feed_target // So we can validate more than just the guy we're grappling.
var/target_grappled = FALSE // If you started grappled, then ending it will end your Feed.
/datum/action/bloodsucker/feed/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/feed/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -33,7 +33,7 @@
// DONE!
return TRUE
/datum/action/bloodsucker/feed/proc/ValidateTarget(mob/living/target, display_error) // Called twice: validating a subtle victim, or validating your grapple victim.
/datum/action/cooldown/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)
// 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.
@@ -76,7 +76,7 @@
return TRUE
// If I'm not grabbing someone, find me someone nearby.
/datum/action/bloodsucker/feed/proc/FindMyTarget(display_error)
/datum/action/cooldown/bloodsucker/feed/proc/FindMyTarget(display_error)
// Default
feed_target = null
target_grappled = FALSE
@@ -132,7 +132,7 @@
feed_target = pick(targets_valid)//targets[1]
return TRUE
/datum/action/bloodsucker/feed/ActivatePower()
/datum/action/cooldown/bloodsucker/feed/ActivatePower()
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up Activate(), so Deactivate() can happen after.
var/mob/living/target = feed_target // Stored during CheckCanUse(). Can be a grabbed OR adjecent character.
var/mob/living/user = owner
@@ -302,16 +302,16 @@
CheckKilledTarget(user,target)
/datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
/datum/action/cooldown/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
// Bad Bloodsucker. You shouldn't do that.
if(target && target.stat >= DEAD && ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankkilled", /datum/mood_event/drankkilled) // BAD // in bloodsucker_life.dm
/datum/action/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target)
/datum/action/cooldown/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target)
return ..() && target && (!target_grappled || user.pulling == target) && blood_sucking_checks(target, TRUE, TRUE) // Active, and still antag,
// NOTE: We only care about pulling if target started off that way. Mostly only important for Aggressive feed.
/datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target)
/datum/action/cooldown/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))
target.Unconscious(50,0)
@@ -320,7 +320,7 @@
if(ishuman(target))
target.adjustStaminaLoss(5, forced = TRUE)// Base Stamina Damage
/datum/action/bloodsucker/feed/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/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

View File

@@ -2,12 +2,12 @@
/datum/action/bloodsucker/fortitude
/datum/action/cooldown/bloodsucker/fortitude
name = "Fortitude"
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 = 30
cooldown = 80
cooldown_time = 80
bloodsucker_can_buy = TRUE
amToggle = TRUE
warn_constant_cost = TRUE
@@ -15,7 +15,7 @@
var/fortitude_resist // So we can raise and lower your brute resist based on what your level_current WAS.
/datum/action/bloodsucker/fortitude/ActivatePower()
/datum/action/cooldown/bloodsucker/fortitude/ActivatePower()
var/datum/antagonist/bloodsucker/B = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
var/mob/living/user = owner
to_chat(user, "<span class='notice'>Your flesh, skin, and muscles become as steel.</span>")
@@ -47,8 +47,8 @@
B.AddBloodVolume(-0.5)
sleep(20) // Check every few ticks that we haven't disabled this power
// Return to Running (if you were before)
/datum/action/bloodsucker/fortitude/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/bloodsucker/fortitude/DeactivatePower(mob/living/user = owner, mob/living/target)
..()
// Restore Traits & Effects
REMOVE_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude")

View File

@@ -1,6 +1,6 @@
/datum/action/bloodsucker/gohome
/datum/action/cooldown/bloodsucker/gohome
name = "Vanishing Act"
desc = "As dawn aproaches, disperse into mist and return directly to your Lair.<br><b>WARNING:</b> You will drop <b>ALL</b> of your possessions if observed by mortals."
button_icon_state = "power_gohome"
@@ -8,7 +8,7 @@
background_icon_state_off = "vamp_power_off_oneshot"
bloodcost = 100
cooldown = 99999 // It'll never come back.
cooldown_time = 99999 // It'll never come back.
amToggle = FALSE
amSingleUse = TRUE
@@ -18,7 +18,7 @@
can_be_immobilized = TRUE
must_be_concious = FALSE
/datum/action/bloodsucker/gohome/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/gohome/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -30,12 +30,12 @@
return FALSE
return TRUE
/datum/action/bloodsucker/gohome/proc/flicker_lights(var/flicker_range, var/beat_volume)
/datum/action/cooldown/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()
/datum/action/cooldown/bloodsucker/gohome/ActivatePower()
var/mob/living/carbon/user = owner
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
// IMPORTANT: Check for lair at every step! It might get destroyed.

View File

@@ -3,12 +3,12 @@
// Level 2: Dodge Bullets
// Level 3: Stun People Passed
/datum/action/bloodsucker/targeted/haste
/datum/action/cooldown/bloodsucker/targeted/haste
name = "Immortal Haste"
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 = 120
cooldown_time = 120
target_range = 15
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -18,7 +18,7 @@
/// If set, uses this speed in deciseconds instead of world.tick_lag
var/speed_override
/datum/action/bloodsucker/targeted/haste/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/targeted/haste/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -33,10 +33,10 @@
return FALSE
return TRUE
/datum/action/bloodsucker/targeted/haste/CheckValidTarget(atom/A)
/datum/action/cooldown/bloodsucker/targeted/haste/CheckValidTarget(atom/A)
return isturf(A) || A.loc != owner.loc // Anything will do, if it's not me or my square
/datum/action/bloodsucker/targeted/haste/CheckCanTarget(atom/A, display_error)
/datum/action/cooldown/bloodsucker/targeted/haste/CheckCanTarget(atom/A, display_error)
// DEFAULT CHECKS (Distance)
if (!..())
return FALSE
@@ -45,7 +45,7 @@
// return FALSE
return TRUE
/datum/action/bloodsucker/targeted/haste/FireTargetedPower(atom/A)
/datum/action/cooldown/bloodsucker/targeted/haste/FireTargetedPower(atom/A)
// This is a non-async proc to make sure the power is "locked" until this finishes.
hit = list()
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/on_move)
@@ -78,11 +78,11 @@
hit = null
user.update_mobility()
/datum/action/bloodsucker/targeted/haste/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/bloodsucker/targeted/haste/DeactivatePower(mob/living/user = owner, mob/living/target)
..() // activate = FALSE
user.update_mobility()
/datum/action/bloodsucker/targeted/haste/proc/on_move()
/datum/action/cooldown/bloodsucker/targeted/haste/proc/on_move()
for(var/mob/living/L in dview(1, get_turf(owner)))
if(!hit[L] && (L != owner))
hit[L] = TRUE

View File

@@ -1,25 +1,25 @@
/datum/action/bloodsucker/lunge
/datum/action/cooldown/bloodsucker/lunge
name = "Predatory Lunge"
desc = "Prepare the strenght to grapple your prey."
button_icon_state = "power_lunge"
bloodcost = 10
cooldown = 30
cooldown_time = 30
bloodsucker_can_buy = TRUE
warn_constant_cost = TRUE
amToggle = TRUE
var/leap_skill_mod = 5
/datum/action/bloodsucker/lunge/New()
/datum/action/cooldown/bloodsucker/lunge/New()
. = ..()
/datum/action/bloodsucker/lunge/Destroy()
/datum/action/cooldown/bloodsucker/lunge/Destroy()
. = ..()
UnregisterSignal(owner, COMSIG_CARBON_TACKLED)
/datum/action/bloodsucker/lunge/ActivatePower()
/datum/action/cooldown/bloodsucker/lunge/ActivatePower()
var/mob/living/carbon/user = owner
var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
var/datum/component/tackler/T = user.LoadComponent(/datum/component/tackler)
@@ -37,10 +37,10 @@
sleep(5)
//Without this, the leap component would get removed too early, causing the normal crash into effects.
/datum/action/bloodsucker/lunge/proc/DelayedDeactivatePower()
/datum/action/cooldown/bloodsucker/lunge/proc/DelayedDeactivatePower()
addtimer(CALLBACK(src, .proc/DeactivatePower), 1 SECONDS, TIMER_UNIQUE)
/datum/action/bloodsucker/lunge/DeactivatePower(mob/living/user = owner)
/datum/action/cooldown/bloodsucker/lunge/DeactivatePower(mob/living/user = owner)
. = ..()
qdel(user.GetComponent(/datum/component/tackler))
UnregisterSignal(user, COMSIG_CARBON_TACKLED)

View File

@@ -16,12 +16,12 @@
// -
/datum/action/bloodsucker/masquerade
/datum/action/cooldown/bloodsucker/masquerade
name = "Masquerade"
desc = "Feign the vital signs of a mortal, and escape both casual and medical notice as the monster you truly are."
button_icon_state = "power_human"
bloodcost = 10
cooldown = 50
cooldown_time = 50
amToggle = TRUE
bloodsucker_can_buy = TRUE
warn_constant_cost = TRUE
@@ -31,7 +31,7 @@
// NOTE: Firing off vulgar powers disables your Masquerade!
/*/datum/action/bloodsucker/masquerade/CheckCanUse(display_error)
/*/datum/action/cooldown/bloodsucker/masquerade/CheckCanUse(display_error)
if(!..(display_error))// DEFAULT CHECKS
return FALSE
// DONE!
@@ -39,7 +39,7 @@
*/
/datum/action/bloodsucker/masquerade/ActivatePower()
/datum/action/cooldown/bloodsucker/masquerade/ActivatePower()
var/mob/living/user = owner
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
@@ -78,14 +78,14 @@
sleep(20) // Check every few ticks that we haven't disabled this power
/datum/action/bloodsucker/masquerade/ContinueActive(mob/living/user)
/datum/action/cooldown/bloodsucker/masquerade/ContinueActive(mob/living/user)
// Disable if unable to use power anymore.
//if (user.stat == DEAD || user.blood_volume <= 0) // not conscious or soft critor uncon, just dead
// return FALSE
return ..() // Active, and still Antag
/datum/action/bloodsucker/masquerade/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/bloodsucker/masquerade/DeactivatePower(mob/living/user = owner, mob/living/target)
..() // activate = FALSE
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)

View File

@@ -5,12 +5,12 @@
// FOLLOW: Target follows you, spouting random phrases from their history (or maybe Polly's or NPC's vocab?)
// ATTACK: Target finds a nearby non-Bloodsucker victim to attack.
/datum/action/bloodsucker/targeted/mesmerize
/datum/action/cooldown/bloodsucker/targeted/mesmerize
name = "Mesmerize"
desc = "Dominate the mind of a mortal who can see your eyes."
button_icon_state = "power_mez"
bloodcost = 30
cooldown = 300
cooldown_time = 300
target_range = 2
power_activates_immediately = TRUE
message_Trigger = "Whom will you subvert to your will?"
@@ -18,7 +18,7 @@
bloodsucker_can_buy = TRUE
var/success
/datum/action/bloodsucker/targeted/mesmerize/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/targeted/mesmerize/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -34,10 +34,10 @@
return FALSE
return TRUE
/datum/action/bloodsucker/targeted/mesmerize/CheckValidTarget(atom/A)
/datum/action/cooldown/bloodsucker/targeted/mesmerize/CheckValidTarget(atom/A)
return iscarbon(A)
/datum/action/bloodsucker/targeted/mesmerize/CheckCanTarget(atom/A,display_error)
/datum/action/cooldown/bloodsucker/targeted/mesmerize/CheckCanTarget(atom/A,display_error)
// Check: Self
if(A == owner)
return FALSE
@@ -88,7 +88,7 @@
return FALSE
return TRUE
/datum/action/bloodsucker/targeted/mesmerize/proc/ContinueTarget(atom/A)
/datum/action/cooldown/bloodsucker/targeted/mesmerize/proc/ContinueTarget(atom/A)
var/mob/living/carbon/target = A
var/mob/living/L = owner
@@ -103,7 +103,7 @@
to_chat(L, "<span class='warning'>[target] has escaped your gaze!</span>")
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
/datum/action/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A)
/datum/action/cooldown/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A)
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
var/mob/living/carbon/target = A
var/mob/living/L = owner
@@ -118,7 +118,7 @@
// 5 second windup
addtimer(CALLBACK(src, .proc/apply_effects, L, target, power_time), 6 SECONDS)
/datum/action/bloodsucker/targeted/mesmerize/proc/apply_effects(aggressor, victim, power_time)
/datum/action/cooldown/bloodsucker/targeted/mesmerize/proc/apply_effects(aggressor, victim, power_time)
var/mob/living/carbon/target = victim
var/mob/living/L = aggressor
if(!success)
@@ -135,5 +135,5 @@
to_chat(L, "<span class='warning'>[target] has snapped out of their trance.</span>")
/datum/action/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target)
/datum/action/cooldown/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target)
return ..() && CheckCanUse() && CheckCanTarget(target)

View File

@@ -1,12 +1,12 @@
/datum/action/bloodsucker/vassal/recuperate
/datum/action/cooldown/bloodsucker/vassal/recuperate
name = "Sanguine Recuperation"
desc = "Slowly heal brute damage while active. This process is exhausting, and requires some of your tainted blood."
button_icon_state = "power_recup"
amToggle = TRUE
bloodcost = 5
cooldown = 100
cooldown_time = 100
/datum/action/bloodsucker/vassal/recuperate/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/vassal/recuperate/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -14,7 +14,7 @@
return FALSE
return TRUE
/datum/action/bloodsucker/vassal/recuperate/ActivatePower()
/datum/action/cooldown/bloodsucker/vassal/recuperate/ActivatePower()
to_chat(owner, "<span class='notice'>Your muscles clench and your skin crawls as your master's immortal blood knits your wounds and gives you stamina.</span>")
var/mob/living/carbon/C = owner
var/mob/living/carbon/human/H
@@ -35,5 +35,5 @@
// DONE!
//DeactivatePower(owner)
/datum/action/bloodsucker/vassal/recuperate/ContinueActive(mob/living/user, mob/living/target)
/datum/action/cooldown/bloodsucker/vassal/recuperate/ContinueActive(mob/living/user, mob/living/target)
return ..() && user.stat <= DEAD && user.blood_volume > 500

View File

@@ -1,12 +1,12 @@
/datum/action/bloodsucker/targeted/trespass
/datum/action/cooldown/bloodsucker/targeted/trespass
name = "Trespass"
desc = "Become mist and advance two tiles in one direction, ignoring all obstacles except for walls. Useful for skipping past doors and barricades."
button_icon_state = "power_tres"
bloodcost = 10
cooldown = 80
cooldown_time = 80
amToggle = FALSE
//target_range = 2
@@ -16,7 +16,7 @@
var/turf/target_turf // We need to decide where we're going based on where we clicked. It's not actually the tile we clicked.
/datum/action/bloodsucker/targeted/trespass/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/targeted/trespass/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -26,7 +26,7 @@
return TRUE
/datum/action/bloodsucker/targeted/trespass/CheckValidTarget(atom/A)
/datum/action/cooldown/bloodsucker/targeted/trespass/CheckValidTarget(atom/A)
// Can't target my tile
if(A == get_turf(owner) || get_turf(A) == get_turf(owner))
return FALSE
@@ -34,7 +34,7 @@
return TRUE // All we care about is destination. Anything you click is fine.
/datum/action/bloodsucker/targeted/trespass/CheckCanTarget(atom/A, display_error)
/datum/action/cooldown/bloodsucker/targeted/trespass/CheckCanTarget(atom/A, display_error)
// NOTE: Do NOT use ..()! We don't want to check distance or anything.
// Get clicked tile
@@ -60,7 +60,7 @@
return TRUE
/datum/action/bloodsucker/targeted/trespass/FireTargetedPower(atom/A)
/datum/action/cooldown/bloodsucker/targeted/trespass/FireTargetedPower(atom/A)
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
// Find target turf, at or below Atom
@@ -87,7 +87,7 @@
user.invisibility = INVISIBILITY_MAXIMUM
// LOSE CUFFS
// Wait...
sleep(mist_delay / 2)

View File

@@ -1,10 +1,10 @@
/datum/action/bloodsucker/veil
/datum/action/cooldown/bloodsucker/veil
name = "Veil of Many Faces"
desc = "Disguise yourself in the illusion of another identity."
button_icon_state = "power_veil"
bloodcost = 15
cooldown = 100
cooldown_time = 100
amToggle = TRUE
bloodsucker_can_buy = TRUE
warn_constant_cost = TRUE
@@ -29,7 +29,7 @@
var/list/prev_features // For lizards and such
/datum/action/bloodsucker/veil/CheckCanUse(display_error)
/datum/action/cooldown/bloodsucker/veil/CheckCanUse(display_error)
. = ..()
if(!.)
return
@@ -37,7 +37,7 @@
return TRUE
/datum/action/bloodsucker/veil/ActivatePower()
/datum/action/cooldown/bloodsucker/veil/ActivatePower()
cast_effect() // POOF
@@ -47,14 +47,14 @@
Disguise_FaceName()
/datum/action/bloodsucker/veil/proc/Disguise_Outfit()
/datum/action/cooldown/bloodsucker/veil/proc/Disguise_Outfit()
// Step One: Back up original items
/datum/action/bloodsucker/veil/proc/Disguise_FaceName()
/datum/action/cooldown/bloodsucker/veil/proc/Disguise_FaceName()
// Change Name/Voice
var/mob/living/carbon/human/H = owner
@@ -112,7 +112,7 @@
sleep(50)
/datum/action/bloodsucker/veil/DeactivatePower(mob/living/user = owner, mob/living/target)
/datum/action/cooldown/bloodsucker/veil/DeactivatePower(mob/living/user = owner, mob/living/target)
..()
if (ishuman(user))
var/mob/living/carbon/human/H = user
@@ -149,7 +149,7 @@
cast_effect() // POOF
// CAST EFFECT // // General effect (poof, splat, etc) when you cast. Doesn't happen automatically!
/datum/action/bloodsucker/veil/proc/cast_effect()
/datum/action/cooldown/bloodsucker/veil/proc/cast_effect()
// Effect
playsound(get_turf(owner), 'sound/magic/smoke.ogg', 20, 1)
var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/()

View File

@@ -80,7 +80,6 @@
/datum/action/innate/cellular_emporium/New(our_target)
. = ..()
button.name = name
if(istype(our_target, /datum/cellular_emporium))
cellular_emporium = our_target
else

View File

@@ -44,7 +44,7 @@
name = "Reviving Stasis"
desc = "We fall into a stasis, allowing us to regenerate and trick our enemies. Costs 15 chemicals."
button_icon_state = "fake_death"
UpdateButtonIcon()
UpdateButtons()
chemical_cost = 15
to_chat(user, "<span class='notice'>We have revived ourselves.</span>")
@@ -56,7 +56,7 @@
name = "Revive"
desc = "We arise once more."
button_icon_state = "revive"
UpdateButtonIcon()
UpdateButtons()
chemical_cost = 0
revive_ready = TRUE

View File

@@ -411,6 +411,6 @@
Q.name = "[quickbind_slot.name] ([Q.scripture_index])"
Q.desc = quickbind_slot.quickbind_desc
Q.button_icon_state = quickbind_slot.name
Q.UpdateButtonIcon()
Q.UpdateButtons()
if(isliving(loc))
Q.Grant(loc)

View File

@@ -2,16 +2,11 @@
name = "Prepare Blood Magic"
button_icon_state = "carve"
desc = "Prepare blood magic by carving runes into your flesh. This rite is most effective with an <b>empowering rune</b>"
default_button_position = DEFAULT_BLOODSPELLS
var/list/spells = list()
var/channeling = FALSE
var/holy_dispel = FALSE
/datum/action/innate/cult/blood_magic/Grant()
..()
button.screen_loc = DEFAULT_BLOODSPELLS
button.moved = DEFAULT_BLOODSPELLS
button.ordered = FALSE
/datum/action/innate/cult/blood_magic/Remove()
for(var/X in spells)
qdel(X)
@@ -23,15 +18,21 @@
return ..()
/datum/action/innate/cult/blood_magic/proc/Positioning()
var/list/screen_loc_split = splittext(button.screen_loc,",")
var/list/screen_loc_X = splittext(screen_loc_split[1],":")
var/list/screen_loc_Y = splittext(screen_loc_split[2],":")
var/pix_X = text2num(screen_loc_X[2])
for(var/datum/action/innate/cult/blood_spell/B in spells)
if(B.button.locked)
var/order = pix_X+spells.Find(B)*31
B.button.screen_loc = "[screen_loc_X[1]]:[order],[screen_loc_Y[1]]:[screen_loc_Y[2]]"
B.button.moved = B.button.screen_loc
for(var/datum/hud/hud as anything in viewers)
var/our_view = hud.mymob?.client?.view || "15x15"
var/atom/movable/screen/movable/action_button/button = viewers[hud]
var/position = screen_loc_to_offset(button.screen_loc)
var/spells_iterated = 0
for(var/datum/action/innate/cult/blood_spell/blood_spell in spells)
spells_iterated += 1
if(blood_spell.positioned)
continue
var/atom/movable/screen/movable/action_button/moving_button = blood_spell.viewers[hud]
if(!moving_button)
continue
var/our_x = position[1] + spells_iterated * world.icon_size // Offset any new buttons into our list
hud.position_action(moving_button, offset_to_screen_loc(our_x, position[2], our_view))
blood_spell.positioned = TRUE
/datum/action/innate/cult/blood_magic/Activate()
if(holy_dispel)
@@ -99,6 +100,8 @@
var/base_desc //To allow for updating tooltips
var/invocation
var/health_cost = 0
/// Have we already been positioned into our starting location?
var/positioned = FALSE
/datum/action/innate/cult/blood_spell/Grant(mob/living/owner, datum/action/innate/cult/blood_magic/BM)
if(health_cost)
@@ -106,9 +109,7 @@
base_desc = desc
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
all_magic = BM
..()
button.locked = TRUE
button.ordered = FALSE
return ..()
/datum/action/innate/cult/blood_spell/Remove()
if(all_magic)
@@ -273,7 +274,7 @@
attached_action.charges--
attached_action.desc = attached_action.base_desc
attached_action.desc += "<br><b><u>Has [attached_action.charges] use\s remaining</u></b>."
attached_action.UpdateButtonIcon()
attached_action.UpdateButtons()
if(attached_action.charges <= 0)
remove_ranged_ability("<span class='cult'>You have exhausted the spell's power!</span>")
qdel(src)
@@ -325,7 +326,7 @@
qdel(src)
desc = base_desc
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
UpdateButtonIcon()
UpdateButtons()
/datum/action/innate/cult/blood_spell/manipulation
name = "Blood Rites"
@@ -373,7 +374,7 @@
source.charges = uses
source.desc = source.base_desc
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
source.UpdateButtonIcon()
source.UpdateButtons()
..()
/obj/item/melee/blood_magic/attack_self(mob/living/user)
@@ -400,7 +401,7 @@
else if(source)
source.desc = source.base_desc
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
source.UpdateButtonIcon()
source.UpdateButtons()
//Stun
/obj/item/melee/blood_magic/stun

View File

@@ -795,14 +795,13 @@
desc = "Call the blood spear back to your hand!"
background_icon_state = "bg_demon"
button_icon_state = "bloodspear"
default_button_position = "6:157,4:-2"
var/obj/item/cult_spear/spear
var/cooldown = 0
/datum/action/innate/cult/spear/Grant(mob/user, obj/blood_spear)
. = ..()
spear = blood_spear
button.screen_loc = "6:157,4:-2"
button.moved = "6:157,4:-2"
/datum/action/innate/cult/spear/Activate()
if(owner == spear.loc || cooldown > world.time)

View File

@@ -176,7 +176,7 @@
user.reveal(reveal)
user.stun(stun)
if(action)
action.UpdateButtonIcon()
action.UpdateButtons()
return TRUE
//Overload Light: Breaks a light that's online and sends out lightning bolts to all nearby people.

View File

@@ -33,9 +33,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/New()
..()
if(uses > 1)
desc = "[desc] It has [uses] use\s remaining."
button.desc = desc
desc = "[desc] It has [uses] use\s remaining."
/datum/action/innate/ai/Grant(mob/living/L)
. = ..()
@@ -63,7 +61,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
if(!silent)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
desc = "[initial(desc)] It has [uses] use\s remaining."
UpdateButtonIcon()
UpdateButtons()
return
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
@@ -92,7 +90,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
if(!silent)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
desc = "[initial(desc)] It has [uses] use\s remaining."
UpdateButtonIcon()
UpdateButtons()
return
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
@@ -203,7 +201,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
else //Adding uses to an existing module
action.uses += initial(action.uses)
action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining."
action.UpdateButtonIcon()
action.UpdateButtons()
temp = "Additional use[action.uses > 1 ? "s" : ""] added to [action.name]!"
processing_time -= AM.cost
@@ -759,6 +757,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
uses = 3
auto_use_uses = FALSE
/datum/action/innate/ai/blackout/New()
..()
desc = "[desc] It has [uses] use\s remaining."
/datum/action/innate/ai/blackout/Activate()
for(var/obj/machinery/power/apc/apc in GLOB.apcs_list)
if(prob(30 * apc.overload))
@@ -768,7 +770,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
to_chat(owner, "<span class='notice'>Overcurrent applied to the powernet.</span>")
owner.playsound_local(owner, "sparks", 50, 0)
adjust_uses(-1)
if(QDELETED(src) || uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
return
desc = "[initial(desc)] It has [uses] use\s remaining."
UpdateButtons()
//Disable Emergency Lights
/datum/AI_Module/small/emergency_lights
@@ -816,6 +821,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
auto_use_uses = FALSE
cooldown_period = 30
/datum/action/innate/ai/reactivate_cameras/New()
..()
desc = "[desc] It has [uses] use\s remaining."
/datum/action/innate/ai/reactivate_cameras/Activate()
var/fixed_cameras = 0
for(var/V in GLOB.cameranet.cameras)
@@ -830,7 +839,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
to_chat(owner, "<span class='notice'>Diagnostic complete! Cameras reactivated: <b>[fixed_cameras]</b>. Reactivations remaining: <b>[uses]</b>.</span>")
owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0)
adjust_uses(0, TRUE) //Checks the uses remaining
if(QDELETED(src) || !uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
return
desc = "[initial(desc)] It has [uses] use\s remaining."
UpdateButtons()
//Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision.
/datum/AI_Module/large/upgrade_cameras

View File

@@ -134,16 +134,19 @@
var/obj/item/active_mousedown_item = null
///Used in MouseDrag to preserve the original mouse click parameters
var/mouseParams = ""
///Used in MouseDrag to preserve the last mouse-entered location.
var/mouseLocation = null
///Used in MouseDrag to preserve the last mouse-entered object.
var/mouseObject = null
var/mouseControlObject = null
///Used in MouseDrag to preserve the last mouse-entered location. Weakref
var/datum/weakref/mouse_location_ref = null
///Used in MouseDrag to preserve the last mouse-entered object. Weakref
var/datum/weakref/mouse_object_ref
//Middle-mouse-button click dragtime control for aimbot exploit detection.
var/middragtime = 0
//Middle-mouse-button clicked object control for aimbot exploit detection. Weakref
var/datum/weakref/middle_drag_atom_ref
/// Messages currently seen by this client
var/list/seen_messages
/// viewsize datum for holding our view size
var/datum/viewData/view_size
var/datum/view_data/view_size
/// our current tab
var/stat_tab

View File

@@ -881,11 +881,16 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
click_intercept_time = 0 //Reset and return. Next click should work, but not this one.
return
click_intercept_time = 0 //Just reset. Let's not keep re-checking forever.
var/list/L = params2list(params)
var/ab = FALSE
var/list/modifiers = params2list(params)
if(L["drag"])
var/dragged = LAZYACCESS(modifiers, DRAG)
if(dragged && !LAZYACCESS(modifiers, dragged)) //I don't know what's going on here, but I don't trust it
return
if (object && IS_WEAKREF_OF(object, middle_drag_atom_ref) && LAZYACCESS(modifiers, LEFT_CLICK))
ab = max(0, 5 SECONDS-(world.time-middragtime)*0.1)
var/mcl = CONFIG_GET(number/minute_click_limit)
if (!holder && !ignore_spam && mcl)
var/minute = round(world.time, 600)
@@ -901,6 +906,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
clicklimiter[ADMINSWARNED_AT] = minute
msg += " Administrators have been informed."
if (ab)
log_game("[key_name(src)] is using the middle click aimbot exploit")
message_admins("[ADMIN_LOOKUPFLW(usr)] [ADMIN_KICK(usr)] is using the middle click aimbot exploit</span>")
log_click(object, location, control, params, src, "lockout (spam - minute)", TRUE)
log_game("[key_name(src)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
@@ -929,6 +937,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
// so that the visual focus indicator matches reality.
winset(src, null, "input.background-color=[COLOR_INPUT_DISABLED]")
else
winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]")
SEND_SIGNAL(src, COMSIG_CLIENT_CLICK, object, location, control, params, usr)
..()
/client/proc/add_verbs_from_config()

View File

@@ -65,7 +65,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/screentip_pref = SCREENTIP_PREFERENCE_ENABLED
var/screentip_color = "#ffd391"
var/screentip_images = TRUE
var/buttons_locked = FALSE
var/hotkeys = FALSE
///Runechat preference. If true, certain messages will be displayed on the map, not ust on the chat area. Boolean.
@@ -1070,8 +1069,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Runechat message char limit:</b> <a href='?_src_=prefs;preference=max_chat_length;task=input'>[max_chat_length]</a><br>"
dat += "<b>See Runechat for non-mobs:</b> <a href='?_src_=prefs;preference=see_chat_non_mob'>[see_chat_non_mob ? "Enabled" : "Disabled"]</a><br>"
dat += "<br>"
dat += "<b>Action Buttons:</b> <a href='?_src_=prefs;preference=action_buttons'>[(buttons_locked) ? "Locked In Place" : "Unlocked"]</a><br>"
dat += "<br>"
dat += "<b>PDA Color:</b> <span style='border:1px solid #161616; background-color: [pda_color];'><font color='[color_hex2num(pda_color) < 200 ? "FFFFFF" : "000000"]'>[pda_color]</font></span> <a href='?_src_=prefs;preference=pda_color;task=input'>Change</a><BR>"
dat += "<b>PDA Style:</b> <a href='?_src_=prefs;task=input;preference=pda_style'>[pda_style]</a><br>"
dat += "<b>PDA Reskin:</b> <a href='?_src_=prefs;task=input;preference=pda_skin'>[pda_skin]</a><br>"
@@ -3001,8 +2998,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
chat_on_map = !chat_on_map
if("see_chat_non_mob")
see_chat_non_mob = !see_chat_non_mob
if("action_buttons")
buttons_locked = !buttons_locked
if("tgui_fancy")
tgui_fancy = !tgui_fancy
if("outline_enabled")

View File

@@ -435,7 +435,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["see_chat_non_mob"] >> see_chat_non_mob
S["tgui_fancy"] >> tgui_fancy
S["tgui_lock"] >> tgui_lock
S["buttons_locked"] >> buttons_locked
S["windowflash"] >> windowflashing
S["be_special"] >> be_special
@@ -513,7 +512,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
see_chat_non_mob = sanitize_integer(see_chat_non_mob, 0, 1, initial(see_chat_non_mob))
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked))
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 16777215, initial(toggles))
@@ -626,7 +624,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["see_chat_non_mob"], see_chat_non_mob)
WRITE_FILE(S["tgui_fancy"], tgui_fancy)
WRITE_FILE(S["tgui_lock"], tgui_lock)
WRITE_FILE(S["buttons_locked"], buttons_locked)
WRITE_FILE(S["windowflash"], windowflashing)
WRITE_FILE(S["be_special"], be_special)
WRITE_FILE(S["default_slot"], default_slot)

View File

@@ -162,8 +162,8 @@
..()
/datum/action/item_action/chameleon/change/proc/initialize_disguises()
if(button)
button.name = "Change [chameleon_name] Appearance"
name = "Change [chameleon_name] Appearance"
UpdateButtons()
chameleon_blacklist |= typecacheof(target.type)
for(var/V in typesof(chameleon_type))
@@ -209,7 +209,7 @@
update_item(picked_item)
var/obj/item/thing = target
thing.update_slot_icon()
UpdateButtonIcon()
UpdateButtons()
/datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item)
target.name = initial(picked_item.name)
@@ -435,9 +435,9 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/head/chameleon)
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
chameleon_action.random_look()
var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src)
togglehatmask_action.UpdateButtonIcon()
togglehatmask_action.UpdateButtons()
var/datum/action/item_action/chameleon/drone/randomise/randomise_action = new(src)
randomise_action.UpdateButtonIcon()
randomise_action.UpdateButtons()
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon)
name = "gas mask"
@@ -489,9 +489,9 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon)
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
chameleon_action.random_look()
var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src)
togglehatmask_action.UpdateButtonIcon()
togglehatmask_action.UpdateButtons()
var/datum/action/item_action/chameleon/drone/randomise/randomise_action = new(src)
randomise_action.UpdateButtonIcon()
randomise_action.UpdateButtons()
/obj/item/clothing/mask/chameleon/drone/attack_self(mob/user)
to_chat(user, "<span class='notice'>[src] does not have a voice changer.</span>")

View File

@@ -402,7 +402,7 @@ BLIND // can't see anything
C.head_update(src, forced = 1)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
return TRUE
/obj/item/clothing/proc/visor_toggling() //handles all the actual toggling of flags

View File

@@ -62,7 +62,7 @@
update_icon()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/clothing/glasses/meson/engine/attack_self(mob/user)
toggle_mode(user, TRUE)

View File

@@ -389,7 +389,7 @@
set_light(0)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/clothing/head/helmet/durathread
name = "makeshift helmet"

View File

@@ -115,7 +115,7 @@
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
to_chat(user, "<span class='notice'>Your Clown Mask has now morphed into [choice], all praise the Honkmother!</span>")
return TRUE
@@ -181,7 +181,7 @@
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
to_chat(user, "<span class='notice'>Your Mime Mask has now morphed into [choice]!</span>")
return TRUE
@@ -274,7 +274,7 @@
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
to_chat(M, "The Tiki Mask has now changed into the [choice] Mask!")
return TRUE

View File

@@ -109,7 +109,7 @@
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
to_chat(user, "<span class='notice'>Your Joy mask now has a [choice] Emotion!</span>")
return 1
@@ -475,6 +475,6 @@
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
to_chat(user, "<span class='notice'>Your paper mask now has a [choice] symbol!</span>")
return 1

View File

@@ -36,7 +36,7 @@
user.update_gravity(user.has_gravity())
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/clothing/shoes/magboots/negates_gravity()
return clothing_flags & NOSLIP

View File

@@ -91,7 +91,7 @@
if(camera)
camera.remove_target_ui()
camera.forceMove(user)
teleport_now.UpdateButtonIcon()
teleport_now.UpdateButtons()
/obj/item/clothing/suit/space/chronos/proc/chronowalk(atom/location)
var/mob/living/carbon/human/user = src.loc
@@ -105,7 +105,7 @@
if(camera)
camera.remove_target_ui()
teleport_now.UpdateButtonIcon()
teleport_now.UpdateButtons()
var/list/nonsafe_slots = list(ITEM_SLOT_BELT, ITEM_SLOT_BACK)
var/list/exposed = list()

View File

@@ -345,7 +345,7 @@
C.head_update(src, forced = 1)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/clothing/head/helmet/space/hardsuit/syndi/proc/toggle_hardsuit_mode(mob/user) //Helmet Toggles Suit Mode
if(linkedsuit)
@@ -937,7 +937,7 @@
set_light(0)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/update_overlays()
. = ..()

View File

@@ -139,7 +139,7 @@
usr.update_inv_wear_suit()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/clothing/suit/toggle/examine(mob/user)
. = ..()

View File

@@ -85,6 +85,6 @@
description = "Immediately examine anything you're hovering your mouse over."
/datum/keybinding/mob/examine_immediate/down(client/user)
var/atom/A = user.mouseObject
var/atom/A = WEAKREF(user.mouse_object_ref)
if(A)
A.attempt_examinate(user.mob)

View File

@@ -200,7 +200,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/neurotoxin/update_icon()
action.button_icon_state = "alien_neurotoxin_[active]"
action.UpdateButtonIcon()
action.UpdateButtons()
/obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())
@@ -333,7 +333,7 @@ Doesn't work on other aliens/AI.*/
for(var/X in abilities)
var/obj/effect/proc_holder/alien/APH = X
if(APH.has_action)
APH.action.UpdateButtonIcon()
APH.action.UpdateButtons()
return 1
/mob/living/carbon/alien/adjustPlasma(amount)

View File

@@ -37,7 +37,7 @@
to_chat(owner, "There's something stuck to your hand, stopping you from transforming!")
return
if(IsAvailable())
UpdateButtonIcon()
UpdateButtons()
var/mutcolor = owner.get_ability_property(INNATE_ABILITY_SLIME_BLOBFORM, PROPERTY_BLOBFORM_COLOR) || ("#" + H.dna.features["mcolor"])
if(!is_puddle)
if(CHECK_MOBILITY(H, MOBILITY_USE)) //if we can use items, we can turn into a puddle
@@ -78,7 +78,7 @@
owner.update_antag_overlays()
transforming = FALSE
UpdateButtonIcon()
UpdateButtons()
else
detransform()
else
@@ -109,4 +109,4 @@
squeak.RemoveComponent()
H.regenerate_icons()
transforming = FALSE
UpdateButtonIcon()
UpdateButtons()

View File

@@ -480,9 +480,9 @@
spark_system.start()
do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)
last_teleport = world.time
UpdateButtonIcon() //action icon looks unavailable
sleep(cooldown + 5)
UpdateButtonIcon() //action icon looks available again
UpdateButtons() //action icon looks unavailable
//action icon looks available again
addtimer(CALLBACK(src, .proc/UpdateButtons), cooldown + 5)
//honk

View File

@@ -82,7 +82,7 @@
var/datum/action/innate/ability/regrowth = H.ability_actions[INNATE_ABILITY_LIMB_REGROWTH]
if(regrowth)
regrowth.UpdateButtonIcon()
regrowth.UpdateButtons()
return FALSE // to let living/handle_blood know that the species is handling blood instead
@@ -472,9 +472,9 @@
/datum/species/jelly/luminescent/proc/update_slime_actions()
integrate_extract.update_name()
integrate_extract.UpdateButtonIcon()
extract_minor.UpdateButtonIcon()
extract_major.UpdateButtonIcon()
integrate_extract.UpdateButtons()
extract_minor.UpdateButtons()
extract_major.UpdateButtons()
/datum/species/jelly/luminescent/proc/update_glow(mob/living/carbon/C, intensity)
if(intensity)
@@ -514,7 +514,7 @@
name = "Eject Extract"
desc = "Eject your current slime extract."
/datum/action/innate/integrate_extract/UpdateButtonIcon(status_only, force)
/datum/action/innate/integrate_extract/UpdateButton(atom/movable/screen/movable/action_button/button, status_only, force)
if(!species || !species.current_extract)
button_icon_state = "slimeconsume"
else

View File

@@ -636,7 +636,7 @@
if(mind)
for(var/S in mind.spell_list)
var/obj/effect/proc_holder/spell/spell = S
spell.updateButtonIcon()
spell.UpdateButton()
//proc used to remove all immobilisation effects + reset stamina
/mob/living/proc/remove_CC(should_update_mobility = TRUE)

View File

@@ -241,7 +241,7 @@
// before doing anything, check if the user moused over them properly
if(!client)
return BLOCK_NONE
var/found = attacker == client.mouseObject
var/found = attacker == WEAKREF(client.mouse_object_ref)
if(!found)
for(var/i in client.moused_over_objects)
if(i == object)

View File

@@ -44,6 +44,9 @@
var/can_repair_constructs = FALSE
var/can_repair_self = FALSE
var/runetype
var/datum/action/innate/cult/create_rune/our_rune
/// Theme controls color. THEME_CULT is red THEME_WIZARD is purple and THEME_HOLY is blue
var/theme = "cult"
var/datum/mind/original_mind
/mob/living/simple_animal/hostile/construct/Initialize(mapload)
@@ -51,24 +54,24 @@
update_health_hud()
var/spellnum = 1
for(var/spell in construct_spells)
var/the_spell = new spell(null)
AddSpell(the_spell)
var/obj/effect/proc_holder/spell/S = mob_spell_list[spellnum]
var/pos = 2+spellnum*31
if(construct_spells.len >= 4)
pos -= 31*(construct_spells.len - 4)
S.action.button.screen_loc = "6:[pos],4:-2"
S.action.button.moved = "6:[pos],4:-2"
var/obj/effect/proc_holder/spell/the_spell = new spell(null)
the_spell?.action.default_button_position ="6:[pos],4:-2"
AddSpell(the_spell)
spellnum++
if(runetype)
var/datum/action/innate/cult/create_rune/CR = new runetype(src)
CR.Grant(src)
var/pos = 2+spellnum*31
CR.button.screen_loc = "6:[pos],4:-2"
CR.button.moved = "6:[pos],4:-2"
our_rune = new runetype(src)
our_rune.default_button_position = "6:[pos],4:-2" // Set the default position to this random position
our_rune.Grant(src)
if(icon_state)
add_overlay("glow_[icon_state]_[theme]")
/mob/living/simple_animal/hostile/construct/Destroy()
original_mind = null
QDEL_NULL(our_rune)
. = ..()
/mob/living/simple_animal/hostile/construct/death()

View File

@@ -143,7 +143,7 @@
var/datum/action/boss/AB = ab
if(!boss.client && (!AB.req_statuses || (boss.AIStatus in AB.req_statuses)) && prob(AB.usage_probability) && AB.Trigger())
break
AB.UpdateButtonIcon(TRUE)
AB.UpdateButtons(TRUE)
/datum/boss_active_timed_battle/Destroy()

View File

@@ -336,7 +336,7 @@
if(L.blood_volume && (L.stat != DEAD || !consumed_mobs[L.tag])) //if they're not dead, you can consume them anyway
consumed_mobs[L.tag] = TRUE
fed++
lay_eggs.UpdateButtonIcon(TRUE)
lay_eggs.UpdateButtons(TRUE)
visible_message("<span class='danger'>[src] sticks a proboscis into [L] and sucks a viscous substance out.</span>","<span class='notice'>You suck the nutriment out of [L], feeding you enough to lay a cluster of eggs.</span>")
L.death() //you just ate them, they're dead.
else
@@ -402,7 +402,7 @@
/obj/effect/proc_holder/wrap/update_icon()
action.button_icon_state = "wrap_[active]"
action.UpdateButtonIcon()
action.UpdateButtons()
/obj/effect/proc_holder/wrap/Trigger(mob/living/simple_animal/hostile/poison/giant_spider/nurse/user)
if(!istype(user))
@@ -482,7 +482,7 @@
C.poison_per_bite = S.poison_per_bite
C.faction = S.faction.Copy()
S.fed--
UpdateButtonIcon(TRUE)
UpdateButtons(TRUE)
S.busy = SPIDER_IDLE
S.stop_automated_movement = FALSE

View File

@@ -72,19 +72,48 @@ While using this makes the system rely on OnFire, it still gives options for tim
icon_icon = 'icons/mob/actions/actions_elites.dmi'
button_icon_state = ""
background_icon_state = "bg_default"
var/mob/living/simple_animal/hostile/asteroid/elite/M
var/chosen_message
var/chosen_attack_num = 0
/datum/action/innate/elite_attack/CreateButton()
var/atom/movable/screen/movable/action_button/button = ..()
button.maptext = ""
button.maptext_x = 8
button.maptext_y = 0
button.maptext_width = 24
button.maptext_height = 12
return button
/datum/action/innate/elite_attack/process()
if(owner == null)
STOP_PROCESSING(SSfastprocess, src)
qdel(src)
return
UpdateButtons()
/datum/action/innate/elite_attack/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE)
. = ..()
if(!.)
return
if(status_only)
return
var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner
var/timeleft = max(elite_owner.ranged_cooldown - world.time, 0)
if(timeleft == 0)
button.maptext = ""
else
button.maptext = "<b class='maptext'>[round(timeleft/10, 0.1)]</b>"
/datum/action/innate/elite_attack/Grant(mob/living/L)
if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite))
M = L
START_PROCESSING(SSfastprocess, src)
return ..()
return FALSE
/datum/action/innate/elite_attack/Activate()
M.chosen_attack = chosen_attack_num
to_chat(M, chosen_message)
var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner
elite_owner.chosen_attack = chosen_attack_num
to_chat(elite_owner, chosen_message)
/mob/living/simple_animal/hostile/asteroid/elite/updatehealth()
. = ..()

View File

@@ -426,7 +426,7 @@
for(var/obj/item/I in U.held_items)
if(istype(I, /obj/item/turret_control))
qdel(I)
UpdateButtonIcon()
UpdateButtons()
return
else
playsound(PE,'sound/mecha/mechmove01.ogg', 50, TRUE)
@@ -443,7 +443,7 @@
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
var/obj/item/turret_control/TC = new /obj/item/turret_control()
U.put_in_hands(TC)
UpdateButtonIcon()
UpdateButtons()
/obj/item/turret_control

View File

@@ -142,7 +142,7 @@
if(fire_select_modes.len > 1)
firemode_action = new(src)
firemode_action.button_icon_state = "fireselect_[fire_select]"
firemode_action.UpdateButtonIcon()
firemode_action.UpdateButtons()
/obj/item/gun/ComponentInitialize()
. = ..()
@@ -219,7 +219,7 @@
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
update_appearance()
firemode_action.button_icon_state = "fireselect_[fire_select]"
firemode_action.UpdateButtonIcon()
firemode_action.UpdateButtons()
return TRUE
/obj/item/gun/equipped(mob/living/user, slot)
@@ -670,7 +670,7 @@
update_icon()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
A.UpdateButtons()
/obj/item/gun/update_overlays()
. = ..()

View File

@@ -200,7 +200,9 @@
else
P.color = rgb(0, 255, 0)
var/turf/curloc = get_turf(src)
var/turf/targloc = get_turf(current_user.client.mouseObject)
var/atom/target_atom = current_user.client.mouse_object_ref?.resolve()
var/turf/targloc = get_turf(target_atom)
if(!istype(targloc))
if(!istype(curloc))
return
@@ -293,7 +295,9 @@
process_aim()
if(fire_check() && can_trigger_gun(M))
sync_ammo()
do_fire(M.client.mouseObject, M, FALSE, M.client.mouseParams, M.zone_selected)
var/atom/target = M.client.mouse_object_ref?.resolve()
if(target)
afterattack(target, M, FALSE, M.client.mouseParams)
stop_aiming()
QDEL_LIST(current_tracers)
return ..()

View File

@@ -939,12 +939,10 @@
var/y = text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32
//Calculate the "resolution" of screen based on client's view and world's icon size. This will work if the user can view more tiles than average.
var/list/screenview = getviewsize(user.client.view)
var/screenviewX = screenview[1] * world.icon_size
var/screenviewY = screenview[2] * world.icon_size
var/list/screenview = view_to_pixels(user.client.view)
var/ox = round(screenviewX/2) - user.client.pixel_x //"origin" x
var/oy = round(screenviewY/2) - user.client.pixel_y //"origin" y
var/ox = round(screenview[1] / 2) - user.client.pixel_x //"origin" x
var/oy = round(screenview[2] / 2) - user.client.pixel_y //"origin" y
angle = arctan(y - oy, x - ox)
return list(angle, p_x, p_y)

View File

@@ -165,7 +165,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if("holdervar")
adjust_var(user, holder_var_type, holder_var_amount)
if(action)
action.UpdateButtonIcon()
action.UpdateButtons()
return TRUE
/obj/effect/proc_holder/spell/proc/charge_check(mob/user, silent = FALSE)
@@ -243,7 +243,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(recharging && charge_type == "recharge" && (charge_counter < charge_max))
charge_counter += 2 //processes 5 times per second instead of 10.
if(charge_counter >= charge_max)
action.UpdateButtonIcon()
action.UpdateButtons()
charge_counter = charge_max
recharging = FALSE
@@ -259,7 +259,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
cast(targets,user=user)
after_cast(targets)
if(action)
action.UpdateButtonIcon()
action.UpdateButtons()
/obj/effect/proc_holder/spell/proc/before_cast(list/targets)
if(overlay)
@@ -321,7 +321,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if("holdervar")
adjust_var(user, holder_var_type, -holder_var_amount)
if(action)
action.UpdateButtonIcon()
action.UpdateButtons()
/obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types
if (!istype(target))
@@ -438,8 +438,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
perform(targets,user=user)
/obj/effect/proc_holder/spell/proc/updateButtonIcon(status_only, force)
action.UpdateButtonIcon(status_only, force)
/obj/effect/proc_holder/spell/proc/UpdateButton(atom/movable/screen/movable/action_button/button, status_only, force)
action.UpdateButtons(status_only, force)
/obj/effect/proc_holder/spell/targeted/proc/los_check(mob/A,mob/B)
//Checks for obstacles from A to B

View File

@@ -43,7 +43,7 @@
if(!action)
return
action.button_icon_state = "[base_icon_state][active]"
action.UpdateButtonIcon()
action.UpdateButtons()
/obj/effect/proc_holder/spell/aimed/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())

View File

@@ -63,7 +63,7 @@
action.button_icon_state = "[action_icon_state]1"
else
action.button_icon_state = "[action_icon_state]"
action.UpdateButtonIcon()
action.UpdateButtons()
/obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())

View File

@@ -54,7 +54,7 @@
else
action.button_icon_state = action_icon_state
action.UpdateButtonIcon()
action.UpdateButtons()
return
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -18,7 +18,7 @@
//Start recharging.
attached_hand = null
recharging = TRUE
action.UpdateButtonIcon()
action.UpdateButtons()
/obj/effect/proc_holder/spell/targeted/touch/cast(list/targets,mob/user = usr)
if(!QDELETED(attached_hand))

View File

@@ -18,10 +18,11 @@
user.transferItemToLoc(tool, target, TRUE)
var/datum/action/item_action/hands_free/activate_pill/P = new(tool)
P.button.name = "Activate [tool.name]"
P.target = tool
P.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it
var/datum/action/item_action/hands_free/activate_pill/pill_action = new(tool)
pill_action.name = "Activate [tool.name]"
pill_action.UpdateButtons()
pill_action.target = tool
pill_action.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it
user.visible_message("[user] wedges \the [tool] into [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You wedge [tool] into [target]'s [parse_zone(target_zone)].</span>")
return 1

View File

@@ -87,13 +87,13 @@ Notes:
/datum/tooltip/proc/hide()
queueHide = showing ? TRUE : FALSE
if (queueHide)
addtimer(CALLBACK(src, .proc/do_hide), 1)
else
do_hide()
queueHide = showing ? TRUE : FALSE
return TRUE
/datum/tooltip/proc/do_hide()

View File

@@ -136,21 +136,29 @@
//alert(realIconSize + ' | ' +tooltip.tileSize + ' | ' + resizeRatio); //DEBUG
//Parse out the tile and cursor locations from params (e.g. "icon-x=32;icon-y=29;screen-loc=3:10,15:29")
const parameters = new Object();
//Parse out the contents of params (e.g. "icon-x=32;icon-y=29;screen-loc=3:10,15:29")
//It is worth noting that params is not always ordered in the same way. We therefore need to write the code
//To load their values in independantly of their order
var paramsA = tooltip.params.cursor.split(';');
if (paramsA.length < 3) {return false;} //Sometimes screen-loc is never sent ahaha fuck you byond
for (var i = 0; i < paramsA.length; i++) {
var entry = paramsA[i];
var nameAndValue = entry.split("=");
parameters[nameAndValue[0]] = nameAndValue[1];
}
//Sometimes screen-loc is never sent ahaha fuck you byond
if (!parameters["icon-x"] || !parameters["icon-y"] || !parameters["screen-loc"]) {
return false;
}
//icon-x
var iconX = paramsA[0];
iconX = iconX.split('=');
iconX = parseInt(iconX[1]);
var iconX = parseInt(parameters["icon-x"]);
//icon-y
var iconY = paramsA[1];
iconY = iconY.split('=');
iconY = parseInt(iconY[1]);
var iconY = parseInt(parameters["icon-y"]);
//screen-loc
var screenLoc = paramsA[2];
screenLoc = screenLoc.split('=');
screenLoc = screenLoc[1].split(',');
var screenLoc = parameters["screen-loc"];
screenLoc = screenLoc.split(',');
if (screenLoc.length < 2) {return false;}
var left = screenLoc[0];
var top = screenLoc[1];

View File

@@ -194,7 +194,7 @@ own integrity back to max. Shield is automatically dropped if we run out of powe
for(var/occupant in chassis.occupants)
var/datum/action/button = chassis.occupant_actions[occupant][/datum/action/vehicle/sealed/mecha/mech_defense_mode]
button.button_icon_state = "mech_defense_mode_[chassis.defense_mode ? "on" : "off"]"
button.UpdateButtonIcon()
button.UpdateButtons()
set_light(light_range, light_power, light_color)

View File

@@ -37,7 +37,7 @@
button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]"
to_chat(chassis.occupants, "[icon2html(chassis, owner)]<span class='notice'>Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].</span>")
chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].", LOG_MECHA)
UpdateButtonIcon()
UpdateButtons()
/datum/action/vehicle/sealed/mecha/mech_cycle_equip
name = "Cycle Equipment"
@@ -61,7 +61,7 @@
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>You select [chassis.selected].</span>")
send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list())
button_icon_state = "mech_cycle_equip_on"
UpdateButtonIcon()
UpdateButtons()
return
var/number = 0
for(var/equipment in available_equipment)
@@ -77,7 +77,7 @@
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>You switch to [chassis.selected].</span>")
button_icon_state = "mech_cycle_equip_on"
send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list())
UpdateButtonIcon()
UpdateButtons()
return
@@ -100,7 +100,7 @@
chassis.set_light(0)
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].</span>")
chassis.log_message("Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].", LOG_MECHA)
UpdateButtonIcon()
UpdateButtons()
/datum/action/vehicle/sealed/mecha/mech_view_stats
name = "View Stats"
@@ -140,7 +140,7 @@
for(var/occupant in occupants)
var/datum/action/action = LAZYACCESSASSOC(occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/strafe)
action?.UpdateButtonIcon()
action?.UpdateButtons()
//////////////////////////////////////// Specific Ability Actions ///////////////////////////////////////////////
//Need to be granted by the mech type, Not default abilities.
@@ -176,7 +176,7 @@
chassis.movedelay = initial(chassis.movedelay)
chassis.step_energy_drain = chassis.normal_step_energy_drain
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>You disable leg actuators overload.</span>")
UpdateButtonIcon()
UpdateButtons()
/datum/action/vehicle/sealed/mecha/mech_smoke
name = "Smoke"
@@ -208,7 +208,7 @@
SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50))
else
owner.client.view_size.resetToDefault() //Let's not let this stack shall we?
UpdateButtonIcon()
UpdateButtons()
/datum/action/vehicle/sealed/mecha/mech_switch_damtype
name = "Reconfigure arm microtool arrays"
@@ -231,7 +231,7 @@
chassis.damtype = new_damtype
button_icon_state = "mech_damtype_[new_damtype]"
playsound(chassis, 'sound/mecha/mechmove01.ogg', 50, TRUE)
UpdateButtonIcon()
UpdateButtons()
///swap seats, for two person mecha
/datum/action/vehicle/sealed/mecha/swap_seat
@@ -272,4 +272,4 @@
chassis.phasing = !chassis.phasing
button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]"
to_chat(owner, "[icon2html(chassis, owner)]<font color=\"[chassis.phasing?"#00f\">En":"#f00\">Dis"]abled phasing.</font>")
UpdateButtonIcon()
UpdateButtons()