This commit is contained in:
silicons
2020-07-20 10:46:52 -07:00
parent 58e26c540c
commit 984796b8c6
17 changed files with 53 additions and 63 deletions
-8
View File
@@ -138,14 +138,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define MOBILITY_FLAGS_DEFAULT (MOBILITY_MOVE | MOBILITY_STAND | MOBILITY_PICKUP | MOBILITY_USE | MOBILITY_UI | MOBILITY_STORAGE | MOBILITY_PULL | MOBILITY_RESIST)
#define MOBILITY_FLAGS_ANY_INTERACTION (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_UI | MOBILITY_STORAGE)
// melee_attack_chain() attackchain_flags
/// The attack is from a parry counterattack.
#define ATTACKCHAIN_PARRY_COUNTERATTACK (1<<0)
// UnarmedAttack() flags
/// Attack is from a parry counterattack
#define UNARMED_ATTACK_PARRY (1<<0)
/// If the thing can reflect light (lasers/energy)
#define RICOCHET_SHINY (1<<0)
/// If the thing can reflect matter (bullets/bomb shrapnel)
+17
View File
@@ -0,0 +1,17 @@
// melee_attack_chain() attackchain_flags
/// The attack is from a parry counterattack.
#define ATTACKCHAIN_PARRY_COUNTERATTACK (1<<0)
// melee_attack_chain(), attackby(), pre_attack(), afterattack(), and tool_act() return values.
/// Stop the attack chain if still in melee_attack_chain()
#define STOP_ATTACK_PROC_CHAIN (1<<0)
/// This attack should discard last_action instead of flushing (storing) it). You should probably know what you're doing if you use this considering this is how clickdelay is enforced.
#define DISCARD_LAST_ACTION (1<<1)
// UnarmedAttack() flags
/// Attack is from a parry counterattack
#define UNARMED_ATTACK_PARRY (1<<0)
// obj/item/dropped()
/// dropped() relocated this item, return FALSE for doUnEquip.
#define ITEM_RELOCATED_BY_DROPPED "relocated_by_dropped"
-3
View File
@@ -1,3 +0,0 @@
// obj/item/dropped
/// dropped() relocated this item, return FALSE for doUnEquip.
#define ITEM_RELOCATED_BY_DROPPED "relocated_by_dropped"
+2 -4
View File
@@ -111,7 +111,7 @@
//User itself, current loc, and user inventory
if(A in DirectAccess())
if(W)
W.melee_attack_chain(src, A, params)
. = !(W.melee_attack_chain(src, A, params) & DISCARD_LAST_ACTION)
else
UnarmedAttack(A)
return
@@ -123,15 +123,13 @@
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
W.melee_attack_chain(src, A, params)
. = !(W.melee_attack_chain(src, A, params) & DISCARD_LAST_ACTION)
else
DelayNextAction(ismob(A)? 8 : 0)
UnarmedAttack(A, 1)
else
if(W)
W.ranged_attack_chain(src, A, params)
else
DelayNextAction(ismob(A)? 8 : 0)
RangedAttack(A,params)
//Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it
+2 -2
View File
@@ -77,7 +77,7 @@
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents)
if(A == loc || (A in loc) || (A in contents))
W.melee_attack_chain(src, A, params)
. = !(W.melee_attack_chain(src, A, params) & DISCARD_LAST_ACTION)
return
if(!isturf(loc))
@@ -86,7 +86,7 @@
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
if(A.Adjacent(src)) // see adjacent.dm
W.melee_attack_chain(src, A, params)
. = !(W.melee_attack_chain(src, A, params) & DISCARD_LAST_ACTION)
return
else
W.afterattack(A, src, 0, params)
@@ -0,0 +1,58 @@
/obj/screen/mov_intent
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
/obj/screen/sprintbutton
name = "toggle sprint"
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
icon_state = "act_sprint"
layer = ABOVE_HUD_LAYER - 0.1
var/mutable_appearance/flashy
/obj/screen/sprintbutton/Click()
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
H.default_toggle_sprint()
/obj/screen/sprintbutton/update_icon_state()
var/mob/living/user = hud?.mymob
if(!istype(user))
return
if(user.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
icon_state = "act_sprint_on"
else if(HAS_TRAIT(user, TRAIT_SPRINT_LOCKED))
icon_state = "act_sprint_locked"
else
icon_state = "act_sprint"
/obj/screen/sprintbutton/update_overlays()
. = ..()
var/mob/living/carbon/user = hud?.mymob
if(!istype(user) || !user.client)
return
if((user.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) && user.client.prefs.hud_toggle_flash)
if(!flashy)
flashy = mutable_appearance('icons/mob/screen_gen.dmi', "togglehalf_flash")
if(flashy.color != user.client.prefs.hud_toggle_color)
flashy.color = user.client.prefs.hud_toggle_color
. += flashy
//Sprint buffer onscreen code.
/datum/hud/var/obj/screen/sprint_buffer/sprint_buffer
/obj/screen/sprint_buffer
name = "sprint buffer"
icon = 'icons/effects/progessbar.dmi'
icon_state = "prog_bar_100"
/obj/screen/sprint_buffer/Click()
if(isliving(usr))
var/mob/living/L = usr
to_chat(L, "<span class='boldnotice'>Your sprint buffer's maximum capacity is [L.sprint_buffer_max]. It is currently at [L.sprint_buffer], regenerating at [L.sprint_buffer_regen_ds * 10] per second. \
Sprinting while this is empty will incur a [L.sprint_stamina_cost] stamina cost per tile.</span>")
/obj/screen/sprint_buffer/proc/update_to_mob(mob/living/L)
var/amount = 0
if(L.sprint_buffer_max > 0)
amount = round(clamp((L.sprint_buffer / L.sprint_buffer_max) * 100, 0, 100), 5)
icon_state = "prog_bar_[amount]"
@@ -0,0 +1,61 @@
/datum/hud/var/obj/screen/staminas/staminas
/datum/hud/var/obj/screen/staminabuffer/staminabuffer
/obj/screen/staminas
icon = 'modular_citadel/icons/ui/screen_gen.dmi'
name = "stamina"
icon_state = "stamina0"
screen_loc = ui_stamina
mouse_opacity = 1
/obj/screen/staminas/Click(location,control,params)
if(isliving(usr))
var/mob/living/L = usr
to_chat(L, "<span class='notice'>You have <b>[L.getStaminaLoss()]</b> stamina loss.<br>Your stamina buffer can take <b>[L.stambuffer]</b> stamina loss, and recharges at no cost.<br>Your stamina buffer is <b>[(L.stambuffer*(100/L.stambuffer))-(L.bufferedstam*(100/L.stambuffer))]%</b> full.</span>")
/obj/screen/staminas/update_icon_state()
var/mob/living/carbon/user = hud?.mymob
if(!user)
return
if(user.stat == DEAD || (user.combat_flags & COMBAT_FLAG_HARD_STAMCRIT) || (user.hal_screwyhud in 1 to 2))
icon_state = "staminacrit"
else if(user.hal_screwyhud == 5)
icon_state = "stamina0"
else
icon_state = "stamina[clamp(FLOOR(user.getStaminaLoss() /20, 1), 0, 6)]"
//stam buffer
/obj/screen/staminabuffer
icon = 'modular_citadel/icons/ui/screen_gen.dmi'
name = "stamina buffer"
icon_state = "stambuffer0"
screen_loc = ui_stamina
layer = ABOVE_HUD_LAYER + 0.1
mouse_opacity = 0
/obj/screen/staminabuffer/update_icon_state()
var/mob/living/carbon/user = hud?.mymob
if(!user)
return
if(user.stat == DEAD || (user.combat_flags & COMBAT_FLAG_HARD_STAMCRIT) || (user.hal_screwyhud in 1 to 2))
icon_state = "stambuffer7"
else if(user.hal_screwyhud == 5)
icon_state = "stambuffer0"
else
switch(user.bufferedstam / user.stambuffer)
if(0.95 to INFINITY)
icon_state = "stambuffer7"
if(0.9 to 0.95)
icon_state = "stambuffer6"
if(0.8 to 0.9)
icon_state = "stambuffer5"
if(0.6 to 0.8)
icon_state = "stambuffer4"
if(0.4 to 0.6)
icon_state = "stambuffer3"
if(0.2 to 0.4)
icon_state = "stambuffer2"
if(0.05 to 0.2)
icon_state = "stambuffer1"
else
icon_state = "stambuffer0"
+22
View File
@@ -0,0 +1,22 @@
/obj/screen/voretoggle
name = "toggle vore mode"
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
icon_state = "nom_off"
/obj/screen/voretoggle/Click()
if(usr != hud.mymob)
return
var/mob/living/carbon/C = usr
if(SEND_SIGNAL(usr, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
to_chat(usr, "<span class='warning'>Disable combat mode first.</span>")
return
C.toggle_vore_mode()
/obj/screen/voretoggle/update_icon_state()
var/mob/living/carbon/user = hud?.mymob
if(!istype(user))
return
if(user.voremode)
icon_state = "nom"
else
icon_state = "nom_off"
+17 -17
View File
@@ -13,15 +13,15 @@
if(!CHECK_MOBILITY(L, MOBILITY_USE) && !(flags & ATTACKCHAIN_PARRY_COUNTERATTACK))
to_chat(L, "<span class='warning'>You are unable to swing [src] right now!</span>")
return
if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
if(tool_behaviour && ((. = target.tool_act(user, src, tool_behaviour)) & STOP_ATTACK_PROC_CHAIN))
return
if(pre_attack(target, user, params))
if((. |= pre_attack(target, user, params)) & STOP_ATTACK_PROC_CHAIN)
return
if(target.attackby(src, user, params, flags, damage_multiplier))
if((. |= target.attackby(src, user, params, flags, damage_multiplier)) & STOP_ATTACK_PROC_CHAIN)
return
if(QDELETED(src) || QDELETED(target))
return
afterattack(target, user, TRUE, params)
. |= afterattack(target, user, TRUE, params)
/// Like melee_attack_chain but for ranged.
/obj/item/proc/ranged_attack_chain(mob/user, atom/target, params)
@@ -40,25 +40,25 @@
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK)
return TRUE
if(!PreatackClickdelayCheck(user, A))
return TRUE
PreattackClickdelaySet(user, A)
return FALSE //return TRUE to avoid calling attackby after this proc does stuff
return STOP_ATTACK_PROC_CHAIN
if(!CheckAttackCooldown(user, A))
return STOP_ATTACK_PROC_CHAIN
// No comment
/atom/proc/attackby(obj/item/W, mob/user, params)
if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
return TRUE
return FALSE
return STOP_ATTACK_PROC_CHAIN
/obj/attackby(obj/item/I, mob/living/user, params)
return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_obj(src, user))
. = ..()
if(obj_flags & CAN_BE_HIT)
. |= I.attack_obj(src, user)
/mob/living/attackby(obj/item/I, mob/living/user, params, attackchain_flags, damage_multiplier)
if(..())
return TRUE
. = I.attack(src, user, attackchain_flags, damage_multiplier)
. = ..()
if(. & STOP_ATTACK_PROC_CHAIN)
return
. |= I.attack(src, user, attackchain_flags, damage_multiplier)
/obj/item/proc/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
@@ -80,7 +80,7 @@
user.do_attack_animation(M)
M.attacked_by(src, user, attackchain_flags, damage_multiplier)
PostattackClickdelaySet(user, M)
SetAttackCooldown(user, M)
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
add_fingerprint(user)
@@ -97,7 +97,7 @@
return
user.do_attack_animation(O)
O.attacked_by(src, user)
PostattackClickdelaySet(user, O)
SetAttackCooldown(user, O)
var/weight = getweight(user, STAM_COST_ATTACK_OBJ_MULT)
if(weight)
user.adjustStaminaLossBuffered(weight)//CIT CHANGE - makes attacking things cause stamina loss
+70
View File
@@ -0,0 +1,70 @@
/mob/proc/RightClickOn(atom/A, params) //mostly a copy-paste from ClickOn()
var/list/modifiers = params2list(params)
if(incapacitated(ignore_restraints = 1))
return
face_atom(A)
if(!CheckActionCooldown())
return
if(!modifiers["catcher"] && A.IsObscured())
return
if(ismecha(loc))
var/obj/mecha/M = loc
return M.click_action(A,src,params)
if(restrained())
DelayNextAction(CLICK_CD_HANDCUFFED)
RestrainedClickOn(A)
return
if(in_throw_mode)
throw_item(A)//todo: make it plausible to lightly toss items via right-click
return
var/obj/item/W = get_active_held_item()
if(W == A)
if(!W.rightclick_attack_self(src))
W.attack_self(src)
update_inv_hands()
return
//These are always reachable.
//User itself, current loc, and user inventory
if(A in DirectAccess())
if(W)
W.rightclick_melee_attack_chain(src, A, params)
else
if(!AltUnarmedAttack(A))
UnarmedAttack(A)
return
//Can't reach anything else in lockers or other weirdness
if(!loc.AllowClick())
return
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
W.rightclick_melee_attack_chain(src, A, params)
else
if(!AltUnarmedAttack(A,1))
UnarmedAttack(A,1)
else
if(W)
if(!W.altafterattack(A, src, FALSE, params))
W.afterattack(A, src, FALSE, params)
else
if(!AltRangedAttack(A,params))
RangedAttack(A,params)
/mob/proc/AltUnarmedAttack(atom/A, proximity_flag)
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
return FALSE
/mob/proc/AltRangedAttack(atom/A, params)
return FALSE
+20
View File
@@ -0,0 +1,20 @@
/obj/item/proc/rightclick_melee_attack_chain(mob/user, atom/target, params)
if(!alt_pre_attack(target, user, params)) //Hey, does this item have special behavior that should override all normal right-click functionality?
if(!target.altattackby(src, user, params)) //Does the target do anything special when we right-click on it?
melee_attack_chain(user, target, params) //Ugh. Lame! I'm filing a legal complaint about the discrimination against the right mouse button!
else
altafterattack(target, user, TRUE, params)
return
/obj/item/proc/alt_pre_attack(atom/A, mob/living/user, params)
return FALSE //return something other than false if you wanna override attacking completely
/atom/proc/altattackby(obj/item/W, mob/user, params)
return FALSE //return something other than false if you wanna add special right-click behavior to objects.
/obj/item/proc/rightclick_attack_self(mob/user)
return FALSE
/obj/item/proc/altafterattack(atom/target, mob/user, proximity_flag, click_parameters)
SEND_SIGNAL(src, COMSIG_ITEM_ALT_AFTERATTACK, target, user, proximity_flag, click_parameters)
return FALSE
+51
View File
@@ -0,0 +1,51 @@
/mob/living/carbon/human/AltUnarmedAttack(atom/A, proximity)
if(!has_active_hand())
to_chat(src, "<span class='notice'>You look at the state of the universe and sigh.</span>") //lets face it, people rarely ever see this message in its intended condition.
return TRUE
if(!A.alt_attack_hand(src))
A.attack_hand(src)
return TRUE
return TRUE
/mob/living/carbon/human/AltRangedAttack(atom/A, params)
if(isturf(A) || incapacitated()) // pretty annoying to wave your fist at floors and walls. And useless.
return TRUE
changeNext_move(CLICK_CD_RANGE)
var/list/target_viewers = fov_viewers(11, A) //doesn't check for blindness.
if(!(src in target_viewers)) //click catcher issuing calls for out of view objects.
return TRUE
if(!has_active_hand())
to_chat(src, "<span class='notice'>You ponder your life choices and sigh.</span>")
return TRUE
var/list/src_viewers = viewers(DEFAULT_MESSAGE_RANGE, src) - src // src has a different message.
var/the_action = "waves to [A]"
var/what_action = "waves to something you can't see"
var/self_action = "wave to [A]"
switch(a_intent)
if(INTENT_DISARM)
the_action = "shoos away [A]"
what_action = "shoo away something out of your vision"
self_action = "shoo away [A]"
if(INTENT_GRAB)
the_action = "beckons [A] to come"
what_action = "beckons something out of your vision to come"
self_action = "beckon [A] to come"
if(INTENT_HARM)
var/pronoun = "[p_their()]"
the_action = "shakes [pronoun] fist at [A]"
what_action = "shakes [pronoun] fist at something out of your vision"
self_action = "shake your fist at [A]"
if(!eye_blind)
to_chat(src, "You [self_action].")
for(var/B in src_viewers)
var/mob/M = B
if(!M.eye_blind)
var/message = (M in target_viewers) ? the_action : what_action
to_chat(M, "[src] [message].")
return TRUE
/atom/proc/alt_attack_hand(mob/user)
return FALSE
+1
View File
@@ -8,6 +8,7 @@
icon = 'icons/obj/card.dmi'
item_flags = NOBLUDGEON
w_class = WEIGHT_CLASS_TINY
attack_cooldown = CLICK_CD_MELEE
var/datum/supply_pack/discounted_pack
var/discount_pct_off = 0.05
var/obj/machinery/computer/cargo/inserted_console
+7 -16
View File
@@ -133,34 +133,25 @@
/obj/item
// Standard clickdelay variables
/// Amount of time to check for from a mob's last attack, checked before an attack happens
var/preattack_cooldown_check = CLICK_CD_MELEE
/// Amount of time to delay a mob's next attack, added after an attack happens
var/postattack_cooldown_penalty = 0
/// 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
/// This item sets clickdelay in preattack rather than post attack. This means it's set in a melee attack even if the user doesn't bash or bop it against something.
var/clickdelay_set_on_pre_attack = FALSE
/**
* Checks if a user's clickdelay is met for a standard attack
* Checks if a user's clickdelay is met for a standard attack, this is called before an attack happens.
*/
/obj/item/proc/PreattackClickdelayCheck(mob/user, atom/target)
/obj/item/proc/CheckAttackCooldown(mob/user, atom/target)
return user.CheckActionCooldown(action_cooldown_preattack, clickdelay_from_next_action, clickdelay_mod_bypass, clickdelay_ignores_next_action)
/**
* Called if check is successful before the attack happens.
*/
/obj/item/proc/PreattackClickdelaySet(mob/user, atom/target)
if(clickdelay_set_on_pre_attack)
user.DelayNextAction(0, FALSE, TRUE)
/**
* Called after a successful attack to set a mob's clickdelay.
*/
/obj/item/proc/PostattackClickdelaySet(mob/user, atom/target)
/obj/item/proc/ApplyAttackCooldown(mob/user, atom/target)
user.DelayNextAction(postattack_cooldown_penalty, clickdelay_mod_bypass, FALSE)
+2 -2
View File
@@ -812,11 +812,11 @@
return
/obj/item/light/attack(mob/living/M, mob/living/user, def_zone)
..()
. = ..()
shatter()
/obj/item/light/attack_obj(obj/O, mob/living/user)
..()
. = ..()
shatter()
/obj/item/light/proc/shatter()
+1 -2
View File
@@ -366,8 +366,7 @@
/obj/item/gun/attack_obj(obj/O, mob/user)
if(user.a_intent == INTENT_HARM)
if(bayonet)
O.attackby(bayonet, user)
return TRUE
return O.attackby(bayonet, user)
return ..()
/obj/item/gun/attackby(obj/item/I, mob/user, params)