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
+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.
@@ -28,8 +28,7 @@
fold_in(force = 1)
DefaultCombatKnockdown(200)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user)
/mob/living/silicon/pai/on_attack_hand(mob/living/carbon/human/user)
switch(user.a_intent)
if(INTENT_HELP)
visible_message("<span class='notice'>[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.</span>",
@@ -16,8 +16,6 @@
return item
return module_active
/mob/living/silicon/robot/proc/uneq_module(obj/item/O)
if(!O)
return 0
@@ -289,7 +289,7 @@
/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src))
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
if (!getBruteLoss())
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
return
@@ -311,7 +311,7 @@
return
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
user.changeNext_move(CLICK_CD_MELEE)
user.DelayNextAction(CLICK_CD_MELEE)
if (getFireLoss() > 0 || getToxLoss() > 0)
if(src == user)
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
@@ -62,8 +62,7 @@
return
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user)
/mob/living/silicon/robot/on_attack_hand(mob/living/carbon/human/user)
add_fingerprint(user)
if(opened && !wiresexposed && cell && !issilicon(user))
cell.update_icon()
@@ -70,7 +70,7 @@
return TRUE
return FALSE
/mob/living/silicon/attack_hand(mob/living/carbon/human/M)
/mob/living/silicon/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //the attack was blocked
return
@@ -1,6 +1,6 @@
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
/mob/living/simple_animal/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //the attack was blocked
return
@@ -41,7 +41,11 @@
to_chat(src, "<span class='notice'>Your astral projection is interrupted and your mind is sent back to your body with a shock!</span>")
/mob/living/simple_animal/astral/ClickOn(var/atom/A, var/params)
..()
. = ..()
attempt_possess(A)
/mob/living/simple_animal/astral/proc/attempt_possess(atom/A)
set waitfor = FALSE
if(pseudo_death == FALSE)
if(isliving(A))
if(ishuman(A))
@@ -290,7 +290,7 @@
return TRUE //Successful completion. Used to prevent child process() continuing if this one is ended early.
/mob/living/simple_animal/bot/attack_hand(mob/living/carbon/human/H)
/mob/living/simple_animal/bot/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_HELP)
interact(H)
else
@@ -335,7 +335,6 @@
user.visible_message("<span class='notice'>[user] uses [W] to pull [paicard] out of [bot_name]!</span>","<span class='notice'>You pull [paicard] out of [bot_name] with [W].</span>")
ejectpai(user)
else
user.changeNext_move(CLICK_CD_MELEE)
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
if(health >= maxHealth)
to_chat(user, "<span class='warning'>[src] does not need a repair!</span>")
@@ -177,7 +177,7 @@ Auto Patrol[]"},
target = H
mode = BOT_HUNT
/mob/living/simple_animal/bot/ed209/attack_hand(mob/living/carbon/human/H)
/mob/living/simple_animal/bot/ed209/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_HARM)
retaliate(H)
return ..()
@@ -532,8 +532,10 @@ Auto Patrol[]"},
/mob/living/simple_animal/bot/ed209/RangedAttack(atom/A)
if(!on)
return
return ..()
shootAt(A)
DelayNextAction()
return TRUE
/mob/living/simple_animal/bot/ed209/proc/stun_attack(mob/living/carbon/C)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
@@ -112,7 +112,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
target = H
mode = BOT_HUNT
/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
/mob/living/simple_animal/bot/honkbot/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_HARM)
retaliate(H)
addtimer(CALLBACK(src, .proc/react_buzz), 5)
@@ -604,7 +604,7 @@
/mob/living/simple_animal/bot/medbot/proc/get_healchem_toxin(mob/M)
return HAS_TRAIT(M, TRAIT_TOXINLOVER)? treatment_tox_toxlover : treatment_tox
/mob/living/simple_animal/bot/medbot/attack_hand(mob/living/carbon/human/H)
/mob/living/simple_animal/bot/medbot/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_DISARM && mode != BOT_TIPPED)
H.visible_message("<span class='danger'>[H] begins tipping over [src].</span>", "<span class='warning'>You begin tipping over [src]...</span>")
@@ -284,7 +284,7 @@ Auto Patrol: []"},
/mob/living/simple_animal/bot/secbot/proc/special_retaliate_after_attack(mob/user) //allows special actions to take place after being attacked.
return
/mob/living/simple_animal/bot/secbot/attack_hand(mob/living/carbon/human/H)
/mob/living/simple_animal/bot/secbot/on_attack_hand(mob/living/carbon/human/H)
if((H.a_intent == INTENT_HARM) || (H.a_intent == INTENT_DISARM))
retaliate(H)
if(special_retaliate_after_attack(H))
@@ -283,7 +283,7 @@
if(!D.is_decorated)
D.decorate_donut()
/mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L)
/mob/living/simple_animal/pet/cat/cak/on_attack_hand(mob/living/L)
. = ..()
if(.) //the attack was blocked
return
@@ -166,7 +166,7 @@
if(stat == CONSCIOUS)
udder.generateMilk(milk_reagent)
/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M)
/mob/living/simple_animal/cow/on_attack_hand(mob/living/carbon/M)
if(!stat && M.a_intent == INTENT_DISARM && icon_state != icon_dead)
M.visible_message("<span class='warning'>[M] tips over [src].</span>",
"<span class='notice'>You tip over [src].</span>")
@@ -86,8 +86,7 @@
/obj/guardian_bomb/attackby(mob/living/user)
detonate(user)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/guardian_bomb/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/guardian_bomb/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
detonate(user)
/obj/guardian_bomb/examine(mob/user)
@@ -3,7 +3,7 @@
melee_damage_lower = 20
melee_damage_upper = 20
obj_damage = 80
next_move_modifier = 0.5 //attacks 50% faster
action_cooldown_mod = 0.5 //attacks 50% faster
environment_smash = ENVIRONMENT_SMASH_WALLS
playstyle_string = "<span class='holoparasite'>As a <b>standard</b> type you have no special abilities, but take half damage and have powerful attack capable of smashing through walls.</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the Assistant, faceless and generic, but never to be underestimated.</span>"
@@ -136,7 +136,7 @@ mob/living/simple_animal/hostile/bear/butter //The mighty companion to Cak. Seve
if(health < maxHealth)
heal_overall_damage(10) //Fast life regen, makes it hard for you to get eaten to death.
/mob/living/simple_animal/hostile/bear/butter/attack_hand(mob/living/L) //Borrowed code from Cak, feeds people if they hit you. More nutriment but less vitamin to represent BUTTER.
/mob/living/simple_animal/hostile/bear/butter/on_attack_hand(mob/living/L) //Borrowed code from Cak, feeds people if they hit you. More nutriment but less vitamin to represent BUTTER.
..()
if(L.a_intent == INTENT_HARM && L.reagents && !stat)
L.reagents.add_reagent(/datum/reagent/consumable/nutriment, 1)
@@ -523,9 +523,9 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
if(ranged && ranged_cooldown <= world.time)
target = A
OpenFire(A)
..()
DelayNextAction()
. = ..()
return TRUE
////// AI Status ///////
/mob/living/simple_animal/hostile/proc/AICanContinue(var/list/possible_targets)
@@ -136,7 +136,7 @@
target = A
if(!isturf(loc))
return
if(next_move > world.time)
if(!CheckActionCooldown())
return
if(hopping)
return
@@ -70,7 +70,7 @@ Difficulty: Medium
/obj/item/melee/transforming/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user)
target.add_stun_absorption("miner", 10, INFINITY)
..()
. = ..()
target.stun_absorption -= "miner"
/obj/item/projectile/kinetic/miner
@@ -86,8 +86,8 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
var/adjustment_amount = amount * 0.1
if(world.time + adjustment_amount > next_move)
changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly
if(world.time + adjustment_amount > next_action)
DelayNextAction(adjustment_amount, considered_action = FALSE, flush = TRUE) //attacking it interrupts it attacking, but only briefly
. = ..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/death()
@@ -109,7 +109,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/AttackingTarget()
if(QDELETED(target))
return
if(next_move > world.time || !Adjacent(target)) //some cheating
if(!CheckActionCooldown() || !Adjacent(target)) //some cheating
INVOKE_ASYNC(src, .proc/quick_attack_loop)
return
face_atom(target)
@@ -125,8 +125,8 @@ Difficulty: Medium
adjustHealth(-(L.maxHealth * 0.5))
L.gib()
return TRUE
changeNext_move(CLICK_CD_MELEE)
miner_saw.melee_attack_chain(src, target)
miner_saw.melee_attack_chain(src, target, null, ATTACK_IGNORE_CLICKDELAY)
FlushCurrentAction()
if(guidance)
adjustHealth(-2)
transform_weapon()
@@ -161,19 +161,19 @@ Difficulty: Medium
face_atom(target)
new /obj/effect/temp_visual/dir_setting/firing_effect(loc, dir)
Shoot(target)
changeNext_move(CLICK_CD_RANGE)
DelayNextAction(CLICK_CD_RANGE, flush = TRUE)
//I'm still of the belief that this entire proc needs to be wiped from existence.
// do not take my touching of it to be endorsement of it. ~mso
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop()
while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep.
while(!QDELETED(target) && !CheckActionCooldown()) //this is done this way because next_move can change to be sooner while we sleep.
stoplag(1)
sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about
sleep((next_action - world.time) * 1.5) //but don't ask me what the fuck this is about
if(QDELETED(target))
return
if(dashing || next_move > world.time || !Adjacent(target))
if(dashing && next_move <= world.time)
next_move = world.time + 1
if(dashing || !CheckActionCooldown() || !Adjacent(target))
if(dashing && next_action <= world.time)
SetNextAction(1, considered_action = FALSE, immediate = FALSE, flush = TRUE)
INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again.
return
AttackingTarget()
@@ -385,10 +385,7 @@ Difficulty: Very Hard
if(isliving(speaker))
ActivationReaction(speaker, ACTIVATE_SPEECH)
/obj/machinery/anomalous_crystal/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
/obj/machinery/anomalous_crystal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
ActivationReaction(user, ACTIVATE_TOUCH)
/obj/machinery/anomalous_crystal/attackby(obj/item/I, mob/user, params)
@@ -105,7 +105,7 @@ IGNORE_PROC_IF_NOT_TARGET(attack_slime)
/mob/living/simple_animal/hostile/asteroid/curseblob/attacked_by(obj/item/I, mob/living/L, attackchain_flags = NONE, damage_multiplier = 1)
if(L != set_target)
L.changeNext_move(I.click_delay) //pre_attacked_by not called
I.ApplyAttackCooldown(L, src)
return
return ..()
@@ -148,7 +148,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
desc = "You're not quite sure how a signal can be menacing."
invisibility = 100
/obj/structure/elite_tumor/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/elite_tumor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(ishuman(user))
switch(activity)
@@ -170,7 +170,7 @@
Bruise()
..()
/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M)
/mob/living/simple_animal/hostile/mushroom/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) // the attack was blocked
return
@@ -86,7 +86,7 @@
.=..()
START_PROCESSING(SSprocessing, src)
/obj/structure/spawner/nether/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/structure/spawner/nether/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
user.visible_message("<span class='warning'>[user] is violently pulled into the link!</span>", \
"<span class='userdanger'>Touching the portal, you are quickly pulled through into a world of unimaginable horror!</span>")
contents.Add(user)
@@ -51,7 +51,7 @@
else
clear_alert("temp")
/mob/living/simple_animal/hostile/retaliate/clown/attack_hand(mob/living/carbon/human/M)
/mob/living/simple_animal/hostile/retaliate/clown/on_attack_hand(mob/living/carbon/human/M)
..()
playsound(src.loc, 'sound/items/bikehorn.ogg', 50, TRUE)
@@ -271,7 +271,7 @@
* Attack responces
*/
//Humans, monkeys, aliens
/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M)
/mob/living/simple_animal/parrot/on_attack_hand(mob/living/carbon/M)
..()
if(client)
return
@@ -296,7 +296,7 @@
discipline_slime(user)
return ..()
/mob/living/simple_animal/slime/attack_hand(mob/living/carbon/human/M)
/mob/living/simple_animal/slime/on_attack_hand(mob/living/carbon/human/M)
if(buckled)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if(buckled == M)
@@ -356,7 +356,7 @@
attacked += 10
if(prob(25))
user.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
W.ApplyAttackCooldown(user, src)
to_chat(user, "<span class='danger'>[W] passes right through [src]!</span>")
return
if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??