More lenient soft stamina combat, decentralized gun inaccuracy from combat mode. (#12347)

* A more lenient soft stamina crit.

* Yea, your shots are gonna go straight toh.

* accuracy whacks (leaves the bow as is for now).

* Fixing stam penalties calculations, spread the range.

* aaaaaah

* 1.4 seconds delay vs 1.2

* Thanks, linter.

* Missed one.
This commit is contained in:
Ghom
2020-06-02 15:22:06 -07:00
committed by GitHub
parent 0d7d2071ec
commit a41f40503d
38 changed files with 268 additions and 180 deletions
+51 -28
View File
@@ -15,7 +15,7 @@
throw_speed = 3
throw_range = 5
force = 5
item_flags = NEEDS_PERMIT | NO_ATTACK_CHAIN_SOFT_STAMCRIT
item_flags = NEEDS_PERMIT
attack_verb = list("struck", "hit", "bashed")
var/fire_sound = "gunshot"
@@ -140,12 +140,13 @@
to_chat(user, "<span class='danger'>*click*</span>")
playsound(src, "gun_dry_fire", 30, 1)
/obj/item/gun/proc/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1)
/obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
if(recoil)
shake_camera(user, recoil + 1, recoil)
if(isliving(user)) //CIT CHANGE - makes gun recoil cause staminaloss
user.adjustStaminaLossBuffered(getstamcost(user)*(firing && burst_size >= 2 ? 1/burst_size : 1)) //CIT CHANGE - ditto
if(stam_cost) //CIT CHANGE - makes gun recoil cause staminaloss
var/safe_cost = clamp(stam_cost, 0, STAMINA_NEAR_CRIT - user.getStaminaLoss())*(firing && burst_size >= 2 ? 1/burst_size : 1)
user.adjustStaminaLossBuffered(safe_cost) //CIT CHANGE - ditto
if(suppressed)
playsound(user, fire_sound, 10, 1)
@@ -172,9 +173,10 @@
return
if(firing)
return
if(IS_STAMCRIT(user)) //respect stamina softcrit
to_chat(user, "<span class='warning'>You are too exhausted to fire [src]!</span>")
return
var/stamloss = user.getStaminaLoss()
if(stamloss >= STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_GUN_DELAY
user.changeNext_move(CLICK_CD_RANGE+(CLICK_CD_RANGE*penalty))
if(flag) //It's adjacent, is the user, or is on the user's person
if(target in user.contents) //can't shoot stuff inside us.
return
@@ -216,7 +218,7 @@
var/loop_counter = 0
if(user)
bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming
bonus_spread = getinaccuracy(user, bonus_spread, stamloss) //CIT CHANGE - adds bonus spread while not aiming
if(ishuman(user) && user.a_intent == INTENT_HARM && weapon_weight <= WEAPON_LIGHT)
var/mob/living/carbon/human/H = user
for(var/obj/item/gun/G in H.held_items)
@@ -225,9 +227,11 @@
else if(G.can_trigger_gun(user))
bonus_spread += 24 * G.weapon_weight * G.dualwield_spread_mult
loop_counter++
addtimer(CALLBACK(G, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread), loop_counter)
var/stam_cost = G.getstamcost(user)
addtimer(CALLBACK(G, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread, stam_cost), loop_counter)
process_fire(target, user, TRUE, params, null, bonus_spread)
var/stam_cost = getstamcost(user)
process_fire(target, user, TRUE, params, null, bonus_spread, stam_cost)
/obj/item/gun/can_trigger_gun(mob/living/user)
. = ..()
@@ -258,21 +262,21 @@
/obj/item/gun/proc/on_cooldown()
return busy_action || firing || ((last_fire + fire_delay) > world.time)
/obj/item/gun/proc/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/proc/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
add_fingerprint(user)
if(on_cooldown())
return
firing = TRUE
. = do_fire(target, user, message, params, zone_override, bonus_spread)
. = do_fire(target, user, message, params, zone_override, bonus_spread, stam_cost)
firing = FALSE
last_fire = world.time
if(user)
user.update_inv_hands()
SEND_SIGNAL(user, COMSIG_LIVING_GUN_PROCESS_FIRE, target, params, zone_override)
SEND_SIGNAL(user, COMSIG_LIVING_GUN_PROCESS_FIRE, target, params, zone_override, bonus_spread, stam_cost)
/obj/item/gun/proc/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0)
/obj/item/gun/proc/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0, stam_cost = 0)
var/sprd = 0
var/randomized_gun_spread = 0
var/rand_spr = rand()
@@ -290,7 +294,7 @@
sleep(burst_shot_delay)
if(QDELETED(src))
break
do_burst_shot(user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i)
do_burst_shot(user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i, stam_cost)
else
if(chambered)
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
@@ -300,9 +304,9 @@
return
else
if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot
shoot_live_shot(user, 1, target, message)
shoot_live_shot(user, 1, target, message, stam_cost)
else
shoot_live_shot(user, 0, target, message)
shoot_live_shot(user, 0, target, message, stam_cost)
else
shoot_with_empty_chamber(user)
return
@@ -312,7 +316,7 @@
SSblackbox.record_feedback("tally", "gun_fired", 1, type)
return TRUE
/obj/item/gun/proc/do_burst_shot(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0)
/obj/item/gun/proc/do_burst_shot(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0, stam_cost = 0)
if(!user || !firing)
firing = FALSE
return FALSE
@@ -336,9 +340,9 @@
return FALSE
else
if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot
shoot_live_shot(user, 1, target, message)
shoot_live_shot(user, 1, target, message, stam_cost)
else
shoot_live_shot(user, 0, target, message)
shoot_live_shot(user, 0, target, message, stam_cost)
if (iteration >= burst_size)
firing = FALSE
else
@@ -349,20 +353,21 @@
update_icon()
return TRUE
/obj/item/gun/attack(mob/M as mob, mob/user)
/obj/item/gun/attack(mob/living/M, mob/user)
if(user.a_intent == INTENT_HARM) //Flogging
if(bayonet)
M.attackby(bayonet, user)
attack_delay_done = TRUE
return
else
return ..()
return
attack_delay_done = TRUE //we are firing the gun, not bashing people with its butt.
/obj/item/gun/attack_obj(obj/O, mob/user)
if(user.a_intent == INTENT_HARM)
if(bayonet)
O.attackby(bayonet, user)
return
return TRUE
return ..()
/obj/item/gun/attackby(obj/item/I, mob/user, params)
@@ -498,7 +503,7 @@
if(chambered && chambered.BB)
chambered.BB.damage *= 5
process_fire(target, user, TRUE, params)
process_fire(target, user, TRUE, params, stam_cost = getstamcost(user))
/obj/item/gun/proc/unlock() //used in summon guns and as a convience for admins
if(pin)
@@ -566,7 +571,25 @@
chambered = null
update_icon()
/obj/item/gun/proc/getinaccuracy(mob/user)
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
return ((weapon_weight * 25) * inaccuracy_modifier)
return 0
/obj/item/gun/proc/getinaccuracy(mob/living/user, bonus_spread, stamloss)
if(inaccuracy_modifier == 0)
return bonus_spread
var/base_inaccuracy = weapon_weight * 25 * inaccuracy_modifier
var/aiming_delay = 0 //Otherwise aiming would be meaningless for slower guns such as sniper rifles and launchers.
if(fire_delay)
var/penalty = (last_fire + GUN_AIMING_TIME + fire_delay) - world.time
if(penalty > 0) //Yet we only penalize users firing it multiple times in a haste. fire_delay isn't necessarily cumbersomeness.
aiming_delay = penalty
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //To be removed in favor of something less tactless later.
base_inaccuracy /= 1.5
if(stamloss > STAMINA_NEAR_SOFTCRIT) //This can null out the above bonus.
base_inaccuracy *= 1 + (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*0.5
var/mult = max((GUN_AIMING_TIME + aiming_delay + user.last_click_move - world.time)/GUN_AIMING_TIME, -0.5) //Yes, there is a bonus for taking time aiming.
if(mult < 0) //accurate weapons should provide a proper bonus with negative inaccuracy. the opposite is true too.
mult *= 1/inaccuracy_modifier
return max(bonus_spread + (base_inaccuracy * mult), 0) //no negative spread.
/obj/item/gun/proc/getstamcost(mob/living/carbon/user)
. = recoil
if(user && !user.has_gravity())
. = recoil*5