Merge pull request #12834 from silicons/clickcd_experimental

Experimental hybrid clickdelay system (No seriously I'm trying my best to not call it Minecraft attack delays)
This commit is contained in:
Lin
2020-07-28 21:51:10 -05:00
committed by GitHub
350 changed files with 1127 additions and 1207 deletions
+1 -1
View File
@@ -118,4 +118,4 @@
D.target = null
D.error = "Connection to quantum relay severed"
return ..()
return ..()
-31
View File
@@ -22,37 +22,6 @@
show_air_status_to(target, usr)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Air Status") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/fix_next_move()
set category = "Debug"
set name = "Unfreeze Everyone"
var/largest_move_time = 0
var/largest_click_time = 0
var/mob/largest_move_mob = null
var/mob/largest_click_mob = null
for(var/mob/M in world)
if(!M.client)
continue
if(M.next_move >= largest_move_time)
largest_move_mob = M
if(M.next_move > world.time)
largest_move_time = M.next_move - world.time
else
largest_move_time = 1
if(M.next_click >= largest_click_time)
largest_click_mob = M
if(M.next_click > world.time)
largest_click_time = M.next_click - world.time
else
largest_click_time = 0
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] lastDblClick = [M.next_click] world.time = [world.time]")
M.next_move = 1
M.next_click = 0
message_admins("[ADMIN_LOOKUPFLW(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [DisplayTimeText(largest_move_time)]!")
message_admins("[ADMIN_LOOKUPFLW(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [DisplayTimeText(largest_click_time)]!")
message_admins("world.time = [world.time]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Unfreeze Everyone") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/radio_report()
set category = "Debug"
set name = "Radio report"
@@ -24,10 +24,7 @@
var/obj/machinery/computer/camera_advanced/abductor/camera
var/list/datum/icon_snapshot/disguises = list()
/obj/machinery/abductor/console/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/abductor/console/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) && !HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
to_chat(user, "<span class='warning'>You start mashing alien buttons at random!</span>")
if(do_after(user,100, target = src))
@@ -22,10 +22,7 @@
gland_colors[i] = random_color()
amounts[i] = rand(1,5)
/obj/machinery/abductor/gland_dispenser/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/abductor/gland_dispenser/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!isabductor(user))
return
user.set_machine(src)
@@ -21,10 +21,7 @@
return
close_machine(target)
/obj/machinery/abductor/experiment/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/abductor/experiment/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
experimentUI(user)
@@ -47,8 +44,6 @@
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
/obj/machinery/abductor/experiment/container_resist(mob/living/user)
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
@@ -225,7 +225,7 @@
/obj/structure/blob/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/analyzer))
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
to_chat(user, "<b>The analyzer beeps once, then reports:</b><br>")
SEND_SOUND(user, sound('sound/machines/ping.ogg'))
if(overmind)
@@ -217,7 +217,7 @@
return FALSE
return ..()
/obj/structure/bloodsucker/vassalrack/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/bloodsucker/vassalrack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
//. = ..() // Taken from sacrificial altar in divine.dm
//if(.)
// return
@@ -469,7 +469,7 @@
. += {"<span class='cult'>This is a magical candle which drains at the sanity of the fools who havent yet accepted your master, as long as it is active.\n
You can turn it on and off by clicking on it while you are next to it</span>"} */
/obj/structure/bloodsucker/candelabrum/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/bloodsucker/candelabrum/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
var/datum/antagonist/vassal/T = user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
if(AmBloodsucker(user) || istype(T))
toggle()
@@ -128,11 +128,9 @@
target.face_atom(L)
target.Stun(power_time)
to_chat(L, "<span class='notice'>[target] is fixed in place by your hypnotic gaze.</span>")
target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm
target.mob_transforming = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze.
target.DelayNextAction(power_time)
spawn(power_time)
if(istype(target) && success)
target.mob_transforming = FALSE
if(istype(L) && target.stat == CONSCIOUS && (target in L.fov_view(10))) // They Woke Up! (Notice if within view)
to_chat(L, "<span class='warning'>[target] has snapped out of their trance.</span>")
@@ -81,9 +81,7 @@
var/mist_delay = max(5, 20 - level_current * 2.5) // Level up and do this faster.
// Freeze Me
user.next_move = world.time + mist_delay
user.Stun(mist_delay, ignore_canstun = TRUE)
user.mob_transforming = TRUE
user.density = FALSE
var/invis_was = user.invisibility
user.invisibility = INVISIBILITY_MAXIMUM
@@ -96,7 +94,6 @@
// Move & Freeze
if(isturf(target_turf))
do_teleport(owner, target_turf, no_effects=TRUE, channel = TELEPORT_CHANNEL_QUANTUM) // in teleport.dm?
user.next_move = world.time + mist_delay / 2
user.Stun(mist_delay / 2, ignore_canstun = TRUE)
// Wait...
@@ -104,9 +101,7 @@
// Un-Hide & Freeze
user.dir = get_dir(my_turf, target_turf)
user.next_move = world.time + mist_delay / 2
user.Stun(mist_delay / 2, ignore_canstun = TRUE)
user.mob_transforming = FALSE
user.density = 1
user.invisibility = invis_was
@@ -17,8 +17,7 @@
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/glasses/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/glasses/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -33,8 +32,7 @@
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/under/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/under/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -50,8 +48,7 @@
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/suit/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/suit/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -65,8 +62,7 @@
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/head/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/head/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -81,8 +77,7 @@
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/shoes/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/shoes/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -97,8 +92,7 @@
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/gloves/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/gloves/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -113,8 +107,7 @@
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/mask/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/mask/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -131,8 +124,7 @@
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
qdel(src)
@@ -36,8 +36,7 @@
return
. = ..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/effect/clockwork/city_of_cogs_rift/attack_hand(atom/movable/AM)
/obj/effect/clockwork/city_of_cogs_rift/on_attack_hand(atom/movable/AM)
beckon(AM)
/obj/effect/clockwork/city_of_cogs_rift/Bumped(atom/movable/AM)
@@ -27,8 +27,7 @@
/obj/effect/clockwork/sigil/attack_tk(mob/user)
return //you can't tk stomp sigils, but you can hit them with something
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/effect/clockwork/sigil/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/effect/clockwork/sigil/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user) && !user.stat)
if(is_servant_of_ratvar(user) && user.a_intent != INTENT_HARM)
return ..()
@@ -63,8 +63,7 @@
user.forceMove(get_turf(linked_gateway))
..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/effect/clockwork/spatial_gateway/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!uses)
return FALSE
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
@@ -57,8 +57,7 @@
to_chat(user, "<span class='userdanger'>[src] falls dark. It appears you weren't worthy.</span>")
return ..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clockwork/slab/debug/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clockwork/slab/debug/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_servant_of_ratvar(user))
add_servant_of_ratvar(user)
return ..()
@@ -31,8 +31,7 @@
. = ..()
clockwork_desc = initial(clockwork_desc)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clockwork/construct_chassis/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clockwork/construct_chassis/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(w_class >= WEIGHT_CLASS_HUGE)
to_chat(user, "<span class='warning'>[src] is too cumbersome to carry! Drag it around instead!</span>")
return
@@ -114,24 +114,27 @@
superheat_wall(A)
return
if(modifiers["middle"] || modifiers["ctrl"])
issue_command(A)
INVOKE_ASYNC(src, .proc/issue_command, A)
return
if(GLOB.ark_of_the_clockwork_justiciar == A)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G.recalling)
return
if(!G.recalls_remaining)
to_chat(src, "<span class='warning'>The Ark can no longer recall!</span>")
return
if(alert(src, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(src) || QDELETED(G) || !G.obj_integrity)
return
G.initiate_mass_recall() //wHOOPS LOOKS LIKE A HULK GOT THROUGH
INVOKE_ASYNC(src, .proc/attempt_recall, G)
else if(istype(A, /obj/structure/destructible/clockwork/trap/trigger))
var/obj/structure/destructible/clockwork/trap/trigger/T = A
T.visible_message("<span class='danger'>[T] clunks as it's activated remotely.</span>")
to_chat(src, "<span class='brass'>You activate [T].</span>")
T.activate()
/mob/camera/eminence/proc/attempt_recall(obj/structure/destructible/clockwork/massive/celestial_gateway/G)
if(G.recalling)
return
if(!G.recalls_remaining)
to_chat(src, "<span class='warning'>The Ark can no longer recall!</span>")
return
if(alert(src, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(src) || QDELETED(G) || !G.obj_integrity)
return
G.initiate_mass_recall() //wHOOPS LOOKS LIKE A HULK GOT THROUGH
/mob/camera/eminence/ratvar_act()
name = "\improper Radiance"
real_name = "\improper Radiance"
@@ -41,7 +41,7 @@
affected += try_use_power(MIN_CLOCKCULT_POWER*4)
return affected
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -11,7 +11,7 @@
var/selection_timer //Timer ID; this is canceled if the vote is canceled
var/kingmaking
/obj/structure/destructible/clockwork/eminence_spire/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/destructible/clockwork/eminence_spire/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -58,7 +58,7 @@
. += "<span class='brass'>There are <b>[time_remaining]</b> second[time_remaining != 1 ? "s" : ""] remaining to vote.</span>"
. += "<span class='big brass'>There are <b>[voters.len]/[votes_needed]</b> votes to activate the beacon!</span>"
/obj/structure/destructible/clockwork/heralds_beacon/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/destructible/clockwork/heralds_beacon/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -30,7 +30,7 @@
toggle()
return TRUE
/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/destructible/clockwork/powered/mania_motor/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -6,7 +6,7 @@
max_integrity = 75
icon_state = "lever"
/obj/structure/destructible/clockwork/trap/trigger/lever/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/destructible/clockwork/trap/trigger/lever/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -6,7 +6,7 @@
max_integrity = 15 //Fragile!
icon_state = "repeater"
/obj/structure/destructible/clockwork/trap/trigger/repeater/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/destructible/clockwork/trap/trigger/repeater/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
+1 -1
View File
@@ -258,7 +258,7 @@
/datum/action/innate/cult/spin2win/Activate()
cooldown = world.time + sword.spin_cooldown
holder.changeNext_move(50)
holder.DelayNextAction(50)
holder.apply_status_effect(/datum/status_effect/sword_spin)
sword.spinning = TRUE
sword.block_chance = 100
@@ -44,15 +44,16 @@
/obj/structure/destructible/cult/attack_animal(mob/living/simple_animal/M)
if(istype(M, /mob/living/simple_animal/hostile/construct/builder))
if(obj_integrity < max_integrity)
M.changeNext_move(CLICK_CD_MELEE)
M.DelayNextAction(CLICK_CD_MELEE)
obj_integrity = min(max_integrity, obj_integrity + 5)
Beam(M, icon_state="sendbeam", time=4)
M.visible_message("<span class='danger'>[M] repairs \the <b>[src]</b>.</span>", \
"<span class='cult'>You repair <b>[src]</b>, leaving [p_they()] at <b>[round(obj_integrity * 100 / max_integrity)]%</b> stability.</span>")
return TRUE
else
to_chat(M, "<span class='cult'>You cannot repair [src], as [p_theyre()] undamaged!</span>")
else
..()
return ..()
/obj/structure/destructible/cult/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user))
+1 -1
View File
@@ -67,7 +67,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
to_chat(user, "<span class='danger'>You disrupt the magic of [src] with [I].</span>")
qdel(src)
/obj/effect/rune/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/effect/rune/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -144,7 +144,7 @@
/mob/living/carbon/true_devil/resist_fire()
//They're immune to fire.
/mob/living/carbon/true_devil/attack_hand(mob/living/carbon/human/M)
/mob/living/carbon/true_devil/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.)
switch(M.a_intent)
@@ -291,16 +291,19 @@ the new instance inside the host to be updated to the template's stats.
/mob/camera/disease/ClickOn(var/atom/A, params)
if(freemove && ishuman(A))
var/mob/living/carbon/human/H = A
if(alert(src, "Select [H.name] as your initial host?", "Select Host", "Yes", "No") != "Yes")
return
if(!freemove)
return
if(QDELETED(H) || !force_infect(H))
to_chat(src, "<span class='warning'>[H ? H.name : "Host"] cannot be infected.</span>")
confirm_initial_infection(A)
else
..()
/mob/camera/disease/proc/confirm_initial_infection(mob/living/carbon/human/H)
set waitfor = FALSE
if(alert(src, "Select [H.name] as your initial host?", "Select Host", "Yes", "No") != "Yes")
return
if(!freemove)
return
if(QDELETED(H) || !force_infect(H))
to_chat(src, "<span class='warning'>[H ? H.name : "Host"] cannot be infected.</span>")
/mob/camera/disease/proc/adapt_cooldown()
to_chat(src, "<span class='notice'>You have altered your genetic structure. You will be unable to adapt again for [DisplayTimeText(adaptation_cooldown)].</span>")
next_adaptation_time = world.time + adaptation_cooldown
@@ -17,6 +17,7 @@
//Harvest; activated ly clicking the target, will try to drain their essence.
/mob/living/simple_animal/revenant/proc/Harvest(mob/living/carbon/human/target)
set waitfor = FALSE
if(!castcheck(0))
return
if(draining)
+5 -5
View File
@@ -36,7 +36,7 @@
if(A)
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/effect/mob_spawn/swarmer/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -158,10 +158,11 @@
face_atom(A)
if(!isturf(loc))
return
if(next_move > world.time)
if(!CheckActionCooldown())
return
if(!A.Adjacent(src))
return
DelayNextAction()
A.swarmer_act(src)
/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
@@ -497,7 +498,7 @@
if(resource_gain)
resources += resource_gain
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
DelayNextAction(CLICK_CD_MELEE)
var/obj/effect/temp_visual/swarmer/integrate/I = new /obj/effect/temp_visual/swarmer/integrate(get_turf(target))
I.pixel_x = target.pixel_x
I.pixel_y = target.pixel_y
@@ -517,10 +518,9 @@
/mob/living/simple_animal/hostile/swarmer/proc/DisIntegrate(atom/movable/target)
new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
DelayNextAction(CLICK_CD_MELEE)
target.ex_act(EXPLODE_LIGHT)
/mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(mob/living/target)
if(target == src)
return
+1 -1
View File
@@ -90,7 +90,7 @@
if(bombassembly)
bombassembly.on_found(finder)
/obj/item/onetankbomb/attack_hand() //also for mousetraps
/obj/item/onetankbomb/on_attack_hand() //also for mousetraps
. = ..()
if(.)
return
+1 -1
View File
@@ -87,7 +87,7 @@
if(a_right)
a_right.dropped(user)
/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
/obj/item/assembly_holder/on_attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
. = ..()
if(.)
return
+1 -1
View File
@@ -125,7 +125,7 @@
return
refreshBeam()
/obj/item/assembly/infra/attack_hand()
/obj/item/assembly/infra/on_attack_hand()
. = ..()
refreshBeam()
+1 -2
View File
@@ -84,8 +84,7 @@
playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/assembly/mousetrap/attack_hand(mob/living/carbon/human/user)
/obj/item/assembly/mousetrap/on_attack_hand(mob/living/carbon/human/user)
if(armed)
if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
var/which_hand = BODY_ZONE_PRECISE_L_HAND
@@ -276,8 +276,6 @@
return occupant
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/living/user)
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("<span class='notice'>You see [user] kicking against the glass of [src]!</span>", \
"<span class='notice'>You struggle inside [src], kicking the release with your foot... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a thump from [src].</span>")
@@ -53,8 +53,7 @@
to_chat(M, "<span class='userdanger'>\The [src] has been returned to base!</span>")
STOP_PROCESSING(SSobj, src)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/ctf/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/ctf/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_ctf_target(user) && !anyonecanpickup)
to_chat(user, "Non players shouldn't be moving the flag!")
return
@@ -679,10 +678,7 @@
/obj/machinery/control_point/attackby(mob/user, params)
capture(user)
/obj/machinery/control_point/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/control_point/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
capture(user)
/obj/machinery/control_point/proc/capture(mob/user)
+1 -2
View File
@@ -594,8 +594,7 @@
assignedrole = "Space Bar Patron"
job_description = "Space Bar Patron"
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/effect/mob_spawn/human/alive/space_bar_patron/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/effect/mob_spawn/human/alive/space_bar_patron/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
var/despawn = alert("Return to cryosleep? (Warning, Your mob will be deleted!)",,"Yes","No")
if(despawn == "No" || !loc || !Adjacent(user))
return
+2
View File
@@ -8,6 +8,7 @@
icon = 'icons/obj/card.dmi'
item_flags = NOBLUDGEON
w_class = WEIGHT_CLASS_TINY
attack_speed = CLICK_CD_RAPID
var/datum/supply_pack/discounted_pack
var/discount_pct_off = 0.05
var/obj/machinery/computer/cargo/inserted_console
@@ -34,6 +35,7 @@
if(discount_pct_off == COUPON_OMEN)
to_chat(user, "<span class='warning'>\The [O] validates the coupon as authentic, but refuses to accept it...</span>")
O.say("Coupon fulfillment already in progress...")
user.DelayNextAction()
return
inserted_console = O
+3
View File
@@ -30,6 +30,9 @@
var/move_delay = 0
var/area = null
/// Last time we Click()ed. No clicking twice in one tick!
var/last_click = 0
///////////////
//SOUND STUFF//
///////////////
+3
View File
@@ -774,6 +774,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
ip_intel = res.intel
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE)
if(last_click > world.time - world.tick_lag)
return
last_click = world.time
var/ab = FALSE
var/list/L = params2list(params)
if (object && object == middragatom && L["left"])
@@ -4,7 +4,9 @@
var/beamtype = /obj/item/projectile/beam/disabler //change for adminbus
/obj/item/clothing/glasses/hud/security/sunglasses/disablers/ranged_attack(mob/living/carbon/human/user,atom/A, params)
user.changeNext_move(CLICK_CD_RANGE)
if(!user.CheckActionCooldown(CLICK_CD_RANGE))
return
user.last_action = world.time
var/obj/item/projectile/beam/disabler/LE = new beamtype( loc )
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
LE.firer = src
@@ -12,4 +14,4 @@
LE.preparePixelProjectile(A, src, params)
LE.fire()
return TRUE
//shamelessly copied
//shamelessly copied
@@ -105,11 +105,11 @@
return
var/mob/living/M = loc
M.changeNext_move(CLICK_CD_RAPID)
M.SetNextAction(CLICK_CD_RAPID)
if(warcry)
M.say("[warcry]", ignore_spam = TRUE, forced = TRUE)
return FALSE
return NO_AUTO_CLICKDELAY_HANDLING | ATTACK_IGNORE_ACTION
/obj/item/clothing/gloves/fingerless/pugilist/rapid/AltClick(mob/user)
var/input = stripped_input(user,"What do you want your battlecry to be? Max length of 6 characters.", ,"", 7)
@@ -135,9 +135,9 @@
if(target.stat != CONSCIOUS) //Can't hug people who are dying/dead
return FALSE
else
M.changeNext_move(CLICK_CD_RAPID)
M.SetNextAction(CLICK_CD_RAPID)
return FALSE
return NO_AUTO_CLICKDELAY_HANDLING | ATTACK_IGNORE_ACTION
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"
+1 -1
View File
@@ -290,7 +290,7 @@
if(!target.IsUnconscious())
to_chat(target, "<span class='warning'>Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.</span>")
/obj/item/clothing/head/foilhat/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/head/foilhat/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!warped && iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.head)
+1 -1
View File
@@ -219,7 +219,7 @@
lock = TRUE
return
/obj/item/clothing/neck/petcollar/locked/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/neck/petcollar/locked/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.get_item_by_slot(SLOT_NECK) && lock != FALSE)
to_chat(user, "<span class='warning'>The collar is locked! You'll need unlock the collar before you can take it off!</span>")
return
@@ -80,7 +80,7 @@
if(to_turf)
user.forceMove(to_turf)
user.SetStun(0)
user.next_move = 1
user.SetNextAction(0, considered_action = FALSE, immediate = FALSE)
user.alpha = 255
user.update_atom_colour()
user.animate_movement = FORWARD_STEPS
@@ -124,8 +124,8 @@
for(var/obj/item/I in user.held_items)
ADD_TRAIT(I, TRAIT_NODROP, CHRONOSUIT_TRAIT)
user.animate_movement = NO_STEPS
user.changeNext_move(8 + phase_in_ds)
user.mob_transforming = 1
user.DelayNextAction(8 + phase_in_ds, considered_action = FALSE, immediate = FALSE)
user.mob_transforming = TRUE
user.anchored = TRUE
user.Stun(INFINITY)
+1 -5
View File
@@ -107,11 +107,7 @@
/obj/item/clothing/suit/space/hardsuit/Initialize()
if(jetpack && ispath(jetpack))
jetpack = new jetpack(src)
. = ..()
/obj/item/clothing/suit/space/hardsuit/attack_self(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
..()
return ..()
/obj/item/clothing/suit/space/hardsuit/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/tank/jetpack/suit))
+1 -1
View File
@@ -143,7 +143,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
if(L && (L.density || prob(10)))
L.ex_act(EXPLODE_HEAVY)
obj/effect/immovablerod/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
obj/effect/immovablerod/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(ishuman(user))
var/mob/living/carbon/human/U = user
if(U.job in list("Research Director"))
+3 -3
View File
@@ -324,7 +324,7 @@
damage_dealt *= 4
if(I.damtype == BURN)
damage_dealt *= 4
user.DelayNextAction()
for(var/datum/spacevine_mutation/SM in mutations)
damage_dealt = SM.on_hit(src, user, I, damage_dealt) //on_hit now takes override damage as arg and returns new value for other mutations to permutate further
take_damage(damage_dealt, I.damtype, "melee", 1)
@@ -345,8 +345,7 @@
for(var/datum/spacevine_mutation/SM in mutations)
SM.on_cross(src, AM)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/structure/spacevine/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/spacevine/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
for(var/datum/spacevine_mutation/SM in mutations)
SM.on_hit(src, user)
user_unbuckle_mob(user, user)
@@ -356,6 +355,7 @@
for(var/datum/spacevine_mutation/SM in mutations)
SM.on_hit(src, user)
user_unbuckle_mob(user,user)
return ..()
/obj/structure/spacevine/attack_alien(mob/living/user)
eat(user)
+1 -1
View File
@@ -60,7 +60,7 @@
input_speech = replacetext(input_speech, "given_item", given_item.name)
return input_speech
/mob/living/carbon/human/dummy/travelling_trader/attack_hand(mob/living/carbon/human/H)
/mob/living/carbon/human/dummy/travelling_trader/on_attack_hand(mob/living/carbon/human/H)
if(active && last_speech + 3 < world.realtime) //can only talk once per 3 seconds, to avoid spam
last_speech = world.realtime
if(initial_speech)
@@ -23,7 +23,6 @@
gulp_size = max(round(reagents.total_volume / 5), 5)
/obj/item/reagent_containers/food/drinks/attack(mob/living/M, mob/user, def_zone)
if(!reagents || !reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return 0
@@ -37,9 +36,6 @@
if(M == user)
user.visible_message("<span class='notice'>[user] swallows a gulp of [src].</span>", "<span class='notice'>You swallow a gulp of [src].</span>")
if(HAS_TRAIT(M, TRAIT_VORACIOUS))
M.changeNext_move(CLICK_CD_MELEE * 0.5) //chug! chug! chug!
else
M.visible_message("<span class='danger'>[user] attempts to feed the contents of [src] to [M].</span>", "<span class='userdanger'>[user] attempts to feed the contents of [src] to [M].</span>")
if(!do_mob(user, M))
@@ -56,6 +52,10 @@
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
return 1
/obj/item/reagent_containers/food/drinks/CheckAttackCooldown(mob/user, atom/target)
var/fast = HAS_TRAIT(user, TRAIT_VORACIOUS) && (user == target)
return user.CheckActionCooldown(fast? CLICK_CD_RANGE : CLICK_CD_MELEE)
/obj/item/reagent_containers/food/drinks/afterattack(obj/target, mob/user , proximity)
. = ..()
if(!proximity)
+4 -2
View File
@@ -129,8 +129,6 @@ All foods are distributed among various categories. Use common sense.
else if(fullness > (600 * (1 + M.overeatduration / 2000))) // The more you eat - the more you can eat
user.visible_message("<span class='warning'>[user] cannot force any more of \the [src] to go down [user.p_their()] throat!</span>", "<span class='danger'>You cannot force any more of \the [src] to go down your throat!</span>")
return 0
if(HAS_TRAIT(M, TRAIT_VORACIOUS))
M.changeNext_move(CLICK_CD_MELEE * 0.5) //nom nom nom
else
if(!isbrain(M)) //If you're feeding it to someone else.
if(fullness <= (600 * (1 + M.overeatduration / 1000)))
@@ -167,6 +165,10 @@ All foods are distributed among various categories. Use common sense.
return 0
/obj/item/reagent_containers/food/snacks/CheckAttackCooldown(mob/user, atom/target)
var/fast = HAS_TRAIT(user, TRAIT_VORACIOUS) && (user == target)
return user.CheckActionCooldown(fast? CLICK_CD_RANGE : CLICK_CD_MELEE)
/obj/item/reagent_containers/food/snacks/examine(mob/user)
. = ..()
if(food_quality >= 70)
@@ -130,7 +130,7 @@ God bless America.
/obj/machinery/deepfryer/attack_ai(mob/user)
return
/obj/machinery/deepfryer/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/deepfryer/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(frying)
if(frying.loc == src)
to_chat(user, "<span class='notice'>You eject [frying] from [src].</span>")
@@ -146,6 +146,8 @@ God bless America.
fry_loop.stop()
return
else if(user.pulling && user.a_intent == "grab" && iscarbon(user.pulling) && reagents.total_volume)
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
if(user.grab_state < GRAB_AGGRESSIVE)
to_chat(user, "<span class='warning'>You need a better grip to do that!</span>")
return
@@ -155,5 +157,5 @@ God bless America.
C.apply_damage(min(30, reagents.total_volume), BURN, BODY_ZONE_HEAD)
reagents.remove_any((reagents.total_volume/2))
C.DefaultCombatKnockdown(60)
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction()
return ..()
@@ -63,10 +63,7 @@
/obj/machinery/gibber/relaymove(mob/living/user)
go_out()
/obj/machinery/gibber/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/gibber/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(stat & (NOPOWER|BROKEN))
return
if(operating)
@@ -107,7 +107,7 @@
/obj/machinery/grill/attack_ai(mob/user)
return
/obj/machinery/grill/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/grill/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(grilled_item)
to_chat(user, "<span class='notice'>You take out [grilled_item] from [src].</span>")
grilled_item.forceMove(drop_location())
+1 -2
View File
@@ -106,8 +106,7 @@
START_PROCESSING(SSobj, src)
update_icon()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/pizzabox/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/pizzabox/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.get_inactive_held_item() != src)
return ..()
if(open)
@@ -31,7 +31,7 @@
return
say("It doesn't seem like that's magical enough!")
/obj/item/barthpot/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/barthpot/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!active)
say("Meow!")
return
+3 -3
View File
@@ -76,7 +76,7 @@
health = 25
poof()
/mob/living/simple_animal/jacq/attack_hand(mob/living/carbon/human/M)
/mob/living/simple_animal/jacq/on_attack_hand(mob/living/carbon/human/M)
if(!active)
say("Hello there [gender_check(M)]!")
return ..()
@@ -406,14 +406,14 @@
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, GLUED_ITEM_TRAIT)
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/suit/ghost_sheet/sticky/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
to_chat(user, "<span class='spooky'><i>Boooooo~!</i></span>")
return
else
..()
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/suit/ghost_sheet/sticky/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
to_chat(user, "<span class='spooky'><i>Boooooo~!</i></span>")
return
+2 -5
View File
@@ -105,10 +105,7 @@
if(user.transferItemToLoc(W, drop_location()))
visible_message("<span class='warning'> [user] dunks [W] into \the [src]!</span>")
/obj/structure/holohoop/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/structure/holohoop/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
var/mob/living/L = user.pulling
if(user.grab_state < GRAB_AGGRESSIVE)
@@ -164,7 +161,7 @@
/obj/machinery/readybutton/attackby(obj/item/W as obj, mob/user as mob, params)
to_chat(user, "The device is a solid button, there's nothing you can do with it!")
/obj/machinery/readybutton/attack_hand(mob/user as mob)
/obj/machinery/readybutton/on_attack_hand(mob/user as mob)
. = ..()
if(.)
return
+1 -1
View File
@@ -134,7 +134,7 @@
tiled_dirt = FALSE
baseturfs = /turf/open/floor/holofloor/snow
/turf/open/floor/holofloor/snow/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/turf/open/floor/holofloor/snow/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -56,7 +56,7 @@
else
return ..()
/obj/structure/fermenting_barrel/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/fermenting_barrel/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
open = !open
if(open)
DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
+1 -4
View File
@@ -80,10 +80,7 @@
foodtype = FRUIT
wine_power = 50
/obj/item/reagent_containers/food/snacks/grown/ghost_chili/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/reagent_containers/food/snacks/grown/ghost_chili/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if( ismob(loc) )
held_mob = loc
START_PROCESSING(SSobj, src)
+1 -4
View File
@@ -207,10 +207,7 @@
return ..()
/obj/structure/bonfire/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/structure/bonfire/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(burning)
to_chat(user, "<span class='warning'>You need to extinguish [src] before removing the logs!</span>")
return
+1 -4
View File
@@ -888,10 +888,7 @@
return ..()
/obj/machinery/hydroponics/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/hydroponics/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(issilicon(user)) //How does AI know what plant is?
return
if(harvest)
@@ -519,6 +519,7 @@
/obj/item/electronic_assembly/attack_self(mob/user)
set waitfor = FALSE
if(!check_interactivity(user))
return
if(opened)
@@ -611,7 +612,7 @@
return
..()
/obj/item/electronic_assembly/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/electronic_assembly/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(anchored)
attack_self(user)
return
+1 -1
View File
@@ -112,7 +112,7 @@
else
return ..()
/obj/structure/bookcase/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/bookcase/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(. || !istype(user))
return
+1 -4
View File
@@ -523,10 +523,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
else
return ..()
/obj/machinery/libraryscanner/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/libraryscanner/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
usr.set_machine(src)
var/dat = "" // <META HTTP-EQUIV='Refresh' CONTENT='10'>
if(cache)
+1 -2
View File
@@ -149,8 +149,7 @@
if(100)
new /obj/item/clothing/head/bearpelt(src)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/structure/closet/crate/secure/loot/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/closet/crate/secure/loot/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(locked)
to_chat(user, "<span class='notice'>The crate is locked with a Deca-code lock.</span>")
var/input = input(usr, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "") as text
+1 -5
View File
@@ -99,7 +99,6 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
say("Shuttle interface failed.")
if(href_list["random"] && !possible_destinations)
usr.changeNext_move(CLICK_CD_RAPID) //Anti-spam
var/list/all_mining_turfs = list()
for (var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING))
all_mining_turfs += Z_TURFS(z_level)
@@ -275,10 +274,7 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
var/anti_spam_cd = 0 //The linking process might be a bit intensive, so this here to prevent over use.
var/console_range = 15 //Wifi range of the beacon to find the aux base console
/obj/structure/mining_shuttle_beacon/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/structure/mining_shuttle_beacon/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(anchored)
to_chat(user, "<span class='warning'>Landing zone already set.</span>")
return
+1 -1
View File
@@ -187,7 +187,7 @@
if(LAZYLEN(S.rcd_vals(owner,B.RCD)))
rcd_target = S //If we don't break out of this loop we'll get the last placed thing
owner.changeNext_move(CLICK_CD_RANGE)
owner.DelayNextAction(CLICK_CD_RANGE)
B.RCD.afterattack(rcd_target, owner, TRUE) //Activate the RCD and force it to work remotely!
playsound(target_turf, 'sound/items/deconstruct.ogg', 60, 1)
@@ -103,7 +103,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
icon_state = "[initial(icon_state)][lowertext(picked_color)]-on"
set_light(light_range, light_power, GLOB.marker_beacon_colors[picked_color])
/obj/structure/marker_beacon/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/marker_beacon/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
+1 -1
View File
@@ -41,7 +41,7 @@
return
if(LAZYLEN(fields) < fieldlimit)
new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
/obj/item/resonator/pre_attack(atom/target, mob/user, params)
if(check_allowed_items(target, 1))
@@ -167,10 +167,7 @@
qdel(src)
return TRUE
/obj/item/gps/computer/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/item/gps/computer/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
attack_self(user)
//Bed
@@ -141,10 +141,7 @@ GLOBAL_LIST(labor_sheet_values)
icon_state = "console"
density = FALSE
/obj/machinery/mineral/labor_points_checker/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/mineral/labor_points_checker/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
user.examinate(src)
/obj/machinery/mineral/labor_points_checker/attackby(obj/item/I, mob/user, params)
+1 -4
View File
@@ -62,10 +62,7 @@
else
return ..()
/obj/structure/flora/ash/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/structure/flora/ash/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!harvested && !needs_sharp_harvest)
user.visible_message("<span class='notice'>[user] starts to harvest from [src].</span>","<span class='notice'>You begin to harvest from [src].</span>")
if(do_after(user, harvest_time, target = src))
@@ -667,6 +667,8 @@
var/bleed_stacks_per_hit = 3
total_mass = 2.75
total_mass_on = 5
attack_speed = 0
attack_unwieldlyness = CLICK_CD_MELEE * 0.5
/obj/item/melee/transforming/cleaving_saw/examine(mob/user)
. = ..()
@@ -685,8 +687,12 @@
return FALSE
. = ..()
if(.)
if(active)
attack_unwieldlyness = CLICK_CD_MELEE
else
attack_unwieldlyness = CLICK_CD_MELEE * 0.5
transform_cooldown = world.time + (CLICK_CD_MELEE * 0.5)
user.changeNext_move(CLICK_CD_MELEE * 0.25)
user.SetNextAction(CLICK_CD_MELEE * 0.25, considered_action = FALSE, flush = TRUE)
/obj/item/melee/transforming/cleaving_saw/transform_messages(mob/living/user, supress_message_text)
if(!supress_message_text)
@@ -701,11 +707,6 @@
to_chat(user, "<span class='warning'>You accidentally cut yourself with [src], like a doofus!</span>")
user.take_bodypart_damage(10)
/obj/item/melee/transforming/cleaving_saw/melee_attack_chain(mob/user, atom/target, params)
..()
if(!active)
user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly
/obj/item/melee/transforming/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target)
var/datum/status_effect/stacking/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
if(!B)
+2 -2
View File
@@ -8,7 +8,7 @@
var/list/hit_sounds = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg',\
'sound/weapons/punch1.ogg', 'sound/weapons/punch2.ogg', 'sound/weapons/punch3.ogg', 'sound/weapons/punch4.ogg')
/obj/structure/punching_bag/attack_hand(mob/user as mob)
/obj/structure/punching_bag/on_attack_hand(mob/user as mob)
. = ..()
if(.)
return
@@ -29,7 +29,7 @@
/obj/structure/weightmachine/proc/AnimateMachine(mob/living/user)
return
/obj/structure/weightmachine/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/weightmachine/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
+1 -2
View File
@@ -79,8 +79,7 @@
no_destination_swap = 1
var/static/list/dumb_rev_heads = list()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/machinery/computer/shuttle/mining/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/computer/shuttle/mining/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(is_station_level(user.z) && user.mind && is_head_revolutionary(user) && !(user.mind in dumb_rev_heads))
to_chat(user, "<span class='warning'>You get a feeling that leaving the station might be a REALLY dumb idea...</span>")
dumb_rev_heads += user.mind
+1 -1
View File
@@ -118,7 +118,7 @@
deathmessage = "blows apart!"
..()
/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M)
/mob/living/simple_animal/hostile/mining_drone/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.)
return
+1 -4
View File
@@ -38,10 +38,7 @@
ui_interact(user)
. = ..()
/obj/structure/ore_box/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/structure/ore_box/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(Adjacent(user))
ui_interact(user)
+200
View File
@@ -0,0 +1,200 @@
/**
* CLICKDELAY HANDLING SYSTEM
* How this works is mobs can never do actions until their next_action is at or below world.time, but things can specify extra cooldown
* to check for either from the time of last_action or from the end of next_action.
*
* Clickdelay should always be checked via [CheckActionCooldown()], never manually!
*/
/mob
// CLICKDELAY AND RELATED
// Generic clickdelay - Hybrid time-since-last-attack and time-to-next-attack system.
// next_action is a hard cooldown, as Click()s will not pass unless it is passed.
// last_action is not a hard cooldown and different items can check for different delays.
/// Generic clickdelay variable. Marks down the last world.time we did something that should cause or impact generic clickdelay. This should be directly set or set using [DelayNextAction()]. This should only be checked using [CheckActionCooldown()].
var/last_action = 0
/**
* The difference between the above and this is this is set immediately before even the pre-attack begins to ensure clickdelay is respected.
* Then, it is flushed or discarded using [FlushLastAttack()] or [DiscardLastAttack()] respectively.
*/
var/last_action_immediate = 0
/// Generic clickdelay variable. Next world.time we should be able to do something that respects generic clickdelay. This should be set using [DelayNextAction()] This should only be checked using [CheckActionCooldown()].
var/next_action = 0
/// Ditto
var/next_action_immediate = 0
/// Default clickdelay for an UnarmedAttack() that successfully passes. Respects action_cooldown_mod.
var/unarmed_attack_speed = CLICK_CD_MELEE
/// Simple modification variable multiplied to next action modifier on adjust and on checking time since last action using [CheckActionCooldown()].
/// This should only be manually modified using multipliers.
var/action_cooldown_mod = 1
/// Simple modification variable added to amount on adjust and on checking time since last action using [CheckActionCooldown()].
/// This should only be manually modified via addition.
var/action_cooldown_adjust = 0
// Resisting - While resisting will give generic clickdelay, it is also on its own resist delay system. However, resisting does not check generic movedelay.
// Resist cooldown should only be set at the start of a resist chain - whether this is clicking an alert button, pressing or hotkeying the resist button, or moving to resist out of a locker.
/*
* Special clickdelay variable for resisting. Last time we did a special action like resisting. This should only be set using [MarkResistTime()].
* Use [CheckResistCooldown()] to check cooldowns, this should only be used for the resist action bar visual.
*/
var/last_resist = 0
/// How long we should wait before allowing another resist. This should only be manually modified using multipliers.
var/resist_cooldown = CLICK_CD_RESIST
/// Minimum world time for another resist. This should only be checked using [CheckResistCooldown()].
var/next_resist = 0
/**
* Applies a delay to next_action before we can do our next action.
*
* @params
* * amount - Amount to delay by
* * ignore_mod - ignores next action adjust and mult
* * considered_action - Defaults to TRUE - If TRUE, sets last_action to world.time.
* * immediate - defaults to TRUE - if TRUE, writes to cached/last_attack_immediate instead of last_attack. This ensures it can't collide with any delay checks in the actual attack.
* * flush - defaults to FALSE - Use this while using this proc outside of clickcode to ensure everything is set properly. This should never be set to TRUE if this is called from clickcode.
*/
/mob/proc/DelayNextAction(amount = 0, ignore_mod = FALSE, considered_action = TRUE, immediate = TRUE, flush = FALSE)
if(immediate)
if(considered_action)
last_action_immediate = world.time
next_action_immediate = max(next_action, world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust())))
else
if(considered_action)
last_action = world.time
next_action = max(next_action, world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust())))
if(flush)
FlushCurrentAction()
else
hud_used?.clickdelay?.mark_dirty()
/**
* Get estimated time of next attack.
*/
/mob/proc/EstimatedNextActionTime()
var/attack_speed = unarmed_attack_speed * GetActionCooldownMod() + GetActionCooldownAdjust()
var/obj/item/I = get_active_held_item()
if(I)
attack_speed = I.GetEstimatedAttackSpeed()
if(!I.clickdelay_mod_bypass)
attack_speed = attack_speed * GetActionCooldownMod() + GetActionCooldownAdjust()
return max(next_action, next_action_immediate, max(last_action, last_action_immediate) + attack_speed)
/**
* Sets our next action to. The difference is DelayNextAction cannot reduce next_action under any circumstances while this can.
*/
/mob/proc/SetNextAction(amount = 0, ignore_mod = FALSE, considered_action = TRUE, immediate = TRUE, flush = FALSE)
if(immediate)
if(considered_action)
last_action_immediate = world.time
next_action_immediate = world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust()))
else
if(considered_action)
last_action = world.time
next_action = world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust()))
if(flush)
FlushCurrentAction()
else
hud_used?.clickdelay?.mark_dirty()
/**
* Checks if we can do another action.
* Returns TRUE if we can and FALSE if we cannot.
*
* @params
* * cooldown - Time required since last action. Defaults to 0.5
* * from_next_action - Defaults to FALSE. Should we check from the tail end of next_action instead of last_action?
* * ignore_mod - Defaults to FALSE. Ignore all adjusts and multipliers. Do not use this unless you know what you are doing and have a good reason.
* * ignore_next_action - Defaults to FALSE. Ignore next_action and only care about cooldown param and everything else. Generally unused.
* * immediate - Defaults to FALSE. Checks last action using immediate, used on the head end of an attack. This is to prevent colliding attacks in case of sleep. Not that you should sleep() in an attack but.. y'know.
*/
/mob/proc/CheckActionCooldown(cooldown = 0.5, from_next_action = FALSE, ignore_mod = FALSE, ignore_next_action = FALSE, immediate = FALSE)
return (ignore_next_action || (world.time >= (immediate? next_action_immediate : next_action))) && \
(world.time >= ((from_next_action? (immediate? next_action_immediate : next_action) : (immediate? last_action_immediate : last_action)) + max(0, ignore_mod? cooldown : (cooldown * GetActionCooldownMod() + GetActionCooldownAdjust()))))
/**
* Gets action_cooldown_mod.
*/
/mob/proc/GetActionCooldownMod()
return action_cooldown_mod
/**
* Gets action_cooldown_adjust
*/
/mob/proc/GetActionCooldownAdjust()
return action_cooldown_adjust
/**
* Flushes last_action and next_action
*/
/mob/proc/FlushCurrentAction()
last_action = last_action_immediate
next_action = next_action_immediate
hud_used?.clickdelay?.mark_dirty()
/**
* Discards last_action and next_action
*/
/mob/proc/DiscardCurrentAction()
last_action_immediate = last_action
next_action_immediate = next_action
hud_used?.clickdelay?.mark_dirty()
/**
* Checks if we can resist again.
*/
/mob/proc/CheckResistCooldown()
return (world.time >= next_resist)
/**
* Mark the last resist as now.
*
* @params
* * extra_cooldown - Extra cooldown to apply to next_resist. Defaults to this mob's resist_cooldown.
* * override - Defaults to FALSE - if TRUE, extra_cooldown will replace the old next_resist even if the old is longer.
*/
/mob/proc/MarkResistTime(extra_cooldown = resist_cooldown, override = FALSE)
last_resist = world.time
next_resist = override? (world.time + extra_cooldown) : max(next_resist, world.time + extra_cooldown)
hud_used?.resistdelay?.mark_dirty()
/atom
// Standard clickdelay variables
// These 3 are all handled at base of atom/attack_hand so uh.. yeah. Make sure that's called.
/// Amount of time to check for from a mob's last attack to allow an attack_hand().
var/attack_hand_speed = CLICK_CD_MELEE
/// Amount of time to hard stagger (no clicking at all) the mob post attack_hand(). Lower = better
var/attack_hand_unwieldlyness = 0
/// Should we set last action for attack hand? This implies that attack_hands to this atom should flush to clickdelay buffers instead of discarding.
var/attack_hand_is_action = FALSE
/obj/item
// Standard clickdelay variables
/// Amount of time to check for from a mob's last attack, checked before an attack happens. Lower = faster attacks
var/attack_speed = CLICK_CD_MELEE
/// Amount of time to hard-stagger (no clicking at all) the mob when attacking. Lower = better
var/attack_unwieldlyness = 0
/// This item bypasses any click delay mods
var/clickdelay_mod_bypass = FALSE
/// This item checks clickdelay from a user's delayed next action variable rather than the last time they attacked.
var/clickdelay_from_next_action = FALSE
/// This item ignores next action delays.
var/clickdelay_ignores_next_action = FALSE
/**
* Checks if a user's clickdelay is met for a standard attack, this is called before an attack happens.
*/
/obj/item/proc/CheckAttackCooldown(mob/user, atom/target)
return user.CheckActionCooldown(attack_speed, clickdelay_from_next_action, clickdelay_mod_bypass, clickdelay_ignores_next_action)
/**
* Called after a successful attack to set a mob's clickdelay.
*/
/obj/item/proc/ApplyAttackCooldown(mob/user, atom/target, attackchain_flags)
user.DelayNextAction(attack_unwieldlyness, clickdelay_mod_bypass, !(attackchain_flags & ATTACK_IGNORE_ACTION))
/**
* Get estimated time that a user has to not attack for to use us
*/
/obj/item/proc/GetEstimatedAttackSpeed()
return attack_speed
-8
View File
@@ -5,13 +5,11 @@
/mob/proc/get_active_held_item()
return get_item_for_held_index(active_hand_index)
//Finds the opposite limb for the active one (eg: upper left arm will find the item in upper right arm)
//So we're treating each "pair" of limbs as a team, so "both" refers to them
/mob/proc/get_inactive_held_item()
return get_item_for_held_index(get_inactive_hand_index())
//Finds the opposite index for the active one (eg: upper left arm will find the item in upper right arm)
//So we're treating each "pair" of limbs as a team, so "both" refers to them
/mob/proc/get_inactive_hand_index()
@@ -24,12 +22,9 @@
other_hand = 0
return other_hand
/mob/proc/get_item_for_held_index(i)
if(i > 0 && i <= held_items.len)
return held_items[i]
return FALSE
//Odd = left. Even = right
/mob/proc/held_index_to_dir(i)
@@ -37,17 +32,14 @@
return "r"
return "l"
//Check we have an organ for this hand slot (Dismemberment), Only relevant for humans
/mob/proc/has_hand_for_held_index(i)
return TRUE
//Check we have an organ for our active hand slot (Dismemberment),Only relevant for humans
/mob/proc/has_active_hand()
return has_hand_for_held_index(active_hand_index)
//Finds the first available (null) index OR all available (null) indexes in held_items based on a side.
//Lefts: 1, 3, 5, 7...
//Rights:2, 4, 6, 8...
+3 -1
View File
@@ -39,7 +39,9 @@
laws.set_laws_config()
/obj/item/mmi/attackby(obj/item/O, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
user.DelayNextAction()
if(istype(O, /obj/item/organ/brain)) //Time to stick a brain in it --NEO
var/obj/item/organ/brain/newbrain = O
if(brain)
+1 -1
View File
@@ -102,7 +102,7 @@
to_chat(brainmob, "<span class='notice'>You feel slightly disoriented. That's normal when you're just a brain.</span>")
/obj/item/organ/brain/attackby(obj/item/O, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
if(brainmob)
O.attack(brainmob, user) //Oh noooeeeee
@@ -45,7 +45,7 @@ In all, this is a lot like the monkey code. /N
return attack_alien(L)
/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
/mob/living/carbon/alien/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //To allow surgery to return properly.
return
@@ -74,7 +74,6 @@ In all, this is a lot like the monkey code. /N
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(rand(1, 3), BRUTE, affecting)
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
. = ..()
if(.)
@@ -21,7 +21,7 @@
"<span class='userdanger'>[user] has [hitverb] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 1
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
/mob/living/carbon/alien/humanoid/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //To allow surgery to return properly.
return
@@ -1,6 +1,6 @@
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
/mob/living/carbon/alien/larva/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB)
return
@@ -58,8 +58,7 @@
/obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens
return attack_hand(user)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/mask/facehugger/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/item/clothing/mask/facehugger/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if((stat == CONSCIOUS && !sterile) && !isalien(user))
if(Leap(user))
return
+6 -22
View File
@@ -320,14 +320,11 @@
return
if(restrained())
// too soon.
if(last_special > world.time)
return
var/buckle_cd = 600
if(handcuffed)
var/obj/item/restraints/O = src.get_item_by_slot(SLOT_HANDCUFFED)
buckle_cd = O.breakouttime
changeNext_move(min(CLICK_CD_BREAKOUT, buckle_cd))
last_special = world.time + min(CLICK_CD_BREAKOUT, buckle_cd)
MarkResistTime()
visible_message("<span class='warning'>[src] attempts to unbuckle [p_them()]self!</span>", \
"<span class='notice'>You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)</span>")
if(do_after(src, buckle_cd, 0, target = src, required_mobility_flags = MOBILITY_RESIST))
@@ -341,39 +338,26 @@
buckled.user_unbuckle_mob(src,src)
/mob/living/carbon/resist_fire()
if(last_special > world.time)
return
fire_stacks -= 5
DefaultCombatKnockdown(60, TRUE, TRUE)
spin(32,2)
visible_message("<span class='danger'>[src] rolls on the floor, trying to put [p_them()]self out!</span>", \
"<span class='notice'>You stop, drop, and roll!</span>")
last_special = world.time + 30
MarkResistTime(30)
sleep(30)
if(fire_stacks <= 0)
visible_message("<span class='danger'>[src] has successfully extinguished [p_them()]self!</span>", \
"<span class='notice'>You extinguish yourself.</span>")
ExtinguishMob()
/mob/living/carbon/resist_restraints(ignore_delay = FALSE)
/mob/living/carbon/resist_restraints()
var/obj/item/I = null
var/type = 0
if(!ignore_delay && (last_special > world.time))
to_chat(src, "<span class='warning'>You don't have the energy to resist your restraints that fast!</span>")
return
if(handcuffed)
I = handcuffed
type = 1
else if(legcuffed)
I = legcuffed
type = 2
if(I)
if(type == 1)
changeNext_move(min(CLICK_CD_BREAKOUT, I.breakouttime))
last_special = world.time + CLICK_CD_BREAKOUT
if(type == 2)
changeNext_move(min(CLICK_CD_RANGE, I.breakouttime))
last_special = world.time + CLICK_CD_RANGE
MarkResistTime()
cuff_resist(I)
/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0)
@@ -418,7 +402,7 @@
if (W)
W.layer = initial(W.layer)
W.plane = initial(W.plane)
changeNext_move(0)
SetNextAction(0)
if (legcuffed)
var/obj/item/W = legcuffed
legcuffed = null
@@ -431,7 +415,7 @@
if (W)
W.layer = initial(W.layer)
W.plane = initial(W.plane)
changeNext_move(0)
SetNextAction(0)
update_equipment_speed_mods() // In case cuffs ever change speed
/mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break)
@@ -69,7 +69,7 @@
var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
var/list/block_return = list()
if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, block_return) & BLOCK_SUCCESS))
if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, block_return) & BLOCK_SUCCESS))
return FALSE
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
var/obj/item/bodypart/affecting = get_bodypart(impacting_zone)
@@ -111,8 +111,7 @@
/mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user)
return //so we don't call the carbon's attack_hand().
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/carbon/attack_hand(mob/living/carbon/human/user, act_intent, unarmed_attack_flags)
/mob/living/carbon/on_attack_hand(mob/living/carbon/human/user, act_intent, unarmed_attack_flags)
. = ..()
if(.) //was the attack blocked?
return
@@ -151,15 +150,13 @@
if(M.a_intent == INTENT_HELP)
help_shake_act(M)
return 0
return TRUE
. = ..()
if(.) //successful monkey bite.
for(var/thing in M.diseases)
var/datum/disease/D = thing
ForceContractDisease(D)
return 1
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
. = ..()
@@ -735,8 +735,7 @@
/mob/living/carbon/human/resist_restraints()
if(wear_suit && wear_suit.breakouttime)
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
MarkResistTime()
cuff_resist(wear_suit)
else
..()
@@ -122,7 +122,7 @@
apply_damage(15, BRUTE, wound_bonus=10)
return 1
/mob/living/carbon/human/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/mob/living/carbon/human/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.) //To allow surgery to return properly.
return
@@ -131,6 +131,9 @@
dna.species.spec_attack_hand(H, src, null, act_intent, unarmed_attack_flags)
/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
if(!M.CheckActionCooldown(CLICK_CD_MELEE))
return
M.DelayNextAction()
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
@@ -110,7 +110,7 @@
return ..()
visible_message("<span class='warning'>[src] strikes back perfectly at [attacker], staggering them!</span>")
if(D.parry_data["HUMAN_PARRY_PUNCH"])
UnarmedAttack(attacker, TRUE, INTENT_HARM, UNARMED_ATTACK_PARRY)
UnarmedAttack(attacker, TRUE, INTENT_HARM, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_ACTION | ATTACK_IGNORE_CLICKDELAY | NO_AUTO_CLICKDELAY_HANDLING)
var/mob/living/L = attacker
if(istype(L))
L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"])
@@ -1448,7 +1448,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.grabbedby(user)
return 1
/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style, unarmed_attack_flags = NONE)
/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style, attackchain_flags = NONE)
if(!attacker_style && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm [target]!</span>")
return FALSE
@@ -1460,7 +1460,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target_message = "<span class='warning'>[target] blocks your attack!</span>")
return FALSE
if(!(unarmed_attack_flags & UNARMED_ATTACK_PARRY))
if(!(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK))
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount
user.adjustStaminaLossBuffered(1.5)
else
@@ -1502,7 +1502,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected))
var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
if(unarmed_attack_flags & UNARMED_ATTACK_PARRY)
if(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)
miss_chance = 0
else
if(user.dna.species.punchdamagelow)
@@ -1689,7 +1689,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
return
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags)
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, attackchain_flags)
if(!istype(M))
return
CHECK_DNA_AND_SPECIES(M)
@@ -1709,7 +1709,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
grab(M, H, attacker_style)
if("harm")
harm(M, H, attacker_style, unarmed_attack_flags)
harm(M, H, attacker_style, attackchain_flags)
if("disarm")
disarm(M, H, attacker_style)
@@ -1719,7 +1719,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// Allows you to put in item-specific reactions based on species
if(user != H)
var/list/block_return = list()
if(H.mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, block_return) & BLOCK_SUCCESS)
if(H.mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, block_return) & BLOCK_SUCCESS)
return 0
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
if(H.check_martial_melee_block())
@@ -1830,6 +1830,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return TRUE
CHECK_DNA_AND_SPECIES(M)
CHECK_DNA_AND_SPECIES(H)
if(!M.CheckActionCooldown())
return
M.DelayNextAction(CLICK_CD_MELEE)
if(!istype(M)) //sanity check for drones.
return TRUE
@@ -90,8 +90,7 @@
else if(legcuffed)
I = legcuffed
if(I)
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
MarkResistTime()
cuff_resist(I)
/mob/living/carbon/monkey/proc/should_target(var/mob/living/L)
@@ -354,7 +353,7 @@
battle_screech()
a_intent = INTENT_HARM
/mob/living/carbon/monkey/attack_hand(mob/living/L)
/mob/living/carbon/monkey/on_attack_hand(mob/living/L)
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(L)
else if(L.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
@@ -42,7 +42,7 @@
adjustBruteLoss(15)
return TRUE
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
/mob/living/carbon/monkey/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //To allow surgery to return properly.
return
+4
View File
@@ -0,0 +1,4 @@
/mob/living/GetActionCooldownMod()
. = ..()
for(var/datum/status_effect/S in status_effects)
. *= S.action_cooldown_mod()
+11 -10
View File
@@ -273,7 +273,7 @@
return
stop_pulling()
changeNext_move(CLICK_CD_GRABBING)
DelayNextAction(CLICK_CD_GRABBING)
if(AM.pulledby)
if(!supress_message)
@@ -676,7 +676,7 @@
..(pressure_difference, direction, pressure_resistance_prob_delta)
/mob/living/can_resist()
return !((next_move > world.time) || !CHECK_MOBILITY(src, MOBILITY_RESIST))
return CheckResistCooldown() && CHECK_MOBILITY(src, MOBILITY_RESIST)
/// Resist verb for attempting to get out of whatever is restraining your motion. Gives you resist clickdelay if do_resist() returns true.
/mob/living/verb/resist()
@@ -687,10 +687,12 @@
return
if(do_resist())
changeNext_move(CLICK_CD_RESIST)
MarkResistTime()
DelayNextAction(CLICK_CD_RESIST)
/// The actual proc for resisting. Return TRUE to give clickdelay.
/// The actual proc for resisting. Return TRUE to give CLICK_CD_RESIST clickdelay.
/mob/living/proc/do_resist()
set waitfor = FALSE // some of these sleep.
SEND_SIGNAL(src, COMSIG_LIVING_RESIST, src)
//resisting grabs (as if it helps anyone...)
// only works if you're not cuffed.
@@ -701,7 +703,7 @@
return old_gs? TRUE : FALSE
// unbuckling yourself. stops the chain if you try it.
if(buckled && last_special <= world.time)
if(buckled)
log_combat(src, buckled, "resisted buckle")
return resist_buckle()
@@ -730,13 +732,12 @@
if(CHECK_MOBILITY(src, MOBILITY_USE) && resist_embedded()) //Citadel Change for embedded removal memes - requires being able to use items.
// DO NOT GIVE DEFAULT CLICKDELAY - This is a combat action.
changeNext_move(CLICK_CD_MELEE)
DelayNextAction(CLICK_CD_MELEE)
return FALSE
if(last_special <= world.time)
resist_restraints() //trying to remove cuffs.
// DO NOT GIVE CLICKDELAY - last_special handles this.
return FALSE
resist_restraints() //trying to remove cuffs.
// DO NOT GIVE CLICKDELAY
return FALSE
/// Proc to resist a grab. moving_resist is TRUE if this began by someone attempting to move. Return FALSE if still grabbed/failed to break out. Use this instead of resist_grab() directly.
/mob/proc/attempt_resist_grab(moving_resist, forced, log = TRUE)
@@ -10,8 +10,7 @@
REMOVE_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_BLOCK_TRAIT)
remove_movespeed_modifier(/datum/movespeed_modifier/active_block)
var/datum/block_parry_data/data = I.get_block_parry_data()
if(timeToNextMove() < data.block_end_click_cd_add)
changeNext_move(data.block_end_click_cd_add)
DelayNextAction(data.block_end_click_cd_add)
return TRUE
/mob/living/proc/ACTIVE_BLOCK_START(obj/item/I)
@@ -66,7 +66,7 @@
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
// can always implement it later, whatever.
if((data.parry_respect_clickdelay && (next_move > world.time)) || ((parry_end_time_last + data.parry_cooldown) > world.time))
if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
to_chat(src, "<span class='warning'>You are not ready to parry (again)!</span>")
return
// Point of no return, make sure everything is set.
@@ -121,7 +121,7 @@
Stagger(data.parry_failed_stagger_duration)
effect_text += "staggering themselves"
if(data.parry_failed_clickcd_duration)
changeNext_move(data.parry_failed_clickcd_duration)
DelayNextAction(data.parry_failed_clickcd_duration, flush = TRUE)
effect_text += "throwing themselves off balance"
handle_parry_ending_effects(data, effect_text)
parrying = NOT_PARRYING
@@ -277,7 +277,7 @@
if(data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN])
switch(parrying)
if(ITEM_PARRY)
active_parry_item.melee_attack_chain(src, attacker, null, ATTACKCHAIN_PARRY_COUNTERATTACK, data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN])
active_parry_item.melee_attack_chain(src, attacker, null, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_CLICKDELAY | ATTACK_IGNORE_ACTION | NO_AUTO_CLICKDELAY_HANDLING, data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN])
effect_text += "reflexively counterattacking with [active_parry_item]"
if(UNARMED_PARRY) // WARNING: If you are using these two, the attackchain parry counterattack flags and damage multipliers are unimplemented. Be careful with how you handle this.
UnarmedAttack(attacker)
+12 -5
View File
@@ -216,8 +216,8 @@
//proc to upgrade a simple pull into a more aggressive grab.
/mob/living/proc/grippedby(mob/living/carbon/user, instant = FALSE)
if(user.grab_state < GRAB_KILL)
user.changeNext_move(CLICK_CD_GRABBING)
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
user.DelayNextAction(CLICK_CD_GRABBING, flush = TRUE)
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(user.grab_state) //only the first upgrade is instantaneous
var/old_grab_state = user.grab_state
@@ -271,10 +271,10 @@
user.set_pull_offsets(src, grab_state)
return 1
/mob/living/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/mob/living/on_attack_hand(mob/user, act_intent = user.a_intent, attackchain_flags)
..() //Ignoring parent return value here.
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user)
if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((unarmed_attack_flags & UNARMED_ATTACK_PARRY)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
log_combat(user, src, "attempted to touch")
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>",
"<span class='warning'>[user] attempted to touch you!</span>", target = user,
@@ -324,6 +324,9 @@
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
if(!M.CheckActionCooldown(CLICK_CD_MELEE))
return
M.DelayNextAction()
if(M.melee_damage_upper == 0)
M.visible_message("<span class='notice'>\The [M] [M.friendly_verb_continuous] [src]!</span>",
"<span class='notice'>You [M.friendly_verb_simple] [src]!</span>", target = src,
@@ -339,7 +342,7 @@
return 0
damage = block_calculate_resultant_damage(damage, return_list)
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
playsound(src, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M] [M.attack_verb_continuous] [src]!</span>", \
"<span class='userdanger'>\The [M] [M.attack_verb_continuous] you!</span>", null, COMBAT_MESSAGE_RANGE, null,
@@ -348,6 +351,9 @@
return damage
/mob/living/attack_paw(mob/living/carbon/monkey/M)
if(!M.CheckActionCooldown(CLICK_CD_MELEE))
return
M.DelayNextAction()
if (M.a_intent == INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
@@ -369,6 +375,7 @@
visible_message("<span class='danger'>[M.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[M.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE, null,
M, "<span class='danger'>You have attempted to bite [src]!</span>")
return TRUE
return FALSE
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
@@ -53,7 +53,6 @@
var/hallucination = 0 //Directly affects how long a mob will hallucinate for
var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
var/timeofdeath = 0
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.

Some files were not shown because too many files have changed in this diff Show More