diff --git a/code/__DEFINES/ammo.dm b/code/__DEFINES/ammo.dm index 81d18855aa..87a80ddfa0 100644 --- a/code/__DEFINES/ammo.dm +++ b/code/__DEFINES/ammo.dm @@ -53,6 +53,12 @@ #define CALIBER_ANY "anything even remotely ammolike" #define CALIBER_BRICK "bricks" #define CALIBER_FLINTLOCK "blackpowder charges" + +//new defines +#define CALIBER_223 ".223 rounds" +#define CALIBER_38 ".38 rounds" +#define CALIBER_12G "12 gauge shells" + /// Caliber POW levels /// for hobo guns scaling their explodiness to the casing fired /// Heavier rounds than the gun can handle? more chance to POW diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index fc6711b57e..d02bf7a8c9 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -379,9 +379,9 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define ARROW_SPEED_BASE (BULLET_SPEED_BASE / 3) /// Bullet damage modifier defines -#define BULLET_MATCH_MULT_DAMAGE 1.25 // rare, pack a punch -#define BULLET_SURPLUS_MULT_DAMAGE 1 // standard ammo from an ammobench -#define BULLET_HANDLOAD_MULT_DAMAGE 0.75 // trash ammo you can make anywhere with a reloader tool, most common +#define BULLET_MATCH_MULT_DAMAGE 1.5 // rare, pack a punch +#define BULLET_SURPLUS_MULT_DAMAGE 1.25 // standard ammo from an ammobench +#define BULLET_HANDLOAD_MULT_DAMAGE 1 // trash ammo you can make anywhere with a reloader tool, most common /// Bullet speed modifier defines #define BULLET_MATCH_MULT_SPEED 2 @@ -442,6 +442,7 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define BULLET_DAMAGE_PISTOL_9MM 25 #define BULLET_DAMAGE_PISTOL_9MM_HANDLOAD (BULLET_DAMAGE_PISTOL_9MM * BULLET_HANDLOAD_MULT_DAMAGE) +#define BULLET_DAMAGE_PISTOL_9MM_SURPLUS (BULLET_DAMAGE_PISTOL_9MM * BULLET_SURPLUS_MULT_DAMAGE) #define BULLET_DAMAGE_PISTOL_9MM_MATCH (BULLET_DAMAGE_PISTOL_9MM * BULLET_MATCH_MULT_DAMAGE) #define BULLET_STAMINA_PISTOL_9MM (BULLET_DAMAGE_PISTOL_9MM * 0.5) #define BULLET_RECOIL_PISTOL_9MM BULLET_RECOIL_PISTOL_SMALL @@ -461,6 +462,7 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define BULLET_DAMAGE_PISTOL_45ACP 36 #define BULLET_DAMAGE_PISTOL_45ACP_HANDLOAD (BULLET_DAMAGE_PISTOL_45ACP * BULLET_HANDLOAD_MULT_DAMAGE) +#define BULLET_DAMAGE_PISTOL_45ACP_SURPLUS (BULLET_DAMAGE_PISTOL_45ACP * BULLET_SURPLUS_MULT_DAMAGE) #define BULLET_DAMAGE_PISTOL_45ACP_MATCH (BULLET_DAMAGE_PISTOL_45ACP * BULLET_MATCH_MULT_DAMAGE) #define BULLET_STAMINA_PISTOL_45ACP (BULLET_DAMAGE_PISTOL_45ACP * 0.5) #define BULLET_RECOIL_PISTOL_45ACP BULLET_RECOIL_PISTOL_MEDIUM @@ -575,6 +577,7 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define BULLET_DAMAGE_RIFLE_223 36 #define BULLET_DAMAGE_RIFLE_223_HANDLOAD (BULLET_DAMAGE_RIFLE_223 * BULLET_HANDLOAD_MULT_DAMAGE) +#define BULLET_DAMAGE_RIFLE_223_SURPLUS (BULLET_DAMAGE_RIFLE_223 * BULLET_SURPLUS_MULT_DAMAGE) #define BULLET_DAMAGE_RIFLE_223_MATCH (BULLET_DAMAGE_RIFLE_223 * BULLET_MATCH_MULT_DAMAGE) #define BULLET_STAMINA_RIFLE_223 (BULLET_DAMAGE_RIFLE_223 * 0.2) #define BULLET_RECOIL_RIFLE_223 BULLET_RECOIL_RIFLE_SMALL @@ -632,6 +635,7 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define BULLET_DAMAGE_RIFLE_308 45 #define BULLET_DAMAGE_RIFLE_308_HANDLOAD (BULLET_DAMAGE_RIFLE_308 * BULLET_HANDLOAD_MULT_DAMAGE) +#define BULLET_DAMAGE_RIFLE_308_SURPLUS (BULLET_DAMAGE_RIFLE_308 * BULLET_SURPLUS_MULT_DAMAGE) #define BULLET_DAMAGE_RIFLE_308_MATCH (BULLET_DAMAGE_RIFLE_308 * BULLET_MATCH_MULT_DAMAGE) #define BULLET_STAMINA_RIFLE_308 (BULLET_DAMAGE_RIFLE_308 * 0.5) #define BULLET_RECOIL_RIFLE_308 BULLET_RECOIL_RIFLE_MEDIUM @@ -731,6 +735,7 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define BULLET_DAMAGE_NEEDLER_PELLET 3 //will need revision when possible <-- Tox note #define BULLET_DAMAGE_RATSHOT_PELLET 6 //six divides easily into the 36 damage of .357, and 60 damage of .45-70 #define BULLET_DAMAGE_SHOTGUN_PELLET_HANDLOAD (BULLET_DAMAGE_SHOTGUN_PELLET * BULLET_HANDLOAD_MULT_DAMAGE) +#define BULLET_DAMAGE_SHOTGUN_PELLET_SURPLUS (BULLET_DAMAGE_SHOTGUN_PELLET * BULLET_SURPLUS_MULT_DAMAGE) #define BULLET_DAMAGE_SHOTGUN_PELLET_MATCH (BULLET_DAMAGE_SHOTGUN_PELLET * BULLET_MATCH_MULT_DAMAGE) #define BULLET_STAMINA_SHOTGUN_PELLET (BULLET_DAMAGE_SHOTGUN_PELLET * 0.1) #define BULLET_RECOIL_SHOTGUN_PELLET BULLET_RECOIL_SHOTGUN @@ -750,6 +755,7 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define BULLET_DAMAGE_SHOTGUN_SLUG 60 #define BULLET_DAMAGE_SHOTGUN_SLUG_HANDLOAD (BULLET_DAMAGE_SHOTGUN_SLUG * BULLET_HANDLOAD_MULT_DAMAGE) +#define BULLET_DAMAGE_SHOTGUN_SLUG_SURPLUS (BULLET_DAMAGE_SHOTGUN_SLUG * BULLET_SURPLUS_MULT_DAMAGE) #define BULLET_DAMAGE_SHOTGUN_SLUG_MATCH (BULLET_DAMAGE_SHOTGUN_SLUG * BULLET_MATCH_MULT_DAMAGE) #define BULLET_STAMINA_SHOTGUN_SLUG (BULLET_DAMAGE_SHOTGUN_SLUG * 0.5) #define BULLET_RECOIL_SHOTGUN_SLUG BULLET_RECOIL_SHOTGUN @@ -1158,6 +1164,7 @@ GLOBAL_LIST_INIT(main_body_parts2words, list( #define GUN_FIRE_RATE_200 RPM_TO_FIRE_DELAY(400) // 400 RPM = 1.5 deciseconds per shot #define GUN_FIRE_RATE_300 RPM_TO_FIRE_DELAY(600) // 600 RPM = 1 deciseconds per shot #define GUN_FIRE_RATE_400 RPM_TO_FIRE_DELAY(800) // 800 RPM = 0.75 deciseconds per shot +#define GUN_FIRE_RATE_500 RPM_TO_FIRE_DELAY(1000) //1000 RPM = 0.6 deciseconds per shot #define GUN_FIRE_RATE_600 RPM_TO_FIRE_DELAY(1200) // 1200 RPM = 0.5 decisecond per shot #define GUN_FIRE_RATE_800 RPM_TO_FIRE_DELAY(1600) // 1600 RPM = 0.375 deciseconds per shot #define GUN_FIRE_RATE_1000 RPM_TO_FIRE_DELAY(2000) // 2000 RPM = 0.3 deciseconds per shot diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 44519bad47..8f849f33eb 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -181,7 +181,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb var/list/hud_actions var/list/item_upgrades = list() - var/max_upgrades = 5 // was three now five because the amount of mods you need/want has significantly increased. Love you! + var/max_upgrades = 3 // was three now five because the amount of mods you need/want has significantly increased. Love you! /// extra special transform var/matrix/special_transform diff --git a/code/modules/jobs/job_types/tribals.dm b/code/modules/jobs/job_types/tribals.dm index 070dfe2e74..ec0e805d43 100644 --- a/code/modules/jobs/job_types/tribals.dm +++ b/code/modules/jobs/job_types/tribals.dm @@ -20,7 +20,7 @@ ADD_TRAIT(H, TRAIT_GENERIC, src) ADD_TRAIT(H, TRAIT_MACHINE_SPIRITS, src) H.grant_language(/datum/language/tribal) - for(var/datum/crafting_recipe/recipe as() in GLOB.tribal_job_recipes) + for(var/datum/crafting_recipe/recipe in GLOB.tribal_job_recipes) H.mind.teach_crafting_recipe(recipe) /* diff --git a/code/modules/jobs/job_types/wasteland.dm b/code/modules/jobs/job_types/wasteland.dm index 86d1df5326..84fc64cfab 100644 --- a/code/modules/jobs/job_types/wasteland.dm +++ b/code/modules/jobs/job_types/wasteland.dm @@ -460,7 +460,7 @@ Raider ..() if(visualsOnly) return - for(var/datum/crafting_recipe/recipe as() in GLOB.tribal_job_recipes) + for(var/datum/crafting_recipe/recipe in GLOB.tribal_job_recipes) H.mind.teach_crafting_recipe(recipe) H.grant_language(/datum/language/tribal) add_verb(H, /mob/living/proc/create_tribe) diff --git a/code/modules/projectiles/fuzammo/ammo_arrow/arrow_ammo.dm b/code/modules/projectiles/fuzammo/ammo_arrow/arrow_ammo.dm new file mode 100644 index 0000000000..919671468a --- /dev/null +++ b/code/modules/projectiles/fuzammo/ammo_arrow/arrow_ammo.dm @@ -0,0 +1 @@ +// arrow is the standard ofc diff --git a/code/modules/projectiles/fuzammo/ammo_arrow/arrow_magazine.dm b/code/modules/projectiles/fuzammo/ammo_arrow/arrow_magazine.dm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/code/modules/projectiles/fuzammo/ammo_shotgun/shotgun_ammo.dm b/code/modules/projectiles/fuzammo/ammo_shotgun/shotgun_ammo.dm new file mode 100644 index 0000000000..4da4973761 --- /dev/null +++ b/code/modules/projectiles/fuzammo/ammo_shotgun/shotgun_ammo.dm @@ -0,0 +1,271 @@ +// 12 gauge is the standard + + +/////////////////////////////// +////////// 12 gauge ammo ////////// +/////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a12g + name = "handloaded 12 gauge slug shell" + desc = "A low-power 12 gauge slug shell." + icon_state = "gshell" + caliber = CALIBER_12G + projectile_type = /obj/item/projectile/bullet/a12g + material_class = BULLET_IS_SHOTGUN + custom_materials = list( + /datum/material/iron = MATS_SHOTGUN_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_SHOTGUN * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_SHOTGUN + +/obj/item/ammo_casing/a12g/buck + name = "handloaded 12 gauge buckshot shell" + desc = "A low-power 12 gauge buckshot shell." + icon_state = "bbshell" + caliber = CALIBER_12G + projectile_type = /obj/item/projectile/bullet/a12g/buck + material_class = BULLET_IS_SHOTGUN + custom_materials = list( + /datum/material/iron = MATS_SHOTGUN_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_SHOTGUN * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_SHOTGUN + +/obj/item/ammo_casing/a12g/q2 + name = "12 gauge slug shell" + desc = "A 12 gauge slug shell." + projectile_type = /obj/item/projectile/bullet/a12g/q2 + custom_materials = list( + /datum/material/iron = MATS_SHOTGUN_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_SHOTGUN * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a12g/buck/q2 + name = "12 gauge buckshot shell" + desc = "A 12 gauge buckshot shell." + projectile_type = /obj/item/projectile/bullet/a12g/buck/q2 + custom_materials = list( + /datum/material/iron = MATS_SHOTGUN_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_SHOTGUN * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a12g/q3 + name = "magnum 12 gauge slug shell" + desc = "A high-grade 12 gauge slug shell." + projectile_type = /obj/item/projectile/bullet/a12g/q3 + custom_materials = list( + /datum/material/iron = MATS_SHOTGUN_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_SHOTGUN * CASING_POWER_MOD_MATCH + +/obj/item/ammo_casing/a12g/buck/q3 + name = "magnum 12 gauge buckshot shell" + desc = "A high-grade 12 gauge buckshot shell." + projectile_type = /obj/item/projectile/bullet/a12g/buck/q3 + custom_materials = list( + /datum/material/iron = MATS_SHOTGUN_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_SHOTGUN * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a12g + name = "12 gauge slug" + damage = BULLET_DAMAGE_SHOTGUN_SLUG_HANDLOAD + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_SHOTGUN_SLUG // needs a proper define later + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_SHOTGUN_SLUG + + wound_bonus = BULLET_WOUND_SHOTGUN_SLUG + bare_wound_bonus = BULLET_WOUND_SHOTGUN_SLUG_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_SHOTGUN_SLUG + + pixels_per_second = BULLET_SPEED_SHOTGUN_SLUG + damage_falloff = BULLET_FALLOFF_DEFAULT_SHOTGUN_SLUG + +/obj/item/projectile/bullet/a12g/q2 + damage = BULLET_DAMAGE_SHOTGUN_SLUG_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a12g/q3 + damage = BULLET_DAMAGE_SHOTGUN_SLUG_MATCH + spread = BULLET_SPREAD_MATCH + +/obj/item/projectile/bullet/a12g/buck + name = "12 gauge buckshot" + damage = BULLET_DAMAGE_SHOTGUN_PELLET_HANDLOAD + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_SHOTGUN_PELLET // needs a proper define later + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_SHOTGUN_PELLET + + wound_bonus = BULLET_WOUND_SHOTGUN_PELLET + bare_wound_bonus = BULLET_WOUND_SHOTGUN_PELLET_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_SHOTGUN_PELLET + + pixels_per_second = BULLET_SPEED_SHOTGUN_PELLET + damage_falloff = BULLET_FALLOFF_DEFAULT_SHOTGUN_PELLET + +/obj/item/projectile/bullet/a12g/buck/q2 + damage = BULLET_DAMAGE_SHOTGUN_PELLET_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a12g/buck/q3 + damage = BULLET_DAMAGE_SHOTGUN_PELLET_MATCH + spread = BULLET_SPREAD_MATCH + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a12g + name = "12 gauge slug box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "gbox" + multiple_sprites = 3 // I think this is right? + caliber = list(CALIBER_12G) + ammo_type = /obj/item/ammo_casing/a12g + max_ammo = 20 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a12g/q2 + name = "12 gauge slug box (standard)" + ammo_type = /obj/item/ammo_casing/a12g/q2 + +/obj/item/ammo_box/a12g/q3 + name = "12 gauge slug box (magnum)" + ammo_type = /obj/item/ammo_casing/a12g/q3 + +/obj/item/ammo_box/a12g/buck + name = "12 gauge buckshot box (handload)" + icon_state = "lbox" + ammo_type = /obj/item/ammo_casing/a12g/buck + +/obj/item/ammo_box/a12g/buck/q2 + name = "12 gauge buckshot box (standard)" + ammo_type = /obj/item/ammo_casing/a12g/buck/q2 + +/obj/item/ammo_box/a12g/buck/q3 + name = "12 gauge buckshot box (magnum)" + ammo_type = /obj/item/ammo_casing/a12g/buck/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a12g/crate + name = "12 gauge slug crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 120 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a12g/crate/q2 + name = "12 gauge slug crate (standard)" + ammo_type = /obj/item/ammo_casing/a12g/q2 + +/obj/item/ammo_box/a12g/crate/q3 + name = "12 gauge slug crate (magnum)" + ammo_type = /obj/item/ammo_casing/a12g/q3 + +/obj/item/ammo_box/a12g/buck/crate + name = "12 gauge buckshot crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 120 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a12g/buck/crate/q2 + name = "12 gauge buckshot crate (standard)" + ammo_type = /obj/item/ammo_casing/a12g/buck/q2 + +/obj/item/ammo_box/a12g/buck/crate/q3 + name = "12 gauge buckshot crate (magnum)" + ammo_type = /obj/item/ammo_casing/a12g/buck/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a12g + name = "12 gauge slug box (handload)" + id = "a12g" + build_path = /obj/item/ammo_box/a12g + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a12g2 + name = "12 gauge slug box (standard)" + id = "a12g2" + build_path = /obj/item/ammo_box/a12g/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a12g3 + name = "12 gauge slug box (magnum)" + id = "a12g3" + build_path = /obj/item/ammo_box/a12g/q3 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a12gb + name = "12 gauge buckshot box (handload)" + id = "a12gb" + build_path = /obj/item/ammo_box/a12g/buck + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a12gb2 + name = "12 gauge buckshot box (standard)" + id = "a12gb2" + build_path = /obj/item/ammo_box/a12g/buck/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a12gb3 + name = "12 gauge buckshot box (magnum)" + id = "a12gb3" + build_path = /obj/item/ammo_box/a12g/buck/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a12gcrate + name = "12 gauge slug crate (handload)" + id = "a12gcrate" + build_path = /obj/item/ammo_box/a12g/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a12gcrate2 + name = "12 gauge slug crate (standard)" + id = "a12gcrate2" + build_path = /obj/item/ammo_box/a12g/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a12gcrate3 + name = "12 gauge slug crate (magnum)" + id = "a12gcrate3" + build_path = /obj/item/ammo_box/a12g/crate/q3 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a12gbcrate + name = "12 gauge buckshot crate (handload)" + id = "a12gbcrate" + build_path = /obj/item/ammo_box/a12g/buck/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a12gbcrate2 + name = "12 gauge buckshot crate (standard)" + id = "a12gbcrate2" + build_path = /obj/item/ammo_box/a12g/buck/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a12gbcrate3 + name = "12 gauge buckshot crate (magnum)" + id = "a12gbcrate3" + build_path = /obj/item/ammo_box/a12g/buck/crate/q3 + category = list("initial", "Basic ammo") + + + + diff --git a/code/modules/projectiles/fuzammo/ammo_shotgun/shotgun_magazine.dm b/code/modules/projectiles/fuzammo/ammo_shotgun/shotgun_magazine.dm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/code/modules/projectiles/fuzammo/ammo_special/special_ammo.dm b/code/modules/projectiles/fuzammo/ammo_special/special_ammo.dm new file mode 100644 index 0000000000..87d7f9581d --- /dev/null +++ b/code/modules/projectiles/fuzammo/ammo_special/special_ammo.dm @@ -0,0 +1,400 @@ +//40mm is the standard (among other things) + + +/////////////////////////////// +////////// 40mm ammo ////////// +/////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a40mm + name = "handloaded 40mm slug shell" + desc = "A low-power 40mm slug shell." + icon_state = "40mmHE" // it's blue tipped, that means inert practice ammo + caliber = CALIBER_40MM + projectile_type = /obj/item/projectile/bullet/a40mm + material_class = BULLET_IS_SHOTGUN // cheaper than explosives + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_GRENADE * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_40MM + +/obj/item/ammo_casing/a40mm/buck + name = "handloaded 40mm buckshot shell" + desc = "A low-power 40mm buckshot shell." + icon_state = "40mmbuck" + projectile_type = /obj/item/projectile/bullet/a40mm/buck + material_class = BULLET_IS_SHOTGUN // cheaper than explosives + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + pellets = SHOTGUN_PELLET_BASE * 2 + variance = SHOTGUN_SPREAD_BASE + +/obj/item/ammo_casing/a40mm/exp + name = "handmade 40mm grenade shell" + desc = "A low-yield explosive 40mm grenade shell." + icon_state = "40mmHEDP" + projectile_type = /obj/item/projectile/bullet/a40mm/exp + material_class = BULLET_IS_GRENADE // full cost + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_GRENADE_BULLET, + /datum/material/blackpowder = MATS_GRENADE_POWDER) + +/obj/item/ammo_casing/a40mm/q2 + name = "40mm slug shell" + desc = "A 40mm slug shell." + projectile_type = /obj/item/projectile/bullet/a40mm/q2 + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_GRENADE * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a40mm/buck/q2 + name = "40mm buckshot shell" + desc = "A 40mm buckshot shell." + projectile_type = /obj/item/projectile/bullet/a40mm/buck/q2 + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_GRENADE * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a40mm/exp/q2 + name = "40mm grenade shell" + desc = "An explosive 40mm grenade shell." + projectile_type = /obj/item/projectile/bullet/a40mm/exp/q2 + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_GRENADE_BULLET, + /datum/material/blackpowder = MATS_GRENADE_POWDER) + fire_power = CASING_POWER_GRENADE * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a40mm/q3 + name = "magnum 40mm slug shell" + desc = "A high-power 40mm slug shell." + projectile_type = /obj/item/projectile/bullet/a40mm/q3 + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_GRENADE * CASING_POWER_MOD_MATCH + +/obj/item/ammo_casing/a40mm/buck/q3 + name = "magnum 40mm buckshot shell" + desc = "A high-power 40mm buckshot shell." + projectile_type = /obj/item/projectile/bullet/a40mm/buck/q3 + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_SHOTGUN_BULLET, + /datum/material/blackpowder = MATS_SHOTGUN_POWDER) + fire_power = CASING_POWER_GRENADE * CASING_POWER_MOD_MATCH + +/obj/item/ammo_casing/a40mm/exp/q3 + name = "HE 40mm grenade shell" + desc = "A high-explosive 40mm grenade shell." + projectile_type = /obj/item/projectile/bullet/a40mm/exp/q3 + custom_materials = list( + /datum/material/iron = MATS_GRENADE_CASING + MATS_GRENADE_BULLET, + /datum/material/blackpowder = MATS_GRENADE_POWDER) + fire_power = CASING_POWER_GRENADE * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a40mm + name = "40mm slug" + icon_state= "bolter" + damage = BULLET_DAMAGE_SHOTGUN_SLUG_HANDLOAD + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_SHOTGUN_SLUG // needs a proper define later + spread = BULLET_SPREAD_MATCH // High precision, low velocity: what 40mm was designed for + recoil = BULLET_RECOIL_SHOTGUN_SLUG + + wound_bonus = BULLET_WOUND_SHOTGUN_SLUG + bare_wound_bonus = BULLET_WOUND_SHOTGUN_SLUG_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_SHOTGUN_SLUG + + pixels_per_second = BULLET_SPEED_SHOTGUN_SLUG + damage_falloff = BULLET_FALLOFF_DEFAULT_SHOTGUN_SLUG + +/obj/item/projectile/bullet/a40mm/q2 + damage = BULLET_DAMAGE_SHOTGUN_SLUG_SURPLUS + +/obj/item/projectile/bullet/a40mm/q3 + damage = BULLET_DAMAGE_SHOTGUN_SLUG_MATCH + +/obj/item/projectile/bullet/a40mm/buck + name = "buckshot pellet" + icon_state= "bullet" + damage = BULLET_DAMAGE_SHOTGUN_PELLET_HANDLOAD + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_SHOTGUN_PELLET // needs a proper define later + spread = BULLET_SPREAD_MATCH // High precision, low velocity: what 40mm was designed for + recoil = BULLET_RECOIL_SHOTGUN_PELLET + + wound_bonus = BULLET_WOUND_SHOTGUN_PELLET + bare_wound_bonus = BULLET_WOUND_SHOTGUN_PELLET_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_SHOTGUN_PELLET + + pixels_per_second = BULLET_SPEED_SHOTGUN_PELLET + damage_falloff = BULLET_FALLOFF_DEFAULT_SHOTGUN_PELLET + +/obj/item/projectile/bullet/a40mm/buck/q2 + damage = BULLET_DAMAGE_SHOTGUN_PELLET_SURPLUS + +/obj/item/projectile/bullet/a40mm/buck/q3 + damage = BULLET_DAMAGE_SHOTGUN_PELLET_MATCH + +/obj/item/projectile/bullet/a40mm/exp + name = "40mm grenade" + icon_state= "bolter" + damage = 60 // bonus damage because handmade are only light explosion + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_SHOTGUN_SLUG // needs a proper define later + spread = BULLET_SPREAD_MATCH // High precision, low velocity: what 40mm was designed for + recoil = BULLET_RECOIL_SHOTGUN_SLUG + + wound_bonus = BULLET_WOUND_SHOTGUN_SLUG + bare_wound_bonus = BULLET_WOUND_SHOTGUN_SLUG_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_SHOTGUN_SLUG + + pixels_per_second = TILES_TO_PIXELS(10) //slower than bullets + damage_falloff = BULLET_FALLOFF_DEFAULT_SHOTGUN_SLUG + +/obj/item/projectile/bullet/a40mm/he/on_hit(atom/target, blocked = FALSE) + ..() + explosion(target, -1, -1, -1, 3, 0) + new /obj/effect/temp_visual/explosion(get_turf(target)) + return BULLET_ACT_HIT + +/obj/item/projectile/bullet/a40mm/exp/q2 + damage = 10 // 10 direct damage plus a heavy blast at ground zero + +/obj/item/projectile/bullet/a40mm/exp/q2/on_hit(atom/target, blocked = FALSE) + ..() + explosion(target, -1, -1, 1, 3, 0) + new /obj/effect/temp_visual/explosion(get_turf(target)) + return BULLET_ACT_HIT + +/obj/item/projectile/bullet/a40mm/exp/q3 + damage = 10 + +/obj/item/projectile/bullet/a40mm/exp/q3/on_hit(atom/target, blocked = FALSE) + ..() + explosion(target, -1, -1, 2, 3, 0) + new /obj/effect/temp_visual/explosion(get_turf(target)) + return BULLET_ACT_HIT + + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a40mm + name = "40mm slug box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "40mm" + multiple_sprites = 3 // I think this is right? + caliber = list(CALIBER_40MM) + ammo_type = /obj/item/ammo_casing/a40mm + max_ammo = 4 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a40mm/q2 + name = "40mm slug box (standard)" + ammo_type = /obj/item/ammo_casing/a40mm/q2 + +/obj/item/ammo_box/a40mm/q3 + name = "40mm slug box (magnum)" + ammo_type = /obj/item/ammo_casing/a40mm/q3 + +/obj/item/ammo_box/a40mm/buck + name = "40mm buckshot box (handload)" + icon_state = "40mmbuckshot" + ammo_type = /obj/item/ammo_casing/a40mm/buck + +/obj/item/ammo_box/a40mm/buck/q2 + name = "40mm buckshot box (standard)" + ammo_type = /obj/item/ammo_casing/a40mm/buck/q2 + +/obj/item/ammo_box/a40mm/buck/q3 + name = "40mm buckshot box (magnum)" + ammo_type = /obj/item/ammo_casing/a40mm/buck/q3 + +/obj/item/ammo_box/a40mm/exp + name = "40mm grenade box (handmade)" + icon_state = "40mmbuckshot" + ammo_type = /obj/item/ammo_casing/a40mm/exp + +/obj/item/ammo_box/a40mm/exp/q2 + name = "40mm grenade box (standard)" + ammo_type = /obj/item/ammo_casing/a40mm/exp/q2 + +/obj/item/ammo_box/a40mm/exp/q3 + name = "40mm grenade box (high explosive)" + ammo_type = /obj/item/ammo_casing/a40mm/exp/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a40mm/crate + name = "40mm slug crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 24 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a40mm/crate/q2 + name = "40mm slug crate (standard)" + ammo_type = /obj/item/ammo_casing/a40mm/q2 + +/obj/item/ammo_box/a40mm/crate/q3 + name = "40mm slug crate (magnum)" + ammo_type = /obj/item/ammo_casing/a40mm/q3 + +/obj/item/ammo_box/a40mm/buck/crate + name = "40mm buckshot crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 24 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a40mm/buck/crate/q2 + name = "40mm buckshot crate (standard)" + ammo_type = /obj/item/ammo_casing/a40mm/buck/q2 + +/obj/item/ammo_box/a40mm/buck/crate/q3 + name = "40mm buckshot crate (magnum)" + ammo_type = /obj/item/ammo_casing/a40mm/buck/q3 + +/obj/item/ammo_box/a40mm/exp/crate + name = "40mm grenade box (handmade)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 24 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a40mm/exp/crate/q2 + name = "40mm grenade box (standard)" + ammo_type = /obj/item/ammo_casing/a40mm/exp/q2 + +/obj/item/ammo_box/a40mm/exp/crate/q3 + name = "40mm grenade box (high explosive)" + ammo_type = /obj/item/ammo_casing/a40mm/exp/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a40mm + name = "40mm slug box (handload)" + id = "a40mm" + build_path = /obj/item/ammo_box/a40mm + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mm2 + name = "40mm slug box (standard)" + id = "a40mm2" + build_path = /obj/item/ammo_box/a40mm/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mm3 + name = "40mm slug box (magnum)" + id = "a40mm3" + build_path = /obj/item/ammo_box/a40mm/q3 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mmb + name = "40mm buckshot box (handload)" + id = "a40mmb" + build_path = /obj/item/ammo_box/a40mm/buck + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mmb2 + name = "40mm buckshot box (standard)" + id = "a40mmb2" + build_path = /obj/item/ammo_box/a40mm/buck/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mmb3 + name = "40mm buckshot box (magnum)" + id = "a40mmb3" + build_path = /obj/item/ammo_box/a40mm/buck/q3 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mme + name = "40mm grenade box (handmade)" + id = "a40mme" + build_path = /obj/item/ammo_box/a40mm/exp + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mme2 + name = "40mm grenade box (standard)" + id = "a40mme2" + build_path = /obj/item/ammo_box/a40mm/exp/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a40mme3 + name = "40mm grenade box (high explosive)" + id = "a40mme3" + build_path = /obj/item/ammo_box/a40mm/exp/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a40mmcrate + name = "40mm slug crate (handload)" + id = "a40mmcrate" + build_path = /obj/item/ammo_box/a40mm/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmcrate2 + name = "40mm slug crate (standard)" + id = "a40mmcrate2" + build_path = /obj/item/ammo_box/a40mm/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmcrate3 + name = "40mm slug crate (magnum)" + id = "a40mmcrate3" + build_path = /obj/item/ammo_box/a40mm/crate/q3 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmbcrate + name = "40mm buckshot crate (handload)" + id = "a40mmbcrate" + build_path = /obj/item/ammo_box/a40mm/buck/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmbcrate2 + name = "40mm buckshot crate (standard)" + id = "a40mmbcrate2" + build_path = /obj/item/ammo_box/a40mm/buck/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmbcrate3 + name = "40mm buckshot crate (magnum)" + id = "a40mmbcrate3" + build_path = /obj/item/ammo_box/a40mm/buck/crate/q3 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmecrate + name = "40mm grenade crate (handmade)" + id = "a40mmecrate" + build_path = /obj/item/ammo_box/a40mm/exp/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmecrate2 + name = "40mm grenade crate (standard)" + id = "a40mmecrate2" + build_path = /obj/item/ammo_box/a40mm/exp/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a40mmecrate3 + name = "40mm grenade crate (high explosive)" + id = "a40mmecrate3" + build_path = /obj/item/ammo_box/a40mm/exp/crate/q3 + category = list("initial", "Basic ammo") diff --git a/code/modules/projectiles/fuzammo/ammo_special/special_magazine.dm b/code/modules/projectiles/fuzammo/ammo_special/special_magazine.dm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/code/modules/projectiles/fuzammo/pistol_ammo_large/pistol_large_ammo.dm b/code/modules/projectiles/fuzammo/pistol_ammo_large/pistol_large_ammo.dm new file mode 100644 index 0000000000..99843932df --- /dev/null +++ b/code/modules/projectiles/fuzammo/pistol_ammo_large/pistol_large_ammo.dm @@ -0,0 +1,291 @@ +// .45acp is the standard, plus .357mag for the revolver + + +/////////////////////////////// +////////// .45acp ammo ////////// +/////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a45 + name = "handloaded .45ACP bullet casing" + desc = "A low-grade .45ACP bullet casing." + caliber = CALIBER_45ACP + projectile_type = /obj/item/projectile/bullet/a45 + material_class = BULLET_IS_HEAVY_PISTOL + custom_materials = list( + /datum/material/iron = MATS_PISTOL_HEAVY_CASING + MATS_PISTOL_HEAVY_BULLET, + /datum/material/blackpowder = MATS_PISTOL_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_PISTOL * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_PISTOL_HEAVY + +/obj/item/ammo_casing/a45/q2 + name = ".45ACP bullet casing" + desc = "A .45ACP bullet casing." + projectile_type = /obj/item/projectile/bullet/a45/q2 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_HEAVY_CASING + MATS_PISTOL_HEAVY_BULLET, + /datum/material/blackpowder = MATS_PISTOL_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_PISTOL * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a45/q3 + name = "match .45ACP bullet casing" + desc = "A high-grade .45ACP bullet casing." + projectile_type = /obj/item/projectile/bullet/a45/q3 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_HEAVY_CASING + MATS_PISTOL_HEAVY_BULLET, + /datum/material/blackpowder = MATS_PISTOL_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_PISTOL * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a45 + name = ".45ACP bullet" + damage = BULLET_DAMAGE_PISTOL_45ACP_HANDLOAD //36 + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_PISTOL_45ACP + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_PISTOL_45ACP + + wound_bonus = BULLET_WOUND_PISTOL_45ACP + bare_wound_bonus = BULLET_WOUND_PISTOL_45ACP_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_PISTOL_HEAVY + + pixels_per_second = BULLET_SPEED_PISTOL_45ACP + damage_falloff = BULLET_FALLOFF_DEFAULT_PISTOL_HEAVY + +/obj/item/projectile/bullet/a45/q2 + damage = BULLET_DAMAGE_PISTOL_45ACP_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a45/q3 + damage = BULLET_DAMAGE_PISTOL_45ACP_MATCH + spread = BULLET_SPREAD_MATCH + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a45 + name = ".45ACP ammo box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "45box" + multiple_sprites = 2 + caliber = list(CALIBER_45ACP) + ammo_type = /obj/item/ammo_casing/a45 + max_ammo = 50 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a45/q2 + name = ".45ACP ammo box (standard)" + ammo_type = /obj/item/ammo_casing/a45/q2 + +/obj/item/ammo_box/a45/q3 + name = ".45ACP ammo box (match)" + ammo_type = /obj/item/ammo_casing/a45/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a45/crate + name = ".45ACP ammo crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 120 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a45/crate/q2 + name = ".45ACP ammo crate (standard)" + ammo_type = /obj/item/ammo_casing/a45/q2 + +/obj/item/ammo_box/a45/crate/q3 + name = ".45ACP ammo crate (match)" + ammo_type = /obj/item/ammo_casing/a45/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a45 + name = ".45ACP ammo box (handload)" + id = "a45" + build_path = /obj/item/ammo_box/a45 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a45_2 + name = ".45ACP ammo box (standard)" + id = "a45_2" + build_path = /obj/item/ammo_box/a45/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a45_3 + name = ".45ACP ammo box (match)" + id = "a45_3" + build_path = /obj/item/ammo_box/a45/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a45crate + name = ".45ACP ammo crate (surplus)" + id = "a45crate" + build_path = /obj/item/ammo_box/a45/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a45crate2 + name = ".45ACP ammo crate (standard)" + id = "a45crate2" + build_path = /obj/item/ammo_box/a45/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a45crate3 + name = ".45ACP ammo crate (match)" + id = "a45crate3" + build_path = /obj/item/ammo_box/a45/crate/q3 + category = list("initial", "Basic ammo") + + + + +////////////////////////////////// +////////// .357mag ammo ////////// +////////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a357 + name = "handloaded .357mag bullet casing" + desc = "A low-grade .357mag bullet casing." + caliber = CALIBER_357 + projectile_type = /obj/item/projectile/bullet/a357 + material_class = BULLET_IS_LIGHT_PISTOL + custom_materials = list( + /datum/material/iron = MATS_PISTOL_HEAVY_CASING + MATS_PISTOL_HEAVY_BULLET, + /datum/material/blackpowder = MATS_PISTOL_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_PISTOL * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_PISTOL_LIGHT + +/obj/item/ammo_casing/a357/q2 + name = ".357mag bullet casing" + desc = "A .357mag bullet casing." + projectile_type = /obj/item/projectile/bullet/a357/q2 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_HEAVY_CASING + MATS_PISTOL_HEAVY_BULLET, + /datum/material/blackpowder = MATS_PISTOL_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_PISTOL * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a357/q3 + name = "match .357mag bullet casing" + desc = "A high-grade .357mag bullet casing." + projectile_type = /obj/item/projectile/bullet/a357/q3 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_HEAVY_CASING + MATS_PISTOL_HEAVY_BULLET, + /datum/material/blackpowder = MATS_PISTOL_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_PISTOL * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a357 + name = ".357mag bullet" + damage = BULLET_DAMAGE_PISTOL_45ACP_HANDLOAD // same as the .45acp right now as they are heavy pistol baseline + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_PISTOL_45ACP + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_PISTOL_45ACP + + wound_bonus = BULLET_WOUND_PISTOL_45ACP + bare_wound_bonus = BULLET_WOUND_PISTOL_45ACP_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_PISTOL_HEAVY + + pixels_per_second = BULLET_SPEED_PISTOL_45ACP + damage_falloff = BULLET_FALLOFF_DEFAULT_PISTOL_HEAVY + +/obj/item/projectile/bullet/a357/q2 + damage = BULLET_DAMAGE_PISTOL_45ACP_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a357/q3 + damage = BULLET_DAMAGE_PISTOL_45ACP_MATCH + spread = BULLET_SPREAD_MATCH + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a357 + name = ".357mag ammo box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "357box" + multiple_sprites = 2 + caliber = list(CALIBER_357) + ammo_type = /obj/item/ammo_casing/a357 + max_ammo = 50 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a357/q2 + name = ".357mag ammo box (standard)" + ammo_type = /obj/item/ammo_casing/a357/q2 + +/obj/item/ammo_box/a357/q3 + name = ".357mag ammo box (match)" + ammo_type = /obj/item/ammo_casing/a357/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a357/crate + name = ".357mag ammo crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 120 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a357/crate/q2 + name = ".357mag ammo crate (standard)" + ammo_type = /obj/item/ammo_casing/a357/q2 + +/obj/item/ammo_box/a357/crate/q3 + name = ".357mag ammo crate (match)" + ammo_type = /obj/item/ammo_casing/a357/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a357 + name = ".357mag ammo box (handload)" + id = "a357" + build_path = /obj/item/ammo_box/a357 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a357_2 + name = ".357mag ammo box (standard)" + id = "a357_2" + build_path = /obj/item/ammo_box/a357/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a357_3 + name = ".357mag ammo box (match)" + id = "a357_3" + build_path = /obj/item/ammo_box/a357/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a357crate + name = ".357mag ammo crate (handload)" + id = "a357crate" + build_path = /obj/item/ammo_box/a357/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a357crate2 + name = ".357mag ammo crate (standard)" + id = "a357crate2" + build_path = /obj/item/ammo_box/a357/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a357crate3 + name = ".357mag ammo crate (match)" + id = "a357crate3" + build_path = /obj/item/ammo_box/a357/crate/q3 + category = list("initial", "Basic ammo") diff --git a/code/modules/projectiles/fuzammo/pistol_ammo_large/pistol_large_magazine.dm b/code/modules/projectiles/fuzammo/pistol_ammo_large/pistol_large_magazine.dm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/code/modules/projectiles/fuzammo/pistol_ammo_small/pistol_small_ammo.dm b/code/modules/projectiles/fuzammo/pistol_ammo_small/pistol_small_ammo.dm new file mode 100644 index 0000000000..f63b8fe1f8 --- /dev/null +++ b/code/modules/projectiles/fuzammo/pistol_ammo_small/pistol_small_ammo.dm @@ -0,0 +1,290 @@ +//9mm is the standard, plus .38 for revolvers + + +/////////////////////////////// +////////// 9mm ammo ////////// +/////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a9mm + name = "handloaded 9mm bullet casing" + desc = "A low-grade 9mm bullet casing." + caliber = CALIBER_9MM + projectile_type = /obj/item/projectile/bullet/a9mm + material_class = BULLET_IS_LIGHT_PISTOL + custom_materials = list( + /datum/material/iron = MATS_PISTOL_LIGHT_CASING + MATS_PISTOL_LIGHT_BULLET, + /datum/material/blackpowder = MATS_PISTOL_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_PISTOL * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_PISTOL_LIGHT + +/obj/item/ammo_casing/a9mm/q2 + name = "9mm bullet casing" + desc = "A 9mm bullet casing." + projectile_type = /obj/item/projectile/bullet/a9mm/q2 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_LIGHT_CASING + MATS_PISTOL_LIGHT_BULLET, + /datum/material/blackpowder = MATS_PISTOL_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_PISTOL * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a9mm/q3 + name = "match 9mm bullet casing" + desc = "A high-grade 9mm bullet casing." + projectile_type = /obj/item/projectile/bullet/a9mm/q3 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_LIGHT_CASING + MATS_PISTOL_LIGHT_BULLET, + /datum/material/blackpowder = MATS_PISTOL_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_PISTOL * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a9mm + name = "9mm bullet" + damage = BULLET_DAMAGE_PISTOL_9MM_HANDLOAD //36 + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_PISTOL_9MM + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_PISTOL_9MM + + wound_bonus = BULLET_WOUND_PISTOL_9MM + bare_wound_bonus = BULLET_WOUND_PISTOL_9MM_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_PISTOL_LIGHT + + pixels_per_second = BULLET_SPEED_PISTOL_9MM + damage_falloff = BULLET_FALLOFF_DEFAULT_PISTOL_LIGHT + +/obj/item/projectile/bullet/a9mm/q2 + damage = BULLET_DAMAGE_PISTOL_9MM_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a9mm/q3 + damage = BULLET_DAMAGE_PISTOL_9MM_MATCH + spread = BULLET_SPREAD_MATCH + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a9mm + name = "9mm ammo box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "9mmbox" + multiple_sprites = 2 + caliber = list(CALIBER_9MM) + ammo_type = /obj/item/ammo_casing/a9mm + max_ammo = 100 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a9mm/q2 + name = "9mm ammo box (standard)" + ammo_type = /obj/item/ammo_casing/a9mm/q2 + +/obj/item/ammo_box/a9mm/q3 + name = "9mm ammo box (match)" + ammo_type = /obj/item/ammo_casing/a9mm/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a9mm/crate + name = "9mm ammo crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 600 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a9mm/crate/q2 + name = "9mm ammo crate (standard)" + ammo_type = /obj/item/ammo_casing/a9mm/q2 + +/obj/item/ammo_box/a9mm/crate/q3 + name = "9mm ammo crate (match)" + ammo_type = /obj/item/ammo_casing/a9mm/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a9mm + name = "9mm ammo box (handload)" + id = "a9mm" + build_path = /obj/item/ammo_box/a9mm + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a9mm_2 + name = "9mm ammo box (standard)" + id = "a9mm_2" + build_path = /obj/item/ammo_box/a9mm/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a9mm_3 + name = "9mm ammo box (match)" + id = "a9mm_3" + build_path = /obj/item/ammo_box/a9mm/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a9mmcrate + name = "9mm ammo crate (surplus)" + id = "a9mmcrate" + build_path = /obj/item/ammo_box/a9mm/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a9mmcrate2 + name = "9mm ammo crate (standard)" + id = "a9mmcrate2" + build_path = /obj/item/ammo_box/a9mm/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a9mmcrate3 + name = "9mm ammo crate (match)" + id = "a9mmcrate3" + build_path = /obj/item/ammo_box/a9mm/crate/q3 + category = list("initial", "Basic ammo") + + + +////////////////////////////// +////////// .38 ammo ////////// +////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a38 + name = "handloaded .38 bullet casing" + desc = "A low-grade .38 bullet casing." + caliber = CALIBER_38 + projectile_type = /obj/item/projectile/bullet/a38 + material_class = BULLET_IS_LIGHT_PISTOL + custom_materials = list( + /datum/material/iron = MATS_PISTOL_LIGHT_CASING + MATS_PISTOL_LIGHT_BULLET, + /datum/material/blackpowder = MATS_PISTOL_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_PISTOL * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_PISTOL_LIGHT + +/obj/item/ammo_casing/a38/q2 + name = ".38 bullet casing" + desc = "A .38 bullet casing." + projectile_type = /obj/item/projectile/bullet/a38/q2 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_LIGHT_CASING + MATS_PISTOL_LIGHT_BULLET, + /datum/material/blackpowder = MATS_PISTOL_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_PISTOL * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a38/q3 + name = "match .38 bullet casing" + desc = "A high-grade .38 bullet casing." + projectile_type = /obj/item/projectile/bullet/a38/q3 + custom_materials = list( + /datum/material/iron = MATS_PISTOL_LIGHT_CASING + MATS_PISTOL_LIGHT_BULLET, + /datum/material/blackpowder = MATS_PISTOL_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_PISTOL * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a38 + name = ".38 bullet" + damage = BULLET_DAMAGE_PISTOL_9MM_HANDLOAD // same as the 9mm right now as they are heavy pistol baseline + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_PISTOL_9MM + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_PISTOL_9MM + + wound_bonus = BULLET_WOUND_PISTOL_9MM + bare_wound_bonus = BULLET_WOUND_PISTOL_9MM_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_PISTOL_LIGHT + + pixels_per_second = BULLET_SPEED_PISTOL_9MM + damage_falloff = BULLET_FALLOFF_DEFAULT_PISTOL_LIGHT + +/obj/item/projectile/bullet/a38/q2 + damage = BULLET_DAMAGE_PISTOL_9MM_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a38/q3 + damage = BULLET_DAMAGE_PISTOL_9MM_MATCH + spread = BULLET_SPREAD_MATCH + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a38 + name = ".38 ammo box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "38box" + multiple_sprites = 2 + caliber = list(CALIBER_38) + ammo_type = /obj/item/ammo_casing/a38 + max_ammo = 100 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a38/q2 + name = ".38 ammo box (standard)" + ammo_type = /obj/item/ammo_casing/a38/q2 + +/obj/item/ammo_box/a38/q3 + name = ".38 ammo box (match)" + ammo_type = /obj/item/ammo_casing/a38/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a38/crate + name = ".38 ammo crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 600 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a38/crate/q2 + name = ".38 ammo crate (standard)" + ammo_type = /obj/item/ammo_casing/a38/q2 + +/obj/item/ammo_box/a38/crate/q3 + name = ".38 ammo crate (match)" + ammo_type = /obj/item/ammo_casing/a38/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a38 + name = ".38 ammo box (handload)" + id = "a38" + build_path = /obj/item/ammo_box/a38 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a38_2 + name = ".38 ammo box (standard)" + id = "a38_2" + build_path = /obj/item/ammo_box/a38/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a38_3 + name = ".38 ammo box (match)" + id = "a38_3" + build_path = /obj/item/ammo_box/a38/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a38crate + name = ".38 ammo crate (handload)" + id = "a38crate" + build_path = /obj/item/ammo_box/a38/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a38mcrate2 + name = ".38 ammo crate (standard)" + id = "a38crate2" + build_path = /obj/item/ammo_box/a38/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a38crate3 + name = ".38 ammo crate (match)" + id = "a38crate3" + build_path = /obj/item/ammo_box/a38/crate/q3 + category = list("initial", "Basic ammo") diff --git a/code/modules/projectiles/fuzammo/pistol_ammo_small/pistol_small_magazine.dm b/code/modules/projectiles/fuzammo/pistol_ammo_small/pistol_small_magazine.dm new file mode 100644 index 0000000000..d59778a877 --- /dev/null +++ b/code/modules/projectiles/fuzammo/pistol_ammo_small/pistol_small_magazine.dm @@ -0,0 +1,28 @@ +/obj/item/ammo_box/magazine/internal/cylinder/a38 + name = ".38 cylinder" + ammo_type = /obj/item/ammo_casing/a357 + caliber = list(CALIBER_38) + max_ammo = 6 + + + + +/obj/item/ammo_box/magazine/a9mm/doublestack + name = "doublestack pistol magazine (9mm)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "m9mmds" + ammo_type = /obj/item/ammo_casing/a9mm + caliber = list(CALIBER_9MM) + max_ammo = 15 + multiple_sprites = 2 + custom_materials = list(/datum/material/iron = MATS_MEDIUM_PISTOL_MAGAZINE) + +/obj/item/ammo_box/magazine/a9mm/doublestack/empty + start_empty = 1 + +/datum/design/ammolathe/a9mmds + name = "doublestack pistol magazine (9mm)" + id = "a9mmds" + materials = list(/datum/material/iron = 4000) + build_path = /obj/item/ammo_box/magazine/a9mm/doublestack/empty + category = list("initial", "Simple Magazines") diff --git a/code/modules/projectiles/fuzammo/rifle_ammo_large/rifle_large_ammo.dm b/code/modules/projectiles/fuzammo/rifle_ammo_large/rifle_large_ammo.dm new file mode 100644 index 0000000000..a8c96cccaa --- /dev/null +++ b/code/modules/projectiles/fuzammo/rifle_ammo_large/rifle_large_ammo.dm @@ -0,0 +1,144 @@ +// .308 is the standard + +/////////////////////////////// +////////// .308 ammo ////////// +/////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a308 + name = "handloaded .308 bullet casing" + desc = "A low-grade .308 bullet casing." + caliber = CALIBER_308 + projectile_type = /obj/item/projectile/bullet/a308 + material_class = BULLET_IS_HEAVY_RIFLE + custom_materials = list( + /datum/material/iron = MATS_RIFLE_HEAVY_CASING + MATS_RIFLE_HEAVY_BULLET, + /datum/material/blackpowder = MATS_RIFLE_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_RIFLE * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_RIFLE_HEAVY + +/obj/item/ammo_casing/a308/q2 + name = ".308 bullet casing" + desc = "A .308 bullet casing." + projectile_type = /obj/item/projectile/bullet/a308/q2 + custom_materials = list( + /datum/material/iron = MATS_RIFLE_HEAVY_CASING + MATS_RIFLE_HEAVY_BULLET, + /datum/material/blackpowder = MATS_RIFLE_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_RIFLE * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a308/q3 + name = "match .308 bullet casing" + desc = "A high-grade .308 bullet casing." + projectile_type = /obj/item/projectile/bullet/a308/q3 + custom_materials = list( + /datum/material/iron = MATS_RIFLE_HEAVY_CASING + MATS_RIFLE_HEAVY_BULLET, + /datum/material/blackpowder = MATS_RIFLE_HEAVY_POWDER) + fire_power = CASING_POWER_HEAVY_RIFLE * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a308 + name = ".308 bullet" + damage = BULLET_DAMAGE_RIFLE_308_HANDLOAD //36 + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_RIFLE_308 + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_RIFLE_308 + + wound_bonus = BULLET_WOUND_RIFLE_308 + bare_wound_bonus = BULLET_WOUND_RIFLE_308_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_RIFLE_HEAVY + + pixels_per_second = BULLET_SPEED_RIFLE_308 + damage_falloff = BULLET_FALLOFF_DEFAULT_RIFLE_HEAVY + +/obj/item/projectile/bullet/a308/q2 + damage = BULLET_DAMAGE_RIFLE_308_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a308/q3 + damage = BULLET_DAMAGE_RIFLE_308_MATCH + spread = BULLET_SPREAD_MATCH + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a308 + name = ".308 ammo box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "308box" + multiple_sprites = 2 + caliber = list(CALIBER_308) + ammo_type = /obj/item/ammo_casing/a308 + max_ammo = 20 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a308/q2 + name = ".308 ammo box (standard)" + ammo_type = /obj/item/ammo_casing/a308/q2 + +/obj/item/ammo_box/a308/q3 + name = ".308 ammo box (match)" + ammo_type = /obj/item/ammo_casing/a308/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a308/crate + name = ".308 ammo crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 120 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a308/crate/q2 + name = ".308 ammo crate (standard)" + ammo_type = /obj/item/ammo_casing/a308/q2 + +/obj/item/ammo_box/a308/crate/q3 + name = ".308 ammo crate (match)" + ammo_type = /obj/item/ammo_casing/a308/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a308 + name = ".308 ammo box (handload)" + id = "a308" + build_path = /obj/item/ammo_box/a308 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a308_2 + name = ".308 ammo box (standard)" + id = "a308_2" + build_path = /obj/item/ammo_box/a308/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a308_3 + name = ".308 ammo box (match)" + id = "a308_3" + build_path = /obj/item/ammo_box/a308/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a308crate + name = ".308 ammo crate (handload)" + id = "a308crate" + build_path = /obj/item/ammo_box/a308/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a308crate2 + name = ".308 ammo crate (standard)" + id = "a308crate2" + build_path = /obj/item/ammo_box/a308/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a308crate3 + name = ".308 ammo crate (match)" + id = "a308crate3" + build_path = /obj/item/ammo_box/a308/crate/q3 + category = list("initial", "Basic ammo") diff --git a/code/modules/projectiles/fuzammo/rifle_ammo_large/rifle_large_magazine.dm b/code/modules/projectiles/fuzammo/rifle_ammo_large/rifle_large_magazine.dm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/code/modules/projectiles/fuzammo/rifle_ammo_small/rifle_small_ammo.dm b/code/modules/projectiles/fuzammo/rifle_ammo_small/rifle_small_ammo.dm new file mode 100644 index 0000000000..995a5f59be --- /dev/null +++ b/code/modules/projectiles/fuzammo/rifle_ammo_small/rifle_small_ammo.dm @@ -0,0 +1,144 @@ +// .223 is the standard + +/////////////////////////////// +////////// .223 ammo ////////// +/////////////////////////////// + +///////////////casing/////////////// + +/obj/item/ammo_casing/a223 + name = "handloaded .223 bullet casing" + desc = "A low-grade .223 bullet casing." + caliber = CALIBER_223 + projectile_type = /obj/item/projectile/bullet/a223 + material_class = BULLET_IS_LIGHT_RIFLE + custom_materials = list( + /datum/material/iron = MATS_RIFLE_LIGHT_CASING + MATS_RIFLE_LIGHT_BULLET, + /datum/material/blackpowder = MATS_RIFLE_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_RIFLE * CASING_POWER_MOD_HANDLOAD + sound_properties = CSP_RIFLE_LIGHT + +/obj/item/ammo_casing/a223/q2 + name = ".223 bullet casing" + desc = "A .223 bullet casing." + projectile_type = /obj/item/projectile/bullet/a223/q2 + custom_materials = list( + /datum/material/iron = MATS_RIFLE_LIGHT_CASING + MATS_RIFLE_LIGHT_BULLET, + /datum/material/blackpowder = MATS_RIFLE_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_RIFLE * CASING_POWER_MOD_SURPLUS + +/obj/item/ammo_casing/a223/q3 + name = "match .223 bullet casing" + desc = "A high-grade .223 bullet casing." + projectile_type = /obj/item/projectile/bullet/a223/q3 + custom_materials = list( + /datum/material/iron = MATS_RIFLE_LIGHT_CASING + MATS_RIFLE_LIGHT_BULLET, + /datum/material/blackpowder = MATS_RIFLE_LIGHT_POWDER) + fire_power = CASING_POWER_LIGHT_RIFLE * CASING_POWER_MOD_MATCH + +///////////////bullet/////////////// + +/obj/item/projectile/bullet/a223 + name = ".223 bullet" + damage = BULLET_DAMAGE_RIFLE_223_HANDLOAD //36 + damage_list = list("30" = 30, "36" = 30, "40" = 30, "41" = 2, "42" = 2, "43" = 2, "44" = 2, "45" = 1, "50" = 0.5, "55" = 0.5) + stamina = BULLET_STAMINA_RIFLE_223 + spread = BULLET_SPREAD_HANDLOAD + recoil = BULLET_RECOIL_RIFLE_223 + + wound_bonus = BULLET_WOUND_RIFLE_223 + bare_wound_bonus = BULLET_WOUND_RIFLE_223_NAKED_MULT + wound_falloff_tile = BULLET_WOUND_FALLOFF_RIFLE_LIGHT + + pixels_per_second = BULLET_SPEED_RIFLE_223 + damage_falloff = BULLET_FALLOFF_DEFAULT_RIFLE_LIGHT + +/obj/item/projectile/bullet/a223/q2 + damage = BULLET_DAMAGE_RIFLE_223_SURPLUS + spread = BULLET_SPREAD_SURPLUS + +/obj/item/projectile/bullet/a223/q3 + damage = BULLET_DAMAGE_RIFLE_223_MATCH + spread = BULLET_SPREAD_MATCH + +///////////////ammo box/////////////// + +/obj/item/ammo_box/a223 + name = ".223 ammo box (handload)" + icon = 'icons/fallout/objects/guns/ammo.dmi' + icon_state = "556box" + multiple_sprites = 2 + caliber = list(CALIBER_223) + ammo_type = /obj/item/ammo_casing/a223 + max_ammo = 50 // don't change this for new calibers + w_class = WEIGHT_CLASS_SMALL + custom_materials = list(/datum/material/iron = MATS_RIFLE_SMALL_BOX) + randomize_ammo_count = FALSE + +/obj/item/ammo_box/a223/q2 + name = ".223 ammo box (standard)" + ammo_type = /obj/item/ammo_casing/a223/q2 + +/obj/item/ammo_box/a223/q3 + name = ".223 ammo box (match)" + ammo_type = /obj/item/ammo_casing/a223/q3 + +///////////////ammo crate/////////////// + +/obj/item/ammo_box/a223/crate + name = ".223 ammo crate (handload)" + desc = "A wooden crate of ammo." + icon = 'modular_coyote/icons/objects/c13ammo.dmi' + icon_state = "wood_ammobox" + w_class = WEIGHT_CLASS_HUGE // don't you dare make this any smaller! + multiple_sprites = 4 + max_ammo = 300 // don't change this for new calibers + load_behavior = AMMOB_CRATE + +/obj/item/ammo_box/a223/crate/q2 + name = ".223 ammo crate (standard)" + ammo_type = /obj/item/ammo_casing/a223/q2 + +/obj/item/ammo_box/a223/crate/q3 + name = ".223 ammo crate (match)" + ammo_type = /obj/item/ammo_casing/a223/q3 + +///////////////ammo box recipe/////////////// + +/datum/design/ammolathe/a223 + name = ".223 ammo box (handload)" + id = "a223" + build_path = /obj/item/ammo_box/a223 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a223_2 + name = ".223 ammo box (standard)" + id = "a223_2" + build_path = /obj/item/ammo_box/a223/q2 + category = list("initial", "Basic Ammo") + +/datum/design/ammolathe/a223_3 + name = ".223 ammo box (match)" + id = "a223_3" + build_path = /obj/item/ammo_box/a223/q3 + category = list("initial", "Basic Ammo") + +///////////////ammo crate recipe/////////////// + +/datum/design/ammolathe/a223crate + name = ".223 ammo crate (handload)" + id = "a223crate" + build_path = /obj/item/ammo_box/a223/crate + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a223crate2 + name = ".223 ammo crate (standard)" + id = "a223crate2" + build_path = /obj/item/ammo_box/a223/crate/q2 + category = list("initial", "Basic ammo") + +/datum/design/ammolathe/a223crate3 + name = ".223 ammo crate (match)" + id = "a223crate3" + build_path = /obj/item/ammo_box/a223/crate/q3 + category = list("initial", "Basic ammo") diff --git a/code/modules/projectiles/fuzammo/rifle_ammo_small/rifle_small_magazine.dm b/code/modules/projectiles/fuzammo/rifle_ammo_small/rifle_small_magazine.dm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/code/modules/projectiles/fuzguns/bow.dm b/code/modules/projectiles/fuzguns/bow.dm new file mode 100644 index 0000000000..965c917b25 --- /dev/null +++ b/code/modules/projectiles/fuzguns/bow.dm @@ -0,0 +1,224 @@ +/obj/item/gun/ballistic/bow + name = "base bow" + desc = "base type of bow used to define features for multiple-loading bows" + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "bow" + inhand_icon_state = "bow" + weapon_class = null + w_class = WEIGHT_CLASS_NORMAL + slot_flags = INV_SLOTBIT_BACK | INV_SLOTBIT_BELT + draw_time = GUN_DRAW_QUICK + weapon_weight = GUN_TWO_HAND_ONLY //need both hands to fire + mag_type = /obj/item/ammo_box/magazine/internal/bow + fire_sound = 'sound/weapons/bowfire.wav' + item_flags = NONE + pin = null + no_pin_required = TRUE + trigger_guard = TRIGGER_GUARD_ALLOW_ALL //so ashwalkers (and monke) can use it + spawnwithmagazine = TRUE + casing_ejector = TRUE + + var/recentdraw + var/draw_sound = 'sound/weapons/bowdraw.wav' + dryfire_text = "*no arrows*" + dryfire_sound = "" + var/release_text = "You gently release the bowstring, removing the arrow." + var/draw_noun = "string" + safety = 0 + restrict_safety = 1 + init_firemodes = list( + /datum/firemode/semi_auto/slowest + ) + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION + + + /// Can this bow link to a quiver? + var/can_link_to_quiver = TRUE + /// Is this bow drawing from a quiver, if linked? + var/drawing_from_quiver = FALSE + /// The quiver the bow is drawing from + var/datum/weakref/our_quiver + var/list/slotlist = list( + SLOT_BACK, + SLOT_BELT, + SLOT_NECK, + SLOT_WEAR_SUIT, + SLOT_L_STORE, + SLOT_R_STORE, + SLOT_S_STORE, + SLOT_GENERIC_DEXTROUS_STORAGE + ) + +/obj/item/gun/ballistic/bow/process_chamber(mob/living/user, empty_chamber = 0) + var/obj/item/ammo_casing/AC = chambered //Find chambered round + if(istype(AC)) //there's a chambered round + AC.forceMove(drop_location()) //Eject casing onto ground. + chambered = null + +/obj/item/gun/ballistic/bow/examine(mob/user) + . = ..() + if(can_link_to_quiver && loc == user) + if(!drawing_from_quiver) + . += "Not drawing from a worn quiver." + . += "Alt-click the bow to start drawing from a quiver." + return + var/obj/item/storage/bag/tribe_quiver/my_quiver = get_quiver(user) + if(istype(my_quiver)) + . += "Currently drawing from [my_quiver]." + . += "Alt-click the bow to stop drawing from this quiver." + . += "Smack a quiver against this bow, or smack this against a quiver, to start drawing arrows from that quiver." + return + . += "No quiver found to draw from. Wear a quiver on your belt, or smack a quiver on this bow, to draw from that quiver." + . += "Alt-click the bow to stop drawing from this quiver." + +/obj/item/gun/ballistic/bow/can_shoot() + return chambered + +/obj/item/gun/ballistic/bow/attack_self(mob/living/user) + if(chambered) + user.put_in_hands(chambered) + chambered = null + update_icon() + to_chat(user, span_notice(release_text)) + return +/* if(recentdraw > world.time || !get_ammo(FALSE)) + return */ + draw(user, TRUE) +// recentdraw = world.time + 2 + +/obj/item/gun/ballistic/bow/proc/draw(mob/M, visible = TRUE) + if(!draw_load(M)) + return TRUE + if(visible) + M.visible_message(span_warning("[M] draws the [draw_noun] on [src]!"), span_warning("You draw the [draw_noun] on [src]!")) + playsound(M, draw_sound, 60, 1) + draw_load(M) + update_icon() + return 1 + +/obj/item/gun/ballistic/bow/proc/draw_load(mob/M) + if(chambered) + return FALSE + if(!magazine.ammo_count() && !load_from_quiver(M)) // if its empty, try sticking a new ammo in there + return FALSE + var/obj/item/ammo_casing/AC = magazine.get_round() //load next casing. + chambered = AC + . = TRUE + var/room_left_in_mag = magazine.max_ammo - LAZYLEN(magazine.stored_ammo) + if(room_left_in_mag) // and fill up the rest of the bow if possible + var/did_a_load = FALSE + for(var/i in 1 to room_left_in_mag) + if(!load_from_quiver(M)) + break + did_a_load = TRUE + if(did_a_load) + M.show_message(span_notice("You ready some arrows from your quiver.")) + +/obj/item/gun/ballistic/bow/proc/load_from_quiver(mob/user) + if(!drawing_from_quiver) + return FALSE + if(!can_link_to_quiver) + return FALSE + if(!istype(user)) + return FALSE + if(LAZYLEN(magazine.stored_ammo) >= magazine.max_ammo) + return FALSE + var/obj/item/storage/bag/tribe_quiver/got_quiver = get_quiver(user) + if(!istype(got_quiver)) + return FALSE + for(var/obj/item/ammo_casing/isit_pointy in got_quiver.contents) + if(!isit_pointy.BB) + continue + if(!SEND_SIGNAL(got_quiver, COMSIG_TRY_STORAGE_TAKE, isit_pointy, magazine)) + continue + if(magazine.give_round(isit_pointy)) + return TRUE + +/obj/item/gun/ballistic/bow/proc/get_quiver(mob/user, just_get_it) + if(!istype(user)) + return + var/obj/item/storage/bag/tribe_quiver/getted_quiver + /// First try and draw from our chosen quiver + if(isweakref(our_quiver)) + getted_quiver = our_quiver.resolve() + if(istype(getted_quiver, /obj/item/storage/bag/tribe_quiver) && (getted_quiver.loc == user || just_get_it)) + return getted_quiver + /// Otherwise, draw from whatever's on the belt + for(var/slut in slotlist) + getted_quiver = user.get_item_by_slot(slut) + if(!istype(getted_quiver, /obj/item/storage/bag/tribe_quiver)) + continue + if((getted_quiver.loc != user && !just_get_it)) + continue + if(link_quiver_to_bow(user, getted_quiver)) + return getted_quiver + +/obj/item/gun/ballistic/bow/proc/link_quiver_to_bow(mob/user, obj/item/storage/bag/tribe_quiver/the_quiver) + if(!istype(the_quiver)) + return + if(!ismob(user)) + return + if(our_quiver) + var/obj/item/storage/bag/tribe_quiver/prev_quiver = our_quiver.resolve() + if(prev_quiver == the_quiver) + user.show_message(span_notice("[src] is already drawing from [the_quiver]!")) + return TRUE + our_quiver = WEAKREF(the_quiver) + if(our_quiver) + user.show_message(span_notice("You are now drawing from [the_quiver]!")) + return TRUE + +/obj/item/gun/ballistic/bow/AltClick(mob/living/carbon/user) + . = ..() + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return FALSE + if(loc != user) + return FALSE + drawing_from_quiver = !drawing_from_quiver + if(can_link_to_quiver) + user.show_message("You're [drawing_from_quiver?"now":"no longer"] drawing from a quiver, if one is worn.") + return TRUE + +/obj/item/gun/ballistic/bow/attackby(obj/item/A, mob/user, params) + if(istype(A, /obj/item/storage/bag/tribe_quiver)) + link_quiver_to_bow(user, A) + return + /*if(istype(A, /obj/item/gun_upgrade)) + return*/ + if(magazine.attackby(A, user, params, 1)) + to_chat(user, span_notice("You load [A] into \the [src].")) + update_icon() + return + // Bows hate attachments, this tries to check for them. I'm done fucking with it, someone skilled is needed + +/obj/item/gun/ballistic/bow/update_icon() + icon_state = "[initial(icon_state)]_[get_ammo() ? (chambered ? "firing" : "loaded") : "unloaded"]" + +/obj/item/gun/ballistic/bow/after_shooting(mob/living/user) + ..() + if(!HAS_TRAIT(user, TRAIT_AUTO_DRAW)) + return + if(chambered) + return + if(!get_ammo(FALSE)) + return + user.visible_message(span_warning("[user] instinctively draws the string on [src]!"), span_warning("You instinctively draw the string on [src]!")) + draw(user, FALSE) + recentdraw = world.time + 2 + +////////////////////////////// +// Coyote Boyou Additions // +////////////////////////////// +/obj/item/gun/ballistic/bow + force = 15 + force_wielded = 30 + +/obj/item/gun/ballistic/bow/CtrlShiftClick(mob/user) + if(damtype == BRUTE) + balloon_alert(user, "Switched to Stamina melee damage.") + damtype = STAMINA + else + balloon_alert(user, "Switched to Brute melee damage.") + damtype = BRUTE +// Hopefully some player somewhere at some point in time will make use of this incredibly niche attack. +// Not without telling them about it lmfao diff --git a/code/modules/projectiles/fuzguns/flintlock.dm b/code/modules/projectiles/fuzguns/flintlock.dm new file mode 100644 index 0000000000..e0434a485d --- /dev/null +++ b/code/modules/projectiles/fuzguns/flintlock.dm @@ -0,0 +1,241 @@ +////////////////////// +//FLINTLOCK TEMPLATE// +////////////////////// + +/obj/item/gun/flintlock + name = "flintlock template" + desc = "should not be here, bugreport." + icon_state = "flintlock" + inhand_icon_state = "flintlock" + dryfire_text = "*not loaded*" + var/cocked = TRUE + var/my_caliber = CALIBER_FLINTLOCK + var/load_time = FLINTLOCK_PISTOL_RELOAD_TIME + var/prefire_time = FLINTLOCK_PISTOL_PREFIRE_TIME + var/prefire_randomness = FLINTLOCK_PISTOL_PREFIRE_STD + var/datum/looping_sound/musket_load/load_loop + var/datum/looping_sound/musket_fuse/fuse_loop + weapon_special_component = null + +/obj/item/gun/flintlock/Initialize() + . = ..() + load_loop = new(list(src), FALSE) + fuse_loop = new(list(src), FALSE) + chambered = new /obj/item/ammo_casing/caseless/flintlock(src) + +/obj/item/gun/flintlock/admin_fill_gun() + if(chambered) + return + chambered = new /obj/item/ammo_casing/caseless/flintlock(src) + cocked = TRUE + update_icon() + return TRUE + +/obj/item/gun/flintlock/generate_guntags() + ..() + gun_tags |= GUN_PROJECTILE + +/obj/item/gun/flintlock/UpdateAmmoCountOverlay() + // if(isturf(loc))//Only show th ammo count if the magazine is, like, in an inventory or something. Mags on the ground don't need a big number on them, that's ugly. + // maptext = "" + // else + // var/txte = "" + // var/culur = "#FF0000" + // if(chambered) + // if(cocked) + // txte = "1/1 !C!" + // culur = "#00FFFF" + // else + // txte = "1/1" + // culur = "#FFFF00" + // else + // if(cocked) + // txte = "0/1 !C!" + // culur = "#FF0000" + // else + // txte = "0/1" + // culur = "#FF0000" + // maptext = "[txte]" + + +/obj/item/gun/flintlock/ui_data(mob/user) + var/list/data = ..() + data["cockable"] = TRUE + data["cocked"] = cocked || FALSE + data["flintlock_load_time"] = (load_time * 0.1) || 0 + data["flintlock_prefire_time"] = (prefire_time * 0.1) || 0 + data["flintlock_prefire_1SD"] = (prefire_randomness * 0.1) || 0 + data["has_magazine"] = TRUE + data["accepted_magazines"] = "powder, and ball" + data["magazine_name"] = "Metal Tube" + data["magazine_calibers"] = "powder, and ball" + data["shots_remaining"] = !!chambered || 0 + data["shots_max"] = 1 + return data + +/obj/item/gun/flintlock/attack_self(mob/living/user) + cock(user) + +/obj/item/gun/flintlock/AltClick(mob/user) + unload(user) + +/obj/item/gun/flintlock/attackby(obj/item/I, mob/user, params) + . = ..() + if(istype(I, /obj/item/ammo_box)) + load_from_box(user, I) + if(istype(I, /obj/item/ammo_casing)) + load_casing(user, I) + +/obj/item/gun/flintlock/update_icon_state() + return + +/// Scans the box, takes a casing if possible +/obj/item/gun/flintlock/proc/load_from_box(mob/living/user, obj/item/ammo_box/bawx) + if(!user) + return + if(chambered) + to_chat(user, span_alert("[src] is already loaded!")) + return + if(!istype(bawx, /obj/item/ammo_box)) + return + var/obj/item/ammo_casing/to_load + for(var/obj/item/ammo_casing/bluuet in bawx.stored_ammo) // magazine procs suck (I should know, i wrote em) + if(bluuet.caliber != my_caliber) + continue + to_load = bluuet + break + if(!to_load) + to_chat(user, span_alert("Couldn't find anything in [bawx] that fits in [src].")) + return + if(!load_casing(user, to_load)) //load the ammo casing into the gun + to_chat(user, span_alert("You can't seem to load [to_load] into [src].")) //tell the user the gun cannot be loaded + return //return + bawx.stored_ammo -= to_load //remove the ammo casing from the boxx + bawx.update_icon() //update the icon of the boxx + +/// Forcemoves bluuet into the gun, and sets its chambered to the bluuet +/obj/item/gun/flintlock/proc/load_casing(mob/living/user, obj/item/ammo_casing/bluuet) + if(!user) //if there is no user + return //return + if(chambered) //if the gun is already loaded + to_chat(user, span_alert("[src] is already loaded!")) //tell the user the gun is already loaded + return //return + if(!istype(bluuet, /obj/item/ammo_casing)) //if the thing you are trying to load is not an ammo casing + return //return + if(bluuet.caliber != my_caliber) //if the gun and the ammo casing do not share the same caliber + to_chat(user, span_alert("[bluuet] doesn't fit in [src].")) //tell the user the casing does not fit + return //return + load_loop.start() + to_chat(user, span_notice("You begin loading [bluuet] into [src].")) //tell the user the gun is being loaded + if(!do_after(user, load_time, TRUE, src, allow_movement = TRUE)) //do after for loading the gun + load_loop.stop() + to_chat(user, span_alert("You were interrupted!")) //tell the user they stopped loading the gun + return //return + load_loop.stop() + if(!user.transferItemToLoc(bluuet, src)) //if the user cannot transfer the item to the location of the gun + to_chat(user, span_alert("You can't seem to load [bluuet] into [src].")) //tell the user the gun cannot be loaded + return //return + chambered = bluuet //set the chambered variable to the ammo casing being loaded + to_chat(user, span_notice("You load [bluuet] into [src].")) //tell the user the gun is loaded + playsound(get_turf(src), 'sound/weapons/stuff_casing_end.ogg', 80, TRUE) + update_icon() + return TRUE + +/// Ejects chambered into the user's hands, and sets chambered to null, and sets cocked to FALSE, and plays a ka-ta-click noise, and updates the icon, and returns TRUE +/obj/item/gun/flintlock/proc/unload(mob/living/user) + if(!user) + return + if(!chambered) + to_chat(user, span_alert("[src] is not loaded!")) + return + chambered = null + cocked = FALSE + playsound(get_turf(src), 'sound/weapons/stuff_casing.ogg', 80, TRUE) + playsound(get_turf(src), 'sound/weapons/hammer_click2.ogg', 90, 1) + to_chat(user, span_notice("You unload [src].")) + update_icon() + if(!user.put_in_hands(chambered)) + chambered.forceMove(get_turf(src)) + return + return TRUE + +/// Sets cocked to TRUE, and plays a ka-ta-click noise +/obj/item/gun/flintlock/proc/cock(mob/living/user) + if(!user) + return FALSE + if(cocked) + uncock(user) + return + cocked = TRUE + playsound(get_turf(src), 'sound/weapons/hammer_cock.ogg', 80, TRUE) + user.visible_message(span_alert("[user] pulls back [src]'s hammer!")) + update_icon() + +/// Sets cocked to FALSE, and plays a ka-ta-click noise +/obj/item/gun/flintlock/proc/uncock(mob/living/user) + if(!user) + return FALSE + if(!cocked) + cock(user) + return + cocked = FALSE + playsound(get_turf(src), 'sound/weapons/hammer_click2.ogg', 90, 1) + user.visible_message(span_notice("[user] gently releases [src]'s hammer back down.")) + update_icon() + +/// Plays a click-sound, then a half-second later, shoots whatever's under the user's cursor. or the mob's direction if the cursor's params are null +/obj/item/gun/flintlock/pre_fire(mob/user, atom/target, params, zone_override, message = TRUE) + if(!user?.client) + return FALSE + if(!cocked) + to_chat(user, span_alert("[src] isn't cocked!")) + playsound(get_turf(src), 'sound/weapons/tap.ogg', 90, 1) + return TRUE + playsound(get_turf(src), 'sound/weapons/hammer_click.ogg', 90, 1) + playsound(get_turf(src), 'sound/weapons/strike_sizzle.ogg', 45, 1) + firing = TRUE + var/shoot_delay = round(max(gaussian(prefire_time, prefire_time * prefire_randomness), prefire_time * 0.75), 0.1) + fuse_loop.start() + addtimer(CALLBACK(src,PROC_REF(fire_at_cursor), user), shoot_delay) + update_icon() + return TRUE + +/// shoots whatever's under the user's cursor. or the user's direction if the cursor's params are null +/obj/item/gun/flintlock/proc/fire_at_cursor(mob/user) + firing = FALSE // the gun's firing btw + cocked = FALSE + fuse_loop.stop() + if(!chambered || !chambered.BB) + shoot_with_empty_chamber(user) + return FALSE + var/atom/tar_get = user?.client?.mouseObject + if(istype(tar_get, /atom/movable/screen)) // we clicked the ~void~, and now we need to do math + tar_get = null + if(user?.client) + var/angel = mouse_angle_from_client(user.client) + var/turf/shootat = get_turf_in_angle(angel, get_turf(src), 20) // sure + if(shootat) + tar_get = shootat + /// this is if they disconnect, or tossed the gun before it fired, or ceased to exist, or something + if(!tar_get || !user || loc != user) + tar_get = null + if(prob(50) || (user && HAS_TRAIT(user, TRAIT_NICE_SHOT))) // pick someone or something to shoot + var/list/luckyboiz = list() + for(var/mob/living/luckyboi in view(get_turf(src), 20)) + luckyboiz += luckyboi + if(LAZYLEN(luckyboiz)) + tar_get = pick(luckyboiz) + else // if there's nothing to shoot, pick a random direction + tar_get = get_step(user, pick(GLOB.alldirs)) + user = null // to prevent factionization, and let it shoot yourself (in the foot) + user?.face_atom(tar_get) + do_fire(tar_get, user, TRUE, user?.client?.mouseParams) + SSeffects.do_effect(EFFECT_SMOKE_CONE, get_turf(src), get_turf(tar_get)) + chambered = null // the caseless casing thing deletes itself + update_icon() + if(!user) // on the ground, so toss it around + var/shootdir = turn(get_dir(get_turf(src), get_turf(tar_get)), 180) + var/turf/toss_thisways = get_step(get_turf(src), shootdir) + if(prob(50)) // throw a bit further + toss_thisways = get_step(toss_thisways, shootdir) + throw_at(toss_thisways, 4, 1, null, TRUE, TRUE) diff --git a/code/modules/projectiles/fuzguns/gun_parents.dm b/code/modules/projectiles/fuzguns/gun_parents.dm new file mode 100644 index 0000000000..d6a467ba7c --- /dev/null +++ b/code/modules/projectiles/fuzguns/gun_parents.dm @@ -0,0 +1,117 @@ +////////////////////// +//AUTOMATIC TEMPLATE// +////////////////////// + +/obj/item/gun/ballistic/automatic + name = "automatic gun template" + desc = "should not be here, bugreport." + + var/auto_eject = 0 //for en blocs + var/auto_eject_sound = null + //var/alarmed = 0 //for a funky, annoying sound when ammo runs out. broken code + equipsound = 'sound/f13weapons/equipsounds/riflequip.ogg' + init_recoil = SMG_RECOIL(1, 1) + +/obj/item/gun/ballistic/automatic/update_icon_state() + if(SEND_SIGNAL(src, COMSIG_ITEM_UPDATE_RESKIN)) + return // all done! + var/bolt_closed = bolt_state == GBOLT_CLOSED + icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][bolt_closed ? "" : "-e"]" + +/obj/item/gun/ballistic/automatic/can_shoot() + return get_ammo() + +/obj/item/gun/ballistic/automatic/afterattack(atom/target, mob/living/user) + ..() + if(auto_eject && magazine && magazine.stored_ammo && !magazine.stored_ammo.len && !chambered) + magazine.dropped() + user.visible_message( + "[magazine] falls out and clatters on the floor!", + span_notice("[magazine] falls out and clatters on the floor!") + ) + if(auto_eject_sound) + playsound(user, auto_eject_sound, 40, 1) + magazine.forceMove(get_turf(src.loc)) + magazine.update_icon() + magazine = null + update_icon() + +/////////////////// +//PISTOL TEMPLATE// +/////////////////// + +/obj/item/gun/ballistic/automatic/pistol + name = "pistol template" + desc = "should not be here. Bugreport." + equipsound = 'sound/f13weapons/equipsounds/pistolequip.ogg' + init_recoil = HANDGUN_RECOIL(1, 1) + +/obj/item/gun/ballistic/automatic/pistol/no_mag + spawnwithmagazine = FALSE + +/obj/item/gun/ballistic/automatic/pistol/update_icon_state() + var/bolt_closed = bolt_state == GBOLT_CLOSED + icon_state = "[initial(icon_state)][bolt_closed ? "" : "-e"]" + +//////////////////// +// RIFLE TEMPLATE // +//////////////////// + +/obj/item/gun/ballistic/rifle + name = "rifle template" + desc = "Should not exist" + init_recoil = RIFLE_RECOIL(1, 1) + init_firemodes = list( + /datum/firemode/bolt_using/straight_pull + ) + manual_bolt_open_sound = 'sound/weapons/biblically_accurate_guns/bolt_rifle_open_short.ogg' + manual_bolt_close_sound = 'sound/weapons/biblically_accurate_guns/bolt_rifle_close_short.ogg' + casing_eject_sound = 'sound/weapons/biblically_accurate_guns/bolt_casing_eject.ogg' + empty_casing_eject_sound = 'sound/weapons/biblically_accurate_guns/bolt_casing_eject_empty.ogg' + + spawnwithmagazine = TRUE + can_load_magazine_through_bolt = TRUE + +/obj/item/gun/ballistic/rifle/blow_up(mob/user) + . = 0 + if(chambered && chambered.BB) + process_fire(user, user, FALSE) + . = 1 + +////////////////////// +// SHOTGUN TEMPLATE // +////////////////////// + +/obj/item/gun/ballistic/shotgun + name = "shotgun template" + desc = "Should not exist" + mag_type = /obj/item/ammo_box/magazine/internal/shot + manual_bolt_open_sound = 'sound/weapons/biblically_accurate_guns/bolt_shotgun_open.ogg' + manual_bolt_close_sound = 'sound/weapons/biblically_accurate_guns/bolt_shotgun_close.ogg' + casing_eject_sound = 'sound/weapons/biblically_accurate_guns/bolt_casing_eject.ogg' + empty_casing_eject_sound = 'sound/weapons/biblically_accurate_guns/bolt_casing_eject_empty.ogg' + + fire_sound = 'sound/f13weapons/shotgun.ogg' + init_recoil = SHOTGUN_RECOIL(1, 1) + init_firemodes = list( + /datum/firemode/bolt_using/pump_action + ) + spawnwithmagazine = TRUE + can_load_magazine_through_bolt = TRUE + +/obj/item/gun/ballistic/shotgun/blow_up(mob/user) + . = 0 + if(chambered && chambered.BB) + process_fire(user, user, FALSE) + . = 1 + +//////////////////////////////// +// AUTOMATIC SHOTGUN TEMPLATE // +//////////////////////////////// + +/obj/item/gun/ballistic/shotgun/automatic/update_icon_state() + var/bolt_open = bolt_state == GBOLT_OPEN + if(bolt_open) + icon_state = "[initial(icon_state)]-e" + else + icon_state = "[initial(icon_state)]" diff --git a/code/modules/projectiles/fuzguns/longarms_high_caliber/automatic_rifle.dm b/code/modules/projectiles/fuzguns/longarms_high_caliber/automatic_rifle.dm new file mode 100644 index 0000000000..8d2f059088 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_high_caliber/automatic_rifle.dm @@ -0,0 +1,80 @@ +// FAL is the baseline +/obj/item/gun/ballistic/automatic/ra + name = "automatic rifle template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/automatic/rpm800, + /datum/firemode/semi_auto/rpm800 + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + auto_eject = 0 // auto-ejects empty magazine + auto_eject_sound = null + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/ra/fal + name = " worn FAL" + desc = "An automatic rifle chambered in .308." +/obj/item/gun/ballistic/automatic/ra/fal/q2 + name = "FAL" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/ra/fal/q3 + name = "unrusted FAL" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_high_caliber/battle_rifle.dm b/code/modules/projectiles/fuzguns/longarms_high_caliber/battle_rifle.dm new file mode 100644 index 0000000000..b7876eb5cc --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_high_caliber/battle_rifle.dm @@ -0,0 +1,80 @@ +// AR-10 is baseline +/obj/item/gun/ballistic/automatic/br + name = "battle rifle template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/automatic/rpm800, + /datum/firemode/semi_auto/rpm800 + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + auto_eject = 0 // auto-ejects empty magazine + auto_eject_sound = null + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/br/ar10 + name = " worn AR-10" + desc = "A battle rifle chambered in .308." +/obj/item/gun/ballistic/automatic/br/ar10/q2 + name = "AR-10" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/br/ar10/q3 + name = "unrusted AR-10" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_high_caliber/medium_machinegun.dm b/code/modules/projectiles/fuzguns/longarms_high_caliber/medium_machinegun.dm new file mode 100644 index 0000000000..3a0983b9fe --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_high_caliber/medium_machinegun.dm @@ -0,0 +1,80 @@ +// bren is the baseline +/obj/item/gun/ballistic/automatic/mmg + name = "medium machine gun template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/automatic/rpm800, + /datum/firemode/semi_auto/rpm800 + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + auto_eject = 0 // auto-ejects empty magazine + auto_eject_sound = null + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/mmg/bren + name = " worn Bren gun" + desc = "A medium machinegun chambered in .308." +/obj/item/gun/ballistic/automatic/mmg/bren/q2 + name = "Bren gun" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/mmg/bren/q3 + name = "unrusted Bren gun" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_high_caliber/repeating_rifle.dm b/code/modules/projectiles/fuzguns/longarms_high_caliber/repeating_rifle.dm new file mode 100644 index 0000000000..8942881a56 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_high_caliber/repeating_rifle.dm @@ -0,0 +1,78 @@ +// Remington 700 is the standard + +/obj/item/gun/ballistic/rifle/repeating_rifle + name = "repeating rifle template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/bolt_using/straight_pull + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE // Load with the bolt closed, like hatch loaded lever actions +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/repeating_rifle/r700 + name = " worn R700" + desc = "A repeating rifle chambered in .308." +/obj/item/gun/ballistic/automatic/repeating_rifle/r700/q2 + name = "R700" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/repeating_rifle/r700/q3 + name = "unrusted R700" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_low_caliber/assault_rifle.dm b/code/modules/projectiles/fuzguns/longarms_low_caliber/assault_rifle.dm new file mode 100644 index 0000000000..8677ac0c52 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_low_caliber/assault_rifle.dm @@ -0,0 +1,82 @@ +// M16 is baseline +//need to choose sprite + +/obj/item/gun/ballistic/automatic/ar + name = "assault rifle template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/automatic/rpm800, + /datum/firemode/semi_auto/rpm800 + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + auto_eject = 0 // auto-ejects empty magazine + auto_eject_sound = null + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/ar/m16 + name = " worn M16" + desc = "An assault rifle chambered in .223. It is not, in fact, self cleaning..." +/obj/item/gun/ballistic/automatic/ar/m16/q2 + name = "M16" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/ar/m16/q3 + name = "unrusted M16" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_low_caliber/light_machinegun.dm b/code/modules/projectiles/fuzguns/longarms_low_caliber/light_machinegun.dm new file mode 100644 index 0000000000..7c3176d578 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_low_caliber/light_machinegun.dm @@ -0,0 +1,82 @@ +// R84 is placeholder baseline +// use it as the M249 maybe + +/obj/item/gun/ballistic/automatic/lmg + name = "light machine gun template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/automatic/rpm800, + /datum/firemode/semi_auto/rpm800 + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + auto_eject = 0 // auto-ejects empty magazine + auto_eject_sound = null + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/automatic/lmg + name = "worn M249" + desc = "A light machine gun chambered in .223." +/obj/item/gun/ballistic/automatic/automatic/lmg/q2 + name = "M249" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/automatic/lmg/q3 + name = "unrusted M249" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_low_caliber/repeating_carbine.dm b/code/modules/projectiles/fuzguns/longarms_low_caliber/repeating_carbine.dm new file mode 100644 index 0000000000..7177376df0 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_low_caliber/repeating_carbine.dm @@ -0,0 +1,77 @@ +// Winchester 1873 is baseline +obj/item/gun/ballistic/rifle/repeating_carbine + name = "repeating carbine template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/bolt_using/straight_pull + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = TRUE // Load with the bolt closed, like hatch loaded lever actions +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/repeating_carbine/m1873 + name = " worn Model 1873" + desc = "A repeating carbine chambered in .357 mag." +/obj/item/gun/ballistic/automatic/repeating_carbine/m1873/q2 + name = "Model 1873" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/repeating_carbine/m1873/q3 + name = "unrusted Model 1873" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_low_caliber/service_rifle.dm b/code/modules/projectiles/fuzguns/longarms_low_caliber/service_rifle.dm new file mode 100644 index 0000000000..8434ffe166 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_low_caliber/service_rifle.dm @@ -0,0 +1,82 @@ +// ar-15 is baseline +//need to choose sprite + +/obj/item/gun/ballistic/automatic/sr + name = "service rifle template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/automatic/rpm800, + /datum/firemode/semi_auto/rpm800 + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + auto_eject = 0 // auto-ejects empty magazine + auto_eject_sound = null + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/sr/ar15 + name = " worn AR-15" + desc = "A service rifle chambered in .223." +/obj/item/gun/ballistic/automatic/sr/ar15/q2 + name = "AR-15" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/sr/ar15/q3 + name = "unrusted AR-15" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_specialty/blackpowder_rifle.dm b/code/modules/projectiles/fuzguns/longarms_specialty/blackpowder_rifle.dm new file mode 100644 index 0000000000..b924b40c04 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_specialty/blackpowder_rifle.dm @@ -0,0 +1,76 @@ +// brown bess is baseline + + +/obj/item/gun/flintlock/blackpowder_rifle + name = "blackpowder rifle template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + my_caliber = CALIBER_FLINTLOCK // defines the acceptable cartridge + load_time = FLINTLOCK_PISTOL_RELOAD_TIME // momentary hang after trigger pull + prefire_time = FLINTLOCK_PISTOL_PREFIRE_TIME // randomness to the hang + prefire_randomness = FLINTLOCK_PISTOL_PREFIRE_STD + init_firemodes = list( // fire modes and fire rate + /datum/firemode/semi_auto + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/flintlock/blackpowder_rifle/bess + name = "worn Brown Bess" + desc = "A blackpowder rifle chambered in .75 ball." +/obj/item/gun/flintlock/blackpowder_rifle/bess/q2 + name = "Brown Bess" + max_upgrades = 4 +/obj/item/gun/flintlock/blackpowder_rifle/bess/q3 + name = "unrusted Brown Bess" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_specialty/bow.dm b/code/modules/projectiles/fuzguns/longarms_specialty/bow.dm new file mode 100644 index 0000000000..1a8d27fdfc --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_specialty/bow.dm @@ -0,0 +1,15 @@ +// recurve bow is baseline +//this category also includes crossbows + +//holy placeholder batman + +/obj/item/gun/ballistic/bow/modern + name = "Modern Recurve Bow" + desc = "A recurve bow manufactured with modern tools and materials." + icon = 'modular_coyote/icons/objects/guns/bows.dmi' + icon_state = "modern" + inhand_icon_state = "bow" + damage_multiplier = GUN_EXTRA_DAMAGE_T3 //Now actually worth taking over the longbow. + init_firemodes = list( + /datum/firemode/semi_auto/slower // Fires faster, more accurate. + ) diff --git a/code/modules/projectiles/fuzguns/longarms_specialty/launcher.dm b/code/modules/projectiles/fuzguns/longarms_specialty/launcher.dm new file mode 100644 index 0000000000..2408f7f702 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_specialty/launcher.dm @@ -0,0 +1,12 @@ +// M79 launcher is baseline + +/obj/item/gun/ballistic/revolver/thumper + name = "M79 Thumper" + desc = "A grenade launcher chambered in 40mm. Affectionally known as the Bloop Gun." + icon = 'modular_coyote/icons/objects/gun.dmi' + icon_state = "m79" // shinier sprite! but also points left :V + inhand_icon_state = "gun" + mag_type = /obj/item/ammo_box/magazine/internal/grenadelauncher + init_mag_type = /obj/item/ammo_box/magazine/internal/grenadelauncher + fire_sound = 'sound/weapons/grenadelaunch.ogg' + weapon_weight = GUN_TWO_HAND_ONLY diff --git a/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_autoloading.dm b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_autoloading.dm new file mode 100644 index 0000000000..71d7235db3 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_autoloading.dm @@ -0,0 +1,78 @@ +// browning auto-5 is baseline + +/obj/item/gun/ballistic/shotgun/automatic/autoloading_shotgun + name = "autoloading shotgun template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/bolt_using/straight_pull + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE // Load with the bolt closed, like hatch loaded lever actions +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/shotgun/automatic/autoloading_shotgun/auto5 + name = " worn Auto-5" + desc = "An autoloading shotgun chambered in 12 gauge." +/obj/item/gun/ballistic/shotgun/automatic/autoloading_shotgun/auto5/q2 + name = "Auto-5" + max_upgrades = 4 +/obj/item/gun/ballistic/shotgun/automatic/autoloading_shotgun/auto5/q3 + name = "unrusted Auto-5" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_automatic.dm b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_automatic.dm new file mode 100644 index 0000000000..0dd77d27f9 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_automatic.dm @@ -0,0 +1,80 @@ +// jackhammer is placeholder full auto shotgun +/obj/item/gun/ballistic/automatic/sa + name = "automatic shotgun template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "pancor" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = null // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "cshotgun1" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = 'sound/f13weapons/repeater_fire.ogg' // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/d12g // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/d12g // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/automatic/rpm250, + /datum/firemode/semi_auto/rpm250 + ) + init_recoil = AUTOSHOTGUN_RECOIL(1, 0.8) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_TWO_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + auto_eject = 0 // auto-ejects empty magazine + auto_eject_sound = null + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/automatic/sa/jackhammer + name = "worn Jackhammer" + desc = "An automatic shotgun chambered in 12 gauge. Only three were ever made, and two of those were destroyed. Yet somehow the weapon became the most common and famous automatic shotguns in media." +/obj/item/gun/ballistic/automatic/sa/jackhammer/q2 + name = "Jackhammer" + max_upgrades = 4 +/obj/item/gun/ballistic/automatic/sa/jackhammer/q3 + name = "unrusted Jackhammer" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_break.dm b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_break.dm new file mode 100644 index 0000000000..0dae3d5b80 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_break.dm @@ -0,0 +1,87 @@ +// coach gun is baseline + +/obj/item/gun/ballistic/revolver/break_shotgun + name = "break-action shotgun template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/bolt_using/straight_pull + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE // Load with the bolt closed, like hatch loaded lever actions +//revolver handling vars + kind = REVKIND_SWINGOUT_DOUBLE_ACTION // loading style + cock_method = REVCOCK_SINGLE_ACTION // determines double or single action + load_index_offset = 0 // which chamber the loading gate opens to + rotate_direction = REV_ADVANCE_FORWARD // defines for 1 or -1. see combat.dm + single_load = FALSE // for revolvers you can only load one bullet at a time + can_speedload = TRUE // speedloader compatible + how_rotatable = REV_BOTH_ALWAYS + eject_style = REV_EJECT_ADVANCED +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/revolver/break_shotgun/coach + name = " worn coach gun" + desc = "A break-action shotgun chambered in 12 gauge." +/obj/item/gun/ballistic/revolver/break_shotgun/coach/q2 + name = "coach gun" + max_upgrades = 4 +/obj/item/gun/ballistic/revolver/break_shotgun/coach/q3 + name = "unrusted coach gun" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_repeating.dm b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_repeating.dm new file mode 100644 index 0000000000..b6c476dc65 --- /dev/null +++ b/code/modules/projectiles/fuzguns/longarms_specialty/shotgun_repeating.dm @@ -0,0 +1,78 @@ +// remington 870 is baseline + +/obj/item/gun/ballistic/shotgun/repeating_shotgun + name = "repeating shotgun template" // use a simple common name. do NOT go overly esoteric or extravagant + desc = "should not be here, bugreport." // use the format "A submachine gun chambered in caliber. Optional flavor text goes here." +// cosmetic vars + icon_state = "mp5" // the object's sprite name + icon = 'modular_coyote/icons/objects/automatic.dmi' // location of the sprite + mob_overlay_icon = 'modular_coyote/icons/objects/back.dmi' // location of the back sprite. Uses icon_state. set this to null if not applicable + inhand_icon_state = "p38" // the inhand sprite name + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' // location of inhand sprites + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + fire_sound = null // null means the cartridge's sound is used. + ejector_side = GUN_EJECTOR_RIGHT // direction casings are ejected +// performance vars + damage_multiplier = GUN_EXTRA_DAMAGE_0 // weapon damage modifier + mag_type = /obj/item/ammo_box/magazine/uzim9mm // family of magazines it can fit + init_mag_type = /obj/item/ammo_box/magazine/uzim9mm // specific mag it starts with + extra_mag_types = list() // extra familes of magazines it can fit + disallowed_mags = list() // members of magazine family it cannot fit + init_firemodes = list( // fire modes and fire rate + /datum/firemode/bolt_using/straight_pull + ) + init_recoil = AUTOCARBINE_RECOIL(1, 1) // recoil: first number modifies 1h recoil. second number modifies 2h recoil + gun_accuracy_zone_type = ZONE_WEIGHT_PRECISION // determines chance of the gun hitting its intended limb + added_spread = GUN_SPREAD_NONE // adds extra inaccuracy + force = GUN_MELEE_FORCE_PISTOL_HEAVY // melee damage + force_unwielded = 10 // must be same as force. spaghet code + force_wielded = 25 // melee damage wielding in two hands + backstab_multiplier = 1 // bonus for pistolwhipping from behind + throwforce = 25 // damage when thrown + throw_speed = 1 // speed of throw + throw_range = 10 // range of throw + block_parry_data = /datum/block_parry_data/bokken // parrying properties +// handling vars + w_class = WEIGHT_CLASS_NORMAL // item size + slot_flags = INV_SLOTBIT_BELT | INV_SLOTBIT_BACK // INV_SLOTBIT_BELT | INV_SLOTBIT_BACK to fit in belt and/or back + draw_time = GUN_DRAW_NORMAL // time between drawing and readying the gun + slowdown = GUN_SLOWDOWN_PISTOL_HEAVY // move speed penalty when drawn + weapon_weight = GUN_ONE_HAND_ONLY // akimbo, one handed, or two handed + restrict_safety = FALSE // setting to true disables safety + insert_magazine_delay = 0.5 SECONDS // time to insert new mag + remove_magazine_delay = 0.5 SECONDS // time to remove mag + can_load_magazine_through_bolt = FALSE // Load with the bolt closed, like hatch loaded lever actions +// accessory vars + gun_tags = list(GUN_FA_MODDABLE, GUN_SCOPE) // special weapon attachment tags + + zoom_factor = 0 // integrated scope zoom. requires can_scope = false + can_scope = FALSE // can attach a scope + scope_state = "scope" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + scope_x_offset = 0 // varedit in test server to zero in + scope_y_offset = 0 + + silenced = FALSE // integrated suppressor. requires can_suppress = false + can_suppress = FALSE // can attach a suppressor + suppressor_state = null // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + suppressor_x_offset = 0 // varedit in test server to zero in + suppressor_y_offset = 0 + + can_flashlight = FALSE // can attach a flashlight + gunlight_state = "flight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + flight_x_offset = 0 // varedit in test server to zero in + flight_y_offset = 0 + + can_bayonet = FALSE // can attach a bayonet + bayonet_state = "bayonetstraight" // sprites are located in 'icons/fallout/objects/guns/attachments.dmi' + knife_x_offset = 0 // varedit in test server to zero in + knife_y_offset = 0 + +/obj/item/gun/ballistic/shotgun/repeating_shotgun/r870 + name = " worn R870" + desc = "A repeating shotgun chambered in 12 gauge. The most common pump shotgun on the market, back when there was a market." +/obj/item/gun/ballistic/shotgun/repeating_shotgun/r870/q2 + name = "R870" + max_upgrades = 4 +/obj/item/gun/ballistic/shotgun/repeating_shotgun/r870/q3 + name = "unrusted R870" + max_upgrades = 5 diff --git a/code/modules/projectiles/fuzguns/revolver_code.dm b/code/modules/projectiles/fuzguns/revolver_code.dm new file mode 100644 index 0000000000..f901ce7e78 --- /dev/null +++ b/code/modules/projectiles/fuzguns/revolver_code.dm @@ -0,0 +1,978 @@ +// In this document: Revolvers, Needlers, Weird revolvers +// See gun.dm for keywords and the system used for gun balance + +/* + * WELCOME TO DAN'S REVAMPED REVOLVER THING, where something as simple as a revolver + * becomes hopelessly complicated for both user and coder! + * + * The 'chambered' round is whichever thing is loaded in the magazine at index 'chamber_index' + * Normal actions advance the index in whichever direction the gun is set to rotate + * Mousewheel can rotate the cylinder! + * Middle-mouse half-cocks the gun, if supported + * Alt-click ejects casings, if it can, in one of a few ways + * - The round at the index offset defined by the gun's 'load_index_offset' + * - This is if its one of those single-load guns, like a single action army + * - All the bullets in the gun just fly out, if its a break-action gun + * - A special third option for revolvers that arent wierd and ancient + * - alt-click instead swngs out the cylinder, and you can either + * - click the gun to pop out the empties (or again to pop the rest) + * - insert a casing into the cylinder, prioritizing ones closest to the current chamber_index + * - use a box or other thing on the gun to continually load it and unload empties + * - use a speedloader to do all this, but faster + * Some revolvers require you to be half-cocked to eject + * half-cock is a state on the hammer that most guns shouldnt be able to get to + * Some revolvers require you to manually rotate the cylinder to eject a different casing + * + * Most of the revolvers are sane and designed to be used by normal people + * Some of the revolvers are not! this is intended for people who like fighting the game to do basic things + * + * Also covers stuff like double barrel guns, cus why not + * + * notes: + * - There is no Halfcock state for the hammer! + * - not all revolvers and such have a halfcock, but all of them require some sort of jerking off to load + * - instead, loader_exposed is our half-cock state! + * + * Revolver defaults to: + * - double-action + * - flip out ammo thing + * - can rotate either way + * + * todo: + * - implement an instruction manual to this nightmare of UX + * - a link in examine to blurt out a bunch of instruction + */ + +/obj/item/gun/ballistic/revolver + name = "revolver template" + desc = "should not exist." + icon_state = "revolver" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder + casing_ejector = FALSE + spawnwithmagazine = TRUE + weapon_class = WEAPON_CLASS_SMALL + weapon_weight = GUN_ONE_HAND_AKIMBO + damage_multiplier = GUN_EXTRA_DAMAGE_0 + init_recoil = HANDGUN_RECOIL(1, 1) + init_firemodes = list( + /datum/firemode/semi_auto + ) + ejector_side = GUN_EJECTOR_ANY + revolver = TRUE + var/kind = REVKIND_SWINGOUT_DOUBLE_ACTION + var/cock_method = REVCOCK_SINGLE_ACTION + // which chamber is currently lined up with the barrel + var/chamber_index = 1 + var/load_index_offset = 0 + var/rotate_direction = REV_ADVANCE_FORWARD // defines for 1 or -1. see combat.dm + /// is the cylinder out / action broken / half-cocked? mainly indicates the ammo is accessible and the shooting isnt + var/loader_exposed = FALSE + var/single_load = FALSE + var/can_speedload = TRUE + var/how_rotatable = REV_BOTH_ALWAYS + var/eject_style = REV_EJECT_ADVANCED + /* sounds! */ + var/rotate_forward_sound = 'sound/weapons/ba_revolver/rotate_forward.ogg' + var/rotate_backward_sound = 'sound/weapons/ba_revolver/rotate_backward.ogg' + cock_hammer_sound = 'sound/weapons/ba_revolver/singleaction_cock.ogg' + uncock_hammer_sound = 'sound/weapons/ba_revolver/singleaction_un_cock.ogg' + /// for when we put the gun into a state where we can access the ammo, like swinging out the cylinder or half-cocking + var/open_gun_sound = 'sound/weapons/ba_revolver/cylinder_open.ogg' + /// for making it not accessible anymore + var/close_gun_sound = 'sound/weapons/ba_revolver/cylinder_close.ogg' + var/insert_single_round_sound = 'sound/weapons/ba_revolver/loadrevolver.ogg' + var/eject_single_round_sound = 'sound/weapons/ba_revolver/eject_single.ogg' + var/speedloader_sound = 'sound/weapons/ba_revolver/speedloader_act.ogg' + var/eject_all_sound = 'sound/weapons/ba_revolver/eject_multiple.ogg' + var/eject_all_no_shells_sound = 'sound/weapons/ba_revolver/eject_multiple_no_shells.ogg' + equipsound = 'sound/f13weapons/equipsounds/pistolequip.ogg' + +/obj/item/gun/ballistic/revolver/Initialize() + init_kind() + . = ..() + if(!istype(magazine, /obj/item/ammo_box/magazine/internal/cylinder)) + verbs += /obj/item/gun/ballistic/revolver/verb/spin + +/obj/item/gun/ballistic/revolver/generate_guntags() + ..() + gun_tags |= GUN_REVOLVER + +/obj/item/gun/ballistic/revolver/proc/init_kind() + switch(kind) + if(REVKIND_SWINGOUT_DOUBLE_ACTION) + single_load = FALSE + can_speedload = TRUE + how_rotatable = REV_BOTH_ALWAYS + eject_style = REV_EJECT_ADVANCED + cock_method = REVCOCK_DOUBLE_ACTION + load_index_offset = 0 + if(REVKIND_SINGLE_ACTION_REVOLVER) + single_load = TRUE + can_speedload = FALSE + how_rotatable = REV_BOTH_HALFCOCK_ONLY + eject_style = REV_EJECT_SINGLE + cock_method = REVCOCK_SINGLE_ACTION + load_index_offset = 3 + rotate_forward_sound = 'sound/weapons/ba_revolver/rotate_forward.ogg' + rotate_backward_sound = 'sound/weapons/ba_revolver/rotate_backward.ogg' + cock_hammer_sound = 'sound/weapons/ba_revolver/singleaction_cock.ogg' + uncock_hammer_sound = 'sound/weapons/ba_revolver/singleaction_un_cock.ogg' + open_gun_sound = 'sound/weapons/ba_revolver/singleload_halfcock_open.ogg' + close_gun_sound = 'sound/weapons/ba_revolver/singleload_halfcock_close.ogg' + insert_single_round_sound = 'sound/weapons/ba_revolver/loadrevolver.ogg' + eject_single_round_sound = 'sound/weapons/ba_revolver/eject_single.ogg' + speedloader_sound = 'sound/weapons/ba_revolver/speedloader_act.ogg' + eject_all_sound = 'sound/weapons/ba_revolver/eject_multiple.ogg' + eject_all_no_shells_sound = 'sound/weapons/ba_revolver/eject_multiple_no_shells.ogg' + if(REVKIND_BREAK_ACTION_REVOLVER) + single_load = FALSE + can_speedload = TRUE + how_rotatable = REV_ADVANCE_ONLY + eject_style = REV_EJECT_ALL + cock_method = REVCOCK_DOUBLE_ACTION + load_index_offset = 0 + if(REVKIND_BREAK_ACTION_SHOTGUN) + single_load = FALSE + can_speedload = TRUE + how_rotatable = REV_BOTH_ALWAYS + eject_style = REV_EJECT_ADVANCED + cock_method = REVCOCK_DOUBLE_ACTION + load_index_offset = 0 + rotate_forward_sound = 'sound/weapons/ba_revolver/shotgun_rotate_forward.ogg' + rotate_backward_sound = 'sound/weapons/ba_revolver/shotgun_rotate_backward.ogg' + cock_hammer_sound = 'sound/weapons/ba_revolver/singleaction_cock.ogg' + uncock_hammer_sound = 'sound/weapons/ba_revolver/singleaction_un_cock.ogg' + open_gun_sound = 'sound/weapons/ba_revolver/shotgun_open.ogg' + close_gun_sound = 'sound/weapons/ba_revolver/shotgun_close.ogg' + insert_single_round_sound = 'sound/weapons/ba_revolver/shotgun_casing_in.ogg' + eject_single_round_sound = 'sound/weapons/ba_revolver/shotgun_casing_eject.ogg' + speedloader_sound = 'sound/weapons/ba_revolver/speedloader_act.ogg' + eject_all_sound = 'sound/weapons/ba_revolver/shotgun_casing_eject.ogg' + eject_all_no_shells_sound = 'sound/weapons/ba_revolver/shotgun_casing_eject.ogg' + +/obj/item/gun/ballistic/revolver/mouse_wheel_signal_handler( + mob/living/user, + atom/wheeled_on, + delta_x, + delta_y, + params, + ) + if(!..()) + return + if(user.get_active_held_item() == src || user.get_inactive_held_item() == src) + advance_chamber(user, SIGN(-delta_y), TRUE) + +/obj/item/gun/ballistic/revolver/middleclick_signal_handler( + mob/living/user, + atom/clicked_on, + ) + if(!..()) + return + var/obj/item/in_active_hand = user.get_active_held_item() + // var/gun_is_in_active_hand = in_active_hand == src + var/obj/item/in_inactive_hand = user.get_inactive_held_item() + var/gun_is_in_inactive_hand = in_inactive_hand == src + if(!istype(in_active_hand) && !istype(in_inactive_hand)) + return + if(gun_is_in_inactive_hand) + if(!istype(in_active_hand)) + user.swap_hand() // gun in off-hand with empty hand, switch to it, then middle-click + INVOKE_ASYNC(src, PROC_REF(toggle_loader_exposure), user) + +/// When something scrollwheels while the mouse is on the gun +/// allows rotating it even if its not in your hand! +/obj/item/gun/ballistic/revolver/MouseWheel(delta_x,delta_y,location,control,params) + // we have everything but who did it. + // HOWEVER CAN WE FIGURE THIS OUT oh byond is based and has a way + advance_chamber(usr, SIGN(-delta_y), TRUE) + +/// does one of three things: +/// - if the gun is a single load one, half-cocks the gun and allows you to load or eject from the single chamber +/// - if the gun is a break action, swings the cylinder open and sprays casings everywhere +/// - if the gun is a normal revolver, swings the cylinder open and waits for you to do things +/obj/item/gun/ballistic/revolver/MiddleClick(mob/living/doer) + if(!can_interact_with_this(doer, TRUE, NONE)) + return + toggle_loader_exposure(doer) + return COMSIG_MOB_CANCEL_CLICKON + +/obj/item/gun/ballistic/revolver/AltClick(mob/living/doer) + return MiddleClick(doer) // alt-click does the same thing as middle click, just for people who dont have a middle mouse button + // also i couldnt figure something to do with the alt-click that middle-click wasnt already doing, so might as well + +/obj/item/gun/ballistic/revolver/dont_shoot(mob/living/user) + if(loader_exposed) + // instead of shooting, try ejecting something! + advance_chamber(user) + update_icon() + return + . = ..() + +/obj/item/gun/ballistic/revolver/get_chambered() + if(!magazine) + return null // shouldnt happen but just in case + return LAZYACCESS(magazine.stored_ammo, chamber_index) + +/obj/item/gun/ballistic/revolver/proc/get_chambered_at_load_index() + if(!magazine) + return null + return LAZYACCESS(magazine.stored_ammo, get_load_offset_index()) + +// handled elsewhere +/obj/item/gun/ballistic/revolver/chamber_round() + return get_chambered() + +/// doer and direction are optional +/// direction can be 1 or -1, and if not provided it will just use the gun's default direction +/// doer just determines who gets the sound +/obj/item/gun/ballistic/revolver/proc/advance_chamber(mob/doer, direction, manually) + if(!magazine) + return + if(LAZYLEN(magazine.stored_ammo) < 2) // just one shoot hole, cant exactly change what you shoot + return + if(doing_something(doer)) + to_chat(doer, span_warning("You're already doing something!")) + return + if(manually && how_rotatable == REV_BOTH_HALFCOCK_ONLY && !loader_exposed) + inform_user(doer, REV_ALERT_NEED_LOADER_EXPOSED_TO_ROTATE) + return + var/dir2moveit = rotate_direction + if(direction) + dir2moveit = direction + chamber_index += dir2moveit + if(manually && how_rotatable == REV_ADVANCE_ONLY && dir2moveit != rotate_direction) + inform_user(doer, REV_ALERT_CAN_ONLY_ROTATE_IN_ADVANCE_DIRECTION) + return + if(chamber_index > LAZYLEN(magazine.stored_ammo)) + chamber_index = 1 + else if(chamber_index < 1) + chamber_index = LAZYLEN(magazine.stored_ammo) + var/snd + // if the rotated rotation is the same as the rotation defined for the gun, play the sound for that rotation. + if(dir2moveit == rotate_direction) + snd = rotate_forward_sound + else + snd = rotate_backward_sound + if(doer) + doer.playsound_local(doer, snd, 80, FALSE) + else + playsound(src, snd, 80, FALSE) + +// finds which index is the one that we can load/unload from +// naturally, only relevant for single-load guns +/obj/item/gun/ballistic/revolver/proc/get_load_offset_index() + if(!magazine) + return null + var/offset_index = chamber_index + load_index_offset + if(offset_index > LAZYLEN(magazine.stored_ammo)) + offset_index -= LAZYLEN(magazine.stored_ammo) + else if(offset_index < 1) + offset_index += LAZYLEN(magazine.stored_ammo) + return offset_index + +/// handles swinging the cylinder out / half-cocking the hammer, or closing it again +/obj/item/gun/ballistic/revolver/proc/toggle_loader_exposure(mob/doer) + if(loader_exposed) + close_gun(doer) + else + open_gun(doer) + update_icon() + +// opens the gun, allowing access to the ammo and whatnot +/obj/item/gun/ballistic/revolver/proc/open_gun(mob/doer, delay_the_thing) + if(!cause_delay(doer, 0.5 SECONDS)) + return + loader_exposed = TRUE + playsound(doer, open_gun_sound, 80, FALSE) + if(eject_style == REV_EJECT_ALL) + auto_eject_casings(doer, TRUE, nodelay = TRUE) + else + inform_user(doer, REV_INFO_OPENED_GUN) + +// closes the gun, making it ready to fire again +/obj/item/gun/ballistic/revolver/proc/close_gun(mob/doer) + loader_exposed = FALSE + hammer_state = GHAMMER_COCKED + playsound(doer, close_gun_sound, 80, FALSE) + inform_user(doer, REV_INFO_CLOSED_GUN) + +/// happens when you do something to automatically trigger the gun to open or close +// such as using an ammo on it, without opening it manually +/obj/item/gun/ballistic/revolver/proc/cause_delay(mob/doer, delay = (0.5 SECONDS)) + if(doing_something(doer)) + to_chat(doer, span_warning("You're already doing something!")) + return + var/datum/weakref/loader = WEAKREF(doer) + GLOB.currently_loading_something[loader] = world.time + delay + . = do_after( + doer, + delay = delay, + needhand = TRUE, + target = src, + progress = TRUE, + public_progbar = TRUE, + allow_movement = TRUE, + progbar_on_target = TRUE, + ) + GLOB.currently_loading_something -= loader + if(!.) + to_chat(doer, span_alert("You were interrupted!")) + +// ejects casings according to the gun's eject style! +/obj/item/gun/ballistic/revolver/proc/auto_eject_casings(mob/doer, do_words, do_sound, force_all_of_them, nodelay) + // indexes! + if(!can_interact_with_this(doer, do_words, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + if(!nodelay) + if(!cause_delay(doer, 0.5 SECONDS)) + return + var/list/toeject = list() + var/spew_everywhere = FALSE + var/what_ejected = "empties" + var/snd = eject_all_sound + var/eject_how = eject_style + if(force_all_of_them) + eject_how = REV_EJECT_ALL + var/obj/item/ammo_casing/singlebie + switch(eject_how) + if(REV_EJECT_SINGLE) + var/lindex = get_load_offset_index() + toeject |= lindex + singlebie = LAZYACCESS(magazine.stored_ammo, lindex) + snd = eject_single_round_sound + if(REV_EJECT_ALL) + for(var/i in 1 to LAZYLEN(magazine.stored_ammo)) + toeject |= i + spew_everywhere = TRUE + what_ejected = "everything" + if(REV_EJECT_ADVANCED) + // eject empties first, then loadeds if there are no empties + var/list/loaded = list() + var/list/empties = list() + for(var/i in 1 to LAZYLEN(magazine.stored_ammo)) + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, i) + if(istype(CB, /obj/item/ammo_casing)) + if(CB.BB) + loaded |= i + else + empties |= i + if(LAZYLEN(empties)) + toeject |= empties + what_ejected = "empties" + else + toeject |= loaded + what_ejected = "loadeds" + //nothing? + // ejected anything? + var/ejected_something = FALSE + for(var/i in toeject) + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, i) + if(istype(CB, /obj/item/ammo_casing)) + snd = eject_all_no_shells_sound + ejected_something = TRUE + if(!ejected_something) + if(do_words) + to_chat(doer, span_notice("Couldn't eject anything!")) + return + for(var/i in toeject) + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, i) + if(!istype(CB, /obj/item/ammo_casing)) + continue + var/fling = spew_everywhere && !CB.BB + eject_casing_at_index(doer, i, fling, TRUE) + update_icon() + if(do_words) + if(singlebie) + inform_user(doer, REV_INFO_EJECTED_SINGLEBIE, singlebie) + else if(eject_how == REV_EJECT_ALL) + inform_user(doer, REV_INFO_EJECTED_ALL) + else if(what_ejected == "empties") + inform_user(doer, REV_INFO_EJECTED_EMPTIES) + else if(what_ejected == "loadeds") + inform_user(doer, REV_INFO_EJECTED_LOADEDS) + if(do_sound) + playsound(doer, snd, 80, FALSE) + +/obj/item/gun/ballistic/revolver/proc/eject_casing_at_index(mob/doer, i, fling, do_sound = TRUE) + if(!can_interact_with_this(doer, FALSE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, i) + if(!istype(CB, /obj/item/ammo_casing)) + return + CB.forceMove(drop_location()) + if(fling) // loadeds are a bit heavier, fling the rest everywhere + var/randodir = pick(GLOB.alldirs) + CB.bounce_away(FALSE, toss_direction = randodir) + // chambered is handled by a proc, its auto-updated! + magazine.stored_ammo[i] = null // eject a shell, it leaves a gap + if(do_sound) + playsound(doer, eject_single_round_sound, 80, FALSE) + +/obj/item/gun/ballistic/revolver/proc/load_casing_at_index(mob/doer, obj/item/ammo_casing/CB, i, do_sound = TRUE) + if(!can_interact_with_this(doer, FALSE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + if(istype(LAZYACCESS(magazine.stored_ammo, i), /obj/item/ammo_casing)) + return // shouldnt load on top of an existing round + magazine.stored_ammo[i] = CB + CB.forceMove(magazine) + if(do_sound) + playsound(doer, insert_single_round_sound, 80, FALSE) + +/obj/item/gun/ballistic/revolver/shoot_with_empty_chamber(mob/living/user as mob|obj) + ..() + if(cock_method == REVCOCK_DOUBLE_ACTION) + toggle_hammer(user, TRUE) + update_icon() + +/obj/item/gun/ballistic/revolver/after_shooting(mob/living/user as mob|obj) + ..() + if(cock_method == REVCOCK_DOUBLE_ACTION) + toggle_hammer(user, TRUE) + update_icon() + +/obj/item/gun/ballistic/revolver/attack_self(mob/living/user) + if(loader_exposed) + auto_eject_casings(user, TRUE, TRUE, FALSE) + update_icon() + return + toggle_hammer(user) + update_icon() + +/obj/item/gun/ballistic/revolver/attackby(obj/item/A, mob/user, params) + if(istype(A, /obj/item/ammo_casing)) + return use_casing_on_gun(user, A) + if(istype(A, /obj/item/ammo_box)) + return use_ammobox_on_gun(user, A) + . = ..() + +// the stuff before actually loading it into the gun +/obj/item/gun/ballistic/revolver/use_casing_on_gun(mob/user, obj/item/ammo_casing/A_casing) + if(!can_interact_with_this(user, TRUE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + if(!room_in_gun_to_load_something()) + to_chat(user, span_warning("There is no room in [src] to load [A_casing]!")) + return + // does it fit? + if(!magazine.does_that_fit_in_this(A_casing)) + to_chat(user, span_warning("[A_casing] doesn't fit in [src]!")) + return + if(!loader_exposed) + open_gun(user, delay_the_thing = TRUE) + if(single_load) + var/found_a_slot = FALSE + for(var/tries in 1 to LAZYLEN(magazine.stored_ammo)) // just in case, should never need to rotate more than the number of chambers + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, get_load_offset_index()) + if(!istype(CB, /obj/item/ammo_casing) || !CB.BB) // if its empty or already has the same type of round, we can load into it + found_a_slot = TRUE + break + if(!cause_delay(user, (0.2 SECONDS))) + return + advance_chamber(user) + if(!found_a_slot) + to_chat(user, span_warning("There is no room in [src] to load [A_casing]!")) + return + insert_casing(user, A_casing) + return TRUE + +/obj/item/gun/ballistic/revolver/use_ammobox_on_gun(mob/user, obj/item/ammo_box/A_box) + if(!can_interact_with_this(user, TRUE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + if(!room_in_gun_to_load_something()) + to_chat(user, span_warning("There is no room in [src] to load anything in [A_box]!")) + return + var/can_load_something = FALSE + for(var/obj/item/ammo_casing/bullet in A_box.stored_ammo) + if(magazine.does_that_fit_in_this(bullet)) + can_load_something = TRUE + break + if(!can_load_something) + to_chat(user, span_warning("[A_box] can't fit anything in [src]!")) + if(!loader_exposed) + open_gun(user, delay_the_thing = TRUE) + insert_casings_from_box(user, A_box) + return TRUE + +// single loaders just load one round, then stop +// otherwise, one of two things happens based on what the box is +// if it is a compatable speedloader for the gumagazine, and we accept speedloaders +// - short delay, then all the rounds get loaded and empties get ejected with no extra delay +// otherwise, we just keep loading rounds one at a time until the box is empty or the gun is full +// - with delays and sounds for each round +/obj/item/gun/ballistic/revolver/proc/insert_casings_from_box(mob/user, obj/item/ammo_box/A_box) + if(!can_interact_with_this(user, TRUE, REV_FLAG_NEEDS_MAGAZINE)) + return + if(!room_in_gun_to_load_something()) + return + if(!loader_exposed) + open_gun(user, delay_the_thing = TRUE) + var/list/loadeds = list() + // okay see if this thing is a speedloader + var/speedload = FALSE + if(can_speedload) + var/datum/ammoholder_behavior/my_mag = magazine.get_load_behavior() + speedload = my_mag.is_speedloader(A_box) + if(speedload) + // check if anything is loaded at all, then delay and eject everything if so + var/anything_loaded = FALSE + for(var/obj/item/ammo_casing/CB in magazine.stored_ammo) + if(istype(CB, /obj/item/ammo_casing)) + anything_loaded = TRUE + break + if(anything_loaded) + if(!cause_delay(user, 0.8 SECONDS)) + return + auto_eject_casings(user, FALSE, TRUE, TRUE) + if(!cause_delay(user, 0.8 SECONDS)) + return + + var/safety = LAZYLEN(magazine.stored_ammo) // just in case, to prevent infinite loops. should never happen unless something is very wrong + mainloop: + while(safety--) + if(!speedload) + if(!cause_delay(user, 0.2 SECONDS)) + return + var/obj/item/ammo_casing/bullet = null + for(var/obj/item/ammo_casing/candidate in A_box.stored_ammo) + if(!candidate.BB) // only try to load live rounds, not empties + continue + if(!magazine.does_that_fit_in_this(candidate)) + continue + bullet = candidate + break + if(!bullet) + if(!LAZYLEN(loadeds)) + to_chat(user, span_warning("There is nothing in [A_box] that can fit in [src]!")) + else + to_chat(user, span_warning("[A_box] no longer has anything that can fit in [src]!")) + return // nothing left to load! + // precheck, make sure there are still rooms in the cylinder, so we dont just uselessly doafter stuff + if(!room_in_gun_to_load_something()) + break + // single action, rotate until theres something to load on the load index, then load it and stop + if(single_load) + var/found_a_slot = FALSE + for(var/tries in 1 to LAZYLEN(magazine.stored_ammo)) // just in case, should never need to rotate more than the number of chambers + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, get_load_offset_index()) + if(!istype(CB, /obj/item/ammo_casing) || !CB.BB) // if its empty or already has the same type of round, we can load into it + found_a_slot = TRUE + break + if(!cause_delay(user, (0.4 SECONDS))) + break mainloop + advance_chamber(user) + if(!found_a_slot) + to_chat(user, span_warning("There is no room in [src] to load [bullet]!")) + break + // load it somewhere! + var/do_sound = (speedload ? LAZYLEN(loadeds) <= 1 : TRUE) // if speedloading, only play the sound on the first one, otherwise play for each one + var/obj/item/ammo_casing/loaded_casing = insert_casing(user, bullet, FALSE, A_box, !speedload, do_sound) + if(!istype(loaded_casing, /obj/item/ammo_casing) && (!speedload || single_load)) + break // didnt load anything, so abort + loadeds |= loaded_casing + advance_chamber(user) + + if(speedload) + playsound(user, speedloader_sound, 80, FALSE) + if(LAZYLEN(loadeds)) + var/list/load_cool = list() + for(var/obj/item/ammo_casing/CB in loadeds) + if(!load_cool[CB.name]) + load_cool[CB.name] = 0 + load_cool[CB.name]++ + //format "5x 9mm pingusbellend", "15x 9mm overpingus" + var/list/loadnames = list() + for(var/strng in load_cool) + var/lcount = load_cool[strng] + loadnames += "[lcount]x [strng]" + var/what_i_loaded = english_list(loadnames) + to_chat(user, span_green("Loaded [what_i_loaded]!")) + update_icon() + A_box.update_icon() + return TRUE + else + to_chat(user, span_alert("Couldn't load anything from [A_box]")) + update_icon() + A_box.update_icon() + return FALSE + +/obj/item/gun/ballistic/revolver/proc/room_in_gun_to_load_something() + for(var/i in 1 to LAZYLEN(magazine.stored_ammo)) + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, i) + if(!istype(CB, /obj/item/ammo_casing)) + return TRUE + if(!CB.BB) + return TRUE + return FALSE + +// works differently based on the load style of the gun! generally tries to insert a casing somewhere it can go +// notably is only really different for single-load guns +/obj/item/gun/ballistic/revolver/proc/insert_casing( + mob/user, + obj/item/ammo_casing/A_casing, + delay_the_thing, + obj/item/ammo_box/camefrom, + initial_delay = TRUE, + do_sound = TRUE) + if(!can_interact_with_this(user, FALSE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + if(!magazine.does_that_fit_in_this(A_casing)) // another check to be safe + to_chat(user, span_warning("[A_casing] doesn't fit in [src]!")) + return + if(single_load) + var/lindex = get_load_offset_index() + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, lindex) + if(istype(CB, /obj/item/ammo_casing) && (!CB.BB || CB.type != A_casing.type)) // if the thing in the load index is an incompatible round, eject it first + eject_casing_at_index(user, lindex, FALSE, do_sound) + delay_the_thing = TRUE + if(delay_the_thing) + if(!cause_delay(user, (0.8 SECONDS))) + return + if(!can_interact_with_this(user, TRUE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + if(camefrom) + camefrom.remove_casing(A_casing) + if(initial_delay) + if(!cause_delay(user, (0.4 SECONDS))) + return + load_casing_at_index(user, A_casing, lindex, do_sound) + inform_user(user, REV_INFO_LOADED_SINGLE, A_casing) + return A_casing + var/index_offset = chamber_index // this way if the chamber index is 5 and the gun capacity is 6, it checks in this order: 5, 6, 1, 2, 3, 4 + // they also can rotate in two directions, so we can check in the opposite direction as well if its set to rotate backwards + var/list/check_order = list() + for(var/i in 1 to LAZYLEN(magazine.stored_ammo)) + // for an index of 4 on a 6 capacity gun + // would output for forward rotation: 4, 5, 6, 1, 2, 3 + // and for backward rotation: 4, 3, 2, 1, 6, 5 + var/real_index = index_offset + (i * rotate_direction) + if(real_index > LAZYLEN(magazine.stored_ammo)) + real_index -= LAZYLEN(magazine.stored_ammo) + else if(real_index < 1) + real_index += LAZYLEN(magazine.stored_ammo) + check_order |= real_index + var/bestslot = 0 + var/obj/item/ammo_casing/casing_at_bestslot + // try to load the slot at the shoot index first, then wrap around from there + // lower indexes in the check order are prioritized over higher ones + for(var/i in 1 to LAZYLEN(check_order)) + var/obj/item/ammo_casing/CB = LAZYACCESS(magazine.stored_ammo, LAZYACCESS(check_order, i)) + if(!istype(CB, /obj/item/ammo_casing)) // empty slot, probably + bestslot = LAZYACCESS(check_order, i) + break + else if(!CB.BB) // if its an empty casing, prioritize it for loading over loaded slots, since it frees up space + bestslot = LAZYACCESS(check_order, i) + casing_at_bestslot = CB + break + if(!bestslot) + return FALSE + if(istype(casing_at_bestslot, /obj/item/ammo_casing)) + delay_the_thing = TRUE + if(delay_the_thing) + if(!cause_delay(user, (0.8 SECONDS))) + return + if(!can_interact_with_this(user, TRUE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + eject_casing_at_index(user, bestslot, FALSE, do_sound) + if(initial_delay) + if(!cause_delay(user, (0.4 SECONDS))) + return + if(!can_interact_with_this(user, TRUE, REV_FLAG_NEEDS_MAGAZINE | REV_FLAG_NEEDS_LOADER_EXPOSED)) + return + if(camefrom) + camefrom.remove_casing(A_casing) + load_casing_at_index(user, A_casing, bestslot, do_sound) + inform_user(user, REV_INFO_LOADED_SINGLE, A_casing) + return A_casing + +/obj/item/gun/ballistic/revolver/proc/can_interact_with_this(mob/living/user, do_words, inter_flags = NONE) + if(user.incapacitated(allow_crit = TRUE)) + if(do_words) + to_chat(user, span_warning("You're way too messed up to muck with [src]!")) + return FALSE + if(!user.can_reach(src, INVENTORY_DEPTH, user.reach)) + if(do_words) + to_chat(user, span_warning("You can't reach [src]!")) + return FALSE + if((inter_flags & REV_FLAG_NEEDS_MAGAZINE) && !magazine) + if(do_words) + to_chat(user, span_warning("[src] doesn't have anywhere to put the ammo!")) + return FALSE + if((inter_flags & REV_FLAG_NEEDS_LOADER_EXPOSED) && !loader_exposed) + if(do_words) + inform_user(user, REV_ALERT_NEED_LOADER_EXPOSED_TO_ROTATE) + return FALSE + if(doing_something(user)) + if(do_words) + to_chat(user, span_warning("You're already doing something!")) + return FALSE + return TRUE + +/obj/item/gun/ballistic/revolver/toggle_hammer(mob/living/user, onlycock) + if(loader_exposed) + return + if(onlycock) + hammer_state = GHAMMER_COCKED + else + switch(hammer_state) + if(GHAMMER_UNCOCKED) + hammer_state = GHAMMER_COCKED + if(GHAMMER_COCKED) + hammer_state = GHAMMER_UNCOCKED + if(hammer_state == GHAMMER_COCKED) + can_click = TRUE + advance_chamber(user) + var/snd = hammer_state == GHAMMER_COCKED ? cock_hammer_sound : uncock_hammer_sound + playsound(user, snd, 80, FALSE) + +/obj/item/gun/ballistic/revolver/verb/spin() + set name = "Spin Chamber" + set category = "Object" + set desc = "Click to spin your revolver's chamber." + + var/mob/M = usr + + if(M.stat || !in_range(M,src)) + return + + if(do_spin()) + M.visible_message("[M] spins [src]'s chamber.", span_notice("You spin [src]'s chamber.")) + playsound(src, 'sound/f13weapons/revolverspin.ogg', 80, FALSE) + else + verbs -= /obj/item/gun/ballistic/revolver/verb/spin + +/obj/item/gun/ballistic/revolver/proc/do_spin() + if(!loader_exposed) + to_chat(usr, span_alert("You gotta open the gun first!")) + return + var/magcap = LAZYLEN(magazine.stored_ammo) + for(var/i in 1 to rand(magcap, magcap*2)) + advance_chamber(usr) + return TRUE // one more time, fen + +/obj/item/gun/ballistic/revolver/can_shoot() + if(loader_exposed) + return FALSE + . = ..() + +/obj/item/gun/ballistic/revolver/examine(mob/user) + . = ..() + . += get_ammo_readout() + . += "Click here for the instruction manual!" + +/obj/item/gun/ballistic/revolver/Topic(href, href_list) + . = ..() + if(href_list["htf_do_i_use_this_thing"]) + open_instruction_manual(usr) + +/obj/item/gun/ballistic/revolver/proc/open_instruction_manual(mob/user) + if(!istype(user)) + return + if(!user.client) + return + to_chat(user, span_notice("Hi!")) + // var/msg = "" + // // outline for manual: + // // - how to load and unload the gun, with an explanation of the different loading styles and eject styles + // // - how to read the ammo display, with a key for what the different symbols mean + // // - how to rotate the cylinder and what the different rotation styles are + // // - any special things about specific guns, like if the gun has a special firemode or something + // msg += "
So you'll likely see something like this when you examine the gun:
+ //+ // \[█\] + // █ + // (█) + // ▄ + // ▄ + // ░+ //
+ // 3 / 6 shots left.
+ //
Each of those symbols represents a chamber in the gun's cylinder! + //
In the example, the gun has 3 live rounds, 2 empties, and 1 empty chamber.
+ //
The brackets, \[ \], indicate which chamber is currently lined up to be fired when you pull the trigger. Firing will generally advance this down the line, so the next chamber will be lined up after you shoot.
+ //
Though, some revolvers work differently and will require you to manually rotate or recock the hammer to rotate the cylinder, so be sure to check the specific instructions for your gun if you're not sure!
+ //
The parentheses, ( ), indicate which chamber you will interact with if you try to load or eject a round. This is only relevant for certain styles of revolver, so if you don't see it, don't worry about it!
+ //