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-03 00:22:06 +02:00
committed by GitHub
parent 0d7d2071ec
commit a41f40503d
38 changed files with 268 additions and 180 deletions

View File

@@ -61,10 +61,18 @@
#define CHECK_STAMCRIT(mob) ((mob.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)? HARD_STAMCRIT : ((mob.combat_flags & COMBAT_FLAG_SOFT_STAMCRIT)? SOFT_STAMCRIT : NOT_STAMCRIT))
//stamina stuff
#define STAMINA_SOFTCRIT 100 //softcrit for stamina damage. prevents standing up, prevents performing actions that cost stamina, etc, but doesn't force a rest or stop movement
#define STAMINA_CRIT 140 //crit for stamina damage. forces a rest, and stops movement until stamina goes back to stamina softcrit
#define STAMINA_SOFTCRIT_TRADITIONAL 0 //same as STAMINA_SOFTCRIT except for the more traditional health calculations
#define STAMINA_CRIT_TRADITIONAL -40 //ditto, but for STAMINA_CRIT
///Threshold over which attacks start being hindered.
#define STAMINA_NEAR_SOFTCRIT 90
///softcrit for stamina damage. prevents standing up, some actions that cost stamina, etc, but doesn't force a rest or stop movement
#define STAMINA_SOFTCRIT 100
///sanity cap to prevent stamina actions (that are still performable) from sending you into crit.
#define STAMINA_NEAR_CRIT 130
///crit for stamina damage. forces a rest, and stops movement until stamina goes back to stamina softcrit
#define STAMINA_CRIT 140
///same as STAMINA_SOFTCRIT except for the more traditional health calculations
#define STAMINA_SOFTCRIT_TRADITIONAL 0
///ditto, but for STAMINA_CRIT
#define STAMINA_CRIT_TRADITIONAL -40
#define CRAWLUNDER_DELAY 30 //Delay for crawling under a standing mob
@@ -182,6 +190,9 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define EGUN_SELFCHARGE 1
#define EGUN_SELFCHARGE_BORG 2
///Time to spend without clicking on other things required for your shots to become accurate.
#define GUN_AIMING_TIME (2 SECONDS)
//Object/Item sharpness
#define IS_BLUNT 0
#define IS_SHARP 1
@@ -249,6 +260,21 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define STAM_COST_W_CLASS_MULT 1.25
#define STAM_COST_THROW_MULT 2
///Multiplier of the (STAMINA_NEAR_CRIT - user current stamina loss) : (STAMINA_NEAR_CRIT - STAMINA_SOFTCRIT) ratio used in damage penalties when stam soft-critted.
#define STAM_CRIT_ITEM_ATTACK_PENALTY 0.66
/// changeNext_move penalty multiplier of the above.
#define STAM_CRIT_ITEM_ATTACK_DELAY 1.75
/// Damage penalty when fighting prone.
#define LYING_DAMAGE_PENALTY 0.5
/// Added delay when firing guns stam-softcritted. Summed with a hardset CLICK_CD_RANGE delay, similar to STAM_CRIT_DAMAGE_DELAY otherwise.
#define STAM_CRIT_GUN_DELAY 2.75
/**
* should the current-attack-damage be lower than the item force multiplied by this value,
* a "inefficiently" prefix will be added to the message.
*/
#define INEFFICIENT_ATTACK_MSG_THRESHOLD 0.7
//bullet_act() return values
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.

View File

@@ -18,18 +18,29 @@
// Flags for the item_flags var on /obj/item
#define BEING_REMOVED (1<<0)
#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips
#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips
#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
///is this item equipped into an inventory slot or hand of a mob? used for tooltips
#define IN_INVENTORY (1<<1)
///used for tooltips
#define FORCE_STRING_OVERRIDE (1<<2)
///Used by security bots to determine if this item is safe for public use.
#define NEEDS_PERMIT (1<<3)
#define SLOWS_WHILE_IN_HAND (1<<4)
#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
#define DROPDEL (1<<6) //When dropped, it calls qdel on itself
#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff
#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
#define NO_ATTACK_CHAIN_SOFT_STAMCRIT (1<<12) //Entirely blocks melee_attack_chain() if user is soft stamcritted. Uses getStaminaLoss() to check at this point in time. THIS DOES NOT BLOCK RANGED AFTERATTACK()S, ONLY MELEE RANGE AFTERATTACK()S.
///Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
#define NO_MAT_REDEMPTION (1<<5)
///When dropped, it calls qdel on itself
#define DROPDEL (1<<6)
///when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
#define NOBLUDGEON (1<<7)
///for all things that are technically items but used for various different stuff
#define ABSTRACT (1<<8)
///When players should not be able to change the slowdown of the item (Speed potions, ect)
#define IMMUTABLE_SLOW (1<<9)
///Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
#define SURGICAL_TOOL (1<<10)
///Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
#define NO_UNIFORM_REQUIRED (1<<11)
///Damage when attacking people is not affected by combat mode.
#define NO_COMBAT_MODE_FORCE_MODIFIER (1<<12)
// Flags for the clothing_flags var on /obj/item/clothing

View File

@@ -21,6 +21,7 @@
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
/mob/living/changeNext_move(num)
last_click_move = next_move
var/mod = next_move_modifier
var/adj = next_move_adjust
for(var/i in status_effects)

View File

@@ -10,10 +10,6 @@
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
if(isliving(user))
var/mob/living/L = user
if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT)
if(IS_STAMCRIT(L))
to_chat(L, "<span class='warning'>You are too exhausted to swing [src]!</span>")
return
if(!CHECK_MOBILITY(L, MOBILITY_USE))
to_chat(L, "<span class='warning'>You are unable to swing [src] right now!</span>")
return
@@ -59,8 +55,10 @@
/mob/living/attackby(obj/item/I, mob/living/user, params)
if(..())
return TRUE
user.changeNext_move(CLICK_CD_MELEE)
return I.attack(src, user)
I.attack_delay_done = FALSE //Should be set TRUE in pre_attacked_by()
. = I.attack(src, user)
if(!I.attack_delay_done) //Otherwise, pre_attacked_by() should handle it.
user.changeNext_move(I.click_delay)
/obj/item/proc/attack(mob/living/M, mob/living/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
@@ -68,11 +66,6 @@
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(item_flags & NOBLUDGEON)
return
if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
return
@@ -91,7 +84,9 @@
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
add_fingerprint(user)
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_MOB_MULT))//CIT CHANGE - makes attacking things cause stamina loss
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT) //CIT CHANGE - makes attacking things cause stamina loss
if(weight)
user.adjustStaminaLossBuffered(weight)
//the equivalent of the standard version of attack() but for object targets.
/obj/item/proc/attack_obj(obj/O, mob/living/user)
@@ -99,13 +94,12 @@
return
if(item_flags & NOBLUDGEON)
return
if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_OBJ_MULT))//CIT CHANGE - makes attacking things cause stamina loss
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(O)
O.attacked_by(src, user)
if(!O.attacked_by(src, user))
user.changeNext_move(click_delay)
var/weight = getweight(user, STAM_COST_ATTACK_OBJ_MULT)
if(weight)
user.adjustStaminaLossBuffered(weight)//CIT CHANGE - makes attacking things cause stamina loss
/atom/movable/proc/attacked_by()
return
@@ -113,9 +107,18 @@
/obj/attacked_by(obj/item/I, mob/living/user)
var/totitemdamage = I.force
var/bad_trait
if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
totitemdamage *= 0.5
var/stamloss = user.getStaminaLoss()
var/next_move_mult = 1
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_ITEM_ATTACK_PENALTY
totitemdamage *= 1 - penalty
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
user.changeNext_move(I.click_delay*next_move_mult)
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
if(I.used_skills && user.mind)
if(totitemdamage)
totitemdamage = user.mind.item_action_skills_mod(I, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_trait)
@@ -123,17 +126,19 @@
if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_OBJ))
continue
user.mind.auto_gain_experience(skill, I.skill_gain)
if(totitemdamage)
visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", null, null, COMBAT_MESSAGE_RANGE)
//only witnesses close by and the victim see a hit message.
log_combat(user, src, "attacked", I)
take_damage(totitemdamage, I.damtype, "melee", 1)
return TRUE
/mob/living/attacked_by(obj/item/I, mob/living/user)
var/totitemdamage = pre_attacked_by(I, user)
if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, null, null) & BLOCK_SUCCESS)
return FALSE
send_item_attack_message(I, user)
send_item_attack_message(I, user, null, totitemdamage)
I.do_stagger_action(src, user, totitemdamage)
if(I.force)
apply_damage(totitemdamage, I.damtype)
@@ -149,19 +154,37 @@
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user)
if(I.force < force_threshold || I.damtype == STAMINA)
playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
user.changeNext_move(I.click_delay) //pre_attacked_by not called
else
return ..()
/mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user)
. = I.force
if(!.)
return
var/stamloss = user.getStaminaLoss()
var/stam_mobility_mult = 1
var/next_move_mult = 1
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_ITEM_ATTACK_PENALTY
stam_mobility_mult -= penalty
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
if(stam_mobility_mult > LYING_DAMAGE_PENALTY && !CHECK_MOBILITY(user, MOBILITY_STAND)) //damage penalty for fighting prone, doesn't stack with the above.
stam_mobility_mult = LYING_DAMAGE_PENALTY
. *= stam_mobility_mult
user.changeNext_move(I.click_delay*next_move_mult)
I.attack_delay_done = TRUE
var/bad_trait
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
. *= 0.5
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
. *= 1.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
. *= 0.5
if(!(I.item_flags & NO_COMBAT_MODE_FORCE_MODIFIER))
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
. *= 0.5
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
. *= 1.5
if(!user.mind || !I.used_skills)
return
if(.)
@@ -171,7 +194,6 @@
continue
user.mind.auto_gain_experience(skill, I.skill_gain)
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
// Click parameters is the params string from byond Click() code, see that documentation.
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
@@ -185,10 +207,12 @@
else
return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, current_force)
var/message_verb = "attacked"
if(I.attack_verb && I.attack_verb.len)
message_verb = "[pick(I.attack_verb)]"
if(current_force < I.force * INEFFICIENT_ATTACK_MSG_THRESHOLD)
message_verb = "inefficiently [message_verb]"
else if(!I.force)
return
var/message_hit_area = ""
@@ -215,6 +239,8 @@
bad_trait = SKILL_COMBAT_MODE
if(used_skills && user.mind)
. = user.mind.item_action_skills_mod(src, ., skill_difficulty, trait, bad_trait, FALSE)
var/total_health = user.getStaminaLoss()
. = clamp(., 0, STAMINA_NEAR_CRIT - total_health)
/// How long this staggers for. 0 and negatives supported.
/obj/item/proc/melee_stagger_duration(force_override)

View File

@@ -147,7 +147,7 @@
/obj/machinery/dominator/attacked_by(obj/item/I, mob/living/user)
add_fingerprint(user)
..()
return ..()
/obj/machinery/dominator/attack_hand(mob/user)
if(operating || (stat & BROKEN))

View File

@@ -71,7 +71,7 @@
return ..()
/obj/machinery/porta_turret_cover/attacked_by(obj/item/I, mob/user)
parent_turret.attacked_by(I, user)
return parent_turret.attacked_by(I, user)
/obj/machinery/porta_turret_cover/attack_alien(mob/living/carbon/alien/humanoid/user)
parent_turret.attack_alien(user)

View File

@@ -284,7 +284,7 @@
/obj/mecha/attacked_by(obj/item/I, mob/living/user)
mecha_log_message("Attacked by [I]. Attacker - [user]")
..()
return ..()
/obj/mecha/proc/mech_toxin_damage(mob/living/target)
playsound(src, 'sound/effects/spray2.ogg', 50, 1)

View File

@@ -55,6 +55,15 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/// How long, in deciseconds, this staggers for, if null it will autocalculate from w_class and force. Unlike total mass this supports 0 and negatives.
var/stagger_force
/**
* Set FALSE and then checked at the end of on mob/living/attackby(), set TRUE on living/pre_attacked_by().
* Should it be FALSE by the end of the item/attack(), that means the item overrode the standard attack behaviour
* and the user still needs the delay applied. We can't be using return values since that'll stop afterattack() from being triggered.
*/
var/attack_delay_done = FALSE
///next_move click/attack delay of this item.
var/click_delay = CLICK_CD_MELEE
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
pass_flags = PASSTABLE
pressure_resistance = 4

View File

@@ -65,7 +65,7 @@
. = ..()
AddElement(/datum/element/update_icon_blocker)
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
if(field)
field_disconnect(field)
..()

View File

@@ -6,6 +6,7 @@
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
flags_1 = CONDUCT_1
item_flags = NEEDS_PERMIT | NO_COMBAT_MODE_FORCE_MODIFIER //To avoid ambushing and oneshotting healthy crewmembers on force setting 3.
attack_verb = list("whacked", "fisted", "power-punched")
force = 20
throwforce = 10
@@ -13,7 +14,7 @@
w_class = WEIGHT_CLASS_NORMAL
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 40)
resistance_flags = FIRE_PROOF
var/click_delay = 1.5
click_delay = CLICK_CD_MELEE * 1.5
var/fisto_setting = 1
var/gasperfist = 3
var/obj/item/tank/internals/tank = null //Tank used for the gauntlet's piston-ram.
@@ -70,42 +71,46 @@
/obj/item/melee/powerfist/attack(mob/living/target, mob/living/user)
if(!tank)
to_chat(user, "<span class='warning'>\The [src] can't operate without a source of gas!</span>")
return
var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting)
var/turf/T = get_turf(src)
if(!T)
return
T.assume_air(gasused)
T.air_update_turf()
if(!gasused)
to_chat(user, "<span class='warning'>\The [src]'s tank is empty!</span>")
target.apply_damage((force / 5), BRUTE)
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punches you!</span>")
return
if(gasused.total_moles() < gasperfist * fisto_setting)
to_chat(user, "<span class='warning'>\The [src]'s piston-ram lets out a weak hiss, it needs more gas!</span>")
playsound(loc, 'sound/weapons/punch4.ogg', 50, 1)
target.apply_damage((force / 2), BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
return
target.apply_damage(force * fisto_setting, BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
new /obj/effect/temp_visual/kinetic_blast(target.loc)
playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1)
playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
return FALSE
if(!tank)
to_chat(user, "<span class='warning'>\The [src] can't operate without a source of gas!</span>")
return FALSE
var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting)
var/turf/T = get_turf(src)
if(!T)
return FALSE
var/totalitemdamage = target.pre_attacked_by(src, user)
T.assume_air(gasused)
T.air_update_turf()
if(!gasused)
to_chat(user, "<span class='warning'>\The [src]'s tank is empty!</span>")
target.apply_damage((totalitemdamage / 5), BRUTE)
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punches you!</span>")
return
if(gasused.total_moles() < gasperfist * fisto_setting)
to_chat(user, "<span class='warning'>\The [src]'s piston-ram lets out a weak hiss, it needs more gas!</span>")
playsound(loc, 'sound/weapons/punch4.ogg', 50, 1)
target.apply_damage((totalitemdamage / 2), BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
return
target.apply_damage(totalitemdamage * fisto_setting, BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
new /obj/effect/temp_visual/kinetic_blast(target.loc)
playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1)
playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1)
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2))
target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2))
log_combat(user, target, "power fisted", src)
log_combat(user, target, "power fisted", src)
user.changeNext_move(CLICK_CD_MELEE * click_delay)
return
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT)
if(weight)
user.adjustStaminaLossBuffered(weight)
return TRUE

View File

@@ -141,7 +141,7 @@
/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
var/interrupt = common_baton_melee(M, user, FALSE)
if(!interrupt)
..()
return ..()
/obj/item/melee/baton/alt_pre_attack(atom/A, mob/living/user, params)
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-disarming.
@@ -154,7 +154,7 @@
if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
clowning_around(user)
if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")
to_chat(user, "<span class='danger'>You're too exhausted to use [src] properly.</span>")
return TRUE
if(ishuman(M))
var/mob/living/carbon/human/L = M

View File

@@ -1176,14 +1176,13 @@
/obj/item/twohanded/electrostaff/attack(mob/living/target, mob/living/user)
if(IS_STAMCRIT(user))//CIT CHANGE - makes it impossible to baton in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")//CIT CHANGE - ditto
to_chat(user, "<span class='danger'>You're too exhausted to use [src] properly.</span>")//CIT CHANGE - ditto
return //CIT CHANGE - ditto
if(on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
clowning_around(user) //ouch!
return
if(iscyborg(target))
..()
return
return ..()
if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS) //No message; run_block() handles that
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE

View File

@@ -343,7 +343,7 @@
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "disintegrate"
item_state = null
item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL | NO_ATTACK_CHAIN_SOFT_STAMCRIT
item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
throwforce = 0

View File

@@ -118,22 +118,10 @@
/mob/living/carbon/true_devil/attacked_by(obj/item/I, mob/living/user, def_zone)
var/weakness = check_weakness(I, user)
apply_damage(I.force * weakness, I.damtype, def_zone)
var/message_verb = ""
if(I.attack_verb && I.attack_verb.len)
message_verb = "[pick(I.attack_verb)]"
else if(I.force)
message_verb = "attacked"
var/attack_message = "[src] has been [message_verb] with [I]."
if(user)
user.do_attack_animation(src)
if(user in viewers(src, null))
attack_message = "[user] has [message_verb] [src] with [I]!"
if(message_verb)
visible_message("<span class='danger'>[attack_message]</span>",
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
var/totitemdamage = pre_attacked_by(I, user)
totitemdamage *= check_weakness(I, user)
apply_damage(totitemdamage, I.damtype, def_zone)
send_item_attack_message(I, user, null, totitemdamage)
return TRUE
/mob/living/carbon/true_devil/singularity_act()

View File

@@ -40,9 +40,6 @@
return ..()
return ..()
/obj/item/holo/esword/attack(target as mob, mob/user as mob)
..()
/obj/item/holo/esword/Initialize()
. = ..()
saber_color = pick("red","blue","green","purple")

View File

@@ -8,6 +8,8 @@
typing_indicator_enabled = TRUE
var/last_click_move = 0 // Stores the previous next_move value.
var/resize = 1 //Badminnery resize
var/lastattacker = null
var/lastattackerckey = null

View File

@@ -105,6 +105,7 @@ IGNORE_PROC_IF_NOT_TARGET(attack_slime)
/mob/living/simple_animal/hostile/asteroid/curseblob/attacked_by(obj/item/I, mob/living/L)
if(L != set_target)
L.changeNext_move(I.click_delay) //pre_attacked_by not called
return
return ..()

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

View File

@@ -365,7 +365,7 @@
can_unsuppress = TRUE
can_suppress = TRUE
w_class = WEIGHT_CLASS_NORMAL
inaccuracy_modifier = 0
inaccuracy_modifier = 0.5
zoomable = TRUE
zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you.
zoom_out_amt = 13

View File

@@ -130,7 +130,7 @@
else
qdel(src)
/obj/item/gun/ballistic/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/ballistic/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
if(ammo_pack)
if(ammo_pack.overheat < ammo_pack.overheat_max)
ammo_pack.overheat += burst_size

View File

@@ -6,7 +6,7 @@
name = "grenade launcher"
icon_state = "dshotgun-sawn"
item_state = "gun"
inaccuracy_modifier = 0
inaccuracy_modifier = 0.5
mag_type = /obj/item/ammo_box/magazine/internal/grenadelauncher
fire_sound = 'sound/weapons/grenadelaunch.ogg'
w_class = WEIGHT_CLASS_NORMAL
@@ -87,7 +87,7 @@
pin = /obj/item/firing_pin/implant/pindicate
burst_size = 1
fire_delay = 0
inaccuracy_modifier = 0
inaccuracy_modifier = 0.25
casing_ejector = FALSE
weapon_weight = WEAPON_HEAVY
magazine_wording = "rocket"

View File

@@ -14,7 +14,7 @@
spread = 0
recoil = 0.1
casing_ejector = FALSE
inaccuracy_modifier = 0
inaccuracy_modifier = 0.15
dualwield_spread_mult = 1.4
weapon_weight = WEAPON_MEDIUM
w_class = WEIGHT_CLASS_BULKY
@@ -46,7 +46,7 @@
return 0
. = ..()
/obj/item/gun/ballistic/automatic/magrifle/shoot_live_shot()
/obj/item/gun/ballistic/automatic/magrifle/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
var/obj/item/ammo_casing/caseless/magnetic/shot = chambered
cell.use(shot.energy_cost)
. = ..()

View File

@@ -102,7 +102,7 @@
. = ..()
safe_calibers = magazine.caliber
/obj/item/gun/ballistic/revolver/detective/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/ballistic/revolver/detective/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
if(chambered && !(chambered.caliber in safe_calibers))
if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60
playsound(user, fire_sound, 50, 1)
@@ -242,7 +242,7 @@
user.visible_message("<span class='danger'>*click*</span>")
playsound(src, "gun_dry_fire", 30, 1)
/obj/item/gun/ballistic/revolver/russian/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/ballistic/revolver/russian/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
add_fingerprint(user)
playsound(src, "gun_dry_fire", 30, TRUE)
user.visible_message("<span class='danger'>[user.name] tries to fire \the [src] at the same time, but only succeeds at looking like an idiot.</span>", "<span class='danger'>\The [src]'s anti-combat mechanism prevents you from firing it at the same time!</span>")

View File

@@ -116,7 +116,7 @@
icon_state = "moistnugget"
item_state = "moistnugget"
slot_flags = 0 //no ITEM_SLOT_BACK sprite, alas
inaccuracy_modifier = 0
inaccuracy_modifier = 0.5
mag_type = /obj/item/ammo_box/magazine/internal/boltaction
var/bolt_open = FALSE
can_bayonet = TRUE
@@ -191,7 +191,7 @@
/obj/item/gun/ballistic/shotgun/boltaction/enchanted/attack_self()
return
/obj/item/gun/ballistic/shotgun/boltaction/enchanted/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1)
/obj/item/gun/ballistic/shotgun/boltaction/enchanted/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
..()
if(guns_left)
var/obj/item/gun/ballistic/shotgun/boltaction/enchanted/GUN = new gun_type
@@ -205,7 +205,7 @@
// Automatic Shotguns//
/obj/item/gun/ballistic/shotgun/automatic/shoot_live_shot(mob/living/user as mob|obj)
/obj/item/gun/ballistic/shotgun/automatic/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
..()
src.pump(user)

View File

@@ -127,12 +127,12 @@
chambered = null //either way, released the prepared shot
recharge_newshot() //try to charge a new shot
/obj/item/gun/energy/do_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/energy/do_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
if(!chambered && can_shoot())
process_chamber() // If the gun was drained and then recharged, load a new shot.
return ..()
/obj/item/gun/energy/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/energy/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(!chambered && can_shoot())
process_chamber() // Ditto.
return ..()

View File

@@ -237,7 +237,7 @@
return FALSE
return TRUE
/obj/item/gun/energy/dueling/process_fire(atom/target, mob/living/user, message, params, zone_override, bonus_spread)
/obj/item/gun/energy/dueling/process_fire(atom/target, mob/living/user, message, params, zone_override, bonus_spread = 0, stam_cost = 0)
if(duel.state == DUEL_READY)
duel.confirmations[src] = TRUE
to_chat(user,"<span class='notice'>You confirm your readiness.</span>")

View File

@@ -110,7 +110,7 @@
fail_tick--
..()
/obj/item/gun/energy/e_gun/nuclear/shoot_live_shot()
/obj/item/gun/energy/e_gun/nuclear/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
failcheck()
update_icon()
..()

View File

@@ -60,6 +60,12 @@
else
cut_overlays()
/obj/item/gun/energy/kinetic_accelerator/getinaccuracy(mob/living/user, bonus_spread, stamloss)
var/old_fire_delay = fire_delay //It's pretty irrelevant tbh but whatever.
fire_delay = overheat_time
. = ..()
fire_delay = old_fire_delay
/obj/item/gun/energy/kinetic_accelerator/examine(mob/user)
. = ..()
if(max_mod_capacity)
@@ -128,7 +134,7 @@
if(!holds_charge)
empty()
/obj/item/gun/energy/kinetic_accelerator/shoot_live_shot()
/obj/item/gun/energy/kinetic_accelerator/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
. = ..()
attempt_reload()
@@ -207,6 +213,12 @@
var/obj/item/gun/energy/kinetic_accelerator/KA = loc
KA.modify_projectile(BB)
/obj/item/gun/energy/kinetic_accelerator/getstamcost(mob/living/carbon/user)
if(user && !lavaland_equipment_pressure_check(get_turf(user)))
return 0
else
return ..()
//Projectiles
/obj/item/projectile/kinetic
name = "kinetic force"

View File

@@ -62,7 +62,7 @@
slot_flags = ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_BULKY
weapon_weight = WEAPON_MEDIUM
inaccuracy_modifier = 0.5
inaccuracy_modifier = 0.7
force = 10
throwforce = 10
cell_type = /obj/item/stock_parts/cell/lascarbine

View File

@@ -89,7 +89,7 @@
suppressed = TRUE
ammo_type = list(/obj/item/ammo_casing/energy/bolt)
weapon_weight = WEAPON_LIGHT
inaccuracy_modifier = 0
inaccuracy_modifier = 0.25
obj_flags = 0
overheat_time = 20
holds_charge = TRUE
@@ -126,7 +126,7 @@
attack_verb = list("attacked", "slashed", "cut", "sliced")
force = 12
sharpness = IS_SHARP
inaccuracy_modifier = 0
inaccuracy_modifier = 0.25
can_charge = 0
heat = 3800
@@ -182,7 +182,7 @@
item_state = null
icon_state = "wormhole_projector"
pin = null
inaccuracy_modifier = 0
inaccuracy_modifier = 0.25
var/obj/effect/portal/p_blue
var/obj/effect/portal/p_orange
var/atmos_link = FALSE
@@ -318,7 +318,7 @@
icon_state = "emitter_carbine"
force = 12
w_class = WEIGHT_CLASS_SMALL
inaccuracy_modifier = 0
inaccuracy_modifier = 0.25
cell_type = /obj/item/stock_parts/cell/super
ammo_type = list(/obj/item/ammo_casing/energy/emitter)

View File

@@ -45,7 +45,7 @@
/obj/item/projectile/magic/death, /obj/item/projectile/magic/teleport, /obj/item/projectile/magic/door, /obj/item/projectile/magic/aoe/fireball,
/obj/item/projectile/magic/spellblade, /obj/item/projectile/magic/arcane_barrage, /obj/item/projectile/magic/locker)
/obj/item/gun/magic/staff/chaos/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/magic/staff/chaos/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
chambered.projectile_type = pick(allowed_projectile_types)
. = ..()

View File

@@ -9,7 +9,7 @@
throw_speed = 3
throw_range = 7
force = 4
inaccuracy_modifier = 0
inaccuracy_modifier = 0.25
custom_materials = list(/datum/material/iron=2000)
clumsy_check = FALSE
fire_sound = 'sound/items/syringeproj.ogg'

View File

@@ -31,7 +31,7 @@
/obj/item/gun/grenadelauncher/can_shoot()
return grenades.len
/obj/item/gun/grenadelauncher/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/grenadelauncher/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
user.visible_message("<span class='danger'>[user] fired a grenade!</span>", \
"<span class='danger'>You fire the grenade launcher!</span>")
var/obj/item/grenade/F = grenades[1] //Now with less copypasta!

View File

@@ -41,7 +41,7 @@
on_beam_release(current_target)
current_target = null
/obj/item/gun/medbeam/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/medbeam/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
if(isliving(user))
add_fingerprint(user)

View File

@@ -7,7 +7,7 @@
throw_speed = 3
throw_range = 7
force = 4
inaccuracy_modifier = 0
inaccuracy_modifier = 0.25
custom_materials = list(/datum/material/iron=2000)
clumsy_check = 0
fire_sound = 'sound/items/syringeproj.ogg'
@@ -160,7 +160,7 @@
item_state = "blowgun"
fire_sound = 'sound/items/syringeproj.ogg'
/obj/item/gun/syringe/blowgun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/syringe/blowgun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
visible_message("<span class='danger'>[user] starts aiming with a blowgun!</span>")
if(do_after(user, 25, target = src))
user.adjustStaminaLoss(20)

View File

@@ -51,10 +51,10 @@
/obj/vehicle/sealed/car/attacked_by(obj/item/I, mob/living/user)
if(!I.force)
return
return FALSE
if(occupants[user])
to_chat(user, "<span class='notice'>Your attack bounces off of the car's padded interior.</span>")
return
return FALSE
return ..()
/obj/vehicle/sealed/car/attack_hand(mob/living/user)

View File

@@ -1,11 +0,0 @@
/obj/item/gun/proc/getstamcost(mob/living/carbon/user)
if(user && user.has_gravity())
return recoil
else
return recoil*5
/obj/item/gun/energy/kinetic_accelerator/getstamcost(mob/living/carbon/user)
if(user && !lavaland_equipment_pressure_check(get_turf(user)))
return 0
else
return ..()

View File

@@ -3407,7 +3407,6 @@
#include "modular_citadel\code\modules\mob\living\carbon\reindex_screams.dm"
#include "modular_citadel\code\modules\mob\living\carbon\human\human.dm"
#include "modular_citadel\code\modules\mob\living\carbon\human\human_defense.dm"
#include "modular_citadel\code\modules\projectiles\gun.dm"
#include "modular_citadel\code\modules\projectiles\ammunition\caseless.dm"
#include "modular_citadel\code\modules\projectiles\ammunition\ballistic\smg\smg.dm"
#include "modular_citadel\code\modules\projectiles\boxes_magazines\ammo_boxes.dm"