mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-01-10 09:22:29 +00:00
A lot of new defines are now in inventory_sizes.dm, which contains; All the size identifiers (the thing that tells the game if something is bulky, or w/e). Storage costs for all the sizes, which are exponents of two, as previously. A few constants for inventory size. Also changes all storage item's capacity definitions by basing it off of how many 'normal slots' exist for it. This allows one to change the definition for all of the defines in the file, and everything will follow along without needing to change 500 files. In testing, I made all ITEMSIZE_COST_* defines doubled, and nothing had broke. The benefit of doing all of this is that it makes adding new weight classes in the future much simpler, and makes knowing how much space a container has easier, as seeing ITEMSIZE_COST_NORMAL * 7 means it can hold seven normal items.
226 lines
8.3 KiB
Plaintext
226 lines
8.3 KiB
Plaintext
//** Shield Helpers
|
|
//These are shared by various items that have shield-like behaviour
|
|
|
|
//bad_arc is the ABSOLUTE arc of directions from which we cannot block. If you want to fix it to e.g. the user's facing you will need to rotate the dirs yourself.
|
|
/proc/check_shield_arc(mob/user, var/bad_arc, atom/damage_source = null, mob/attacker = null)
|
|
//check attack direction
|
|
var/attack_dir = 0 //direction from the user to the source of the attack
|
|
if(istype(damage_source, /obj/item/projectile))
|
|
var/obj/item/projectile/P = damage_source
|
|
attack_dir = get_dir(get_turf(user), P.starting)
|
|
else if(attacker)
|
|
attack_dir = get_dir(get_turf(user), get_turf(attacker))
|
|
else if(damage_source)
|
|
attack_dir = get_dir(get_turf(user), get_turf(damage_source))
|
|
|
|
if(!(attack_dir && (attack_dir & bad_arc)))
|
|
return 1
|
|
return 0
|
|
|
|
/proc/default_parry_check(mob/user, mob/attacker, atom/damage_source)
|
|
//parry only melee attacks
|
|
if(istype(damage_source, /obj/item/projectile) || (attacker && get_dist(user, attacker) > 1) || user.incapacitated())
|
|
return 0
|
|
|
|
//block as long as they are not directly behind us
|
|
var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
|
|
if(!check_shield_arc(user, bad_arc, damage_source, attacker))
|
|
return 0
|
|
|
|
return 1
|
|
|
|
/obj/item/weapon/shield
|
|
name = "shield"
|
|
var/base_block_chance = 50
|
|
item_icons = list(
|
|
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
|
|
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
|
)
|
|
|
|
/obj/item/weapon/shield/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
|
if(user.incapacitated())
|
|
return 0
|
|
|
|
//block as long as they are not directly behind us
|
|
var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
|
|
if(check_shield_arc(user, bad_arc, damage_source, attacker))
|
|
if(prob(get_block_chance(user, damage, damage_source, attacker)))
|
|
user.visible_message("<span class='danger'>\The [user] blocks [attack_text] with \the [src]!</span>")
|
|
return 1
|
|
return 0
|
|
|
|
/obj/item/weapon/shield/proc/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
|
|
return base_block_chance
|
|
|
|
/obj/item/weapon/shield/riot
|
|
name = "riot shield"
|
|
desc = "A shield adept for close quarters engagement. It's also capable of protecting from less powerful projectiles."
|
|
icon = 'icons/obj/weapons.dmi'
|
|
icon_state = "riot"
|
|
flags = CONDUCT
|
|
slot_flags = SLOT_BACK
|
|
force = 5.0
|
|
throwforce = 5.0
|
|
throw_speed = 1
|
|
throw_range = 4
|
|
w_class = ITEMSIZE_LARGE
|
|
origin_tech = list(TECH_MATERIAL = 2)
|
|
matter = list("glass" = 7500, DEFAULT_WALL_MATERIAL = 1000)
|
|
attack_verb = list("shoved", "bashed")
|
|
var/cooldown = 0 //shield bash cooldown. based on world.time
|
|
|
|
/obj/item/weapon/shield/riot/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
|
if(user.incapacitated())
|
|
return 0
|
|
|
|
//block as long as they are not directly behind us
|
|
var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
|
|
if(check_shield_arc(user, bad_arc, damage_source, attacker))
|
|
if(prob(get_block_chance(user, damage, damage_source, attacker)))
|
|
//At this point, we succeeded in our roll for a block attempt, however these kinds of shields struggle to stand up
|
|
//to strong bullets and lasers. They still do fine to pistol rounds of all kinds, however.
|
|
if(istype(damage_source, /obj/item/projectile))
|
|
var/obj/item/projectile/P = damage_source
|
|
if((is_sharp(P) && P.armor_penetration >= 10) || istype(P, /obj/item/projectile/beam))
|
|
//If we're at this point, the bullet/beam is going to go through the shield, however it will hit for less damage.
|
|
//Bullets get slowed down, while beams are diffused as they hit the shield, so these shields are not /completely/
|
|
//useless. Extremely penetrating projectiles will go through the shield without less damage.
|
|
user.visible_message("<span class='danger'>\The [user]'s [src.name] is pierced by [attack_text]!</span>")
|
|
if(P.armor_penetration < 30) //PTR bullets and x-rays will bypass this entirely.
|
|
P.damage = P.damage / 2
|
|
return 0
|
|
//Otherwise, if we're here, we're gonna stop the attack entirely.
|
|
user.visible_message("<span class='danger'>\The [user] blocks [attack_text] with \the [src]!</span>")
|
|
playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
|
|
return 1
|
|
return 0
|
|
|
|
/obj/item/weapon/shield/riot/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
|
if(istype(W, /obj/item/weapon/melee/baton))
|
|
if(cooldown < world.time - 25)
|
|
user.visible_message("<span class='warning'>[user] bashes [src] with [W]!</span>")
|
|
playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1)
|
|
cooldown = world.time
|
|
else
|
|
..()
|
|
|
|
/*
|
|
* Energy Shield
|
|
*/
|
|
|
|
/obj/item/weapon/shield/energy
|
|
name = "energy combat shield"
|
|
desc = "A shield capable of stopping most projectile and melee attacks. It can be retracted, expanded, and stored anywhere."
|
|
icon = 'icons/obj/weapons.dmi'
|
|
icon_state = "eshield0" // eshield1 for expanded
|
|
slot_flags = SLOT_EARS
|
|
flags = CONDUCT
|
|
force = 3.0
|
|
throwforce = 5.0
|
|
throw_speed = 1
|
|
throw_range = 4
|
|
w_class = ITEMSIZE_SMALL
|
|
origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_ILLEGAL = 4)
|
|
attack_verb = list("shoved", "bashed")
|
|
var/active = 0
|
|
|
|
/obj/item/weapon/shield/energy/handle_shield(mob/user)
|
|
if(!active)
|
|
return 0 //turn it on first!
|
|
. = ..()
|
|
|
|
if(.)
|
|
var/datum/effect/effect/system/spark_spread/spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread)
|
|
spark_system.set_up(5, 0, user.loc)
|
|
spark_system.start()
|
|
playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
|
|
|
|
/obj/item/weapon/shield/energy/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
|
|
if(istype(damage_source, /obj/item/projectile))
|
|
var/obj/item/projectile/P = damage_source
|
|
if((is_sharp(P) && damage > 10) || istype(P, /obj/item/projectile/beam))
|
|
return (base_block_chance - round(damage / 3)) //block bullets and beams using the old block chance
|
|
return base_block_chance
|
|
|
|
/obj/item/weapon/shield/energy/attack_self(mob/living/user as mob)
|
|
if ((CLUMSY in user.mutations) && prob(50))
|
|
user << "<span class='warning'>You beat yourself in the head with [src].</span>"
|
|
user.take_organ_damage(5)
|
|
active = !active
|
|
if (active)
|
|
force = 10
|
|
update_icon()
|
|
w_class = ITEMSIZE_LARGE
|
|
slot_flags = null
|
|
playsound(user, 'sound/weapons/saberon.ogg', 50, 1)
|
|
user << "<span class='notice'>\The [src] is now active.</span>"
|
|
|
|
else
|
|
force = 3
|
|
update_icon()
|
|
w_class = ITEMSIZE_TINY
|
|
slot_flags = SLOT_EARS
|
|
playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
|
|
user << "<span class='notice'>\The [src] can now be concealed.</span>"
|
|
|
|
if(istype(user,/mob/living/carbon/human))
|
|
var/mob/living/carbon/human/H = user
|
|
H.update_inv_l_hand()
|
|
H.update_inv_r_hand()
|
|
|
|
add_fingerprint(user)
|
|
return
|
|
|
|
/obj/item/weapon/shield/energy/update_icon()
|
|
icon_state = "eshield[active]"
|
|
if(active)
|
|
set_light(1.5, 1.5, "#006AFF")
|
|
else
|
|
set_light(0)
|
|
|
|
/obj/item/weapon/shield/riot/tele
|
|
name = "telescopic shield"
|
|
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
|
|
icon = 'icons/obj/weapons.dmi'
|
|
icon_state = "teleriot0"
|
|
slot_flags = null
|
|
force = 3
|
|
throwforce = 3
|
|
throw_speed = 3
|
|
throw_range = 4
|
|
w_class = ITEMSIZE_NORMAL
|
|
var/active = 0
|
|
/*
|
|
/obj/item/weapon/shield/energy/IsShield()
|
|
if(active)
|
|
return 1
|
|
else
|
|
return 0
|
|
*/
|
|
/obj/item/weapon/shield/riot/tele/attack_self(mob/living/user)
|
|
active = !active
|
|
icon_state = "teleriot[active]"
|
|
playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1)
|
|
|
|
if(active)
|
|
force = 8
|
|
throwforce = 5
|
|
throw_speed = 2
|
|
w_class = ITEMSIZE_LARGE
|
|
slot_flags = SLOT_BACK
|
|
user << "<span class='notice'>You extend \the [src].</span>"
|
|
else
|
|
force = 3
|
|
throwforce = 3
|
|
throw_speed = 3
|
|
w_class = ITEMSIZE_NORMAL
|
|
slot_flags = null
|
|
user << "<span class='notice'>[src] can now be concealed.</span>"
|
|
|
|
if(istype(user,/mob/living/carbon/human))
|
|
var/mob/living/carbon/human/H = user
|
|
H.update_inv_l_hand()
|
|
H.update_inv_r_hand()
|
|
|
|
add_fingerprint(user)
|
|
return |