From 2bb6c955ba4f5e852c999634047060caeab62776 Mon Sep 17 00:00:00 2001 From: Rykka Date: Thu, 7 Apr 2022 01:58:37 -0600 Subject: [PATCH] TGMC Ammo HUD Earlyport Ports over TGMC's Ammo HUD and all relevant code, adapted to work for Polaris's guns. This took me several days, but hey, I learned a bunch. <: Time to port Aim Mode + Mentorhelp. :3c - All guns now have an ammo HUD sprite. If one lacks one, it will be ??? or blank, at which point, make an issue report, as all guns should be working by now. - Guns will display how many rounds they have left until ammunition runs dry. - Ammo will only count the casings that CURRENTLY have a projectile in them. This is slightly unrealistic, yes, but it is better and more intuitive for the player. This also enables guns like the revolver to work, given they recycle casings. - Up to 4 ammo HUDs can be displayed at once, but given we lack TGMC's attachments and guncode, you'll only ever usually see 2. TBD on porting over TGMC guncode. <: - Ammunition for multiple guns has different colors in the HUD based on what you currently have loaded. - If you're looking at this later on to add new things. DON'T USE _FLASH IN THE HUD_STATE_EMPTY. THE _FLASH IS ADDED ON BY CODE. - Grenades have a hud_state, pending us ever porting over a grenade launcher. Rockets ALSO have a hud_state. Example of Laser/Energy Weapons: https://i.imgur.com/MGvqGxh.mp4 Captain's Gun: https://i.imgur.com/Wd0SS3C.gif Full Test of all weapons: https://streamable.com/usp4dy Upstream port of https://github.com/CHOMPStation2/CHOMPStation2/pull/4033 Earlyport of https://github.com/PolarisSS13/Polaris/pull/8513, with adaptations for VORE's files (Specifically the ML3M medigun and cell-loaded weaponry.) Credit to @SilencedMP5A5 for helping me with sprite names, testing, and making the Full Test video. <3 --- code/_onclick/hud/_defines.dm | 6 ++ code/_onclick/hud/hud.dm | 40 ++++++++- code/_onclick/hud/screen_objects.dm | 77 ++++++++++++++++ .../items/weapons/grenades/explosive.dm | 1 + .../objects/items/weapons/grenades/grenade.dm | 2 + .../items/weapons/grenades/smokebomb.dm | 1 + code/modules/power/cell.dm | 6 ++ code/modules/projectiles/gun.dm | 29 ++++++ code/modules/projectiles/guns/energy.dm | 25 ++++++ .../guns/energy/cell_loaded_vr/cell_loaded.dm | 39 +++++++- .../guns/energy/cell_loaded_vr/ml3m_cells.dm | 1 + .../energy/cell_loaded_vr/multi_cannon.dm | 14 ++- .../cell_loaded_vr/multi_cannon_cells.dm | 13 +++ .../projectiles/guns/energy/laser_vr.dm | 2 + code/modules/projectiles/guns/projectile.dm | 85 ++++++++++++++++++ .../projectiles/guns/projectile/shotgun.dm | 4 + code/modules/projectiles/projectile.dm | 4 + code/modules/projectiles/projectile/beams.dm | 39 +++++++- .../modules/projectiles/projectile/bullets.dm | 47 ++++++++++ code/modules/projectiles/projectile/energy.dm | 33 ++++++- .../projectiles/projectile/explosive.dm | 3 + .../projectiles/projectile/magnetic.dm | 13 +++ .../modules/projectiles/projectile/special.dm | 15 +++- icons/mob/screen_ammo.dmi | Bin 0 -> 5633 bytes 24 files changed, 488 insertions(+), 11 deletions(-) create mode 100644 icons/mob/screen_ammo.dmi diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 44037305dd..14feaf1b5f 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -103,6 +103,12 @@ #define ui_alien_fire "EAST-1:28,NORTH-3:25" #define ui_alien_oxygen "EAST-1:28,NORTH-4:25" +// Goes above HUD, mid-right +#define ui_ammo_hud1 "EAST-1:28,CENTER+1:25" +#define ui_ammo_hud2 "EAST-1:28,CENTER+2:27" +#define ui_ammo_hud3 "EAST-1:28,CENTER+3:29" +#define ui_ammo_hud4 "EAST-1:28,CENTER+4:31" + //Middle right (status indicators) #define ui_temp "EAST-1:28,CENTER-2:13" #define ui_health "EAST-1:28,CENTER-1:15" diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 98c187fc97..aef10cd979 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -1,3 +1,4 @@ +#define MAX_AMMO_HUD_POSSIBLE 4 // Cap the amount of HUDs at 4. /* The global hud: Uses the same visual objects for all players. @@ -191,6 +192,9 @@ var/list/global_huds = list( var/icon/ui_style var/ui_color var/ui_alpha + + // TGMC Ammo HUD Port + var/list/obj/screen/ammo_hud_list = list() var/list/minihuds = list() @@ -220,6 +224,7 @@ var/list/global_huds = list( other_important = null hotkeybuttons = null // item_action_list = null // ? + QDEL_LIST(ammo_hud_list) mymob = null /datum/hud/proc/hidden_inventory_update() @@ -460,4 +465,37 @@ var/list/global_huds = list( client.screen += client.void /mob/new_player/add_click_catcher() - return \ No newline at end of file + return + +/* TGMC Ammo HUD Port + * These procs call to screen_objects.dm's respective procs. + * All these do is manage the amount of huds on screen and set the HUD. +*/ +///Add an ammo hud to the user informing of the ammo count of G +/datum/hud/proc/add_ammo_hud(mob/living/user, obj/item/weapon/gun/G) + if(length(ammo_hud_list) >= MAX_AMMO_HUD_POSSIBLE) + return + var/obj/screen/ammo/ammo_hud = new + ammo_hud_list[G] = ammo_hud + ammo_hud.screen_loc = ammo_hud.ammo_screen_loc_list[length(ammo_hud_list)] + ammo_hud.add_hud(user, G) + ammo_hud.update_hud(user, G) + +///Remove the ammo hud related to the gun G from the user +/datum/hud/proc/remove_ammo_hud(mob/living/user, obj/item/weapon/gun/G) + var/obj/screen/ammo/ammo_hud = ammo_hud_list[G] + if(isnull(ammo_hud)) + return + ammo_hud.remove_hud(user, G) + qdel(ammo_hud) + ammo_hud_list -= G + var/i = 1 + for(var/key in ammo_hud_list) + ammo_hud = ammo_hud_list[key] + ammo_hud.screen_loc = ammo_hud.ammo_screen_loc_list[i] + i++ + +///Update the ammo hud related to the gun G +/datum/hud/proc/update_ammo_hud(mob/living/user, obj/item/weapon/gun/G) + var/obj/screen/ammo/ammo_hud = ammo_hud_list[G] + ammo_hud?.update_hud(user, G) \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 00446add6d..a06df0c082 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -898,3 +898,80 @@ icon_state = null plane = PLANE_HOLOMAP_ICONS appearance_flags = KEEP_TOGETHER + +// Begin TGMC Ammo HUD Port +/obj/screen/ammo + name = "ammo" + icon = 'icons/mob/screen_ammo.dmi' + icon_state = "ammo" + screen_loc = ui_ammo_hud1 + var/warned = FALSE + var/static/list/ammo_screen_loc_list = list(ui_ammo_hud1, ui_ammo_hud2, ui_ammo_hud3 ,ui_ammo_hud4) + +/obj/screen/ammo/proc/add_hud(var/mob/living/user, var/obj/item/weapon/gun/G) + + if(!user?.client) + return + + if(!G) + CRASH("/obj/screen/ammo/proc/add_hud() has been called from [src] without the required param of G") + + if(!G.has_ammo_counter()) + return + + user.client.screen += src + +/obj/screen/ammo/proc/remove_hud(var/mob/living/user) + user?.client?.screen -= src + +/obj/screen/ammo/proc/update_hud(var/mob/living/user, var/obj/item/weapon/gun/G) + if(!user?.client?.screen.Find(src)) + return + + if(!G || !istype(G) || !G.has_ammo_counter() || !G.get_ammo_type() || isnull(G.get_ammo_count())) + remove_hud() + return + + var/list/ammo_type = G.get_ammo_type() + var/rounds = G.get_ammo_count() + + var/hud_state = ammo_type[1] + var/hud_state_empty = ammo_type[2] + + overlays.Cut() + + var/empty = image('icons/mob/screen_ammo.dmi', src, "[hud_state_empty]") + + if(rounds == 0) + if(warned) + overlays += empty + else + warned = TRUE + var/obj/screen/ammo/F = new /obj/screen/ammo(src) + F.icon_state = "frame" + user.client.screen += F + flick("[hud_state_empty]_flash", F) + spawn(20) + user.client.screen -= F + qdel(F) + overlays += empty + else + warned = FALSE + overlays += image('icons/mob/screen_ammo.dmi', src, "[hud_state]") + + rounds = num2text(rounds) + //Handle the amount of rounds + switch(length(rounds)) + if(1) + overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[1]]") + if(2) + overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[2]]") + overlays += image('icons/mob/screen_ammo.dmi', src, "t[rounds[1]]") + if(3) + overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[3]]") + overlays += image('icons/mob/screen_ammo.dmi', src, "t[rounds[2]]") + overlays += image('icons/mob/screen_ammo.dmi', src, "h[rounds[1]]") + else //"0" is still length 1 so this means it's over 999 + overlays += image('icons/mob/screen_ammo.dmi', src, "o9") + overlays += image('icons/mob/screen_ammo.dmi', src, "t9") + overlays += image('icons/mob/screen_ammo.dmi', src, "h9") \ No newline at end of file diff --git a/code/game/objects/items/weapons/grenades/explosive.dm b/code/game/objects/items/weapons/grenades/explosive.dm index 076a7accce..77e07e2c5f 100644 --- a/code/game/objects/items/weapons/grenades/explosive.dm +++ b/code/game/objects/items/weapons/grenades/explosive.dm @@ -12,6 +12,7 @@ //The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern var/spread_range = 7 loadable = null + hud_state = "grenade_frag" // TGMC Ammo HUD Port /obj/item/weapon/grenade/explosive/detonate() ..() diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 209e47b253..9bdf650c64 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -13,6 +13,8 @@ var/det_time = 50 var/loadable = TRUE var/arm_sound = 'sound/weapons/armbomb.ogg' + var/hud_state = "grenade_he" // TGMC Ammo HUD Port + var/hud_state_empty = "grenade_empty" // TGMC Ammo HUD Port /obj/item/weapon/grenade/proc/clown_check(var/mob/living/user) if((CLUMSY in user.mutations) && prob(50)) diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm index 75c0e6a299..1cb98be61a 100644 --- a/code/game/objects/items/weapons/grenades/smokebomb.dm +++ b/code/game/objects/items/weapons/grenades/smokebomb.dm @@ -6,6 +6,7 @@ det_time = 20 item_state = "flashbang" slot_flags = SLOT_BELT + hud_state = "grenade_smoke" var/datum/effect/effect/system/smoke_spread/bad/smoke var/smoke_color var/smoke_strength = 8 diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 4ec2d0a5e2..852a086d97 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -54,6 +54,12 @@ if(self_recharge) if(world.time >= last_use + charge_delay) give(charge_amount) + // TGMC Ammo HUD - Update the HUD every time we're called to recharge. + if(istype(loc, /obj/item/weapon/gun/energy)) // Are we in a gun currently? + var/obj/item/weapon/gun/energy/gun = loc + var/mob/living/user = gun.loc + if(istype(user)) + user?.hud_used.update_ammo_hud(user, gun) // Update the HUD else return PROCESS_KILL diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 7c04ec3750..1565ad5ba2 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -435,6 +435,7 @@ else set_light(0) //VOREStation Edit End + user.hud_used.update_ammo_hud(user, src) // Similar to the above proc, but does not require a user, which is ideal for things like turrets. /obj/item/weapon/gun/proc/Fire_userless(atom/target) @@ -527,6 +528,7 @@ /obj/item/weapon/gun/proc/handle_click_empty(mob/user) if (user) user.visible_message("*click click*", "*click*") + user.hud_used.update_ammo_hud(user, src) else src.visible_message("*click click*") playsound(src, 'sound/weapons/empty.ogg', 100, 1) @@ -758,8 +760,35 @@ var/datum/firemode/new_mode = firemodes[sel_mode] new_mode.apply_to(src) to_chat(user, "\The [src] is now set to [new_mode.name].") + user.hud_used.update_ammo_hud(user, src) // TGMC Ammo HUD return new_mode /obj/item/weapon/gun/attack_self(mob/user) switch_firemodes(user) + +/* TGMC Ammo HUD Port Begin */ +/obj/item/weapon/gun + var/hud_enabled = TRUE + +/obj/item/weapon/gun/proc/has_ammo_counter() + return FALSE + +/obj/item/weapon/gun/proc/get_ammo_type() + return FALSE + +/obj/item/weapon/gun/proc/get_ammo_count() + return FALSE + +/obj/item/weapon/gun/equipped(mob/living/user, slot) // When a gun is equipped to your hands, we'll add the HUD to the user. Pending porting over TGMC guncode where wielding is far more sensible. + if(slot == slot_l_hand || slot == slot_r_hand) + user.hud_used.add_ammo_hud(user, src) + else + user.hud_used.remove_ammo_hud(user, src) + + return ..() + +/obj/item/weapon/gun/dropped(mob/living/user) // Ditto as above, we remove the HUD. Pending porting TGMC code to clean up this fucking nightmare of spaghetti. + user.hud_used.remove_ammo_hud(user, src) + + ..() \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 74dc34a72c..cf68420045 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -91,6 +91,9 @@ power_supply.give(rechargeamt) //... to recharge 1/5th the battery update_icon() + var/mob/living/M = loc // TGMC Ammo HUD + if(istype(M)) // TGMC Ammo HUD + M?.hud_used.update_ammo_hud(M, src) // TGMC Ammo HUD else charge_tick = 0 return 1 @@ -110,6 +113,9 @@ if(!power_supply) return null if(!ispath(projectile_type)) return null if(!power_supply.checked_use(charge_cost)) return null + var/mob/living/M = loc // TGMC Ammo HUD + if(istype(M)) // TGMC Ammo HUD + M?.hud_used.update_ammo_hud(M, src) return new projectile_type(src) /obj/item/weapon/gun/energy/proc/load_ammo(var/obj/item/C, mob/user) @@ -131,6 +137,7 @@ playsound(src, 'sound/weapons/flipblade.ogg', 50, 1) update_icon() update_held_icon() + user.hud_used.update_ammo_hud(user, src) // TGMC Ammo HUD else to_chat(user, "This cell is not fitted for [src].") return @@ -147,6 +154,7 @@ playsound(src, 'sound/weapons/empty.ogg', 50, 1) update_icon() update_held_icon() + user.hud_used.update_ammo_hud(user, src) // TGMC Ammo HUD else to_chat(user, "[src] does not have a power cell.") @@ -234,3 +242,20 @@ results += ..() return results + +// TGMC AMMO HUD +/obj/item/weapon/gun/energy/has_ammo_counter() + return TRUE + +/obj/item/weapon/gun/energy/get_ammo_type() + if(!projectile_type) + return list("unknown", "unknown") + else + var/obj/item/projectile/P = projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) + +/obj/item/weapon/gun/energy/get_ammo_count() + if(!power_supply) + return 0 + else + return FLOOR(power_supply.charge / max(charge_cost, 1), 1) \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/cell_loaded_vr/cell_loaded.dm b/code/modules/projectiles/guns/energy/cell_loaded_vr/cell_loaded.dm index e7edc8418d..68b13e76fe 100644 --- a/code/modules/projectiles/guns/energy/cell_loaded_vr/cell_loaded.dm +++ b/code/modules/projectiles/guns/energy/cell_loaded_vr/cell_loaded.dm @@ -49,8 +49,6 @@ var/obj/item/ammo_casing/microbattery/batt = chambered - charge_left = batt.shots_left - max_charge = initial(batt.shots_left) if(ammo_magazine) //Crawl to find more for(var/obj/item/ammo_casing/microbattery/bullet as anything in ammo_magazine.stored_ammo) if(istype(bullet,batt.type)) @@ -67,6 +65,9 @@ chambered = new_batt update_charge() update_icon() + var/mob/living/M = loc // TGMC Ammo HUD + if(istype(M)) // TGMC Ammo HUD + M?.hud_used.update_ammo_hud(M, src) /obj/item/weapon/gun/projectile/cell_loaded/attack_self(mob/user) if(!chambered) @@ -169,6 +170,11 @@ update_icon() playsound(src, 'sound/weapons/flipblade.ogg', 50, 1) update_icon() + if(istype(loc, /obj/item/weapon/gun/projectile/cell_loaded)) // Update the HUD if we're in a gun + have a user. Not that one should be able to reload the mag while it's in a gun, but just in caaaaase. + var/obj/item/weapon/gun/projectile/cell_loaded/cell_load = loc + var/mob/living/M = cell_load.loc + if(istype(M)) + M?.hud_used.update_ammo_hud(M, cell_load) /obj/item/ammo_magazine/cell_mag/update_icon() cut_overlays() @@ -277,4 +283,31 @@ new /obj/item/ammo_casing/microbattery/combat/xray(src) new /obj/item/ammo_casing/microbattery/medical/stabilize2(src) new /obj/item/ammo_casing/microbattery/medical/haste(src) - new /obj/item/ammo_casing/microbattery/medical/resist(src) \ No newline at end of file + new /obj/item/ammo_casing/microbattery/medical/resist(src) + +// TGMC Ammo HUD: Custom handling for cell-loaded weaponry. +/* +/obj/item/weapon/gun/projectile/cell_loaded/get_ammo_type() + if(!projectile_type) + return list("unknown", "unknown") + else + var/obj/item/projectile/P = projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) +*/ +/obj/item/weapon/gun/projectile/cell_loaded/get_ammo_count() + if(!chambered) + return 0 // We're not chambered, so we have 0 rounds loaded. + + var/obj/item/ammo_casing/microbattery/batt = chambered + + var/shots + if(ammo_magazine) // Check how much ammo we have + for(var/obj/item/ammo_casing/microbattery/bullet as anything in ammo_magazine.stored_ammo) + if(istype(bullet,batt.type)) + shots += bullet.shots_left + if(shots > 0) // We have shots ready to fire. + return shots + else // We're out of shots. + return 0 + else // Else, we're unloaded/don't have a magazine. + return 0 \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/cell_loaded_vr/ml3m_cells.dm b/code/modules/projectiles/guns/energy/cell_loaded_vr/ml3m_cells.dm index 6663d6e380..2e2b0d8bff 100644 --- a/code/modules/projectiles/guns/energy/cell_loaded_vr/ml3m_cells.dm +++ b/code/modules/projectiles/guns/energy/cell_loaded_vr/ml3m_cells.dm @@ -13,6 +13,7 @@ damage = 0 check_armour = "laser" light_color = "#80F5FF" + hud_state = "laser_disabler" combustion = FALSE diff --git a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm index 4c40da9721..426301e756 100644 --- a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm +++ b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm @@ -57,4 +57,16 @@ /obj/item/weapon/gun/projectile/multi_cannon/unload_ammo(mob/user, var/allow_dump=1) .=..() update_icon() - chambered = null \ No newline at end of file + chambered = null + +/obj/item/weapon/gun/projectile/multi_cannon/get_ammo_count() // Custom handling for the Curabitur. + if(istype(chambered, /obj/item/ammo_casing/macrobattery)) + var/obj/item/ammo_casing/macrobattery/battery = chambered + if(battery.charge) // Does the battery have charge? + return battery.charge // This should safely return the amount of shots we have. Every time we fire, we decrement charge by 1, at least in all the cells I can see. + else // No charge in the battery. + return 0 // Return 0 ammo to the HUD. + else if(chambered == null) + return 0 + else + CRASH("/obj/item/weapon/gun/projectile/multi_cannon/get_ammo_count() was called from [src] but did not have a valid magazine loaded, somehow! Chambered is currently [chambered].") \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm index 53dd7c0ad3..d333081c37 100644 --- a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm +++ b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm @@ -38,6 +38,12 @@ //alright, the below seems jank. it IS jank, but for whatever reason I can't reuse BB. big bad BB = null BB = new projectile_type + // TGMC Ammo HUD - Update the HUD every time we expend/fire, given the Curabitur's method of handling firing. + if(istype(loc, /obj/item/weapon/gun/projectile/multi_cannon)) + var/obj/item/weapon/gun/projectile/multi_cannon = loc + var/mob/living/user = multi_cannon.loc + if(istype(user)) + user?.hud_used.update_ammo_hud(user, multi_cannon) return else BB = null @@ -52,6 +58,13 @@ STOP_PROCESSING(SSobj, src) if(istype(loc,/obj/item/weapon/gun/projectile/multi_cannon)) loc.update_icon() + + // TGMC Ammo HUD - Update the HUD every time we're called to recharge. + if(istype(loc, /obj/item/weapon/gun/projectile/multi_cannon)) + var/obj/item/weapon/gun/projectile/multi_cannon = loc + var/mob/living/user = multi_cannon.loc + if(istype(user)) + user?.hud_used.update_ammo_hud(user, multi_cannon) //variants here, there's not many of them. diff --git a/code/modules/projectiles/guns/energy/laser_vr.dm b/code/modules/projectiles/guns/energy/laser_vr.dm index 9472d512c1..0add3098a3 100644 --- a/code/modules/projectiles/guns/energy/laser_vr.dm +++ b/code/modules/projectiles/guns/energy/laser_vr.dm @@ -184,11 +184,13 @@ if(!do_after(user, 10, src)) break playsound(src,'sound/items/change_drill.ogg',25,1) + user.hud_used.update_ammo_hud(user, src) if(power_supply.give(phase_power) < phase_power) break recharging = 0 update_icon() + user.hud_used.update_ammo_hud(user, src) // Update one last time once we're finished! /obj/item/weapon/gun/energy/locked/frontier/update_icon() if(recharging) diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 31ffe40e13..92ca4535fc 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -54,6 +54,10 @@ chambered = ammo_magazine.stored_ammo[ammo_magazine.stored_ammo.len] if(handle_casings != HOLD_CASINGS) ammo_magazine.stored_ammo -= chambered + + var/mob/living/M = loc // TGMC Ammo HUD + if(istype(M)) // TGMC Ammo HUD + M?.hud_used.update_ammo_hud(M, src) if (chambered) return chambered.BB @@ -98,6 +102,10 @@ if(handle_casings != HOLD_CASINGS) chambered = null + + var/mob/living/M = loc // TGMC Ammo HUD + if(istype(M)) // TGMC Ammo HUD + M?.hud_used.update_ammo_hud(M, src) //Attempts to load A into src, depending on the type of thing being loaded and the load_method @@ -117,6 +125,7 @@ AM.loc = src ammo_magazine = AM user.visible_message("[user] inserts [AM] into [src].", "You insert [AM] into [src].") + user.hud_used.update_ammo_hud(user, src) playsound(src, 'sound/weapons/flipblade.ogg', 50, 1) if(SPEEDLOADER) if(loaded.len >= max_shells) @@ -131,8 +140,10 @@ loaded += C AM.stored_ammo -= C //should probably go inside an ammo_magazine proc, but I guess less proc calls this way... count++ + user.hud_used.update_ammo_hud(user, src) if(count) user.visible_message("[user] reloads [src].", "You load [count] round\s into [src].") + user.hud_used.update_ammo_hud(user, src) playsound(src, 'sound/weapons/empty.ogg', 50, 1) AM.update_icon() else if(istype(A, /obj/item/ammo_casing)) @@ -168,6 +179,7 @@ sleep(1 SECOND) update_icon() + user.hud_used.update_ammo_hud(user, src) //attempts to unload src. If allow_dump is set to 0, the speedloader unloading method will be disabled /obj/item/weapon/gun/projectile/proc/unload_ammo(mob/user, var/allow_dump=1) @@ -177,6 +189,7 @@ playsound(src, 'sound/weapons/empty.ogg', 50, 1) ammo_magazine.update_icon() ammo_magazine = null + user.hud_used.update_ammo_hud(user, src) else if(loaded.len) //presumably, if it can be speed-loaded, it can be speed-unloaded. if(allow_dump && (load_method & SPEEDLOADER)) @@ -195,9 +208,11 @@ user.put_in_hands(C) user.visible_message("[user] removes \a [C] from [src].", "You remove \a [C] from [src].") playsound(src, 'sound/weapons/empty.ogg', 50, 1) + user.hud_used.update_ammo_hud(user, src) else to_chat(user, "[src] is empty.") update_icon() + user.hud_used.update_ammo_hud(user, src) /obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob) ..() @@ -228,6 +243,7 @@ ammo_magazine.update_icon() ammo_magazine = null update_icon() //make sure to do this after unsetting ammo_magazine + user.hud_used.update_ammo_hud(user, src) /obj/item/weapon/gun/projectile/examine(mob/user) . = ..() @@ -256,3 +272,72 @@ unload_ammo(usr) */ + +// TGMC Ammo HUD Insertion +/obj/item/weapon/gun/projectile/has_ammo_counter() + return TRUE + +/obj/item/weapon/gun/projectile/get_ammo_type() + if(load_method & MAGAZINE) + if(chambered) // Do we have an ammo casing chambered + var/obj/item/ammo_casing/A = chambered + var/obj/item/projectile/P = A.projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) + else if(ammo_magazine && ammo_magazine.stored_ammo.len) // Do we have a mag, and have ammo in the mag, but nothing chambered? + var/obj/item/ammo_casing/A = ammo_magazine.stored_ammo[1] + var/obj/item/projectile/P = A.projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) + else if(src.projectile_type) // Else, we're entirely empty, and irregardless of the mag we have loaded (as it's empty, or it would've passed the length check above), return the DEFAULT projectile_type on the gun, if set. + var/obj/item/projectile/P = src.projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) + else + return list("unknown", "unknown") // Safety, this shouldn't happen, but just in case + else if(load_method & (SINGLE_CASING|SPEEDLOADER)) // Do we load with single casings OR speedloaders? + if(chambered) // Do we have an ammo casing loaded in the chamber? All casings still have a projectile_type var. + var/obj/item/ammo_casing/A = chambered + var/obj/item/projectile/P = A.projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) // Return the casing's projectile_type ammo hud state + else if(loaded.len) // Else, is the gun loaded, but no ammo casings in chamber currently? + var/obj/item/ammo_casing/A = loaded[1] + var/obj/item/projectile/P = A.projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) // Return the ammunition loaded in the gun's hud_state + else if(src.projectile_type) // Else, we're entirely empty, and have nothing loaded in the gun, and nothing in the chamber. Return the DEFAULT projectile_type on the gun, if set. + var/obj/item/projectile/P = src.projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) + else + return list("unknown", "unknown") // Safety, this shouldn't happen, but just in case + else if(src.projectile_type) // Failsafe if we somehow don't pass the above. Return the DEFAULT projectile_type on the gun, if set. + var/obj/item/projectile/P = src.projectile_type + return list(initial(P.hud_state), initial(P.hud_state_empty)) + else // Failsafe if we somehow fail all three methods + return list("unknown", "unknown") + +/obj/item/weapon/gun/projectile/get_ammo_count() + if(ammo_magazine) // Do we have a magazine loaded? + var/shots_left + if(chambered && chambered.BB) // Do we have a bullet in the currently-chambered casing, if any? + shots_left++ + for(var/obj/item/ammo_casing/bullet in ammo_magazine.stored_ammo) + if(bullet.BB) + shots_left++ + + if(shots_left > 0) + return shots_left + else + return 0 // No ammo left or failsafe. + else if(loaded) // Do we use internal ammunition + var/shots_left + if(chambered && chambered.BB) // Do we have a bullet in the currently-chambered casing, if any? + shots_left++ + for(var/obj/item/ammo_casing/bullet in loaded) + if(bullet.BB) // Only increment how many shots we have left if we're loaded. + shots_left++ + + if(shots_left > 0) + return shots_left + else + return 0 // No ammo left or failsafe. + else if(chambered) // If we don't have a magazine or internal ammunition loaded, but we have a casing in chamber, return the amount. + return chambered.BB ? 1 : 0 + else // Failsafe, or completely unloaded + return 0 diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 20868b555e..d04bd2b31f 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -1,6 +1,7 @@ /* * Shotgun */ + /obj/item/weapon/gun/projectile/shotgun/pump name = "shotgun" desc = "The mass-produced MarsTech Meteor 29 shotgun is a favourite of police and security forces on many worlds. Uses 12g rounds." @@ -43,12 +44,14 @@ else chambered.loc = get_turf(src) // Eject casing chambered = null + M.hud_used.update_ammo_hud(M, src) // TGMC Ammo HUD Port // Load next shell if(loaded.len) var/obj/item/ammo_casing/AC = loaded[1] // Load next casing. loaded -= AC // Remove casing from loaded list. chambered = AC + M.hud_used.update_ammo_hud(M, src) // TGMC Ammo HUD Port if(pump_animation) // This affects all bolt action and shotguns. flick("[pump_animation]", src) // This plays any pumping @@ -180,6 +183,7 @@ burst = 2 user.visible_message("The shotgun goes off!", "The shotgun goes off in your face!") Fire_userless(user) + user.hud_used.update_ammo_hud(user, src) // TGMC Ammo HUD Port burst = burstsetting return if(do_after(user, 30)) // SHIT IS STEALTHY EYYYYY diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index abba257a93..8ed8d98ffd 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -139,6 +139,10 @@ var/impact_effect_type = null var/list/impacted_mobs = list() + + // TGMC Ammo HUD Port + var/hud_state = "unknown" // What HUD state we use when we have ammunition. + var/hud_state_empty = "unknown" // The empty state. DON'T USE _FLASH IN THE NAME OF THE EMPTY STATE STRING, THAT IS ADDED BY THE CODE. /obj/item/projectile/proc/Range() range-- diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 312c92a5ea..9597deb00d 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -23,6 +23,9 @@ tracer_type = /obj/effect/projectile/tracer/laser impact_type = /obj/effect/projectile/impact/laser + hud_state = "laser" + hud_state_empty = "battery_empty" + /obj/item/projectile/beam/practice name = "laser" icon_state = "laser" @@ -31,15 +34,18 @@ damage_type = BURN check_armour = "laser" eyeblur = 2 + hud_state = "laser" /obj/item/projectile/beam/weaklaser name = "weak laser" icon_state = "laser" damage = 15 + hud_state = "laser" /obj/item/projectile/beam/weaklaser/blue icon_state = "bluelaser" light_color = "#0066FF" + hud_state = "laser_disabler" muzzle_type = /obj/effect/projectile/muzzle/laser_blue tracer_type = /obj/effect/projectile/tracer/laser_blue @@ -47,14 +53,17 @@ /obj/item/projectile/beam/smalllaser damage = 25 + hud_state = "laser" /obj/item/projectile/beam/burstlaser damage = 30 armor_penetration = 10 + hud_state = "laser" /obj/item/projectile/beam/midlaser damage = 40 armor_penetration = 10 + hud_state = "laser" /obj/item/projectile/beam/mininglaser name = "pulsating laser" @@ -81,6 +90,7 @@ muzzle_type = /obj/effect/projectile/muzzle/laser_heavy tracer_type = /obj/effect/projectile/tracer/laser_heavy impact_type = /obj/effect/projectile/impact/laser_heavy + hud_state = "laser_overcharge" /obj/item/projectile/beam/heavylaser/fakeemitter name = "emitter beam" @@ -88,6 +98,7 @@ fire_sound = 'sound/weapons/emitter.ogg' light_color = "#00CC33" excavation_amount = 140 // 2 shots to dig a standard rock turf. Superior due to being a mounted tool beam, to make it actually viable. + hud_state = "laser_overcharge" muzzle_type = /obj/effect/projectile/muzzle/emitter tracer_type = /obj/effect/projectile/tracer/emitter @@ -97,6 +108,7 @@ damage = 80 armor_penetration = 50 light_color = "#FF0D00" + hud_state = "laser_overcharge" /obj/item/projectile/beam/xray name = "xray beam" @@ -105,6 +117,7 @@ damage = 25 armor_penetration = 50 light_color = "#00CC33" + hud_state = "laser_sniper" muzzle_type = /obj/effect/projectile/muzzle/xray tracer_type = /obj/effect/projectile/tracer/xray @@ -118,6 +131,7 @@ armor_penetration = 90 irradiate = 20 light_color = "#00CC33" + hud_state = "laser_sniper" muzzle_type = /obj/effect/projectile/muzzle/xray tracer_type = /obj/effect/projectile/tracer/xray @@ -129,6 +143,7 @@ fire_sound = 'sound/weapons/eluger.ogg' damage = 40 light_color = "#00C6FF" + hud_state = "laser_disabler" muzzle_type = /obj/effect/projectile/muzzle/laser_omni tracer_type = /obj/effect/projectile/tracer/laser_omni @@ -141,6 +156,7 @@ damage = 100 //Badmin toy, don't care armor_penetration = 100 light_color = "#0066FF" + hud_state = "pulse" muzzle_type = /obj/effect/projectile/muzzle/laser_pulse tracer_type = /obj/effect/projectile/tracer/laser_pulse @@ -158,6 +174,7 @@ damage = 0 // The actual damage is computed in /code/modules/power/singularity/emitter.dm light_color = "#00CC33" excavation_amount = 70 // 3 shots to mine a turf + hud_state = "laser_overcharge" muzzle_type = /obj/effect/projectile/muzzle/emitter tracer_type = /obj/effect/projectile/tracer/emitter @@ -171,13 +188,14 @@ no_attack_log = 1 damage_type = BURN check_armour = "laser" + hud_state = "monkey" combustion = FALSE /obj/item/projectile/beam/lasertag/blue icon_state = "bluelaser" light_color = "#0066FF" - + hud_state = "monkey" muzzle_type = /obj/effect/projectile/muzzle/laser_blue tracer_type = /obj/effect/projectile/tracer/laser_blue impact_type = /obj/effect/projectile/impact/laser_blue @@ -192,6 +210,7 @@ /obj/item/projectile/beam/lasertag/red icon_state = "laser" light_color = "#FF0D00" + hud_state = "monkey" /obj/item/projectile/beam/lasertag/red/on_hit(var/atom/target, var/blocked = 0) if(ishuman(target)) @@ -203,6 +222,7 @@ /obj/item/projectile/beam/lasertag/omni//A laser tag bolt that stuns EVERYONE icon_state = "omnilaser" light_color = "#00C6FF" + hud_state = "monkey" muzzle_type = /obj/effect/projectile/muzzle/laser_omni tracer_type = /obj/effect/projectile/tracer/laser_omni @@ -222,6 +242,7 @@ damage = 50 armor_penetration = 10 light_color = "#00CC33" + hud_state = "laser_sniper" muzzle_type = /obj/effect/projectile/muzzle/xray tracer_type = /obj/effect/projectile/tracer/xray @@ -238,12 +259,15 @@ light_color = "#FFFFFF" hitsound = 'sound/weapons/zapbang.ogg' + combustion = FALSE muzzle_type = /obj/effect/projectile/muzzle/stun tracer_type = /obj/effect/projectile/tracer/stun impact_type = /obj/effect/projectile/impact/stun + hud_state = "taser" // TGMC Ammo HUD port + /obj/item/projectile/beam/stun/weak name = "weak stun beam" icon_state = "stun" @@ -278,6 +302,7 @@ muzzle_type = /obj/effect/projectile/muzzle/laser_omni tracer_type = /obj/effect/projectile/tracer/laser_omni impact_type = /obj/effect/projectile/impact/laser_omni + hud_state = "laser_disabler" /obj/item/projectile/beam/stun/blue icon_state = "bluelaser" @@ -285,6 +310,7 @@ muzzle_type = /obj/effect/projectile/muzzle/laser_blue tracer_type = /obj/effect/projectile/tracer/laser_blue impact_type = /obj/effect/projectile/impact/laser_blue + hud_state = "laser_disabler" /obj/item/projectile/beam/disable name = "disabler beam" @@ -294,6 +320,7 @@ agony = 100 //One shot stuns for the time being until adjustments are fully made. damage_type = HALLOSS light_color = "#00CECE" + hud_state = "laser_disabler" muzzle_type = /obj/effect/projectile/muzzle/laser_omni tracer_type = /obj/effect/projectile/tracer/laser_omni @@ -312,6 +339,7 @@ agony = 15 eyeblur = 2 hitsound = 'sound/weapons/zapbang.ogg' + hud_state = "taser" /obj/item/projectile/beam/shock/weak damage = 5 @@ -324,6 +352,7 @@ muzzle_type = /obj/effect/projectile/muzzle/xray tracer_type = /obj/effect/projectile/tracer/xray impact_type = /obj/effect/projectile/impact/xray + hud_state = "laser" /obj/item/projectile/beam/imperial name = "laser beam" @@ -333,7 +362,7 @@ muzzle_type = /obj/effect/projectile/muzzle/darkmatter tracer_type = /obj/effect/projectile/tracer/darkmatter impact_type = /obj/effect/projectile/impact/darkmatter - + hud_state = "plasma_rifle_blast" // // Projectile Beam Definitions // @@ -344,7 +373,7 @@ damage_type = ELECTROCUTE //You should be safe inside a voidsuit sharp = FALSE //"Wide" spectrum beam light_color = COLOR_GOLD - + hud_state = "monkey" excavation_amount = 200 // Good at shooting rocks muzzle_type = /obj/effect/projectile/muzzle/pointdefense @@ -361,6 +390,8 @@ agony = 5 damage_type = HALLOSS light_color = "#00CC33" + hud_state = "flame_green" + hud_state_empty = "flame_empty" muzzle_type = /obj/effect/projectile/muzzle/xray tracer_type = /obj/effect/projectile/tracer/xray @@ -386,7 +417,7 @@ damage_type = BURN check_armour = "laser" light_color = "#80F5FF" - + hud_state = "laser_disabler" combustion = FALSE muzzle_type = /obj/effect/projectile/muzzle/medigun diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 76f2e1ad7c..431c8a4b19 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -12,6 +12,8 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect excavation_amount = 20 var/mob_passthrough_check = 0 + hud_state = "pistol_lightap" + hud_state_empty = "pistol_empty" // Just in case we somehow have no hud_state_empty defined muzzle_type = /obj/effect/projectile/muzzle/bullet @@ -70,30 +72,38 @@ /obj/item/projectile/bullet/pistol // 9mm pistols and most SMGs. Sacrifice power for capacity. fire_sound = 'sound/weapons/gunshot2.ogg' damage = 20 + hud_state = "pistol" + hud_state_empty = "pistol_empty" /obj/item/projectile/bullet/pistol/ap damage = 15 armor_penetration = 30 + hud_state = "pistol_light_ap" /obj/item/projectile/bullet/pistol/hp damage = 25 armor_penetration = -50 + hud_state = "pistol_ap" /obj/item/projectile/bullet/pistol/medium // .45 (and maybe .40 if it ever gets added) caliber security pistols. Balance between capacity and power. fire_sound = 'sound/weapons/gunshot3.ogg' // Snappier sound. damage = 25 + hud_state = "pistol" /obj/item/projectile/bullet/pistol/medium/ap damage = 20 armor_penetration = 15 + hud_state = "pistol_light_ap" /obj/item/projectile/bullet/pistol/medium/hp damage = 30 armor_penetration = -50 + hud_state = "pistol_ap" /obj/item/projectile/bullet/pistol/strong // .357 and .44 caliber stuff. High power pistols like the Mateba or Desert Eagle. Sacrifice capacity for power. fire_sound = 'sound/weapons/gunshot4.ogg' damage = 60 + hud_state = "pistol_heavy" /obj/item/projectile/bullet/pistol/rubber/strong // "Rubber" bullets for high power pistols. fire_sound = 'sound/weapons/gunshot3.ogg' // Rubber shots have less powder, but these still have more punch than normal rubber shot. @@ -102,6 +112,7 @@ embed_chance = 0 sharp = FALSE check_armour = "melee" + hud_state = "pistol_special" /obj/item/projectile/bullet/pistol/rubber // "Rubber" bullets for all other pistols. name = "rubber bullet" @@ -110,6 +121,7 @@ embed_chance = 0 sharp = FALSE check_armour = "melee" + hud_state = "pistol_special" fire_sound ='sound/weapons/Gunshot_pathetic.ogg' // Rubber shots have less powder in the casing. /* shotgun projectiles */ @@ -119,6 +131,8 @@ fire_sound = 'sound/weapons/Gunshot_shotgun.ogg' damage = 50 armor_penetration = 20 + hud_state = "shotgun_slug" + hud_state_empty = "shotgun_empty" /obj/item/projectile/bullet/shotgun/beanbag //because beanbags are not bullets name = "beanbag" @@ -127,6 +141,7 @@ embed_chance = 0 sharp = FALSE check_armour = "melee" + hud_state = "shotgun_beanbag" //Should do about 80 damage at 1 tile distance (adjacent), and 50 damage at 3 tiles distance. //Overall less damage than slugs in exchange for more damage at very close range and more embedding @@ -137,12 +152,14 @@ pellets = 6 range_step = 1 spread_step = 10 + hud_state = "shotgun_buckshot" /obj/item/projectile/bullet/pellet/shotgun/flak damage = 2 //The main weapon using these fires four at a time, usually with different destinations. Usually. range_step = 2 spread_step = 30 armor_penetration = 10 + hud_state = "shotgun_flechette" //EMP shotgun 'slug', it's basically a beanbag that pops a tiny emp when it hits. //Not currently used /obj/item/projectile/bullet/shotgun/ion @@ -152,6 +169,7 @@ embed_chance = 0 sharp = FALSE check_armour = "melee" + hud_state = "shotgun_ion" combustion = FALSE @@ -167,46 +185,57 @@ fire_sound = 'sound/weapons/Gunshot_generic_rifle.ogg' armor_penetration = 15 penetrating = 1 + hud_state = "rifle" + hud_state_empty = "rifle_empty" /obj/item/projectile/bullet/rifle/a762 fire_sound = 'sound/weapons/Gunshot_heavy.ogg' damage = 35 + hud_state = "rifle_heavy" /obj/item/projectile/bullet/rifle/a762/sniper // Hitscan specifically for sniper ammo; to be implimented at a later date, probably for the SVD. -Ace fire_sound = 'sound/weapons/Gunshot_sniper.ogg' hitscan = 1 //so the ammo isn't useless as a sniper weapon + hud_state = "hivelo" /obj/item/projectile/bullet/rifle/a762/ap damage = 30 armor_penetration = 50 // At 30 or more armor, this will do more damage than standard rounds. + hud_state = "rifle_ap" /obj/item/projectile/bullet/rifle/a762/hp damage = 40 armor_penetration = -50 penetrating = 0 + hud_state = "hivelo_iff" /obj/item/projectile/bullet/rifle/a762/hunter // Optimized for killing simple animals and not people, because Balance(tm) damage = 20 SA_bonus_damage = 50 // 70 total on animals. SA_vulnerability = SA_ANIMAL + hud_state = "rifle_heavy" /obj/item/projectile/bullet/rifle/a545 fire_sound = 'sound/weapons/Gunshot_light.ogg' damage = 25 + hud_state = "rifle" /obj/item/projectile/bullet/rifle/a545/ap damage = 20 armor_penetration = 50 // At 40 or more armor, this will do more damage than standard rounds. + hud_state = "rifle_ap" /obj/item/projectile/bullet/rifle/a545/hp damage = 35 armor_penetration = -50 penetrating = 0 + hud_state = "hivelo_iff" /obj/item/projectile/bullet/rifle/a545/hunter damage = 15 SA_bonus_damage = 35 // 50 total on animals. SA_vulnerability = SA_ANIMAL + hud_state = "rifle_heavy" /obj/item/projectile/bullet/rifle/a145 // 14.5�114mm is bigger than a .50 BMG round. fire_sound = 'sound/weapons/Gunshot_cannon.ogg' // This is literally an anti-tank rifle caliber. It better sound like a fucking cannon. @@ -216,6 +245,7 @@ penetrating = 5 armor_penetration = 80 hitscan = 1 //so the PTR isn't useless as a sniper weapon + hud_state = "sniper" icon_state = "bullet_alt" tracer_type = /obj/effect/projectile/tracer/cannon @@ -226,10 +256,12 @@ weaken = 0 penetrating = 15 armor_penetration = 90 + hud_state = "sniper_flak" /obj/item/projectile/bullet/rifle/a44rifle fire_sound = 'sound/weapons/gunshot4.ogg' damage = 50 + hud_state = "revolver" /* Miscellaneous */ @@ -237,11 +269,13 @@ name = "co bullet" damage = 20 damage_type = OXY + hud_state = "pistol_tranq" /obj/item/projectile/bullet/cyanideround name = "poison bullet" damage = 40 damage_type = TOX + hud_state = "pistol_tranq" /obj/item/projectile/bullet/burstbullet name = "exploding bullet" @@ -249,6 +283,7 @@ damage = 20 embed_chance = 0 edge = TRUE + hud_state = "pistol_fire" /obj/item/projectile/bullet/burstbullet/on_hit(var/atom/target, var/blocked = 0) if(isturf(target)) @@ -264,6 +299,7 @@ damage_type = BURN incendiary = 0.5 flammability = 2 + hud_state = "pistol_fire" /obj/item/projectile/bullet/incendiary/flamethrower name = "ball of fire" @@ -276,12 +312,14 @@ agony = 30 range = 4 vacuum_traversal = 0 + hud_state = "flame" /obj/item/projectile/bullet/incendiary/flamethrower/large damage = 5 incendiary = 3 flammability = 2 range = 6 + hud_state = "flame" /obj/item/projectile/bullet/incendiary/flamethrower/tiny damage = 2 @@ -291,11 +329,13 @@ modifier_duration = 20 SECONDS range = 6 agony = 0 + hud_state = "flame" /* Practice rounds and blanks */ /obj/item/projectile/bullet/practice damage = 5 + hud_state = "smg_light" /obj/item/projectile/bullet/pistol/cap // Just the primer, such as a cap gun. name = "cap" @@ -305,6 +345,7 @@ nodamage = 1 embed_chance = 0 sharp = FALSE + hud_state = "monkey" combustion = FALSE @@ -320,6 +361,7 @@ nodamage = 1 embed_chance = 0 sharp = FALSE + hud_state = "smg_light" /* BB Rounds */ /obj/item/projectile/bullet/bb // Generic single BB @@ -329,6 +371,7 @@ embed_chance = 0 sharp = FALSE silenced = TRUE + hud_state = "pistol_light" /obj/item/projectile/bullet/pellet/shotgun/bb // Shotgun name = "BB" @@ -340,6 +383,7 @@ range_step = 1 spread_step = 10 silenced = TRUE + hud_state = "pistol_light" /* toy projectiles */ /obj/item/projectile/bullet/cap @@ -353,6 +397,7 @@ impact_effect_type = null fire_sound = 'sound/effects/snap.ogg' combustion = FALSE + hud_state = "pistol_light" /obj/item/projectile/bullet/cap/process() loc = null @@ -372,6 +417,7 @@ icon = 'icons/obj/gun_toy.dmi' icon_state = "foamdart_proj" range = 15 + hud_state = "grenade_dummy" /obj/item/projectile/bullet/foam_dart/on_impact(var/atom/A) . = ..() @@ -400,6 +446,7 @@ icon = 'icons/obj/gun_toy.dmi' icon_state = "foamdart_riot_proj" range = 15 + hud_state = "grenade_he" /obj/item/projectile/bullet/foam_dart_riot/on_impact(var/atom/A) . = ..() diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index f3f1068110..29e082d672 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -8,6 +8,8 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect hitsound_wall = 'sound/weapons/effects/searwall.ogg' hitsound = 'sound/weapons/zapbang.ogg' + hud_state = "plasma" + hud_state_empty = "battery_empty" var/flash_strength = 10 @@ -22,6 +24,7 @@ var/flash_range = 0 var/brightness = 7 var/light_colour = "#ffffff" + hud_state = "grenade_dummy" /obj/item/projectile/energy/flash/on_impact(var/atom/A) var/turf/T = flash_range? src.loc : get_turf(A) @@ -59,6 +62,7 @@ flash_range = 1 brightness = 15 flash_strength = 20 + hud_state = "grenade_dummy" /obj/item/projectile/energy/flash/flare/on_impact(var/atom/A) light_colour = pick("#e58775", "#ffffff", "#90ff90", "#a09030") @@ -77,15 +81,18 @@ light_range = 2 light_power = 0.5 light_color = "#FFFFFF" + hud_state = "taser" //Damage will be handled on the MOB side, to prevent window shattering. /obj/item/projectile/energy/electrode/strong agony = 55 + hud_state = "taser" /obj/item/projectile/energy/electrode/stunshot name = "stunshot" damage = 5 agony = 80 + hud_state = "taser" /obj/item/projectile/energy/electrode/stunshot/strong name = "stunshot" @@ -93,6 +100,7 @@ damage = 10 taser_effect = 1 agony = 100 + hud_state = "taser" /obj/item/projectile/energy/declone name = "declone" @@ -107,6 +115,7 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser combustion = FALSE + hud_state = "plasma_pistol" /obj/item/projectile/energy/excavate name = "kinetic blast" @@ -120,6 +129,7 @@ vacuum_traversal = 0 combustion = FALSE + hud_state = "plasma_blast" /obj/item/projectile/energy/dart name = "dart" @@ -128,6 +138,7 @@ damage_type = TOX agony = 120 check_armour = "energy" + hud_state = "pistol_tranq" combustion = FALSE @@ -138,23 +149,28 @@ damage_type = TOX agony = 40 stutter = 10 + hud_state = "electrothermal" /obj/item/projectile/energy/bolt/large name = "largebolt" damage = 20 + hud_state = "electrothermal" /obj/item/projectile/energy/bow name = "engergy bolt" icon_state = "cbbolt" damage = 20 + hud_state = "electrothermal" /obj/item/projectile/energy/bow/heavy damage = 30 icon_state = "cbbolt" + hud_state = "electrothermal" /obj/item/projectile/energy/bow/stun name = "stun bolt" agony = 30 + hud_state = "electrothermal" /obj/item/projectile/energy/acid //Slightly up-gunned (Read: The thing does agony and checks bio resist) variant of the simple alien mob's projectile, for queens and sentinels. name = "acidic spit" @@ -166,6 +182,7 @@ armor_penetration = 25 // It's acid hitsound_wall = 'sound/weapons/effects/alien_spit_wall.ogg' hitsound = 'sound/weapons/effects/alien_spit_wall.ogg' + hud_state = "electrothermal" combustion = FALSE @@ -179,6 +196,7 @@ armor_penetration = 25 // It's acid-based hitsound_wall = 'sound/weapons/effects/alien_spit_wall.ogg' hitsound = 'sound/weapons/effects/alien_spit_wall.ogg' + hud_state = "electrothermal" combustion = FALSE @@ -188,6 +206,7 @@ damage = 20 damage_type = BIOACID agony = 20 + hud_state = "electrothermal" check_armour = "bio" armor_penetration = 25 // It's acid-based @@ -202,6 +221,7 @@ light_power = 0.5 light_color = "#33CC00" impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser + hud_state = "plasma_rifle" combustion = FALSE @@ -215,6 +235,7 @@ agony = 55 damage_type = BURN vacuum_traversal = 0 //Projectile disappears in empty space + hud_state = "plasma_rifle_blast" /obj/item/projectile/energy/plasmastun/proc/bang(var/mob/living/carbon/M) @@ -259,6 +280,7 @@ embed_chance = 0 muzzle_type = /obj/effect/projectile/muzzle/pulse impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser + hud_state = "plasma_sphere" /obj/item/projectile/energy/phase name = "phase wave" @@ -267,28 +289,35 @@ damage = 5 SA_bonus_damage = 45 // 50 total on animals SA_vulnerability = SA_ANIMAL + hud_state = "laser_heat" /obj/item/projectile/energy/phase/light range = 4 SA_bonus_damage = 35 // 40 total on animals + hud_state = "laser_heat" /obj/item/projectile/energy/phase/heavy range = 8 SA_bonus_damage = 55 // 60 total on animals + hud_state = "laser_heat" /obj/item/projectile/energy/phase/heavy/cannon range = 10 damage = 15 SA_bonus_damage = 60 // 75 total on animals + hud_state = "laser_heat" /obj/item/projectile/energy/electrode/strong agony = 70 + hud_state = "taser" /obj/item/projectile/energy flash_strength = 10 + hud_state = "taser" /obj/item/projectile/energy/flash flash_range = 1 + hud_state = "grenade_dummy" /obj/item/projectile/energy/flash/strong name = "chemical shell" @@ -297,6 +326,8 @@ range = 15 //if the shell hasn't hit anything after travelling this far it just explodes. flash_strength = 15 brightness = 15 + hud_state = "grenade_dummy" /obj/item/projectile/energy/flash/flare - flash_range = 2 \ No newline at end of file + flash_range = 2 + hud_state = "grenade_dummy" \ No newline at end of file diff --git a/code/modules/projectiles/projectile/explosive.dm b/code/modules/projectiles/projectile/explosive.dm index 307febc8bc..76da8f3e3a 100644 --- a/code/modules/projectiles/projectile/explosive.dm +++ b/code/modules/projectiles/projectile/explosive.dm @@ -7,6 +7,8 @@ icon_state = "missile" damage = 30 //Meaty whack. *Chuckles* does_spin = 0 + hud_state = "rocket_he" + hud_state_empty = "rocket_empty" /obj/item/projectile/bullet/srmrocket/on_hit(atom/target, blocked=0) if(!isliving(target)) //if the target isn't alive, so is a wall or something @@ -24,6 +26,7 @@ /obj/item/projectile/bullet/srmrocket/weak //Used in the jury rigged one. damage = 10 + hud_state = "rocket_he" /obj/item/projectile/bullet/srmrocket/weak/on_hit(atom/target, blocked=0) explosion(target, 0, 0, 2, 4)//No need to have a question. diff --git a/code/modules/projectiles/projectile/magnetic.dm b/code/modules/projectiles/projectile/magnetic.dm index 8b003bb6e5..b1041d6d17 100644 --- a/code/modules/projectiles/projectile/magnetic.dm +++ b/code/modules/projectiles/projectile/magnetic.dm @@ -8,12 +8,14 @@ weaken = 1 penetrating = 5 armor_penetration = 70 + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/slug name = "slug" icon_state = "gauss_silenced" damage = 75 armor_penetration = 90 + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/flechette name = "flechette" @@ -21,6 +23,7 @@ fire_sound = 'sound/weapons/rapidslice.ogg' damage = 20 armor_penetration = 100 + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/flechette/small name = "small flechette" @@ -28,6 +31,7 @@ fire_sound = 'sound/weapons/rapidslice.ogg' damage = 12 armor_penetration = 100 + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/flechette/small/khi name = "small carbyne flechette" @@ -36,12 +40,14 @@ damage = 18 armor_penetration = 100 penetrating = 10 + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/flechette/hunting name = "shredder slug" armor_penetration = 30 SA_bonus_damage = 40 SA_vulnerability = SA_ANIMAL + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/heated name = "slug" @@ -53,6 +59,7 @@ embed_chance = 0 armor_penetration = 40 penetrating = 1 + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/heated/weak icon_state = "gauss_silenced" @@ -61,6 +68,7 @@ embed_chance = 0 armor_penetration = 30 penetrating = 0 + hud_state = "alloy_spike" /obj/item/projectile/bullet/magnetic/fuelrod name = "fuel rod" @@ -75,6 +83,7 @@ embed_chance = 0 armor_penetration = 40 range = 20 + hud_state = "rocket_he" var/searing = 0 //Does this fuelrod ignore shields? var/detonate_travel = 0 //Will this fuelrod explode when it reaches maximum distance? @@ -121,6 +130,7 @@ flammability = -1 armor_penetration = 50 penetrating = 3 + hud_state = "rocket_ap" /obj/item/projectile/bullet/magnetic/fuelrod/phoron name = "blazing fuel rod" @@ -132,6 +142,7 @@ penetrating = 5 irradiate = 20 detonate_mob = 1 + hud_state = "rocket_fire" /obj/item/projectile/bullet/magnetic/fuelrod/supermatter name = "painfully incandescent fuel rod" @@ -148,6 +159,7 @@ detonate_travel = 1 detonate_mob = 1 energetic_impact = 1 + hud_state = "rocket_thermobaric" /obj/item/projectile/bullet/magnetic/fuelrod/supermatter/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null) //You cannot touch the supermatter without disentigrating. Assumedly, this is true for condensed rods of it flying at relativistic speeds. if(istype(target,/turf/simulated/wall) || istype(target,/mob/living)) @@ -168,6 +180,7 @@ check_armour = "melee" irradiate = 20 range = 6 + hud_state = "plasma_rifle_blast" /obj/item/projectile/bullet/magnetic/bore/Initialize(loc, range_mod) // i'm gonna be real honest i dunno how this works but it does . = ..() diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 142cde4071..e45e4ee3a5 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -9,6 +9,8 @@ light_range = 2 light_power = 0.5 light_color = "#55AAFF" + hud_state = "plasma_blast" + hud_state_empty = "battery_empty" combustion = FALSE impact_effect_type = /obj/effect/temp_visual/impact_effect/ion @@ -43,6 +45,7 @@ check_armour = "bullet" sharp = TRUE edge = TRUE + hud_state = "rocket_fire" /obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0) explosion(target, -1, 0, 2) @@ -62,6 +65,7 @@ light_power = 0.5 light_color = "#55AAFF" impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser + hud_state = "water" combustion = FALSE @@ -98,6 +102,7 @@ /obj/item/projectile/temp/hot name = "heat beam" target_temperature = 1000 + hud_state = "flame" combustion = TRUE @@ -109,6 +114,7 @@ damage_type = BRUTE nodamage = 1 check_armour = "bullet" + hud_state = "monkey" /obj/item/projectile/meteor/Bump(atom/A as mob|obj|turf|area) if(A == firer) @@ -145,6 +151,7 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser var/lasermod = 0 combustion = FALSE + hud_state = "electrothermal" /obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0) var/mob/living/M = target @@ -187,6 +194,7 @@ nodamage = 1 check_armour = "energy" var/decl/plantgene/gene = null + hud_state = "electrothermal" /obj/item/projectile/energy/florayield name = "beta somatoray" @@ -201,6 +209,7 @@ light_color = "#FFFFFF" impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser var/lasermod = 0 + hud_state = "electrothermal" /obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0) var/mob/living/M = target @@ -218,6 +227,7 @@ name = "flayer ray" combustion = FALSE + hud_state = "electrothermal" /obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0) if(ishuman(target)) @@ -233,6 +243,7 @@ nodamage = 1 damage_type = HALLOSS muzzle_type = /obj/effect/projectile/muzzle/bullet + hud_state = "monkey" /obj/item/projectile/bola name = "bola" @@ -241,6 +252,7 @@ embed_chance = 0 //Nada. damage_type = HALLOSS muzzle_type = null + hud_state = "monkey" combustion = FALSE @@ -260,7 +272,7 @@ embed_chance = 0 //Nada. damage_type = BRUTE muzzle_type = null - + hud_state = "monkey" combustion = FALSE /obj/item/projectile/webball/on_hit(var/atom/target, var/blocked = 0) @@ -282,6 +294,7 @@ light_range = 4 light_power = 3 light_color = "#3300ff" + hud_state = "alloy_spike" muzzle_type = /obj/effect/projectile/muzzle/tungsten tracer_type = /obj/effect/projectile/tracer/tungsten diff --git a/icons/mob/screen_ammo.dmi b/icons/mob/screen_ammo.dmi new file mode 100644 index 0000000000000000000000000000000000000000..57ab8e772e95e5c28da09592b8f1c4b0afc4d4bc GIT binary patch literal 5633 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 Ylv|rU=grWjbN`+ncXT^ibr^m5UtS#DF#rGn literal 0 HcmV?d00001