Files
Polaris/code/modules/projectiles/guns/energy.dm
T
Rykka 3fd5296682 TGMC Ammo HUD Port
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
2022-04-07 01:00:23 -06:00

259 lines
8.1 KiB
Plaintext

/obj/item/weapon/gun/energy
name = "energy gun"
desc = "A basic energy-based gun."
icon_state = "energy"
fire_sound_text = "laser blast"
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
var/charge_cost = 240 //How much energy is needed to fire.
var/accept_cell_type = /obj/item/weapon/cell/device
var/cell_type = /obj/item/weapon/cell/device/weapon
projectile_type = /obj/item/projectile/beam/practice
var/modifystate
var/charge_meter = 1 //if set, the icon state will be chosen based on the current charge
//self-recharging
var/self_recharge = 0 //if set, the weapon will recharge itself
var/use_external_power = 0 //if set, the weapon will look for an external power source to draw from, otherwise it recharges magically
var/use_organic_power = 0 // If set, the weapon will draw from nutrition or blood.
var/recharge_time = 4
var/charge_tick = 0
var/charge_delay = 75 //delay between firing and charging
var/battery_lock = 0 //If set, weapon cannot switch batteries
/obj/item/weapon/gun/energy/Initialize()
. = ..()
if(self_recharge)
power_supply = new /obj/item/weapon/cell/device/weapon(src)
START_PROCESSING(SSobj, src)
else
if(cell_type)
power_supply = new cell_type(src)
else
power_supply = null
update_icon()
/obj/item/weapon/gun/energy/Destroy()
if(self_recharge)
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/weapon/gun/energy/get_cell()
return power_supply
/obj/item/weapon/gun/energy/process()
if(self_recharge) //Every [recharge_time] ticks, recharge a shot for the battery
if(world.time > last_shot + charge_delay) //Doesn't work if you've fired recently
if(!power_supply || power_supply.charge >= power_supply.maxcharge)
return 0 // check if we actually need to recharge
charge_tick++
if(charge_tick < recharge_time) return 0
charge_tick = 0
var/rechargeamt = power_supply.maxcharge*0.2
if(use_external_power)
var/obj/item/weapon/cell/external = get_external_power_supply()
if(!external || !external.use(rechargeamt)) //Take power from the borg...
return 0
if(use_organic_power)
var/mob/living/carbon/human/H
if(ishuman(loc))
H = loc
if(istype(loc, /obj/item/organ))
var/obj/item/organ/O = loc
if(O.owner)
H = O.owner
if(istype(H))
var/start_nutrition = H.nutrition
var/end_nutrition = 0
H.adjust_nutrition(-rechargeamt / 15)
end_nutrition = H.nutrition
if(start_nutrition - max(0, end_nutrition) < rechargeamt / 15)
if(H.isSynthetic())
H.adjustToxLoss((rechargeamt / 15) - (start_nutrition - max(0, end_nutrition)))
else
H.remove_blood((rechargeamt / 15) - (start_nutrition - max(0, end_nutrition)))
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
/obj/item/weapon/gun/energy/attackby(var/obj/item/A as obj, mob/user as mob)
..()
/obj/item/weapon/gun/energy/switch_firemodes(mob/user)
if(..())
update_icon()
/obj/item/weapon/gun/energy/emp_act(severity)
..()
update_icon()
/obj/item/weapon/gun/energy/consume_next_projectile()
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)
if(istype(C, /obj/item/weapon/cell))
if(self_recharge || battery_lock)
to_chat(user, "<span class='notice'>[src] does not have a battery port.</span>")
return
if(istype(C, accept_cell_type))
var/obj/item/weapon/cell/P = C
if(power_supply)
to_chat(user, "<span class='notice'>[src] already has a power cell.</span>")
else
user.visible_message("[user] is reloading [src].", "<span class='notice'>You start to insert [P] into [src].</span>")
if(do_after(user, 5 * P.w_class))
user.remove_from_mob(P)
power_supply = P
P.loc = src
user.visible_message("[user] inserts [P] into [src].", "<span class='notice'>You insert [P] into [src].</span>")
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, "<span class='notice'>This cell is not fitted for [src].</span>")
return
/obj/item/weapon/gun/energy/proc/unload_ammo(mob/user)
if(self_recharge || battery_lock)
to_chat(user, "<span class='notice'>[src] does not have a battery port.</span>")
return
if(power_supply)
user.put_in_hands(power_supply)
power_supply.update_icon()
user.visible_message("[user] removes [power_supply] from [src].", "<span class='notice'>You remove [power_supply] from [src].</span>")
power_supply = null
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, "<span class='notice'>[src] does not have a power cell.</span>")
/obj/item/weapon/gun/energy/attackby(var/obj/item/A as obj, mob/user as mob)
..()
load_ammo(A, user)
/obj/item/weapon/gun/energy/attack_hand(mob/user as mob)
if(user.get_inactive_hand() == src)
unload_ammo(user)
else
return ..()
/obj/item/weapon/gun/energy/proc/get_external_power_supply()
if(isrobot(src.loc))
var/mob/living/silicon/robot/R = src.loc
return R.cell
if(istype(src.loc, /obj/item/rig_module))
var/obj/item/rig_module/module = src.loc
if(module.holder && module.holder.wearer)
var/mob/living/carbon/human/H = module.holder.wearer
if(istype(H) && H.get_rig())
var/obj/item/weapon/rig/suit = H.get_rig()
if(istype(suit))
return suit.cell
return null
/obj/item/weapon/gun/energy/examine(mob/user)
. = ..()
if(power_supply)
if(charge_cost)
var/shots_remaining = round(power_supply.charge / max(1, charge_cost)) // Paranoia
. += "Has [shots_remaining] shot\s remaining."
else
. += "Has infinite shots remaining."
else
. += "Does not have a power cell."
/obj/item/weapon/gun/energy/update_icon(var/ignore_inhands)
if(power_supply == null)
if(modifystate)
icon_state = "[modifystate]_open"
else
icon_state = "[initial(icon_state)]_open"
return
else if(charge_meter)
var/ratio = power_supply.charge / power_supply.maxcharge
//make sure that rounding down will not give us the empty state even if we have charge for a shot left.
if(power_supply.charge < charge_cost)
ratio = 0
else
ratio = max(round(ratio, 0.25) * 100, 25)
if(modifystate)
icon_state = "[modifystate][ratio]"
else
icon_state = "[initial(icon_state)][ratio]"
else if(power_supply)
if(modifystate)
icon_state = "[modifystate]"
else
icon_state = "[initial(icon_state)]"
if(!ignore_inhands) update_held_icon()
/obj/item/weapon/gun/energy/proc/start_recharge()
if(power_supply == null)
power_supply = new /obj/item/weapon/cell/device/weapon(src)
self_recharge = 1
START_PROCESSING(SSobj, src)
update_icon()
/obj/item/weapon/gun/energy/get_description_interaction()
var/list/results = list()
if(!battery_lock && !self_recharge)
if(power_supply)
results += "[desc_panel_image("offhand")]to remove the weapon cell."
else
results += "[desc_panel_image("weapon cell")]to add a new weapon cell."
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)