//For projectiles that actually represent clouds of projectiles /obj/item/projectile/bullet/pellet name = "shrapnel" //'shrapnel' sounds more dangerous (i.e. cooler) than 'pellet' damage = 20 //icon_state = "bullet" //TODO: would be nice to have it's own icon state var/pellets = 4 //number of pellets var/range_step = 2 //projectile will lose a fragment each time it travels this distance. Can be a non-integer. var/base_spread = 90 //lower means the pellets spread more across body parts. If zero then this is considered a shrapnel explosion instead of a shrapnel cone var/spread_step = 10 //higher means the pellets spread more across body parts with distance /obj/item/projectile/bullet/pellet/proc/get_pellets(var/distance) var/pellet_loss = round((distance - 1)/range_step) //pellets lost due to distance return max(pellets - pellet_loss, 1) /obj/item/projectile/bullet/pellet/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier) if (pellets < 0) return 1 var/total_pellets = get_pellets(distance) var/spread = max(base_spread - (spread_step*distance), 0) //shrapnel explosions miss prone mobs with a chance that increases with distance var/prone_chance = 0 if(!base_spread) prone_chance = max(spread_step*(distance - 2), 0) var/hits = 0 for (var/i in 1 to total_pellets) if(target_mob.lying && target_mob != original && prob(prone_chance)) continue //pellet hits spread out across different zones, but 'aim at' the targeted zone with higher probability //whether the pellet actually hits the def_zone or a different zone should still be determined by the parent using get_zone_with_miss_chance(). var/old_zone = def_zone def_zone = ran_zone(def_zone, spread) if (..()) hits++ def_zone = old_zone //restore the original zone the projectile was aimed at pellets -= hits //each hit reduces the number of pellets left if (hits >= total_pellets || pellets <= 0) return 1 return 0 /obj/item/projectile/bullet/pellet/get_structure_damage() var/distance = get_dist(loc, starting) return ..() * get_pellets(distance) /obj/item/projectile/bullet/pellet/Move() . = ..() //If this is a shrapnel explosion, allow mobs that are prone to get hit, too if(. && !base_spread && isturf(loc)) for(var/mob/living/M in loc) if(M.lying || !M.CanPass(src, loc)) //Bump if lying or if we would normally Bump. if(Bump(M)) //Bump will make sure we don't hit a mob multiple times return //Explosive grenade projectile, borrowed from fragmentation grenade code. /obj/item/projectile/bullet/pellet/fragment damage = 10 armor_penetration = 30 range_step = 2 //projectiles lose a fragment each time they travel this distance. Can be a non-integer. base_spread = 0 //causes it to be treated as a shrapnel explosion instead of cone spread_step = 20 silenced = 1 //embedding messages are still produced so it's kind of weird when enabled. no_attack_log = 1 muzzle_type = null /obj/item/projectile/bullet/pellet/fragment/strong damage = 15 armor_penetration = 20 /obj/item/projectile/bullet/pellet/fragment/weak damage = 4 armor_penetration = 40 // Tank rupture fragments /obj/item/projectile/bullet/pellet/fragment/tank name = "metal fragment" damage = 9 //Big chunks flying off. range_step = 2 //controls damage falloff with distance. projectiles lose a "pellet" each time they travel this distance. Can be a non-integer. base_spread = 0 //causes it to be treated as a shrapnel explosion instead of cone spread_step = 20 armor_penetration = 20 silenced = 1 no_attack_log = 1 muzzle_type = null pellets = 3 /obj/item/projectile/bullet/pellet/fragment/tank/small name = "small metal fragment" damage = 6 armor_penetration = 5 pellets = 5 /obj/item/projectile/bullet/pellet/fragment/tank/big name = "large metal fragment" damage = 17 armor_penetration = 10 range_step = 5 //controls damage falloff with distance. projectiles lose a "pellet" each time they travel this distance. Can be a non-integer. pellets = 1