Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular M14 Rifle #451

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions code/__DEFINES/shuttles.dm
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,13 @@
#define ESCAPE_SHUTTLE_WEST "escape_shuttle_w"
#define ESCAPE_SHUTTLE_NORTH "escape_shuttle_n"
#define ESCAPE_SHUTTLE_SOUTH "escape_shuttle_s"
#define ESCAPE_SHUTTLE_BREACH "breacher_shuttle"

#define ESCAPE_SHUTTLE_WEST_PREFIX "escape_shuttle_w"
#define ESCAPE_SHUTTLE_EAST_PREFIX "escape_shuttle_e"
#define ESCAPE_SHUTTLE_NORTH_PREFIX "escape_shuttle_n"
#define ESCAPE_SHUTTLE_SOUTH_PREFIX "escape_shuttle_s"
#define ESCAPE_SHUTTLE_BREACH_PREFIX "breacher_shuttle"

#define ESCAPE_SHUTTLE_DOCK_PREFIX "almayer-hangar-escape-shuttle-"

Expand Down
4 changes: 4 additions & 0 deletions code/game/area/shuttles.dm
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@
icon = 'icons/turf/area_almayer.dmi'
icon_state = "lifeboat"

/area/shuttle/breach
icon = 'icons/turf/area_almayer.dmi'
icon_state = "lifeboat"

/area/shuttle/escape_pod/afterShuttleMove(new_parallax_dir)
. = ..()
playsound_area(src, 'sound/effects/escape_pod_launch.ogg', 50, 1)
Expand Down
121 changes: 121 additions & 0 deletions code/modules/projectiles/guns/rifles.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1962,3 +1962,124 @@
f90_shotgun_barrel.Attach(src)
update_attachable(f90_shotgun.slot)
update_attachable(f90_shotgun_barrel.slot)

//M14 Modular Rifle

/obj/item/weapon/gun/rifle/m14
name = "\improper M14 modular rifle"
desc = "The M14 modular rifle is a designated marksman rifle in service with the USCM. Sporting a bullpup configuration, the M4RA battle rifle is perfect for reconnaissance and fire support teams.\nTakes *only* non-high-velocity M14 magazines."
icon_state = "m4ra"
item_state = "m4ra"
fire_sound = 'sound/weapons/gun_m4ra.ogg'
reload_sound = 'sound/weapons/handling/l42_reload.ogg'
unload_sound = 'sound/weapons/handling/l42_unload.ogg'
current_mag = /obj/item/ammo_magazine/rifle/m14
attachable_allowed = list(
/obj/item/attachable/suppressor,
/obj/item/attachable/bayonet,
/obj/item/attachable/bayonet/upp,
/obj/item/attachable/bayonet/co2,
/obj/item/attachable/reddot,
/obj/item/attachable/reflex,
/obj/item/attachable/flashlight,
/obj/item/attachable/extended_barrel,
/obj/item/attachable/magnetic_harness,
/obj/item/attachable/bipod,
/obj/item/attachable/verticalgrip,
/obj/item/attachable/angledgrip,
/obj/item/attachable/lasersight,
/obj/item/attachable/scope,
/obj/item/attachable/scope/mini,
/obj/item/attachable/scope/mini_iff,
/obj/item/attachable/flashlight/grip,
)

flags_gun_features = GUN_AUTO_EJECTOR|GUN_CAN_POINTBLANK|GUN_AMMO_COUNTER
wield_delay = WIELD_DELAY_VERY_FAST
aim_slowdown = SLOWDOWN_ADS_QUICK
map_specific_decoration = TRUE

// Sprite offsets need to be configured - murphy
/obj/item/weapon/gun/rifle/m14/set_gun_attachment_offsets()
attachable_offset = list("muzzle_x" = 43, "muzzle_y" = 17,"rail_x" = 22, "rail_y" = 21, "under_x" = 30, "under_y" = 13, "stock_x" = 24, "stock_y" = 13, "special_x" = 37, "special_y" = 16)

/obj/item/weapon/gun/rifle/m14/set_gun_config_values()
..()
set_fire_delay(FIRE_DELAY_TIER_9)
set_burst_amount(0)
accuracy_mult = BASE_ACCURACY_MULT + HIT_ACCURACY_MULT_TIER_5
accuracy_mult_unwielded = BASE_ACCURACY_MULT - HIT_ACCURACY_MULT_TIER_4
damage_mult = BASE_BULLET_DAMAGE_MULT + BULLET_DAMAGE_MULT_TIER_8
recoil_unwielded = RECOIL_AMOUNT_TIER_4
damage_falloff_mult = 0
scatter = SCATTER_AMOUNT_TIER_8

/obj/item/weapon/gun/rifle/m14/handle_starting_attachment()
..()
var/obj/item/attachable/m4ra_barrel/integrated = new(src)
integrated.flags_attach_features &= ~ATTACH_REMOVABLE
integrated.Attach(src)
update_attachable(integrated.slot)

/obj/item/weapon/gun/rifle/m14/training
current_mag = /obj/item/ammo_magazine/rifle/m14/rubber

// pve - kinda weird icon usage, uses urban M4RA sprite w/ custom attachie sprite
/obj/item/weapon/gun/rifle/m14/pve
name = "\improper M4RA-R2 battle rifle"
desc = "The M4RA-R2 is a souped-up M4RA, the result of an ARMAT upgrade program that didn't pan out in huge numbers. Its main attraction is the ability to chamber and fire devastating <b>A19 depleted uranium rounds,</b> infamous for their overpenetration abilities and toxic effects on anyone unfortunate enough to survive a hit. The thicker barrel, of course, also has no issue with non-HV ammo."
desc_lore = "The USCMC was not terribly enthusiastic about unproven hand-held plasma weaponry. Before the XM99A was eventually adopted into use, the USCMC instead sought out a traditional squad-portable, precision, armor-piercing weapon, and contracted ARMAT to upgrade their M4RA platform to be capable of firing advanced AP rounds. They succeeded- sort of. <BR> <BR> The R2 was rejected for several reasons. It's a killer, but also a piece of junk. It kicks hard enough that precision sights simply don't stay zeroed, and its oversized muzzle-device extends an already long barrel-length. Additionally, A19 ammo, already expensive, was driven to absurd highs by the ammunition's specs. Depleted uranium is expensive...and cutting the service life of the M4RA's barrel in half is even more expensive. <BR> <BR> Those that were made, however, are still service-ready and were issued where the XM99A was unavailable due to its production only just starting."
icon = 'icons/obj/items/weapons/guns/guns_by_map/urban/guns_obj.dmi'
icon_state = "m4ra"
item_state = "m4ra"
fire_sound = 'sound/weapons/gun_m4ra.ogg'
reload_sound = 'sound/weapons/handling/l42_reload.ogg'
unload_sound = 'sound/weapons/handling/l42_unload.ogg'

current_mag = /obj/item/ammo_magazine/rifle/m14/pve
attachable_allowed = list(
/obj/item/attachable/reddot,
/obj/item/attachable/reflex,
/obj/item/attachable/flashlight,
/obj/item/attachable/extended_barrel,
/obj/item/attachable/magnetic_harness,
/obj/item/attachable/bipod,
/obj/item/attachable/verticalgrip,
/obj/item/attachable/angledgrip,
/obj/item/attachable/lasersight,
/obj/item/attachable/scope,
/obj/item/attachable/scope/mini,
/obj/item/attachable/scope/mini_iff,
/obj/item/attachable/flashlight/grip,
)

flags_gun_features = GUN_AUTO_EJECTOR|GUN_CAN_POINTBLANK|GUN_AMMO_COUNTER
wield_delay = WIELD_DELAY_VERY_FAST
aim_slowdown = SLOWDOWN_ADS_QUICK
map_specific_decoration = FALSE

/obj/item/weapon/gun/rifle/m14/pve/set_gun_config_values()
..()
set_fire_delay(FIRE_DELAY_TIER_4)
recoil_unwielded = RECOIL_AMOUNT_TIER_1
recoil = RECOIL_AMOUNT_TIER_3


// obnoxiously enough, need to do this manually...
item_icons = list(
WEAR_L_HAND = 'icons/obj/items/weapons/guns/guns_by_map/urban/guns_lefthand.dmi',
WEAR_R_HAND = 'icons/obj/items/weapons/guns/guns_by_map/urban/guns_righthand.dmi',
WEAR_BACK = 'icons/obj/items/weapons/guns/guns_by_map/urban/back.dmi'
)

/obj/item/weapon/gun/rifle/m14/pve/handle_starting_attachment()
..()
var/obj/item/attachable/m4ra_barrel/pve/integrated = new(src)
integrated.flags_attach_features &= ~ATTACH_REMOVABLE
var/obj/item/attachable/old_barrel = attachments[integrated.slot]
if(old_barrel)
old_barrel.Detach(detaching_gub = src, drop_attachment = FALSE)
qdel(old_barrel)
integrated.Attach(src)
update_attachable(integrated.slot)

233 changes: 233 additions & 0 deletions code/modules/shuttle/computers/breacher_computer.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
#define STATE_IDLE 4 //Pod is idle, not ready to launch.
#define STATE_BROKEN 5 //Pod failed to launch, is now broken.
#define STATE_READY 6 //Pod is armed and ready to go.
#define STATE_DELAYED 7 //Pod is being delayed from launching automatically.
#define STATE_LAUNCHING 8 //Pod is about to launch.
#define STATE_LAUNCHED 9 //Pod has successfully launched.

/obj/structure/machinery/computer/shuttle/breacher_pod_panel
name = "breacher shuttle controller"
icon = 'icons/obj/structures/machinery/airlock_machines.dmi'
icon_state = "airlock_control_standby"
unslashable = TRUE
unacidable = TRUE
var/pod_state = STATE_IDLE
var/launch_without_evac = FALSE

/obj/structure/machinery/computer/shuttle/breacher_pod_panel/ex_act(severity)
return FALSE

// TGUI stufferinos \\

/obj/structure/machinery/computer/shuttle/breacher_pod_panel/attack_hand(mob/user)
if(..())
return
tgui_interact(user)

/obj/structure/machinery/computer/shuttle/breacher_pod_panel/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "EscapePodConsole", "[src.name]")
ui.open()

/obj/structure/machinery/computer/shuttle/breacher_pod_panel/ui_state(mob/user)
return GLOB.not_incapacitated_and_adjacent_state

/obj/structure/machinery/computer/shuttle/breacher_pod_panel/ui_status(mob/user, datum/ui_state/state)
. = ..()
if(inoperable())
return UI_CLOSE

/obj/structure/machinery/computer/shuttle/breacher_pod_panel/ui_data(mob/user)
. = list()
var/obj/docking_port/mobile/crashable/breacher/shuttle = SSshuttle.getShuttle(shuttleId)

if(pod_state == STATE_IDLE && shuttle.evac_set)
pod_state = STATE_READY

.["docking_status"] = pod_state
switch(shuttle.mode)
if(SHUTTLE_CRASHED)
.["docking_status"] = STATE_BROKEN
if(SHUTTLE_IGNITING)
.["docking_status"] = STATE_LAUNCHING
if(SHUTTLE_CALL)
.["docking_status"] = STATE_LAUNCHED
var/obj/structure/machinery/door/door = shuttle.door_handler.doors[1]
.["door_state"] = door.density
.["door_lock"] = shuttle.door_handler.status == SHUTTLE_DOOR_LOCKED
.["can_delay"] = TRUE//launch_status[2]
.["launch_without_evac"] = launch_without_evac


/obj/structure/machinery/computer/shuttle/breacher_pod_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return

var/obj/docking_port/mobile/crashable/breacher/shuttle = SSshuttle.getShuttle(shuttleId)
switch(action)
if("force_launch")
if(!launch_without_evac && pod_state != STATE_READY && pod_state != STATE_DELAYED)
return

shuttle.evac_launch()
pod_state = STATE_LAUNCHING
. = TRUE
if("delay_launch")
pod_state = pod_state == STATE_DELAYED ? STATE_READY : STATE_DELAYED
. = TRUE
if("lock_door")
var/obj/structure/machinery/door/target_door = shuttle.door_handler.doors[1]
if(target_door.density) //Closed
shuttle.door_handler.control_doors("force-unlock")
else //Open
shuttle.door_handler.control_doors("force-lock-launch")
. = TRUE

/obj/structure/machinery/computer/shuttle/breacher_pod_panel/liaison
launch_without_evac = TRUE

//=========================================================================================
//================================Evacuation Sleeper=======================================
//=========================================================================================

/obj/structure/machinery/cryopod/evacuation/ex_act(severity)
return FALSE

/obj/structure/machinery/cryopod/evacuation/attackby(obj/item/grab/G, mob/user)
if(istype(G))
if(being_forced)
to_chat(user, SPAN_WARNING("There's something forcing it open!"))
return FALSE

if(occupant)
to_chat(user, SPAN_WARNING("There is someone in there already!"))
return FALSE

if(dock_state < STATE_READY)
to_chat(user, SPAN_WARNING("The cryo pod is not responding to commands!"))
return FALSE

var/mob/living/carbon/human/M = G.grabbed_thing
if(!istype(M))
return FALSE

visible_message(SPAN_WARNING("[user] starts putting [M.name] into the cryo pod."), null, null, 3)

if(do_after(user, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC))
if(!M || !G || !G.grabbed_thing || !G.grabbed_thing.loc || G.grabbed_thing != M)
return FALSE
move_mob_inside(M)

/obj/structure/machinery/cryopod/evacuation/eject()
set name = "Eject Pod"
set category = "Object"
set src in oview(1)

if(!occupant || !usr.stat || usr.is_mob_restrained())
return FALSE

if(occupant) //Once you're in, you cannot exit, and outside forces cannot eject you.
//The occupant is actually automatically ejected once the evac is canceled.
if(occupant != usr) to_chat(usr, SPAN_WARNING("You are unable to eject the occupant unless the evacuation is canceled."))

add_fingerprint(usr)

/obj/structure/machinery/cryopod/evacuation/go_out() //When the system ejects the occupant.
if(occupant)
occupant.forceMove(get_turf(src))
occupant.in_stasis = FALSE
occupant = null
icon_state = orient_right ? "body_scanner_open-r" : "body_scanner_open"

/obj/structure/machinery/cryopod/evacuation/move_inside()
set name = "Enter Pod"
set category = "Object"
set src in oview(1)

var/mob/living/carbon/human/user = usr

if(!istype(user) || user.stat || user.is_mob_restrained())
return FALSE

if(being_forced)
to_chat(user, SPAN_WARNING("You can't enter when it's being forced open!"))
return FALSE

if(occupant)
to_chat(user, SPAN_WARNING("The cryogenic pod is already in use! You will need to find another."))
return FALSE

if(dock_state < STATE_READY)
to_chat(user, SPAN_WARNING("The cryo pod is not responding to commands!"))
return FALSE

visible_message(SPAN_WARNING("[user] starts climbing into the cryo pod."), null, null, 3)

if(do_after(user, 20, INTERRUPT_NO_NEEDHAND, BUSY_ICON_GENERIC))
user.stop_pulling()
move_mob_inside(user)

/obj/structure/machinery/cryopod/evacuation/attack_alien(mob/living/carbon/xenomorph/user)
if(being_forced)
to_chat(user, SPAN_XENOWARNING("It's being forced open already!"))
return XENO_NO_DELAY_ACTION

if(!occupant)
to_chat(user, SPAN_XENOWARNING("There is nothing of interest in there."))
return XENO_NO_DELAY_ACTION

being_forced = !being_forced
xeno_attack_delay(user)
visible_message(SPAN_WARNING("[user] begins to pry \the [src]'s cover!"), null, null, 3)
playsound(src,'sound/effects/metal_creaking.ogg', 25, 1)
if(do_after(user, 20, INTERRUPT_ALL, BUSY_ICON_HOSTILE)) go_out() //Force the occupant out.
being_forced = !being_forced
return XENO_NO_DELAY_ACTION

/obj/structure/machinery/door/airlock/evacuation/Initialize()
. = ..()
if(start_locked)
INVOKE_ASYNC(src, PROC_REF(lock))

/obj/structure/machinery/door/airlock/evacuation/Destroy()
if(linked_shuttle)
linked_shuttle.mode = SHUTTLE_CRASHED
linked_shuttle.door_handler.doors -= list(src)
. = ..()

//Can't interact with them, mostly to prevent grief and meta.
/obj/structure/machinery/door/airlock/evacuation/Collided()
return FALSE

/obj/structure/machinery/door/airlock/evacuation/attackby()
return FALSE

/obj/structure/machinery/door/airlock/evacuation/attack_hand()
return FALSE

/obj/structure/machinery/door/airlock/evacuation/attack_alien(mob/living/carbon/xenomorph/xeno)
if(!density || unslashable) //doors become slashable after evac is called
return FALSE

if(xeno.claw_type < CLAW_TYPE_SHARP)
to_chat(xeno, SPAN_WARNING("[src] is bolted down tight."))
return XENO_NO_DELAY_ACTION

xeno.animation_attack_on(src)
playsound(src, 'sound/effects/metalhit.ogg', 25, 1)
take_damage(HEALTH_DOOR / XENO_HITS_TO_DESTROY_BOLTED_DOOR)
return XENO_ATTACK_ACTION


/obj/structure/machinery/door/airlock/evacuation/attack_remote()
return FALSE

/obj/structure/machinery/door/airlock/evacuation/get_applying_acid_time() //you can melt evacuation doors only when they are manually locked
if(!density)
return -1
return ..()

/obj/structure/machinery/door/airlock/evacuation/liaison
start_locked = FALSE
Loading
Loading